spinach 0.0.6 → 0.1.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.
- data/Gemfile +1 -0
- data/Readme.md +3 -0
- data/bin/spinach +3 -1
- data/features/steps/error_reporting.rb +4 -8
- data/features/steps/exit_status.rb +0 -1
- data/features/steps/feature_name_guessing.rb +1 -2
- data/features/support/spinach_runner.rb +0 -2
- data/lib/spinach/capybara.rb +8 -8
- data/lib/spinach/cli.rb +30 -18
- data/lib/spinach/config.rb +29 -10
- data/lib/spinach/dsl.rb +45 -21
- data/lib/spinach/exceptions.rb +21 -8
- data/lib/spinach/feature.rb +8 -4
- data/lib/spinach/parser.rb +13 -7
- data/lib/spinach/reporter/stdout.rb +251 -53
- data/lib/spinach/reporter.rb +43 -26
- data/lib/spinach/runner/feature.rb +39 -26
- data/lib/spinach/runner/scenario.rb +43 -28
- data/lib/spinach/runner.rb +40 -20
- data/lib/spinach/support.rb +8 -7
- data/lib/spinach/version.rb +2 -1
- data/lib/spinach.rb +17 -9
- data/spinach.gemspec +2 -1
- data/test/spinach/capybara_test.rb +32 -3
- data/test/spinach/cli_test.rb +32 -11
- data/test/spinach/config_test.rb +9 -6
- data/test/spinach/dsl_test.rb +8 -1
- data/test/spinach/feature_test.rb +14 -11
- data/test/spinach/parser_test.rb +33 -20
- data/test/spinach/reporter/stdout_test.rb +364 -103
- data/test/spinach/reporter_test.rb +145 -20
- data/test/spinach/runner/feature_test.rb +26 -51
- data/test/spinach/runner/scenario_test.rb +64 -35
- data/test/spinach/runner_test.rb +41 -32
- data/test/spinach/support_test.rb +2 -10
- data/test/spinach_test.rb +14 -14
- data/test/test_helper.rb +13 -5
- metadata +36 -28
- data/examples/steps/user_logs_in.rb +0 -23
- data/examples/user_logs_in.feature +0 -6
- data/examples/user_logs_in.rb +0 -23
@@ -1,24 +1,17 @@
|
|
1
1
|
require_relative '../../test_helper'
|
2
2
|
|
3
3
|
describe Spinach::Runner::Feature do
|
4
|
-
|
5
|
-
|
6
|
-
@reporter = stub_everything
|
7
|
-
@feature = Spinach::Runner::Feature.new(@filename, @reporter)
|
8
|
-
end
|
4
|
+
let(:filename) { 'feature/a_cool_feature.feature' }
|
5
|
+
let(:feature) { Spinach::Runner::Feature.new(filename) }
|
9
6
|
|
10
7
|
describe '#initialize' do
|
11
8
|
it 'initializes the given filename' do
|
12
|
-
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'initializes the given reporter' do
|
16
|
-
@feature.reporter.must_equal @reporter
|
9
|
+
feature.filename.must_equal filename
|
17
10
|
end
|
18
11
|
|
19
12
|
it 'initalizes the given scenario line' do
|
20
13
|
@filename = 'feature/a_cool_feature.feature:12'
|
21
|
-
@feature = Spinach::Runner::Feature.new(@filename
|
14
|
+
@feature = Spinach::Runner::Feature.new(@filename)
|
22
15
|
|
23
16
|
@feature.instance_variable_get(:@scenario_line).must_equal '12'
|
24
17
|
end
|
@@ -26,77 +19,69 @@ describe Spinach::Runner::Feature do
|
|
26
19
|
|
27
20
|
describe '#feature' do
|
28
21
|
it 'finds the feature given a feature name' do
|
29
|
-
feature = stub_everything
|
30
|
-
|
31
|
-
|
32
|
-
|
22
|
+
@feature = stub_everything
|
23
|
+
feature.stubs(feature_name: 'A cool feature')
|
24
|
+
|
25
|
+
Spinach.expects(:find_feature).with('A cool feature').returns(@feature)
|
26
|
+
feature.feature
|
33
27
|
end
|
34
28
|
end
|
35
29
|
|
36
30
|
describe '#data' do
|
37
31
|
it 'returns the parsed data' do
|
38
|
-
parsed_data = {
|
39
|
-
parser = stub(:
|
32
|
+
parsed_data = {name: 'A cool feature'}
|
33
|
+
parser = stub(parse: parsed_data)
|
40
34
|
Spinach::Parser.expects(:new).returns(parser)
|
41
|
-
|
35
|
+
feature.data.must_equal parsed_data
|
42
36
|
end
|
43
37
|
end
|
44
38
|
|
45
39
|
describe '#scenarios' do
|
46
40
|
it 'returns the parsed scenarios' do
|
47
|
-
|
48
|
-
|
41
|
+
feature.stubs(data: {'elements' => [1, 2, 3]})
|
42
|
+
feature.scenarios.must_equal [1,2,3]
|
49
43
|
end
|
50
44
|
end
|
51
45
|
|
52
46
|
describe '#run' do
|
53
47
|
before do
|
54
|
-
|
48
|
+
feature.stubs(data: {
|
55
49
|
'name' => 'A cool feature',
|
56
50
|
'elements' => [{'keyword'=>'Scenario', 'name'=>'Basic guess', 'line'=>6, 'description'=>'', 'type'=>'scenario'},
|
57
51
|
{'keyword'=>'Scenario', 'name'=>'Basic guess II', 'line'=>12, 'description'=>'', 'type'=>'scenario'},
|
58
52
|
{'keyword'=>'Scenario', 'name'=>'Basic guess III', 'line'=>18, 'description'=>'', 'type'=>'scenario'}]
|
59
53
|
})
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
it 'reports' do
|
64
|
-
Spinach::Runner::Scenario.stubs(new: stub_everything)
|
65
|
-
|
66
|
-
@reporter.expects(:feature).with('A cool feature')
|
67
|
-
@feature.run
|
54
|
+
feature.stubs(feature: stub_everything)
|
68
55
|
end
|
69
56
|
|
70
57
|
it 'calls the steps as expected' do
|
71
58
|
seq = sequence('feature')
|
59
|
+
feature.feature.expects(:run_hook).with(:before, kind_of(Hash))
|
72
60
|
3.times do
|
73
|
-
@feature.feature.expects(:before).in_sequence(seq)
|
74
61
|
Spinach::Runner::Scenario.
|
75
62
|
expects(:new).
|
76
63
|
returns(stub_everything).
|
77
64
|
in_sequence(seq)
|
78
|
-
@feature.feature.expects(:after).in_sequence(seq)
|
79
65
|
end
|
80
|
-
|
66
|
+
feature.feature.expects(:run_hook).with(:after, kind_of(Hash))
|
67
|
+
feature.run
|
81
68
|
end
|
82
69
|
|
83
|
-
it
|
84
|
-
@feature.stubs(reporter: stub_everything)
|
70
|
+
it 'returns true if the execution succeeds' do
|
85
71
|
Spinach::Runner::Scenario.any_instance.
|
86
|
-
expects(run:
|
87
|
-
|
72
|
+
expects(run: true).times(3)
|
73
|
+
feature.run.must_equal true
|
88
74
|
end
|
89
75
|
|
90
|
-
it
|
91
|
-
@feature.stubs(reporter: stub_everything)
|
76
|
+
it 'returns false if the execution fails' do
|
92
77
|
Spinach::Runner::Scenario.any_instance.
|
93
|
-
expects(run:
|
94
|
-
|
78
|
+
expects(run: false).times(3)
|
79
|
+
feature.run.must_equal false
|
95
80
|
end
|
96
81
|
|
97
82
|
it 'calls only the given scenario' do
|
98
83
|
@filename = 'feature/a_cool_feature.feature:12'
|
99
|
-
@feature = Spinach::Runner::Feature.new(@filename
|
84
|
+
@feature = Spinach::Runner::Feature.new(@filename)
|
100
85
|
@feature.stubs(data: {
|
101
86
|
'name' => 'A cool feature',
|
102
87
|
'elements' => [{'keyword'=>'Scenario', 'name'=>'Basic guess', 'line'=>6, 'description'=>'', 'type'=>'scenario'},
|
@@ -108,15 +93,5 @@ describe Spinach::Runner::Feature do
|
|
108
93
|
Spinach::Runner::Scenario.expects(:new).with(anything, anything, @feature.scenarios[1], anything).once.returns(stub_everything)
|
109
94
|
@feature.run
|
110
95
|
end
|
111
|
-
|
112
|
-
it "calls an error summary if there are any failures" do
|
113
|
-
failure = stub('failure')
|
114
|
-
scenario = stub(run: failure)
|
115
|
-
Spinach::Runner::Scenario.stubs(:new).returns scenario
|
116
|
-
|
117
|
-
@reporter.expects(:error_summary).with [failure, failure, failure]
|
118
|
-
|
119
|
-
@feature.run
|
120
|
-
end
|
121
96
|
end
|
122
97
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require_relative '../../test_helper'
|
2
2
|
|
3
3
|
describe Spinach::Runner::Scenario do
|
4
|
-
|
5
|
-
|
4
|
+
let(:data) do
|
5
|
+
{
|
6
6
|
'name' => 'A cool scenario',
|
7
7
|
'steps' => [
|
8
8
|
{'keyword' => 'Given', 'name' => 'I herd you like steps'},
|
@@ -10,68 +10,97 @@ describe Spinach::Runner::Scenario do
|
|
10
10
|
{'keyword' => 'Then', 'name' => 'I go step by step'}
|
11
11
|
]
|
12
12
|
}
|
13
|
-
@feature = stub_everything
|
14
|
-
@feature_name = "My feature"
|
15
|
-
@reporter = stub_everything
|
16
|
-
@scenario = Spinach::Runner::Scenario.new(@feature_name, @feature, @data, @reporter)
|
17
13
|
end
|
18
14
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
15
|
+
let(:feature) { stub_everything }
|
16
|
+
let(:feature_name) { 'My feature' }
|
17
|
+
let(:scenario) { Spinach::Runner::Scenario.new(feature_name, feature, data) }
|
23
18
|
|
19
|
+
describe '#initialize' do
|
24
20
|
it 'lists all the steps' do
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
it 'sets the reporter' do
|
29
|
-
@scenario.reporter.must_equal @reporter
|
21
|
+
scenario.steps.count.must_equal 3
|
30
22
|
end
|
31
23
|
|
32
24
|
it 'sets the feature' do
|
33
|
-
|
25
|
+
scenario.feature.must_equal feature
|
34
26
|
end
|
35
27
|
end
|
36
28
|
|
37
29
|
describe '#run' do
|
38
30
|
it 'calls the appropiate feature steps' do
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
31
|
+
feature.expects(:execute_step).with('I herd you like steps')
|
32
|
+
feature.expects(:execute_step).with('I test steps')
|
33
|
+
feature.expects(:execute_step).with('I go step by step')
|
34
|
+
scenario.run
|
43
35
|
end
|
44
36
|
|
45
37
|
describe 'when throwing exceptions' do
|
46
38
|
it 'rescues a MiniTest::Assertion' do
|
47
|
-
|
48
|
-
|
49
|
-
|
39
|
+
feature.expects(:execute_step).raises(MiniTest::Assertion)
|
40
|
+
scenario.expects(:run_hook).with(:before_run, has_value("A cool scenario"))
|
41
|
+
scenario.expects(:run_hook).with(:after_run, has_value("A cool scenario"))
|
42
|
+
scenario.expects(:run_hook).with(
|
43
|
+
:on_failed_step, anything, anything, anything)
|
44
|
+
scenario.expects(:run_hook).with(
|
45
|
+
:on_skipped_step, anything, anything).twice
|
46
|
+
scenario.run
|
50
47
|
end
|
51
48
|
|
52
49
|
it 'rescues a Spinach::StepNotDefinedException' do
|
53
|
-
|
54
|
-
|
55
|
-
|
50
|
+
feature.expects(:execute_step).raises(
|
51
|
+
Spinach::StepNotDefinedException.new('foo', 'bar'))
|
52
|
+
scenario.expects(:run_hook).with(:before_run, has_value("A cool scenario"))
|
53
|
+
scenario.expects(:run_hook).with(:after_run, has_value("A cool scenario"))
|
54
|
+
scenario.expects(:run_hook).with(
|
55
|
+
:on_undefined_step, anything, anything, anything)
|
56
|
+
scenario.expects(:run_hook).with(
|
57
|
+
:on_skipped_step, anything, anything).twice
|
58
|
+
scenario.run
|
56
59
|
end
|
57
60
|
|
58
61
|
it 'rescues any other error' do
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
+
feature.expects(:execute_step).raises
|
63
|
+
scenario.expects(:run_hook).with(:after_run, has_value("A cool scenario"))
|
64
|
+
scenario.expects(:run_hook).with(:before_run, has_value("A cool scenario"))
|
65
|
+
scenario.expects(:run_hook).with(
|
66
|
+
:on_error_step, anything, anything, anything)
|
67
|
+
scenario.expects(:run_hook).with(
|
68
|
+
:on_skipped_step, anything, anything).twice
|
69
|
+
scenario.run
|
62
70
|
end
|
63
71
|
|
64
|
-
it
|
65
|
-
|
66
|
-
|
72
|
+
it 'returns an failure' do
|
73
|
+
feature.expects(:execute_step).raises(MiniTest::Assertion)
|
74
|
+
scenario.run.wont_equal nil
|
67
75
|
end
|
68
|
-
|
69
76
|
end
|
70
77
|
|
71
78
|
it 'runs a step' do
|
72
|
-
|
73
|
-
|
79
|
+
feature.expects(:execute_step).with(anything).times(3)
|
80
|
+
scenario.run.must_equal true
|
74
81
|
end
|
75
82
|
|
83
|
+
describe 'hooks' do
|
84
|
+
it 'fires up the scenario hooks' do
|
85
|
+
feature.expects(:execute_step).raises(Spinach::StepNotDefinedException.new('foo', 'bar'))
|
86
|
+
feature.expects(:run_hook).with(:before_scenario, has_value("A cool scenario"))
|
87
|
+
feature.expects(:run_hook).with(:after_scenario, has_value("A cool scenario"))
|
88
|
+
scenario.run
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'fires up the step hooks' do
|
92
|
+
feature.expects(:execute_step).raises(Spinach::StepNotDefinedException.new('foo', 'bar'))
|
93
|
+
%w{before_step after_step}.each do |hook|
|
94
|
+
feature.expects(:run_hook).with(
|
95
|
+
hook.to_sym, kind_of(Hash))
|
96
|
+
feature.expects(:run_hook).with(
|
97
|
+
hook.to_sym, kind_of(Hash))
|
98
|
+
feature.expects(:run_hook).with(
|
99
|
+
hook.to_sym, kind_of(Hash))
|
100
|
+
end
|
101
|
+
|
102
|
+
scenario.run
|
103
|
+
end
|
104
|
+
end
|
76
105
|
end
|
77
106
|
end
|
data/test/spinach/runner_test.rb
CHANGED
@@ -1,61 +1,70 @@
|
|
1
1
|
require_relative '../test_helper'
|
2
2
|
|
3
3
|
describe Spinach::Runner do
|
4
|
-
|
5
|
-
|
6
|
-
%w{features/cool_feature.feature features/great_feature.feature}
|
4
|
+
let(:filenames) { %w{features/cool_feature.feature features/great_feature.feature} }
|
5
|
+
let(:runner) { Spinach::Runner.new(filenames) }
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
it "sets the filenames" do
|
12
|
-
@runner.filenames.must_equal @filenames
|
7
|
+
describe '#initialize' do
|
8
|
+
it 'sets the filenames' do
|
9
|
+
runner.filenames.must_equal filenames
|
13
10
|
end
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
|
12
|
+
describe 'step_definitions_path' do
|
13
|
+
it 'sets a default' do
|
14
|
+
runner.step_definitions_path.must_be_kind_of String
|
17
15
|
end
|
18
|
-
|
19
|
-
|
16
|
+
|
17
|
+
it 'can be overriden' do
|
18
|
+
runner = Spinach::Runner.new(
|
20
19
|
@filename, step_definitions_path: 'spinach/step_definitions'
|
21
20
|
)
|
22
|
-
|
21
|
+
runner.step_definitions_path.must_equal 'spinach/step_definitions'
|
23
22
|
end
|
24
23
|
end
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
|
25
|
+
describe 'support_path' do
|
26
|
+
it 'sets a default' do
|
27
|
+
runner.support_path.must_be_kind_of String
|
28
28
|
end
|
29
|
-
|
30
|
-
|
29
|
+
|
30
|
+
it 'can be overriden' do
|
31
|
+
runner = Spinach::Runner.new(
|
31
32
|
@filename, support_path: 'spinach/environment'
|
32
33
|
)
|
33
|
-
|
34
|
+
runner.support_path.must_equal 'spinach/environment'
|
34
35
|
end
|
35
36
|
end
|
36
37
|
end
|
37
|
-
|
38
|
-
|
39
|
-
@runner.reporter.wont_equal nil
|
40
|
-
end
|
41
|
-
end
|
42
|
-
describe "#run" do
|
38
|
+
|
39
|
+
describe '#run' do
|
43
40
|
before do
|
44
41
|
@feature = stub
|
45
|
-
|
46
|
-
@filenames.each do |filename|
|
42
|
+
filenames.each do |filename|
|
47
43
|
Spinach::Runner::Feature.expects(:new).
|
48
44
|
with(filename, anything).
|
49
45
|
returns(@feature)
|
50
46
|
end
|
51
47
|
end
|
52
|
-
|
48
|
+
|
49
|
+
it 'instantiates a new Feature and runs it with every file' do
|
53
50
|
@feature.stubs(run: true)
|
54
|
-
|
51
|
+
runner.run.must_equal true
|
55
52
|
end
|
56
|
-
|
53
|
+
|
54
|
+
it 'returns false if it fails' do
|
57
55
|
@feature.stubs(run: false)
|
58
|
-
|
56
|
+
runner.run
|
57
|
+
end
|
58
|
+
end
|
59
|
+
describe '#require_dependencies' do
|
60
|
+
it 'requires support files and step definitions' do
|
61
|
+
runner.stubs(
|
62
|
+
support_files: ['a', 'b'], step_definition_files: ['c', 'd']
|
63
|
+
)
|
64
|
+
%w{a b c d}.each do |file|
|
65
|
+
runner.expects(:require).with(file)
|
66
|
+
end
|
67
|
+
runner.require_dependencies
|
59
68
|
end
|
60
69
|
end
|
61
70
|
end
|
@@ -7,26 +7,18 @@ describe Spinach::Support do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
it 'downcases the given value' do
|
10
|
-
|
11
|
-
|
12
|
-
Spinach::Support.camelize('VALUE').must_equal 'value'
|
10
|
+
Spinach::Support.camelize('VALUE').must_equal 'Value'
|
13
11
|
end
|
14
12
|
|
15
13
|
it 'squeezes the spaces for the given value' do
|
16
|
-
ActiveSupport::Inflector.expects(:camelize).with('feature_name').returns('FeatureName')
|
17
|
-
|
18
14
|
Spinach::Support.camelize('feature name').must_equal 'FeatureName'
|
19
15
|
end
|
20
16
|
|
21
17
|
it 'strips the given value' do
|
22
|
-
|
23
|
-
|
24
|
-
Spinach::Support.camelize(' value ').must_equal 'value'
|
18
|
+
Spinach::Support.camelize(' value ').must_equal 'Value'
|
25
19
|
end
|
26
20
|
|
27
21
|
it 'strips the given value' do
|
28
|
-
ActiveSupport::Inflector.expects(:camelize).with('feature_name').returns('FeatureName')
|
29
|
-
|
30
22
|
Spinach::Support.camelize('feature name').must_equal 'FeatureName'
|
31
23
|
end
|
32
24
|
end
|
data/test/spinach_test.rb
CHANGED
@@ -2,25 +2,25 @@ require_relative 'test_helper'
|
|
2
2
|
|
3
3
|
describe Spinach do
|
4
4
|
before do
|
5
|
-
@feature1 = OpenStruct.new(feature_name:
|
6
|
-
@feature2 = OpenStruct.new(feature_name:
|
7
|
-
@feature3 = OpenStruct.new(feature_name:
|
8
|
-
@feature4 = OpenStruct.new(name:
|
5
|
+
@feature1 = OpenStruct.new(feature_name: 'User authentication')
|
6
|
+
@feature2 = OpenStruct.new(feature_name: 'Slip management')
|
7
|
+
@feature3 = OpenStruct.new(feature_name: 'File attachments')
|
8
|
+
@feature4 = OpenStruct.new(name: 'UserSendsAMessage')
|
9
9
|
[@feature1, @feature2, @feature3, @feature4].each do |feature|
|
10
10
|
Spinach.features << feature
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
describe
|
15
|
-
it
|
14
|
+
describe '#features' do
|
15
|
+
it 'returns all the loaded features' do
|
16
16
|
Spinach.features.must_include @feature1
|
17
17
|
Spinach.features.must_include @feature2
|
18
18
|
Spinach.features.must_include @feature3
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
describe
|
23
|
-
it
|
22
|
+
describe '#reset_features' do
|
23
|
+
it 'resets the features to a pristine state' do
|
24
24
|
Spinach.reset_features
|
25
25
|
[@feature1, @feature3, @feature3].each do |feature|
|
26
26
|
Spinach.features.wont_include feature
|
@@ -28,14 +28,14 @@ describe Spinach do
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
describe
|
32
|
-
it
|
33
|
-
Spinach.find_feature(
|
34
|
-
Spinach.find_feature(
|
35
|
-
Spinach.find_feature(
|
31
|
+
describe '#find_feature' do
|
32
|
+
it 'finds a feature by name' do
|
33
|
+
Spinach.find_feature('User authentication').must_equal @feature1
|
34
|
+
Spinach.find_feature('Slip management').must_equal @feature2
|
35
|
+
Spinach.find_feature('File attachments').must_equal @feature3
|
36
36
|
end
|
37
37
|
|
38
|
-
describe
|
38
|
+
describe 'when a feature class does no set a feature_name' do
|
39
39
|
it 'guesses the feature class from the feature name' do
|
40
40
|
Spinach.find_feature('User sends a message').must_equal @feature4
|
41
41
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,17 +1,26 @@
|
|
1
1
|
gem 'minitest'
|
2
|
-
|
2
|
+
|
3
|
+
if ENV['COVERAGE']
|
4
|
+
require 'simplecov'
|
5
|
+
|
6
|
+
SimpleCov.start do
|
7
|
+
add_filter '/test/'
|
8
|
+
add_filter '/features/'
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'minitest/spec'
|
3
13
|
require 'minitest/autorun'
|
4
14
|
require 'mocha'
|
5
15
|
require 'ostruct'
|
6
16
|
require 'purdytest'
|
17
|
+
require 'stringio'
|
18
|
+
require 'pry'
|
7
19
|
|
8
20
|
require 'spinach'
|
9
21
|
require 'spinach/capybara'
|
10
22
|
|
11
|
-
require 'stringio'
|
12
|
-
|
13
23
|
module Kernel
|
14
|
-
|
15
24
|
def capture_stdout
|
16
25
|
out = StringIO.new
|
17
26
|
$stdout = out
|
@@ -20,5 +29,4 @@ module Kernel
|
|
20
29
|
ensure
|
21
30
|
$stdout = STDOUT
|
22
31
|
end
|
23
|
-
|
24
32
|
end
|