Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

var validationRegex = /^[a-z0-9]{1,4}\s*?\d[a-z]{2}$/i,
incodeRegex = /\d[a-z]{2}$/i,
validOutcodeRegex = /^[a-z0-9]{1,4}$/i;
validOutcodeRegex = /^[a-z0-9]{1,4}$/i,
areaRegex = /^[a-z]{1,2}/i,
sectorRegex = /^[a-z0-9]{1,4}\s*?\d/i,
unitRegex = /[a-z]{2}$/i;

function isValidPostcode (postcode) {
return !!postcode.match(validationRegex);
Expand All @@ -16,6 +19,18 @@ function parseIncode (postcode) {
return postcode.match(incodeRegex)[0];
}

function parseArea (postcode) {
return postcode.match(areaRegex)[0];
}

function parseSector (postcode) {
return postcode.match(sectorRegex)[0];
}

function parseUnit (postcode) {
return postcode.match(unitRegex)[0];
}

function Postcode (rawPostcode) {
this._raw = rawPostcode;
this._valid = isValidPostcode(rawPostcode);
Expand Down Expand Up @@ -47,10 +62,31 @@ Postcode.prototype.outcode = function () {
return this._outcode;
}

Postcode.prototype.area = function () {
if (!this._valid) return null;
if (this._area) return this._area;
this._area = parseArea(this._raw).toUpperCase();
return this._area;
}

Postcode.prototype.sector = function () {
if (!this._valid) return null;
if (this._sector) return this._sector;
this._sector = parseSector(this.normalise()).toUpperCase();
return this._sector;
}

Postcode.prototype.unit = function () {
if (!this._valid) return null;
if (this._unit) return this._unit;
this._unit = parseUnit(this._raw).toUpperCase();
return this._unit;
}

Postcode.prototype.normalise = function () {
if (!this._valid) return null;
if (this.postcode) return this.postcode;
return [this.outcode()," ", this.incode()].join("");
}

module.exports = Postcode;
module.exports = Postcode;
52 changes: 52 additions & 0 deletions tests/data/areas.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"tests" : [
{
"base" : "L27 8XY",
"expected" : "L"
},
{
"base" : "NR10 3EZ",
"expected" : "NR"
},
{
"base" : "RG4 5AY",
"expected" : "RG"
},
{
"base" : "NE69 7AW",
"expected" : "NE"
},
{
"base" : "SE23 2NF",
"expected" : "SE"
},
{
"base" : "BT35 8GE",
"expected" : "BT"
},
{
"base" : "L278XY",
"expected" : "L"
},
{
"base" : "NR103EZ",
"expected" : "NR"
},
{
"base" : "RG45AY",
"expected" : "RG"
},
{
"base" : "NE697AW",
"expected" : "NE"
},
{
"base" : "SE232NF",
"expected" : "SE"
},
{
"base" : "BT358GE",
"expected" : "BT"
}
]
}
52 changes: 52 additions & 0 deletions tests/data/sectors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"tests" : [
{
"base" : "L27 8XY",
"expected" : "L27 8"
},
{
"base" : "NR10 3EZ",
"expected" : "NR10 3"
},
{
"base" : "RG4 5AY",
"expected" : "RG4 5"
},
{
"base" : "NE69 7AW",
"expected" : "NE69 7"
},
{
"base" : "SE23 2NF",
"expected" : "SE23 2"
},
{
"base" : "BT35 8GE",
"expected" : "BT35 8"
},
{
"base" : "L278XY",
"expected" : "L27 8"
},
{
"base" : "NR103EZ",
"expected" : "NR10 3"
},
{
"base" : "RG45AY",
"expected" : "RG4 5"
},
{
"base" : "NE697AW",
"expected" : "NE69 7"
},
{
"base" : "SE232NF",
"expected" : "SE23 2"
},
{
"base" : "BT358GE",
"expected" : "BT35 8"
}
]
}
52 changes: 52 additions & 0 deletions tests/data/units.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"tests" : [
{
"base" : "L27 8XY",
"expected" : "XY"
},
{
"base" : "NR10 3EZ",
"expected" : "EZ"
},
{
"base" : "RG4 5AY",
"expected" : "AY"
},
{
"base" : "NE69 7AW",
"expected" : "AW"
},
{
"base" : "SE23 2NF",
"expected" : "NF"
},
{
"base" : "BT35 8GE",
"expected" : "GE"
},
{
"base" : "L278XY",
"expected" : "XY"
},
{
"base" : "NR103EZ",
"expected" : "EZ"
},
{
"base" : "RG45AY",
"expected" : "AY"
},
{
"base" : "NE697AW",
"expected" : "AW"
},
{
"base" : "SE232NF",
"expected" : "NF"
},
{
"base" : "BT358GE",
"expected" : "GE"
}
]
}
74 changes: 73 additions & 1 deletion tests/exhaustive_unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,4 +111,76 @@ describe("Exhaustive postcode test", function () {
done();
});
});
});
describe("Area parsing", function () {
it("should return the correct area", function (done) {
this.timeout(60000);
testData.forEach(function (testPostcode) {
var pc = testPostcode[0],
postcode = new Postcode(pc),
downcasePostcode = new Postcode(pc.toLowerCase()),
unspacedPostcode = new Postcode(pc.replace(/\s/, "")),
testArea;
if (pc.length === 7) {
// Since this isn't normalised in dataset, best we can do is see if normalised data matches
assert.equal(postcode.area(), downcasePostcode.area());
assert.equal(postcode.area(), unspacedPostcode.area());
} else {
// Any space indicates incode/outcode
testArea = pc.match(/\s.*/)[0].replace(/\s/, "");
assert.equal(postcode.area(), testArea);
assert.equal(downcasePostcode.area(), testArea);
assert.equal(unspacedPostcode.area(), testArea);
}
});
done();
});
});
describe("Sector parsing", function () {
it("should return the correct sector", function (done) {
this.timeout(60000);
testData.forEach(function (testPostcode) {
var pc = testPostcode[0],
postcode = new Postcode(pc),
downcasePostcode = new Postcode(pc.toLowerCase()),
unspacedPostcode = new Postcode(pc.replace(/\s/, "")),
testSector;
if (pc.length === 7) {
// Since this isn't normalised in dataset, best we can do is see if normalised data matches
assert.equal(postcode.sector(), downcasePostcode.sector());
assert.equal(postcode.sector(), unspacedPostcode.sector());
} else {
// Any space indicates incode/outcode
testSector = pc.match(/\s.*/)[0].replace(/\s/, "");
assert.equal(postcode.sector(), testSector);
assert.equal(downcasePostcode.sector(), testSector);
assert.equal(unspacedPostcode.sector(), testSector);
}
});
done();
});
});
describe("Unit parsing", function () {
it("should return the correct unit", function (done) {
this.timeout(60000);
testData.forEach(function (testPostcode) {
var pc = testPostcode[0],
postcode = new Postcode(pc),
downcasePostcode = new Postcode(pc.toLowerCase()),
unspacedPostcode = new Postcode(pc.replace(/\s/, "")),
testUnit;
if (pc.length === 7) {
// Since this isn't normalised in dataset, best we can do is see if normalised data matches
assert.equal(postcode.unit(), downcasePostcode.unit());
assert.equal(postcode.unit(), unspacedPostcode.unit());
} else {
// Any space indicates incode/outcode
testUnit = pc.match(/\s.*/)[0].replace(/\s/, "");
assert.equal(postcode.unit(), testUnit);
assert.equal(downcasePostcode.unit(), testUnit);
assert.equal(unspacedPostcode.unit(), testUnit);
}
});
done();
});
});
});
59 changes: 58 additions & 1 deletion tests/unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,61 @@ describe("Outcode parsing", function () {
it ("should return null if invalid postcode", function () {
assert.isNull(new Postcode("Definitly bogus").outcode());
});
});
});

