page_magic 2.0.0.alpha1 → 2.0.0
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/.rubocop.yml +5 -2
- data/.zsh_config +5 -5
- data/Dockerfile +2 -1
- data/Gemfile +2 -1
- data/Gemfile.lock +9 -5
- data/Makefile +7 -3
- data/README.md +16 -4
- data/VERSION +1 -1
- data/lib/active_support/core_ext/object/to_query.rb +6 -6
- data/lib/page_magic.rb +15 -16
- data/lib/page_magic/class_methods.rb +1 -1
- data/lib/page_magic/comparator.rb +37 -0
- data/lib/page_magic/comparator/fuzzy.rb +23 -0
- data/lib/page_magic/comparator/literal.rb +22 -0
- data/lib/page_magic/comparator/null.rb +26 -0
- data/lib/page_magic/comparator/parameter_map.rb +52 -0
- data/lib/page_magic/drivers.rb +2 -2
- data/lib/page_magic/element.rb +19 -8
- data/lib/page_magic/element/locators.rb +4 -4
- data/lib/page_magic/element/not_found.rb +38 -0
- data/lib/page_magic/element/query.rb +19 -27
- data/lib/page_magic/element/query/multiple_results.rb +21 -0
- data/lib/page_magic/element/query/prefetched_result.rb +26 -0
- data/lib/page_magic/element/query/single_result.rb +20 -0
- data/lib/page_magic/element/selector.rb +38 -16
- data/lib/page_magic/element/selector/methods.rb +18 -0
- data/lib/page_magic/element/selector/model.rb +21 -0
- data/lib/page_magic/element_context.rb +5 -21
- data/lib/page_magic/element_definition_builder.rb +17 -24
- data/lib/page_magic/elements.rb +62 -102
- data/lib/page_magic/elements/config.rb +103 -0
- data/lib/page_magic/elements/inheritance_hooks.rb +15 -0
- data/lib/page_magic/elements/types.rb +25 -0
- data/lib/page_magic/exceptions.rb +3 -0
- data/lib/page_magic/instance_methods.rb +2 -2
- data/lib/page_magic/mapping.rb +79 -0
- data/lib/page_magic/session.rb +10 -32
- data/lib/page_magic/session_methods.rb +1 -1
- data/lib/page_magic/transitions.rb +49 -0
- data/lib/page_magic/utils/string.rb +4 -0
- data/lib/page_magic/utils/url.rb +20 -0
- data/lib/page_magic/watcher.rb +10 -17
- data/lib/page_magic/watchers.rb +28 -15
- data/spec/page_magic/class_methods_spec.rb +64 -37
- data/spec/page_magic/comparator/fuzzy_spec.rb +44 -0
- data/spec/page_magic/comparator/literal_spec.rb +41 -0
- data/spec/page_magic/comparator/null_spec.rb +35 -0
- data/spec/page_magic/comparator/parameter_map_spec.rb +75 -0
- data/spec/page_magic/driver_spec.rb +25 -29
- data/spec/page_magic/drivers/poltergeist_spec.rb +4 -7
- data/spec/page_magic/drivers/rack_test_spec.rb +4 -9
- data/spec/page_magic/drivers/selenium_spec.rb +9 -12
- data/spec/page_magic/drivers_spec.rb +36 -29
- data/spec/page_magic/element/locators_spec.rb +26 -25
- data/spec/page_magic/element/not_found_spec.rb +24 -0
- data/spec/page_magic/element/query/multiple_results_spec.rb +14 -0
- data/spec/page_magic/element/query/single_result_spec.rb +21 -0
- data/spec/page_magic/element/query_spec.rb +26 -47
- data/spec/page_magic/element/selector_spec.rb +118 -110
- data/spec/page_magic/element_context_spec.rb +46 -88
- data/spec/page_magic/element_definition_builder_spec.rb +12 -71
- data/spec/page_magic/element_spec.rb +256 -0
- data/spec/page_magic/elements/config_spec.rb +200 -0
- data/spec/page_magic/elements_spec.rb +87 -138
- data/spec/page_magic/instance_methods_spec.rb +63 -63
- data/spec/page_magic/mapping_spec.rb +181 -0
- data/spec/page_magic/session_methods_spec.rb +27 -25
- data/spec/page_magic/session_spec.rb +109 -198
- data/spec/page_magic/transitions_spec.rb +43 -0
- data/spec/page_magic/utils/string_spec.rb +20 -27
- data/spec/page_magic/utils/url_spec.rb +9 -0
- data/spec/page_magic/wait_methods_spec.rb +14 -22
- data/spec/page_magic/watcher_spec.rb +22 -0
- data/spec/page_magic/watchers_spec.rb +56 -62
- data/spec/page_magic_spec.rb +27 -24
- data/spec/spec_helper.rb +7 -3
- data/spec/support/shared_examples.rb +15 -17
- metadata +48 -15
- data/lib/page_magic/element/query_builder.rb +0 -61
- data/lib/page_magic/element/selector_methods.rb +0 -16
- data/lib/page_magic/matcher.rb +0 -130
- data/spec/element_spec.rb +0 -251
- data/spec/page_magic/element/query_builder_spec.rb +0 -110
- data/spec/page_magic/matcher_spec.rb +0 -338
- data/spec/support/shared_contexts/files_context.rb +0 -9
- data/spec/support/shared_contexts/nested_elements_html_context.rb +0 -18
- data/spec/support/shared_contexts/rack_application_context.rb +0 -11
- data/spec/support/shared_contexts/webapp_fixture_context.rb +0 -41
- data/spec/watcher_spec.rb +0 -64
@@ -1,110 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module PageMagic
|
4
|
-
class Element
|
5
|
-
describe QueryBuilder do
|
6
|
-
it 'has a predefined query for each element type' do
|
7
|
-
missing = PageMagic::Elements::TYPES.dup.delete_if { |type| type.to_s.end_with?('s') }.find_all do |type|
|
8
|
-
described_class.constants.include?(type)
|
9
|
-
end
|
10
|
-
expect(missing).to be_empty
|
11
|
-
end
|
12
|
-
|
13
|
-
describe '.find' do
|
14
|
-
it 'finds the constant with the given name' do
|
15
|
-
expect(described_class.find(:button)).to be(described_class::BUTTON)
|
16
|
-
end
|
17
|
-
|
18
|
-
context 'constant not found' do
|
19
|
-
it 'returns a default' do
|
20
|
-
expect(described_class.find(:billy)).to be(described_class::ELEMENT)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
describe '#build' do
|
26
|
-
let(:selector) { Selector.new }
|
27
|
-
before do
|
28
|
-
expect(Selector).to receive(:find).with(:css).and_return(selector)
|
29
|
-
end
|
30
|
-
let(:locator) { { css: '.css' } }
|
31
|
-
|
32
|
-
it 'builds a query using the correct selector' do
|
33
|
-
expected = Query.new(locator.values)
|
34
|
-
expect(subject.build(locator)).to eq(expected)
|
35
|
-
end
|
36
|
-
|
37
|
-
it 'adds options to the result' do
|
38
|
-
expected = Query.new(locator.values.concat([:options]))
|
39
|
-
expect(subject.build(locator, :options)).to eq(expected)
|
40
|
-
end
|
41
|
-
|
42
|
-
context 'selector support element type' do
|
43
|
-
subject do
|
44
|
-
described_class.new(:field)
|
45
|
-
end
|
46
|
-
|
47
|
-
it 'passes element type through to the selector' do
|
48
|
-
expect(selector).to receive(:build).with(:field, '.css').and_call_original
|
49
|
-
subject.build(locator)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
class QueryBuilder
|
56
|
-
describe BUTTON do
|
57
|
-
it 'has an element type' do
|
58
|
-
expect(described_class.type).to eq(:button)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
describe ELEMENT do
|
63
|
-
it ' does not has an element type' do
|
64
|
-
expect(described_class.type).to be_nil
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
describe LINK do
|
69
|
-
it 'has an element type' do
|
70
|
-
expect(described_class.type).to eq(:link)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
describe TEXT_FIELD do
|
75
|
-
it 'has an element type' do
|
76
|
-
expect(described_class.type).to eq(:field)
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'the same as all form field types' do
|
80
|
-
expect(described_class).to eq(CHECKBOX).and eq(SELECT_LIST).and eq(RADIO).and eq(TEXTAREA).and eq(FILE_FIELD).and eq(FILLABLE_FIELD).and eq(RADIO_BUTTON)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
context 'integration' do
|
86
|
-
include_context :webapp_fixture
|
87
|
-
let(:capybara_session) { Capybara::Session.new(:rack_test, rack_app).tap { |s| s.visit('/elements') } }
|
88
|
-
|
89
|
-
it 'finds fields' do
|
90
|
-
query = QueryBuilder.find(:text_field).build({ name: 'field_name' })
|
91
|
-
expect(query.execute(capybara_session).tag_name).to eq('input')
|
92
|
-
end
|
93
|
-
|
94
|
-
it 'finds buttons' do
|
95
|
-
query = QueryBuilder.find(:button).build({ text: 'a button' })
|
96
|
-
expect(query.execute(capybara_session).tag_name).to eq('button')
|
97
|
-
end
|
98
|
-
|
99
|
-
it 'finds links' do
|
100
|
-
query = QueryBuilder.find(:link).build({ text: 'a link' })
|
101
|
-
expect(query.execute(capybara_session).tag_name).to eq('a')
|
102
|
-
end
|
103
|
-
|
104
|
-
it 'finds elements' do
|
105
|
-
query = QueryBuilder.find(:element).build({ name: 'field_name' })
|
106
|
-
expect(query.execute(capybara_session).tag_name).to eq('input')
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
@@ -1,338 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# rubocop:disable Metrics/ModuleLength
|
4
|
-
module PageMagic
|
5
|
-
describe Matcher do
|
6
|
-
describe '#initialize' do
|
7
|
-
context 'no componentes specified' do
|
8
|
-
it 'raises an exeception' do
|
9
|
-
expect { described_class.new }.to raise_exception(MatcherInvalidException)
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
describe '#can_compute_uri?' do
|
14
|
-
context 'regex in path' do
|
15
|
-
it 'returns false' do
|
16
|
-
expect(described_class.new(//).can_compute_uri?).to eq(false)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
context 'regex in parameters' do
|
21
|
-
it 'returns false' do
|
22
|
-
expect(described_class.new(parameters: { param: // }).can_compute_uri?).to eq(false)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
context 'regexp in fragment' do
|
27
|
-
it 'returns false' do
|
28
|
-
expect(described_class.new(fragment: //).can_compute_uri?).to eq(false)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
context 'regexp not present' do
|
33
|
-
it 'returns true' do
|
34
|
-
expect(described_class.new('/').can_compute_uri?).to eq(true)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
describe 'compare' do
|
40
|
-
subject { described_class.new('/') }
|
41
|
-
context 'param 1 not nil' do
|
42
|
-
context 'param 2 not nil' do
|
43
|
-
context 'literal to fuzzy' do
|
44
|
-
it 'returns -1' do
|
45
|
-
expect(subject.instance_eval { compare('/', //) }).to eq(-1)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
context 'literal to literal' do
|
50
|
-
it 'returns 0' do
|
51
|
-
expect(subject.instance_eval { compare('/', '/') }).to eq(0)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
context 'fuzzy to fuzzy' do
|
56
|
-
it 'returns 0' do
|
57
|
-
expect(subject.instance_eval { compare(//, //) }).to eq(0)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
context 'fuzzy to literal' do
|
62
|
-
it 'returns 1' do
|
63
|
-
expect(subject.instance_eval { compare(//, '/') }).to eq(1)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
context 'param2 is nil' do
|
69
|
-
it 'returns -1' do
|
70
|
-
expect(subject.instance_eval { compare('/', nil) }).to eq(-1)
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
context 'param1 is nil' do
|
76
|
-
context 'param2 not nil' do
|
77
|
-
it 'returns 1' do
|
78
|
-
expect(subject.instance_eval { compare(nil, '/') }).to eq(1)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
context 'param2 nil' do
|
83
|
-
it 'returns 0' do
|
84
|
-
expect(subject.instance_eval { compare(nil, nil) }).to eq(0)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
describe 'compute_uri' do
|
91
|
-
context 'path present' do
|
92
|
-
it 'returns a uri' do
|
93
|
-
expect(described_class.new('/').compute_uri).to eq('/')
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
context 'params present' do
|
98
|
-
context '1 param' do
|
99
|
-
it 'returns a uri' do
|
100
|
-
expect(described_class.new(parameters: { a: 1 }).compute_uri).to eq('?a=1')
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
context 'more than 1 param' do
|
105
|
-
it 'returns a uri' do
|
106
|
-
expect(described_class.new(parameters: { a: 1, b: 2 }).compute_uri).to eq('?a=1&b=2')
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
context 'fragment present' do
|
112
|
-
it 'returns a uri' do
|
113
|
-
expect(described_class.new(fragment: 'fragment').compute_uri).to eq('#fragment')
|
114
|
-
end
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
describe '#matches?' do
|
119
|
-
let(:matching_url) { 'http://www.example.com/path?foo=bar#fragment' }
|
120
|
-
let(:incompatible_url) { 'http://www.example.com/mismatch?miss=match#mismatch' }
|
121
|
-
context 'path requirement exists' do
|
122
|
-
context 'path is literal' do
|
123
|
-
subject do
|
124
|
-
described_class.new('/path')
|
125
|
-
end
|
126
|
-
it 'returns true for an exact match' do
|
127
|
-
expect(subject.match?(matching_url)).to eq(true)
|
128
|
-
end
|
129
|
-
|
130
|
-
it 'returns false when not an exact match' do
|
131
|
-
expect(subject.match?(incompatible_url)).to eq(false)
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
context 'path is regexp' do
|
136
|
-
subject do
|
137
|
-
described_class.new(/\d/)
|
138
|
-
end
|
139
|
-
it 'returns true for a match on the regexp' do
|
140
|
-
expect(subject.match?('3')).to eq(true)
|
141
|
-
end
|
142
|
-
|
143
|
-
it 'returns false when regexp is not a match' do
|
144
|
-
expect(subject.match?('/mismatch')).to eq(false)
|
145
|
-
end
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
context 'query string requirement exists' do
|
150
|
-
context 'parameter requirement is a literal' do
|
151
|
-
subject do
|
152
|
-
described_class.new(parameters: { foo: 'bar' })
|
153
|
-
end
|
154
|
-
|
155
|
-
it 'returns true for a match' do
|
156
|
-
expect(subject.match?(matching_url)).to eq(true)
|
157
|
-
end
|
158
|
-
|
159
|
-
it 'returns false when regexp is not a match' do
|
160
|
-
expect(subject.match?(incompatible_url)).to eq(false)
|
161
|
-
end
|
162
|
-
end
|
163
|
-
|
164
|
-
context 'parameter requirement is a regexp' do
|
165
|
-
subject do
|
166
|
-
described_class.new(parameters: { foo: /bar/ })
|
167
|
-
end
|
168
|
-
|
169
|
-
it 'returns true for a match on the regexp' do
|
170
|
-
expect(subject.match?(matching_url)).to eq(true)
|
171
|
-
end
|
172
|
-
|
173
|
-
it 'returns false when regexp is not a match' do
|
174
|
-
expect(subject.match?(incompatible_url)).to eq(false)
|
175
|
-
end
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
|
-
context 'fragment requirement exists' do
|
180
|
-
context 'fragment requirement is a literal' do
|
181
|
-
subject do
|
182
|
-
described_class.new(fragment: 'fragment')
|
183
|
-
end
|
184
|
-
|
185
|
-
it 'returns true for a match' do
|
186
|
-
expect(subject.match?(matching_url)).to eq(true)
|
187
|
-
end
|
188
|
-
|
189
|
-
it 'returns false when regexp is not a match' do
|
190
|
-
expect(subject.match?(incompatible_url)).to eq(false)
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
context 'fragment requirement is a regexp' do
|
195
|
-
subject do
|
196
|
-
described_class.new(fragment: /fragment/)
|
197
|
-
end
|
198
|
-
|
199
|
-
it 'returns true for a match on the regexp' do
|
200
|
-
expect(subject.match?(matching_url)).to eq(true)
|
201
|
-
end
|
202
|
-
|
203
|
-
it 'returns false when regexp is not a match' do
|
204
|
-
expect(subject.match?(incompatible_url)).to eq(false)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
describe '<=>' do
|
211
|
-
let(:literal_path_matcher) { '/' }
|
212
|
-
let(:fuzzy_path_matcher) { // }
|
213
|
-
let(:literal_parameter_matchers) { { param: 'value' } }
|
214
|
-
let(:fuzzy_parameter_matchers) { { param: // } }
|
215
|
-
|
216
|
-
let(:literal_fragment_matcher) { 'fragment' }
|
217
|
-
let(:fuzzy_fragment_matcher) { // }
|
218
|
-
|
219
|
-
context 'path' do
|
220
|
-
context 'path is of same class as path on other' do
|
221
|
-
subject(:a) { described_class.new('/a') }
|
222
|
-
subject(:b) { described_class.new('/b') }
|
223
|
-
it 'returns self and other as equivalent' do
|
224
|
-
expect(a <=> b).to eq(0)
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
context 'path on other is fuzzy' do
|
229
|
-
subject(:a) { described_class.new(literal_path_matcher) }
|
230
|
-
subject(:b) { described_class.new(fuzzy_path_matcher) }
|
231
|
-
it 'returns other as lesser' do
|
232
|
-
expect(a <=> b).to eq(-1)
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
|
237
|
-
context 'parameters' do
|
238
|
-
context 'parameters on self and other contain literal values' do
|
239
|
-
subject(:a) do
|
240
|
-
described_class.new(literal_path_matcher,
|
241
|
-
parameters: literal_parameter_matchers)
|
242
|
-
end
|
243
|
-
subject(:b) do
|
244
|
-
described_class.new(literal_path_matcher,
|
245
|
-
parameters: literal_parameter_matchers)
|
246
|
-
end
|
247
|
-
it 'returns self and other as equivalent' do
|
248
|
-
expect(a <=> b).to eq(0)
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
context 'parameters on self literal values and other has fuzzy values' do
|
253
|
-
subject(:a) do
|
254
|
-
described_class.new(literal_path_matcher,
|
255
|
-
parameters: literal_parameter_matchers)
|
256
|
-
end
|
257
|
-
subject(:b) do
|
258
|
-
described_class.new(literal_path_matcher,
|
259
|
-
parameters: fuzzy_parameter_matchers)
|
260
|
-
end
|
261
|
-
it 'returns other as lesser' do
|
262
|
-
expect(a <=> b).to eq(-1)
|
263
|
-
end
|
264
|
-
end
|
265
|
-
context 'parameters on self fuzzy values and other has literal values' do
|
266
|
-
subject(:a) do
|
267
|
-
described_class.new(literal_path_matcher,
|
268
|
-
parameters: fuzzy_parameter_matchers)
|
269
|
-
end
|
270
|
-
|
271
|
-
subject(:b) do
|
272
|
-
described_class.new(literal_path_matcher,
|
273
|
-
parameters: literal_parameter_matchers)
|
274
|
-
end
|
275
|
-
|
276
|
-
it 'returns other as greater' do
|
277
|
-
expect(a <=> b).to eq(1)
|
278
|
-
end
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
context 'fragment' do
|
283
|
-
context 'fragment is of same class as path on other' do
|
284
|
-
subject(:a) do
|
285
|
-
described_class.new(literal_path_matcher,
|
286
|
-
parameters: literal_parameter_matchers,
|
287
|
-
fragment: literal_fragment_matcher)
|
288
|
-
end
|
289
|
-
|
290
|
-
subject(:b) do
|
291
|
-
described_class.new(literal_path_matcher,
|
292
|
-
parameters: literal_parameter_matchers,
|
293
|
-
fragment: literal_fragment_matcher)
|
294
|
-
end
|
295
|
-
|
296
|
-
it 'returns self and other as equivalent' do
|
297
|
-
expect(a <=> b).to eq(0)
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
context 'fragment is literal on self and fuzzy on other' do
|
302
|
-
subject(:a) do
|
303
|
-
described_class.new(literal_path_matcher,
|
304
|
-
parameters: literal_parameter_matchers,
|
305
|
-
fragment: literal_fragment_matcher)
|
306
|
-
end
|
307
|
-
|
308
|
-
subject(:b) do
|
309
|
-
described_class.new(literal_path_matcher,
|
310
|
-
parameters: literal_parameter_matchers,
|
311
|
-
fragment: fuzzy_fragment_matcher)
|
312
|
-
end
|
313
|
-
|
314
|
-
it 'returns other as lesser' do
|
315
|
-
expect(a <=> b).to eq(-1)
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
context 'fragment is fuzzy on self and literal on other' do
|
320
|
-
subject(:a) do
|
321
|
-
described_class.new(literal_path_matcher,
|
322
|
-
parameters: literal_parameter_matchers,
|
323
|
-
fragment: fuzzy_fragment_matcher)
|
324
|
-
end
|
325
|
-
|
326
|
-
subject(:b) do
|
327
|
-
described_class.new(literal_path_matcher,
|
328
|
-
parameters: literal_parameter_matchers,
|
329
|
-
fragment: literal_fragment_matcher)
|
330
|
-
end
|
331
|
-
it 'returns other as lesser' do
|
332
|
-
expect(a <=> b).to eq(1)
|
333
|
-
end
|
334
|
-
end
|
335
|
-
end
|
336
|
-
end
|
337
|
-
end
|
338
|
-
end
|