uk_postcode 1.0.1 → 2.0.0.alpha
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/COPYING.txt +25 -0
- data/README.md +105 -55
- data/lib/uk_postcode/country_finder.rb +15 -0
- data/lib/uk_postcode/country_lookup.rb +10 -0
- data/lib/uk_postcode/geographic_postcode.rb +98 -0
- data/lib/uk_postcode/giro_postcode.rb +61 -0
- data/lib/uk_postcode/invalid_postcode.rb +38 -0
- data/lib/uk_postcode/tree.rb +75 -0
- data/lib/uk_postcode/version.rb +2 -2
- data/lib/uk_postcode.rb +13 -106
- data/test/country_finder_test.rb +33 -0
- data/test/full_postcode_test.rb +35 -0
- data/test/geographic_postcode_test.rb +271 -0
- data/test/giro_postcode_test.rb +100 -0
- data/test/invalid_postcode_test.rb +75 -0
- data/test/special_postcode_test.rb +50 -0
- data/test/tree_test.rb +84 -0
- data/test/uk_postcode_test.rb +17 -265
- metadata +20 -9
- data/Rakefile +0 -8
- data/test/samples/wikipedia.list +0 -35
- data/test/samples_test.rb +0 -18
data/lib/uk_postcode.rb
CHANGED
|
@@ -1,112 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
( [A-PR-UWYZ01][A-Z01]? ) # area
|
|
6
|
-
( [0-9IO][0-9A-HJKMNPR-YIO]? ) # district
|
|
7
|
-
(?: \s*
|
|
8
|
-
( [0-9IO] ) # sector
|
|
9
|
-
( [ABD-HJLNPQ-Z10]{2} ) # unit
|
|
10
|
-
)?
|
|
11
|
-
) \s* \Z/x
|
|
12
|
-
|
|
13
|
-
attr_reader :raw
|
|
14
|
-
|
|
15
|
-
# Initialise a new UKPostcode instance from the given postcode string
|
|
16
|
-
#
|
|
17
|
-
def initialize(postcode_as_string)
|
|
18
|
-
@raw = postcode_as_string
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
# Returns true if the postcode is a valid full postcode (e.g. W1A 1AA) or outcode (e.g. W1A)
|
|
22
|
-
#
|
|
23
|
-
def valid?
|
|
24
|
-
!!outcode
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
# Returns true if the postcode is a valid full postcode (e.g. W1A 1AA)
|
|
28
|
-
#
|
|
29
|
-
def full?
|
|
30
|
-
!!(outcode && incode)
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# The left-hand part of the postcode, e.g. W1A 1AA -> W1A
|
|
34
|
-
#
|
|
35
|
-
def outcode
|
|
36
|
-
area && district && [area, district].join
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
# The right-hand part of the postcode, e.g. W1A 1AA -> 1AA
|
|
40
|
-
#
|
|
41
|
-
def incode
|
|
42
|
-
sector && unit && [sector, unit].join
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# The first part of the outcode, e.g. W1A 2AB -> W
|
|
46
|
-
#
|
|
47
|
-
def area
|
|
48
|
-
parts[0]
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# The second part of the outcode, e.g. W1A 2AB -> 1A
|
|
52
|
-
#
|
|
53
|
-
def district
|
|
54
|
-
parts[1]
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# The first part of the incode, e.g. W1A 2AB -> 2
|
|
58
|
-
#
|
|
59
|
-
def sector
|
|
60
|
-
parts[2]
|
|
61
|
-
end
|
|
1
|
+
require "uk_postcode/version"
|
|
2
|
+
require "uk_postcode/geographic_postcode"
|
|
3
|
+
require "uk_postcode/giro_postcode"
|
|
4
|
+
require "uk_postcode/invalid_postcode"
|
|
62
5
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
def unit
|
|
66
|
-
parts[3]
|
|
67
|
-
end
|
|
6
|
+
module UKPostcode
|
|
7
|
+
module_function
|
|
68
8
|
|
|
69
|
-
#
|
|
70
|
-
#
|
|
9
|
+
# Attempt to parse the string str as a postcode. Returns an object
|
|
10
|
+
# representing the postcode, or an InvalidPostcode if the string cannot be
|
|
11
|
+
# parsed.
|
|
71
12
|
#
|
|
72
|
-
def
|
|
73
|
-
[
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
alias_method :normalize, :norm
|
|
77
|
-
|
|
78
|
-
alias_method :to_s, :raw
|
|
79
|
-
alias_method :to_str, :raw
|
|
80
|
-
|
|
81
|
-
def inspect(*args)
|
|
82
|
-
"<#{self.class.to_s} #{raw}>"
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
private
|
|
86
|
-
def parts
|
|
87
|
-
return @parts if @matched
|
|
88
|
-
|
|
89
|
-
@matched = true
|
|
90
|
-
matches = raw.upcase.match(MATCH) || []
|
|
91
|
-
if matches[1]
|
|
92
|
-
@parts = %w[ G IR 0 AA ]
|
|
93
|
-
else
|
|
94
|
-
a, b, c, d = (2..5).map{ |i| matches[i] }
|
|
95
|
-
if a =~ /^[A-Z][I1]$/
|
|
96
|
-
a = a[0, 1]
|
|
97
|
-
b = "1" + b
|
|
98
|
-
end
|
|
99
|
-
@parts = [letters(a), digits(b), digits(c), letters(d)]
|
|
13
|
+
def parse(str)
|
|
14
|
+
[GiroPostcode, GeographicPostcode, InvalidPostcode].each do |klass|
|
|
15
|
+
pc = klass.parse(str)
|
|
16
|
+
return pc if pc
|
|
100
17
|
end
|
|
101
18
|
end
|
|
102
|
-
|
|
103
|
-
def letters(s)
|
|
104
|
-
s && s.tr("10", "IO")
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def digits(s)
|
|
108
|
-
s && s.tr("IO", "10")
|
|
109
|
-
end
|
|
110
19
|
end
|
|
111
|
-
|
|
112
|
-
require "uk_postcode/version"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require_relative "./test_helper"
|
|
2
|
+
require "uk_postcode"
|
|
3
|
+
|
|
4
|
+
describe UKPostcode do
|
|
5
|
+
it 'should find the country of a full postcode in England' do
|
|
6
|
+
UKPostcode.parse('W1A 1AA').country.must_equal :england
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'should find the country of a full postcode in Scotland' do
|
|
10
|
+
UKPostcode.parse('EH8 8DX').country.must_equal :scotland
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'should find the country of a full postcode in Wales' do
|
|
14
|
+
UKPostcode.parse('CF99 1NA').country.must_equal :wales
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'should find the country of a full postcode in Northern Ireland' do
|
|
18
|
+
UKPostcode.parse('BT4 3XX').country.must_equal :northern_ireland
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'should find the country of a postcode in a border region' do
|
|
22
|
+
UKPostcode.parse('CA6 5HS').country.must_equal :scotland
|
|
23
|
+
UKPostcode.parse('CA6 5HT').country.must_equal :england
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'should find the country of an unambiguous partial postcode' do
|
|
27
|
+
UKPostcode.parse('BT4').country.must_equal :northern_ireland
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'should return :unknown for an ambiguous partial postcode' do
|
|
31
|
+
UKPostcode.parse('DG16').country.must_equal :unknown
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require_relative "./test_helper"
|
|
2
|
+
require "csv"
|
|
3
|
+
require "uk_postcode"
|
|
4
|
+
|
|
5
|
+
describe "Full set of postcodes" do
|
|
6
|
+
CSV_PATH = File.expand_path("../data/postcodes.csv", __FILE__)
|
|
7
|
+
|
|
8
|
+
COUNTRIES = {
|
|
9
|
+
'E92000001' => :england,
|
|
10
|
+
'N92000002' => :northern_ireland,
|
|
11
|
+
'S92000003' => :scotland,
|
|
12
|
+
'W92000004' => :wales,
|
|
13
|
+
'L93000001' => :channel_islands,
|
|
14
|
+
'M83000003' => :isle_of_man
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
it "should correctly parse and find the country of every extant postcode" do
|
|
18
|
+
if File.exist?(CSV_PATH)
|
|
19
|
+
CSV.foreach(CSV_PATH, headers: [:postcode, :country]) do |row|
|
|
20
|
+
outcode = row[:postcode][0,4].strip
|
|
21
|
+
incode = row[:postcode][4,3].strip
|
|
22
|
+
country = COUNTRIES.fetch(row[:country])
|
|
23
|
+
|
|
24
|
+
postcode = UKPostcode.parse(outcode + incode)
|
|
25
|
+
|
|
26
|
+
postcode.wont_be_nil
|
|
27
|
+
postcode.outcode.must_equal outcode
|
|
28
|
+
postcode.incode.must_equal incode
|
|
29
|
+
postcode.country.must_equal country
|
|
30
|
+
end
|
|
31
|
+
else
|
|
32
|
+
skip "Skipping because #{CSV_PATH} does not exist"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
require_relative "./test_helper"
|
|
2
|
+
require "uk_postcode/geographic_postcode"
|
|
3
|
+
|
|
4
|
+
describe UKPostcode::GeographicPostcode do
|
|
5
|
+
described_class = UKPostcode::GeographicPostcode
|
|
6
|
+
|
|
7
|
+
describe "parse" do
|
|
8
|
+
it "should parse a full postcode" do
|
|
9
|
+
pc = described_class.parse("W1A 1AA")
|
|
10
|
+
pc.must_be_instance_of described_class
|
|
11
|
+
pc.area.must_equal "W"
|
|
12
|
+
pc.district.must_equal "1A"
|
|
13
|
+
pc.sector.must_equal "1"
|
|
14
|
+
pc.unit.must_equal "AA"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should parse a postcode with no unit" do
|
|
18
|
+
pc = described_class.parse("W1A 1")
|
|
19
|
+
pc.must_be_instance_of described_class
|
|
20
|
+
pc.area.must_equal "W"
|
|
21
|
+
pc.district.must_equal "1A"
|
|
22
|
+
pc.sector.must_equal "1"
|
|
23
|
+
pc.unit.must_be_nil
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it "should parse an outcode" do
|
|
27
|
+
pc = described_class.parse("W1A")
|
|
28
|
+
pc.must_be_instance_of described_class
|
|
29
|
+
pc.area.must_equal "W"
|
|
30
|
+
pc.district.must_equal "1A"
|
|
31
|
+
pc.sector.must_be_nil
|
|
32
|
+
pc.unit.must_be_nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "should parse an area" do
|
|
36
|
+
pc = described_class.parse("W")
|
|
37
|
+
pc.must_be_instance_of described_class
|
|
38
|
+
pc.area.must_equal "W"
|
|
39
|
+
pc.district.must_be_nil
|
|
40
|
+
pc.sector.must_be_nil
|
|
41
|
+
pc.unit.must_be_nil
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
it "should handle extra spaces" do
|
|
45
|
+
pc = described_class.parse(" W1A 1AA ")
|
|
46
|
+
pc.must_be_instance_of described_class
|
|
47
|
+
pc.to_s.must_equal "W1A 1AA"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should handle no spaces" do
|
|
51
|
+
pc = described_class.parse("W1A1AA")
|
|
52
|
+
pc.must_be_instance_of described_class
|
|
53
|
+
pc.to_s.must_equal "W1A 1AA"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should be case-insensitive" do
|
|
57
|
+
pc = described_class.parse("w1a 1aa")
|
|
58
|
+
pc.must_be_instance_of described_class
|
|
59
|
+
pc.to_s.must_equal "W1A 1AA"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should return nil if unable to parse" do
|
|
63
|
+
pc = described_class.parse("Can't parse this")
|
|
64
|
+
pc.must_be_nil
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe "single-letter area" do
|
|
68
|
+
it "should extract area without trailing I from outcode" do
|
|
69
|
+
pc = described_class.parse("B11")
|
|
70
|
+
pc.area.must_equal "B"
|
|
71
|
+
pc.district.must_equal "11"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "should extract area without trailing I from full postcode with space" do
|
|
75
|
+
pc = described_class.parse("E17 1AA")
|
|
76
|
+
pc.area.must_equal "E"
|
|
77
|
+
pc.district.must_equal "17"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should extract area without trailing I from full postcode without space" do
|
|
81
|
+
pc = described_class.parse("E171AA")
|
|
82
|
+
pc.area.must_equal "E"
|
|
83
|
+
pc.district.must_equal "17"
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
describe "trailing O in area" do
|
|
88
|
+
it "should extract area with trailing O from outcode" do
|
|
89
|
+
pc = described_class.parse("CO1")
|
|
90
|
+
pc.area.must_equal "CO"
|
|
91
|
+
pc.district.must_equal "1"
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "should extract area with trailing O from full postcode with space" do
|
|
95
|
+
pc = described_class.parse("CO1 1BT")
|
|
96
|
+
pc.area.must_equal "CO"
|
|
97
|
+
pc.district.must_equal "1"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it "should extract area with trailing O from full postcode without space" do
|
|
101
|
+
pc = described_class.parse("CO11BT")
|
|
102
|
+
pc.area.must_equal "CO"
|
|
103
|
+
pc.district.must_equal "1"
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
describe "tricky postcodes" do
|
|
108
|
+
it "should parse B11 1LL" do
|
|
109
|
+
pc = described_class.parse("B111LL")
|
|
110
|
+
pc.area.must_equal "B"
|
|
111
|
+
pc.district.must_equal "11"
|
|
112
|
+
pc.sector.must_equal "1"
|
|
113
|
+
pc.unit.must_equal "LL"
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it "should parse BII ILL" do
|
|
117
|
+
pc = described_class.parse("BIIILL")
|
|
118
|
+
pc.area.must_equal "B"
|
|
119
|
+
pc.district.must_equal "11"
|
|
120
|
+
pc.sector.must_equal "1"
|
|
121
|
+
pc.unit.must_equal "LL"
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "should parse BB11 1DJ" do
|
|
125
|
+
pc = described_class.parse("BB111DJ")
|
|
126
|
+
pc.area.must_equal "BB"
|
|
127
|
+
pc.district.must_equal "11"
|
|
128
|
+
pc.sector.must_equal "1"
|
|
129
|
+
pc.unit.must_equal "DJ"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it "should parse BBII IDJ" do
|
|
133
|
+
pc = described_class.parse("BBIIIDJ")
|
|
134
|
+
pc.area.must_equal "BB"
|
|
135
|
+
pc.district.must_equal "11"
|
|
136
|
+
pc.sector.must_equal "1"
|
|
137
|
+
pc.unit.must_equal "DJ"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
it "should parse B10 0JP" do
|
|
141
|
+
pc = described_class.parse("B100JP")
|
|
142
|
+
pc.area.must_equal "B"
|
|
143
|
+
pc.district.must_equal "10"
|
|
144
|
+
pc.sector.must_equal "0"
|
|
145
|
+
pc.unit.must_equal "JP"
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it "should parse BIO OJP" do
|
|
149
|
+
pc = described_class.parse("BIOOJP")
|
|
150
|
+
pc.area.must_equal "B"
|
|
151
|
+
pc.district.must_equal "10"
|
|
152
|
+
pc.sector.must_equal "0"
|
|
153
|
+
pc.unit.must_equal "JP"
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
describe "area" do
|
|
159
|
+
it "should be capitalised" do
|
|
160
|
+
described_class.new("w", "1a", "1", "aa").area.must_equal "W"
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it "should correct 0 to O" do
|
|
164
|
+
described_class.new("0X", "1", "0", "AB").area.must_equal "OX"
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it "should correct 1 to I" do
|
|
168
|
+
described_class.new("1G", "1", "1", "AA").area.must_equal "IG"
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
describe "district" do
|
|
173
|
+
it "should be capitalised" do
|
|
174
|
+
described_class.new("w", "1a", "1", "aa").district.must_equal "1A"
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it "should correct O to 0" do
|
|
178
|
+
described_class.new("B", "2O", "2", "XB").district.must_equal "20"
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it "should correct I to 1" do
|
|
182
|
+
described_class.new("B", "I", "I", "DF").district.must_equal "1"
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
describe "sector" do
|
|
187
|
+
it "should correct O to 0" do
|
|
188
|
+
described_class.new("AB", "1", "O", "DN").sector.must_equal "0"
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it "should correct I to 1" do
|
|
192
|
+
described_class.new("W", "1A", "I", "AA").sector.must_equal "1"
|
|
193
|
+
end
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
describe "unit" do
|
|
197
|
+
it "should be capitalised" do
|
|
198
|
+
described_class.new("w", "1a", "1", "aa").unit.must_equal "AA"
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
# Note: neither I nor O appear in units
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
describe "outcode" do
|
|
205
|
+
it "should be generated from area and district" do
|
|
206
|
+
described_class.new("W", "1A").outcode.must_equal "W1A"
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
it "should be nil if missing district" do
|
|
210
|
+
described_class.new("W").outcode.must_be_nil
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
describe "incode" do
|
|
215
|
+
it "should be generated from sector and unit" do
|
|
216
|
+
described_class.new("W", "1A", "1", "AA").incode.must_equal "1AA"
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it "should be nil if missing sector" do
|
|
220
|
+
described_class.new("W", "1A").incode.must_be_nil
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
it "should be nil if missing unit" do
|
|
224
|
+
described_class.new("W", "1A", "1").incode.must_be_nil
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
describe "to_s" do
|
|
229
|
+
it "should generate a full postcode" do
|
|
230
|
+
described_class.new("W", "1A", "1", "AA").to_s.must_equal "W1A 1AA"
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
it "should generate an outcode" do
|
|
234
|
+
described_class.new("W", "1A").to_s.must_equal "W1A"
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
it "should generate a postcode with no unit" do
|
|
238
|
+
described_class.new("W", "1A", "1").to_s.must_equal "W1A 1"
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
it "should generate an area alone" do
|
|
242
|
+
described_class.new("W").to_s.must_equal "W"
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
describe "full?" do
|
|
247
|
+
it "should be true if outcode and incode are given" do
|
|
248
|
+
described_class.new("W", "1A", "1", "AA").must_be :full?
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
it "should not be true if something is missing" do
|
|
252
|
+
described_class.new("W", "1A", "1").wont_be :full?
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
describe "valid?" do
|
|
257
|
+
it "should be true" do
|
|
258
|
+
described_class.new("W", "1A", "1", "AA").must_be :valid?
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
describe "country" do
|
|
263
|
+
it "should look up the country of a full postcode" do
|
|
264
|
+
described_class.new("EH", "8", "8", "DX").country.must_equal :scotland
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
it "should look up the country of a partial postcode" do
|
|
268
|
+
described_class.new("W", "1A").country.must_equal :england
|
|
269
|
+
end
|
|
270
|
+
end
|
|
271
|
+
end
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
require_relative "./test_helper"
|
|
2
|
+
require "uk_postcode/giro_postcode"
|
|
3
|
+
|
|
4
|
+
describe UKPostcode::GiroPostcode do
|
|
5
|
+
described_class = UKPostcode::GiroPostcode
|
|
6
|
+
|
|
7
|
+
let(:subject) { described_class.instance }
|
|
8
|
+
|
|
9
|
+
describe "parse" do
|
|
10
|
+
it "should parse the canonical form" do
|
|
11
|
+
pc = described_class.parse("GIR 0AA")
|
|
12
|
+
pc.must_be_instance_of described_class
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "should parse transcribed 0/O and 1/I" do
|
|
16
|
+
pc = described_class.parse("G1R OAA")
|
|
17
|
+
pc.must_be_instance_of described_class
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "should handle extra spaces" do
|
|
21
|
+
pc = described_class.parse(" GIR 0AA ")
|
|
22
|
+
pc.must_be_instance_of described_class
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should handle no spaces" do
|
|
26
|
+
pc = described_class.parse("GIR0AA")
|
|
27
|
+
pc.must_be_instance_of described_class
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it "should be case-insensitive" do
|
|
31
|
+
pc = described_class.parse("gir 0aa")
|
|
32
|
+
pc.must_be_instance_of described_class
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "should return nil if unable to parse" do
|
|
36
|
+
pc = described_class.parse("Can't parse this")
|
|
37
|
+
pc.must_be_nil
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "area" do
|
|
42
|
+
it "should be nil" do
|
|
43
|
+
subject.area.must_be_nil
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
describe "district" do
|
|
48
|
+
it "should be nil" do
|
|
49
|
+
subject.district.must_be_nil
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
describe "sector" do
|
|
54
|
+
it "should be nil" do
|
|
55
|
+
subject.sector.must_be_nil
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe "unit" do
|
|
60
|
+
it "should be nil" do
|
|
61
|
+
subject.unit.must_be_nil
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
describe "outcode" do
|
|
66
|
+
it "should be GIR" do
|
|
67
|
+
subject.outcode.must_equal("GIR")
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
describe "incode" do
|
|
72
|
+
it "should be 0AA" do
|
|
73
|
+
subject.incode.must_equal("0AA")
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
describe "to_s" do
|
|
78
|
+
it "should be the canonical form" do
|
|
79
|
+
subject.to_s.must_equal "GIR 0AA"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
describe "full?" do
|
|
84
|
+
it "should be true" do
|
|
85
|
+
subject.must_be :full?
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
describe "valid?" do
|
|
90
|
+
it "should be true" do
|
|
91
|
+
subject.must_be :valid?
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
describe "country" do
|
|
96
|
+
it "should be England" do
|
|
97
|
+
subject.country.must_equal :england
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
require_relative "./test_helper"
|
|
2
|
+
require "uk_postcode/invalid_postcode"
|
|
3
|
+
|
|
4
|
+
describe UKPostcode::InvalidPostcode do
|
|
5
|
+
described_class = UKPostcode::InvalidPostcode
|
|
6
|
+
|
|
7
|
+
let(:subject) { described_class.new("anything") }
|
|
8
|
+
|
|
9
|
+
describe "parse" do
|
|
10
|
+
it "should parse anything" do
|
|
11
|
+
pc = described_class.parse("Any old junk")
|
|
12
|
+
pc.must_be_instance_of described_class
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe "area" do
|
|
17
|
+
it "should be nil" do
|
|
18
|
+
subject.area.must_be_nil
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
describe "district" do
|
|
23
|
+
it "should be nil" do
|
|
24
|
+
subject.district.must_be_nil
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe "sector" do
|
|
29
|
+
it "should be nil" do
|
|
30
|
+
subject.sector.must_be_nil
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe "unit" do
|
|
35
|
+
it "should be nil" do
|
|
36
|
+
subject.unit.must_be_nil
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
describe "outcode" do
|
|
41
|
+
it "should be nil" do
|
|
42
|
+
subject.outcode.must_be_nil
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "incode" do
|
|
47
|
+
it "should be nil" do
|
|
48
|
+
subject.incode.must_be_nil
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
describe "to_s" do
|
|
53
|
+
it "should return the initialisation string" do
|
|
54
|
+
subject.to_s.must_equal "anything"
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
describe "full?" do
|
|
59
|
+
it "should be false" do
|
|
60
|
+
subject.wont_be :full?
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe "valid?" do
|
|
65
|
+
it "should be false" do
|
|
66
|
+
subject.wont_be :valid?
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
describe "country" do
|
|
71
|
+
it "should be unknown" do
|
|
72
|
+
subject.country.must_equal :unknown
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require_relative "./test_helper"
|
|
2
|
+
require "uk_postcode"
|
|
3
|
+
|
|
4
|
+
describe "Special postcodes" do
|
|
5
|
+
# Special postcodes listed in http://en.wikipedia.org/wiki/UK_postcode
|
|
6
|
+
SPECIAL = %w[
|
|
7
|
+
SW1A 0AA
|
|
8
|
+
SW1A 1AA
|
|
9
|
+
SW1A 2AA
|
|
10
|
+
BS98 1TL
|
|
11
|
+
BX1 1LT
|
|
12
|
+
BX5 5AT
|
|
13
|
+
CF99 1NA
|
|
14
|
+
DH99 1NS
|
|
15
|
+
E16 1XL
|
|
16
|
+
E98 1NW
|
|
17
|
+
E98 1SN
|
|
18
|
+
E98 1ST
|
|
19
|
+
E98 1TT
|
|
20
|
+
EC4Y 0HQ
|
|
21
|
+
EH99 1SP
|
|
22
|
+
EN8 9SL
|
|
23
|
+
G58 1SB
|
|
24
|
+
GIR 0AA
|
|
25
|
+
L30 4GB
|
|
26
|
+
LS98 1FD
|
|
27
|
+
M2 5BE
|
|
28
|
+
N81 1ER
|
|
29
|
+
S2 4SU
|
|
30
|
+
S6 1SW
|
|
31
|
+
SE1 8UJ
|
|
32
|
+
SE9 2UG
|
|
33
|
+
SN38 1NW
|
|
34
|
+
SW1A 0PW
|
|
35
|
+
SW1A 2HQ
|
|
36
|
+
SW1W 0DT
|
|
37
|
+
TS1 3BA
|
|
38
|
+
W1A 1AA
|
|
39
|
+
W1F 9DJ
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
SPECIAL.each_slice(2) do |outcode, incode|
|
|
43
|
+
it "should correctly handle special postcode #{outcode} #{incode}" do
|
|
44
|
+
postcode = UKPostcode.parse(outcode + incode)
|
|
45
|
+
postcode.wont_be_nil
|
|
46
|
+
postcode.outcode.must_equal outcode
|
|
47
|
+
postcode.incode.must_equal incode
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|