describe("Area parsing", function () {
before(function (done) {
testData = fs.readFile(path.join(dataDir, "areas.json"), function (error, data) {
if (error) throw error;
testData = JSON.parse(data);
done();
});
});

it ("should correctly parse areas", function () {
testData.tests.forEach(function (elem) {
assert.equal(new Postcode(elem.base).area(), elem.expected);
});
});
it ("should return null if invalid postcode", function () {
assert.isNull(new Postcode("Definitely bogus").area());
});
});

describe("Sector parsing", function () {
before(function (done) {
testData = fs.readFile(path.join(dataDir, "sectors.json"), function (error, data) {
if (error) throw error;
testData = JSON.parse(data);
done();
});
});

it ("should correctly parse sectors", function () {
testData.tests.forEach(function (elem) {
assert.equal(new Postcode(elem.base).sector(), elem.expected);
});
});
it ("should return null if invalid postcode", function () {
assert.isNull(new Postcode("Definitely bogus").sector());
});
});

describe("Unit parsing", function () {
before(function (done) {
testData = fs.readFile(path.join(dataDir, "units.json"), function (error, data) {
if (error) throw error;
testData = JSON.parse(data);
done();
});
});

it ("should correctly parse units", function () {
testData.tests.forEach(function (elem) {
assert.equal(new Postcode(elem.base).unit(), elem.expected);
});
});
it ("should return null if invalid postcode", function () {
assert.isNull(new Postcode("Definitely bogus").unit());
});
});