napybara 0.2.0 → 0.3.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/README.md +23 -23
- data/lib/napybara.rb +3 -2
- data/lib/napybara/element.rb +46 -0
- data/lib/napybara/version.rb +1 -1
- data/napybara.gemspec +1 -0
- data/spec/integration/napybara_spec.rb +12 -14
- data/spec/napybara/element_spec.rb +107 -0
- metadata +19 -5
- data/lib/napybara/dsl.rb +0 -30
- data/spec/napybara/dsl_spec.rb +0 -121
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1acb0ab3b95532810db2654efd6a23ff89d23a58
|
4
|
+
data.tar.gz: 8d24168fbf6adc727fdd89afe2ecf8d1c6c1d714
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3f4c003ac74d14684fcff69c18e06d571ae68d43f00df59738581af6b4711127eaf8657d7adb07e2c3ea9f46a25738b224a5949ec0165738011f43ac300d571
|
7
|
+
data.tar.gz: 0a46fea43e3df63a71780a4691894d4cb61efbe380e02f2185442d590cf9af67c4c4b14a0f47529b17671b5d07679986f57cc1b8d82221fd470482d3f16fbd4c
|
data/README.md
CHANGED
@@ -23,7 +23,7 @@ Wouldn't it be nice if your test helpers followed the structure of the page?
|
|
23
23
|
|
24
24
|
```ruby
|
25
25
|
messages_page.visit!
|
26
|
-
messages_page.form.message.text_field.set 'Hello World!'
|
26
|
+
messages_page.form.message.text_field.get.set 'Hello World!'
|
27
27
|
messages_page.form.submit!
|
28
28
|
expect(messages_page.messages[0]).to have_content('Hello world!')
|
29
29
|
expect(messages_page.messages[1]).to have_content('Kamusta mundo!')
|
@@ -34,49 +34,49 @@ With Napybara, now they can! All you need is to define the structure of the page
|
|
34
34
|
```ruby
|
35
35
|
# spec/features/messages_spec.rb
|
36
36
|
|
37
|
-
:
|
38
|
-
Napybara::
|
39
|
-
|
37
|
+
let(:new_message_page) do
|
38
|
+
Napybara::Element.new(self) do |page|
|
39
|
+
page.finder :message, '.messages-list .message'
|
40
40
|
|
41
|
-
|
42
|
-
|
43
|
-
|
41
|
+
page.finder :form, 'form.new-message' do |form|
|
42
|
+
form.finder :message, '.message' do |row|
|
43
|
+
row.finder :text_field, 'input#message'
|
44
44
|
end
|
45
45
|
|
46
|
-
|
46
|
+
form.finder :submit_button, 'input[type=submit]'
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
50
50
|
```
|
51
51
|
|
52
|
-
In the integration test above, the `self` in `Napybara::
|
52
|
+
In the integration test above, the `self` in `Napybara::Element.new(self)` points to the current test session. In Rails integration tests which include `Capybara::DSL`, `self` would already have access to `Capybara::DSL`'s methods.
|
53
53
|
|
54
|
-
What about the custom `messages_page.visit!` and `form.submit!` methods? With Napybara, you can extend each element in the structure
|
54
|
+
What about the custom `messages_page.visit!` and `form.submit!` methods? With Napybara, you can extend each element in the structure. So if you want to add a `visit!` method to the `messages_page` element, you can write
|
55
55
|
|
56
56
|
```ruby
|
57
|
-
Napybara::
|
58
|
-
|
59
|
-
|
60
|
-
visit '/messages/index'
|
61
|
-
end
|
57
|
+
Napybara::Element.new(self) do |page|
|
58
|
+
def page.visit!
|
59
|
+
get.visit '/messages/index'
|
62
60
|
end
|
63
61
|
|
64
62
|
# ...
|
65
63
|
end
|
66
64
|
```
|
67
65
|
|
68
|
-
|
66
|
+
`get` here points to the Capybara element that the Napybara element is wrapping.
|
67
|
+
|
68
|
+
You can also reuse helpers by extend the Napybara element with a module. For example, with `form.submit!`:
|
69
69
|
|
70
70
|
```ruby
|
71
71
|
module FormExtensions
|
72
72
|
def submit!
|
73
|
-
submit_button.click
|
73
|
+
submit_button.get.click
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
Napybara::
|
78
|
-
|
79
|
-
|
77
|
+
Napybara::Element.new(self) do |page|
|
78
|
+
page.finder :form, 'form.new-message' do |form|
|
79
|
+
form.extend FormExtensions
|
80
80
|
# ...
|
81
81
|
end
|
82
82
|
end
|
@@ -86,7 +86,7 @@ end
|
|
86
86
|
|
87
87
|
Add this line to your application's Gemfile:
|
88
88
|
|
89
|
-
gem '
|
89
|
+
gem 'Napybara'
|
90
90
|
|
91
91
|
And then execute:
|
92
92
|
|
@@ -94,11 +94,11 @@ And then execute:
|
|
94
94
|
|
95
95
|
Or install it yourself as:
|
96
96
|
|
97
|
-
$ gem install
|
97
|
+
$ gem install Napybara
|
98
98
|
|
99
99
|
## Contributing
|
100
100
|
|
101
|
-
1. Fork it ( http://github.com/<my-github-username>/
|
101
|
+
1. Fork it ( http://github.com/<my-github-username>/Napybara/fork )
|
102
102
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
103
103
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
104
104
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/lib/napybara.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'napybara'
|
2
|
+
|
3
|
+
module Napybara
|
4
|
+
class Element
|
5
|
+
attr_reader :capybara_element
|
6
|
+
alias_method :get, :capybara_element
|
7
|
+
|
8
|
+
def initialize(capybara_element, &block)
|
9
|
+
@capybara_element = capybara_element
|
10
|
+
block.call(self) if block_given?
|
11
|
+
end
|
12
|
+
|
13
|
+
def finder(child_element_name, child_element_selector, method_name = :id, &block)
|
14
|
+
self.define_singleton_method(child_element_name) do |record = nil|
|
15
|
+
selector = Selector.new(child_element_selector, method_name, record)
|
16
|
+
self.class.new(self.get.find(selector.to_s), &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
self.define_singleton_method("has_#{child_element_name}?") do |record|
|
20
|
+
selector = Selector.new(child_element_selector, method_name, record)
|
21
|
+
self.get.has_css?(selector.to_s)
|
22
|
+
end
|
23
|
+
|
24
|
+
self.define_singleton_method("has_no_#{child_element_name}?") do |record|
|
25
|
+
selector = Selector.new(child_element_selector, method_name, record)
|
26
|
+
self.get.has_no_css?(selector.to_s)
|
27
|
+
end
|
28
|
+
|
29
|
+
self.define_singleton_method(child_element_name.to_s.pluralize) do
|
30
|
+
self.get.all(child_element_selector).map do |child_element|
|
31
|
+
self.class.new(child_element, &block)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class Selector < Struct.new(:child_element_selector, :method_name, :record)
|
37
|
+
def record_id
|
38
|
+
record && record.public_send(method_name)
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_s
|
42
|
+
"#{child_element_selector}#{record_id}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/napybara/version.rb
CHANGED
data/napybara.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
+
spec.add_dependency "activesupport"
|
21
22
|
spec.add_dependency "capybara"
|
22
23
|
|
23
24
|
spec.add_development_dependency "bundler", "~> 1.5"
|
@@ -2,7 +2,7 @@ require 'capybara/poltergeist'
|
|
2
2
|
require 'spec_helper'
|
3
3
|
require 'dummy_app/dummy_app'
|
4
4
|
|
5
|
-
describe Napybara do
|
5
|
+
describe 'Napybara::Element#get' do
|
6
6
|
describe '#has_content?' do
|
7
7
|
describe 'waits for Ajax events to complete before processing' do
|
8
8
|
let(:session) do
|
@@ -10,16 +10,14 @@ describe Napybara do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
let(:test_page) do
|
13
|
-
Napybara::
|
14
|
-
|
15
|
-
|
16
|
-
visit '/test.html'
|
17
|
-
end
|
13
|
+
Napybara::Element.new(session) do |page|
|
14
|
+
def page.visit!
|
15
|
+
get.visit '/test.html'
|
18
16
|
end
|
19
17
|
|
20
|
-
|
21
|
-
|
22
|
-
|
18
|
+
page.finder :form, 'form' do |form|
|
19
|
+
form.finder :notice_updater, 'button.update'
|
20
|
+
form.finder :notice, '.notice'
|
23
21
|
end
|
24
22
|
end
|
25
23
|
end
|
@@ -29,17 +27,17 @@ describe Napybara do
|
|
29
27
|
another element B is clicked' do
|
30
28
|
test_page.visit!
|
31
29
|
|
32
|
-
expect(test_page.form.notice).to have_content('Old content.')
|
33
|
-
expect(test_page.form.notice).to have_no_content('New content.')
|
30
|
+
expect(test_page.form.notice.get).to have_content('Old content.')
|
31
|
+
expect(test_page.form.notice.get).to have_no_content('New content.')
|
34
32
|
end
|
35
33
|
|
36
34
|
When 'I click on element B' do
|
37
|
-
test_page.form.notice_updater.click
|
35
|
+
test_page.form.notice_updater.get.click
|
38
36
|
end
|
39
37
|
|
40
38
|
Then 'checking if element A has the new content should be true' do
|
41
|
-
expect(test_page.form.notice).to have_content('New content.')
|
42
|
-
expect(test_page.form.notice).to have_no_content('Old content.')
|
39
|
+
expect(test_page.form.notice.get).to have_content('New content.')
|
40
|
+
expect(test_page.form.notice.get).to have_no_content('Old content.')
|
43
41
|
end
|
44
42
|
end
|
45
43
|
end
|
@@ -0,0 +1,107 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Napybara::Element do
|
4
|
+
let(:capybara_page) do
|
5
|
+
Capybara.string <<-HTML
|
6
|
+
<form class='some-form', id='form-1'>
|
7
|
+
<button class='some-button'>
|
8
|
+
<img />
|
9
|
+
</button>
|
10
|
+
|
11
|
+
<button class='another-button'>
|
12
|
+
<img />
|
13
|
+
</button>
|
14
|
+
</form>
|
15
|
+
HTML
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#new' do
|
19
|
+
it 'returns the element' do
|
20
|
+
element = described_class.new(capybara_page)
|
21
|
+
expect(element).to be_a(Napybara::Element)
|
22
|
+
expect(element.get).to eq(capybara_page)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'adds child elements from the block to the return element' do
|
26
|
+
element = described_class.new(capybara_page) do |page|
|
27
|
+
page.finder :form, '.some-form'
|
28
|
+
end
|
29
|
+
|
30
|
+
expect(element.form.get['class']).to eq('some-form')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
describe '#finder' do
|
35
|
+
it 'adds a method to the element for finding the given selector' do
|
36
|
+
page = described_class.new(capybara_page)
|
37
|
+
page.finder(:form, '.some-form')
|
38
|
+
|
39
|
+
expect(page.form.get['class']).to eq('some-form')
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'adds child elements from the block to the finder element' do
|
43
|
+
page = described_class.new(capybara_page)
|
44
|
+
page.finder(:form, '.some-form') do |form|
|
45
|
+
form.finder(:button, '.some-button')
|
46
|
+
end
|
47
|
+
|
48
|
+
expect(page.form.button.get['class']).to eq('some-button')
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'allows the element to find a sub-element with an id' do
|
52
|
+
page = described_class.new(capybara_page)
|
53
|
+
page.finder(:form, '#form-')
|
54
|
+
|
55
|
+
object = OpenStruct.new(id: 1)
|
56
|
+
|
57
|
+
expect(page.form(object).get['class']).to eq('some-form')
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'allows the element to find a sub-element with a record method' do
|
61
|
+
page = described_class.new(capybara_page)
|
62
|
+
page.finder(:form, '#form-', :name)
|
63
|
+
|
64
|
+
object = OpenStruct.new(name: 1)
|
65
|
+
|
66
|
+
expect(page.form(object).get['class']).to eq('some-form')
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'adds a method to get all the elements matching the selector' do
|
70
|
+
page = described_class.new(capybara_page)
|
71
|
+
page.finder(:button, 'button')
|
72
|
+
|
73
|
+
expect(page.buttons).to have(2).elements
|
74
|
+
expect(page.buttons).to be_all do |element|
|
75
|
+
element.get.tag_name == 'button'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'adds child elements from the block to each element returned' do
|
80
|
+
page = described_class.new(capybara_page)
|
81
|
+
page.finder(:button, 'button') do |button|
|
82
|
+
button.finder :img, 'img'
|
83
|
+
end
|
84
|
+
|
85
|
+
expect(page.buttons).to have(2).elements
|
86
|
+
expect(page.buttons[0].img.get.tag_name).to eq('img')
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'adds a method to check if the element has a sub-element matching a record' do
|
90
|
+
page = described_class.new(capybara_page)
|
91
|
+
page.finder(:form, '#form-')
|
92
|
+
|
93
|
+
object = OpenStruct.new(id: 1)
|
94
|
+
|
95
|
+
expect(page.has_form?(object)).to be_true
|
96
|
+
end
|
97
|
+
|
98
|
+
it 'adds a method to check if the element has no sub-element matching a record' do
|
99
|
+
page = described_class.new(capybara_page)
|
100
|
+
page.finder(:form, '#form-')
|
101
|
+
|
102
|
+
object = OpenStruct.new(id: 1)
|
103
|
+
|
104
|
+
expect(page.has_no_form?(object)).to be_false
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: napybara
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- George Mendoza
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: capybara
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -182,7 +196,7 @@ files:
|
|
182
196
|
- README.md
|
183
197
|
- Rakefile
|
184
198
|
- lib/napybara.rb
|
185
|
-
- lib/napybara/
|
199
|
+
- lib/napybara/element.rb
|
186
200
|
- lib/napybara/version.rb
|
187
201
|
- napybara.gemspec
|
188
202
|
- spec/dummy_app/config.ru
|
@@ -191,7 +205,7 @@ files:
|
|
191
205
|
- spec/dummy_app/public/new_content.html
|
192
206
|
- spec/dummy_app/public/test.html
|
193
207
|
- spec/integration/napybara_spec.rb
|
194
|
-
- spec/napybara/
|
208
|
+
- spec/napybara/element_spec.rb
|
195
209
|
- spec/spec_helper.rb
|
196
210
|
homepage: ''
|
197
211
|
licenses:
|
@@ -224,5 +238,5 @@ test_files:
|
|
224
238
|
- spec/dummy_app/public/new_content.html
|
225
239
|
- spec/dummy_app/public/test.html
|
226
240
|
- spec/integration/napybara_spec.rb
|
227
|
-
- spec/napybara/
|
241
|
+
- spec/napybara/element_spec.rb
|
228
242
|
- spec/spec_helper.rb
|
data/lib/napybara/dsl.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
module Napybara
|
2
|
-
class DSL < Struct.new(:element)
|
3
|
-
def self.build(capybara_node, &block)
|
4
|
-
@element = capybara_node
|
5
|
-
capybara_node.tap do |element|
|
6
|
-
dsl_instance = new(element)
|
7
|
-
dsl_instance.instance_eval(&block) if block_given?
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
def all(child_element_name, child_element_selector, &block)
|
12
|
-
element.define_singleton_method(child_element_name) do
|
13
|
-
self.all(child_element_selector).each do |child_element|
|
14
|
-
Napybara::DSL.build(child_element, &block)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def extend_element(a_module = Module.new, &block)
|
20
|
-
block_module = Module.new(&block)
|
21
|
-
element.extend(block_module, a_module)
|
22
|
-
end
|
23
|
-
|
24
|
-
def find(child_element_name, child_element_selector, &block)
|
25
|
-
element.define_singleton_method(child_element_name) do
|
26
|
-
Napybara::DSL.build(self.find(child_element_selector), &block)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
data/spec/napybara/dsl_spec.rb
DELETED
@@ -1,121 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Napybara::DSL do
|
4
|
-
let(:capybara_page) do
|
5
|
-
Capybara.string <<-HTML
|
6
|
-
<form class='some-form'>
|
7
|
-
<button class='some-button'>
|
8
|
-
<img />
|
9
|
-
</button>
|
10
|
-
|
11
|
-
<button class='another-button'>
|
12
|
-
<img />
|
13
|
-
</button>
|
14
|
-
</form>
|
15
|
-
HTML
|
16
|
-
end
|
17
|
-
|
18
|
-
describe '.build' do
|
19
|
-
it 'returns the capybara_page as is' do
|
20
|
-
element = described_class.build(capybara_page)
|
21
|
-
expect(element).to eq(capybara_page)
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'adds child elements from the block to the return element' do
|
25
|
-
element = described_class.build(capybara_page) do
|
26
|
-
find :form, '.some-form'
|
27
|
-
end
|
28
|
-
|
29
|
-
expect(element.form['class']).to eq('some-form')
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
describe '#find' do
|
34
|
-
it 'adds a method to the element for finding the given selector' do
|
35
|
-
dsl = described_class.new(capybara_page)
|
36
|
-
dsl.find(:form, '.some-form')
|
37
|
-
|
38
|
-
expect(dsl.element.form['class']).to eq('some-form')
|
39
|
-
end
|
40
|
-
|
41
|
-
it 'adds child elements from the block to the finder element' do
|
42
|
-
dsl = described_class.new(capybara_page)
|
43
|
-
dsl.find(:form, '.some-form') do
|
44
|
-
find(:button, '.some-button')
|
45
|
-
end
|
46
|
-
|
47
|
-
expect(dsl.element.form.button['class']).to eq('some-button')
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
describe '#all' do
|
52
|
-
it 'adds a method to get all the elements matching the selector' do
|
53
|
-
dsl = described_class.new(capybara_page)
|
54
|
-
dsl.all(:buttons, 'button')
|
55
|
-
|
56
|
-
expect(dsl.element.buttons).to have(2).elements
|
57
|
-
expect(dsl.element.buttons).to be_all do |element|
|
58
|
-
element.tag_name == 'button'
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'adds child elements from the block to each element returned' do
|
63
|
-
dsl = described_class.new(capybara_page)
|
64
|
-
dsl.all(:buttons, 'button') do
|
65
|
-
find :img, 'img'
|
66
|
-
end
|
67
|
-
|
68
|
-
expect(dsl.element.buttons).to have(2).elements
|
69
|
-
expect(dsl.element.buttons[0].img.tag_name).to eq('img')
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
describe '#extend_element' do
|
74
|
-
it 'can accept a module' do
|
75
|
-
some_module = Module.new do
|
76
|
-
def responds_to_this_method?
|
77
|
-
true
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
dsl = described_class.new(capybara_page)
|
82
|
-
dsl.extend_element(some_module)
|
83
|
-
|
84
|
-
expect(dsl.element.responds_to_this_method?).to be_true
|
85
|
-
end
|
86
|
-
|
87
|
-
it 'can accept a block' do
|
88
|
-
dsl = described_class.new(capybara_page)
|
89
|
-
dsl.extend_element do
|
90
|
-
def responds_to_this_method?
|
91
|
-
true
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
expect(dsl.element.responds_to_this_method?).to be_true
|
96
|
-
end
|
97
|
-
|
98
|
-
it 'prefers the passed module with the block' do
|
99
|
-
some_module = Module.new do
|
100
|
-
def responds_to_module_method?
|
101
|
-
true
|
102
|
-
end
|
103
|
-
|
104
|
-
def responds_to_block_method?
|
105
|
-
false
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
dsl = described_class.new(capybara_page)
|
110
|
-
|
111
|
-
dsl.extend_element(some_module) do
|
112
|
-
def responds_to_block_method?
|
113
|
-
true
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
expect(dsl.element.responds_to_module_method?).to be_true
|
118
|
-
expect(dsl.element.responds_to_block_method?).to be_true
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|