rspec-expectations 2.12.1 → 2.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/Changelog.md +31 -0
  2. data/README.md +1 -1
  3. data/features/built_in_matchers/be.feature +6 -4
  4. data/features/built_in_matchers/be_within.feature +3 -1
  5. data/features/built_in_matchers/cover.feature +2 -0
  6. data/features/built_in_matchers/end_with.feature +2 -0
  7. data/features/built_in_matchers/equality.feature +9 -15
  8. data/features/built_in_matchers/exist.feature +2 -0
  9. data/features/built_in_matchers/expect_error.feature +14 -8
  10. data/features/built_in_matchers/have.feature +11 -5
  11. data/features/built_in_matchers/include.feature +53 -0
  12. data/features/built_in_matchers/match.feature +2 -0
  13. data/features/built_in_matchers/operators.feature +17 -11
  14. data/features/built_in_matchers/predicates.feature +21 -13
  15. data/features/built_in_matchers/respond_to.feature +7 -1
  16. data/features/built_in_matchers/satisfy.feature +2 -0
  17. data/features/built_in_matchers/start_with.feature +2 -0
  18. data/features/built_in_matchers/throw_symbol.feature +6 -0
  19. data/features/built_in_matchers/types.feature +8 -6
  20. data/lib/rspec/expectations/deprecation.rb +1 -1
  21. data/lib/rspec/expectations/differ.rb +8 -8
  22. data/lib/rspec/expectations/fail_with.rb +17 -3
  23. data/lib/rspec/expectations/syntax.rb +46 -0
  24. data/lib/rspec/expectations/version.rb +1 -1
  25. data/lib/rspec/matchers/built_in/be.rb +7 -3
  26. data/lib/rspec/matchers/built_in/be_within.rb +13 -4
  27. data/lib/rspec/matchers/built_in/change.rb +2 -2
  28. data/lib/rspec/matchers/built_in/equal.rb +5 -1
  29. data/lib/rspec/matchers/built_in/exist.rb +1 -1
  30. data/lib/rspec/matchers/built_in/have.rb +8 -8
  31. data/lib/rspec/matchers/built_in/include.rb +19 -3
  32. data/lib/rspec/matchers/built_in/respond_to.rb +1 -1
  33. data/lib/rspec/matchers/extensions/instance_eval_with_args.rb +1 -1
  34. data/lib/rspec/matchers/matcher.rb +4 -3
  35. data/lib/rspec/matchers/operator_matcher.rb +1 -1
  36. data/lib/rspec/matchers/pretty.rb +5 -1
  37. data/spec/rspec/expectations/differ_spec.rb +8 -15
  38. data/spec/rspec/expectations/expectation_target_spec.rb +18 -8
  39. data/spec/rspec/expectations/extensions/kernel_spec.rb +15 -15
  40. data/spec/rspec/expectations/fail_with_spec.rb +41 -16
  41. data/spec/rspec/expectations/handler_spec.rb +13 -13
  42. data/spec/rspec/expectations/syntax_spec.rb +70 -8
  43. data/spec/rspec/matchers/base_matcher_spec.rb +14 -12
  44. data/spec/rspec/matchers/be_close_spec.rb +1 -1
  45. data/spec/rspec/matchers/be_instance_of_spec.rb +14 -8
  46. data/spec/rspec/matchers/be_kind_of_spec.rb +12 -8
  47. data/spec/rspec/matchers/be_spec.rb +212 -148
  48. data/spec/rspec/matchers/be_within_spec.rb +91 -42
  49. data/spec/rspec/matchers/change_spec.rb +52 -38
  50. data/spec/rspec/matchers/configuration_spec.rb +19 -15
  51. data/spec/rspec/matchers/cover_spec.rb +19 -19
  52. data/spec/rspec/matchers/description_generation_spec.rb +86 -86
  53. data/spec/rspec/matchers/dsl_spec.rb +7 -7
  54. data/spec/rspec/matchers/eq_spec.rb +17 -11
  55. data/spec/rspec/matchers/eql_spec.rb +10 -10
  56. data/spec/rspec/matchers/equal_spec.rb +27 -9
  57. data/spec/rspec/matchers/exist_spec.rb +35 -21
  58. data/spec/rspec/matchers/has_spec.rb +33 -29
  59. data/spec/rspec/matchers/have_spec.rb +165 -151
  60. data/spec/rspec/matchers/include_matcher_integration_spec.rb +30 -0
  61. data/spec/rspec/matchers/include_spec.rb +282 -124
  62. data/spec/rspec/matchers/match_array_spec.rb +90 -49
  63. data/spec/rspec/matchers/match_spec.rb +21 -21
  64. data/spec/rspec/matchers/matcher_spec.rb +85 -48
  65. data/spec/rspec/matchers/matchers_spec.rb +12 -6
  66. data/spec/rspec/matchers/method_missing_spec.rb +5 -1
  67. data/spec/rspec/matchers/operator_matcher_spec.rb +216 -237
  68. data/spec/rspec/matchers/raise_error_spec.rb +132 -132
  69. data/spec/rspec/matchers/respond_to_spec.rb +109 -112
  70. data/spec/rspec/matchers/satisfy_spec.rb +16 -16
  71. data/spec/rspec/matchers/start_with_end_with_spec.rb +36 -32
  72. data/spec/rspec/matchers/throw_symbol_spec.rb +24 -24
  73. data/spec/rspec/matchers/yield_spec.rb +7 -7
  74. data/spec/spec_helper.rb +46 -19
  75. data/spec/support/in_sub_process.rb +27 -20
  76. metadata +81 -83
@@ -5,8 +5,8 @@ module RSpec
5
5
  module Matchers
6
6
  describe "RSpec::Matchers.configuration" do
7
7
  it 'returns a memoized configuration instance' do
8
- RSpec::Matchers.configuration.should be_a(RSpec::Matchers::Configuration)
9
- RSpec::Matchers.configuration.should be(RSpec::Matchers.configuration)
8
+ expect(RSpec::Matchers.configuration).to be_a(RSpec::Matchers::Configuration)
9
+ expect(RSpec::Matchers.configuration).to be(RSpec::Matchers.configuration)
10
10
  end
11
11
  end
12
12
 
@@ -41,7 +41,7 @@ module RSpec
41
41
  end
42
42
  end
43
43
 
44
- context 'on an interpreter that does not provide BasicObject', :unless => defined?(::BasicObject) do
44
+ context 'on an interpreter that does not provide BasicObject', :uses_should, :unless => defined?(::BasicObject) do
45
45
  before { RSpec::Expectations::Syntax.disable_should(Delegator) }
46
46
 
47
47
  let(:klass) do
@@ -72,23 +72,16 @@ module RSpec
72
72
  # it could leave things in a "broken" state where tons of other examples fail.
73
73
  if RUBY_PLATFORM == "java"
74
74
  def sandboxed
75
+ orig_syntax = RSpec::Matchers.configuration.syntax
75
76
  yield
76
77
  ensure
77
- configure_syntax([:should, :expect])
78
+ configure_syntax(orig_syntax)
78
79
  end
79
80
  else
80
81
  include InSubProcess
81
82
  alias sandboxed in_sub_process
82
83
  end
83
84
 
84
- it 'is configured to :should and :expect by default' do
85
- configured_syntax.should eq([:should, :expect])
86
-
87
- 3.should eq(3)
88
- 3.should_not eq(4)
89
- expect(3).to eq(3)
90
- end
91
-
92
85
  it 'can limit the syntax to :should' do
93
86
  sandboxed do
94
87
  configure_syntax :should
@@ -102,9 +95,12 @@ module RSpec
102
95
 
103
96
  it 'is a no-op when configured to :should twice' do
104
97
  sandboxed do
105
- ::Kernel.stub(:method_added).and_raise("no methods should be added here")
106
-
107
98
  configure_syntax :should
99
+
100
+ Expectations::Syntax.default_should_host.
101
+ stub(:method_added).
102
+ and_raise("no methods should be added here")
103
+
108
104
  configure_syntax :should
109
105
  end
110
106
  end
@@ -227,8 +223,16 @@ module RSpec
227
223
  end
228
224
  end
229
225
  end
230
- end
231
226
 
227
+ it 'enables both syntaxes by default' do
228
+ # This is kinda a hack, but since we want to enforce use of
229
+ # the expect syntax within our specs here, we have modified the
230
+ # config setting, which makes it hard to get at the original
231
+ # default value. in spec_helper.rb we store the default value
232
+ # in $default_expectation_syntax so we can use it here.
233
+ expect($default_expectation_syntax).to match_array([:expect, :should])
234
+ end
235
+ end
232
236
  end
233
237
  end
234
238
 
@@ -1,67 +1,67 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  if (1..2).respond_to?(:cover?)
4
- describe "should cover(expected)" do
4
+ describe "expect(...).to cover(expected)" do
5
5
  it_behaves_like "an RSpec matcher", :valid_value => (1..10), :invalid_value => (20..30) do
6
6
  let(:matcher) { cover(5) }
7
7
  end
8
8
 
9
9
  context "for a range target" do
10
10
  it "passes if target covers expected" do
11
- (1..10).should cover(5)
11
+ expect((1..10)).to cover(5)
12
12
  end
13
13
 
14
14
  it "fails if target does not cover expected" do
15
- lambda {
16
- (1..10).should cover(11)
17
- }.should fail_with("expected 1..10 to cover 11")
15
+ expect {
16
+ expect((1..10)).to cover(11)
17
+ }.to fail_with("expected 1..10 to cover 11")
18
18
  end
19
19
  end
20
20
  end
21
21
 
22
- describe "should cover(with, multiple, args)" do
22
+ describe "expect(...).to cover(with, multiple, args)" do
23
23
  context "for a range target" do
24
24
  it "passes if target covers all items" do
25
- (1..10).should cover(4, 6)
25
+ expect((1..10)).to cover(4, 6)
26
26
  end
27
27
 
28
28
  it "fails if target does not cover any one of the items" do
29
- lambda {
30
- (1..10).should cover(4, 6, 11)
31
- }.should fail_with("expected 1..10 to cover 4, 6, and 11")
29
+ expect {
30
+ expect((1..10)).to cover(4, 6, 11)
31
+ }.to fail_with("expected 1..10 to cover 4, 6, and 11")
32
32
  end
33
33
  end
34
34
  end
35
35
 
36
- describe "should_not cover(expected)" do
36
+ describe "expect(...).not_to cover(expected)" do
37
37
  context "for a range target" do
38
38
  it "passes if target does not cover expected" do
39
- (1..10).should_not cover(11)
39
+ expect((1..10)).not_to cover(11)
40
40
  end
41
41
 
42
42
  it "fails if target covers expected" do
43
- lambda {
44
- (1..10).should_not cover(5)
45
- }.should fail_with("expected 1..10 not to cover 5")
43
+ expect {
44
+ expect((1..10)).not_to cover(5)
45
+ }.to fail_with("expected 1..10 not to cover 5")
46
46
  end
47
47
  end
48
48
  end
49
49
 
50
- describe "should_not cover(with, multiple, args)" do
50
+ describe "expect(...).not_to cover(with, multiple, args)" do
51
51
  context "for a range target" do
52
52
  it "passes if the target does not cover any of the expected" do
53
- (1..10).should_not cover(11, 12, 13)
53
+ expect((1..10)).not_to cover(11, 12, 13)
54
54
  end
55
55
 
56
56
  it "fails if the target covers all of the expected" do
57
57
  expect {
58
- (1..10).should_not cover(4, 6)
58
+ expect((1..10)).not_to cover(4, 6)
59
59
  }.to fail_with("expected 1..10 not to cover 4 and 6")
60
60
  end
61
61
 
62
62
  it "fails if the target covers some (but not all) of the expected" do
63
63
  expect {
64
- (1..10).should_not cover(5, 11)
64
+ expect((1..10)).not_to cover(5, 11)
65
65
  }.to fail_with("expected 1..10 not to cover 5 and 11")
66
66
  end
67
67
  end
@@ -5,151 +5,151 @@ describe "Matchers should be able to generate their own descriptions" do
5
5
  RSpec::Matchers.clear_generated_description
6
6
  end
7
7
 
8
- it "should eq expected" do
9
- "this".should eq "this"
10
- RSpec::Matchers.generated_description.should eq "should eq \"this\""
8
+ it "expect(...).to eq expected" do
9
+ expect("this").to eq "this"
10
+ expect(RSpec::Matchers.generated_description).to eq "should eq \"this\""
11
11
  end
12
12
 
13
- it "should not eq expected" do
14
- "this".should_not eq "that"
15
- RSpec::Matchers.generated_description.should eq "should not eq \"that\""
13
+ it "expect(...).to not eq expected" do
14
+ expect("this").not_to eq "that"
15
+ expect(RSpec::Matchers.generated_description).to eq "should not eq \"that\""
16
16
  end
17
17
 
18
- it "should be empty (arbitrary predicate)" do
19
- [].should be_empty
20
- RSpec::Matchers.generated_description.should eq "should be empty"
18
+ it "expect(...).to be empty (arbitrary predicate)" do
19
+ expect([]).to be_empty
20
+ expect(RSpec::Matchers.generated_description).to eq "should be empty"
21
21
  end
22
22
 
23
- it "should not be empty (arbitrary predicate)" do
24
- [1].should_not be_empty
25
- RSpec::Matchers.generated_description.should eq "should not be empty"
23
+ it "expect(...).to not be empty (arbitrary predicate)" do
24
+ expect([1]).not_to be_empty
25
+ expect(RSpec::Matchers.generated_description).to eq "should not be empty"
26
26
  end
27
27
 
28
- it "should be true" do
29
- true.should be_true
30
- RSpec::Matchers.generated_description.should eq "should be true"
28
+ it "expect(...).to be true" do
29
+ expect(true).to be_true
30
+ expect(RSpec::Matchers.generated_description).to eq "should be true"
31
31
  end
32
32
 
33
- it "should be false" do
34
- false.should be_false
35
- RSpec::Matchers.generated_description.should eq "should be false"
33
+ it "expect(...).to be false" do
34
+ expect(false).to be_false
35
+ expect(RSpec::Matchers.generated_description).to eq "should be false"
36
36
  end
37
37
 
38
- it "should be nil" do
39
- nil.should be_nil
40
- RSpec::Matchers.generated_description.should eq "should be nil"
38
+ it "expect(...).to be nil" do
39
+ expect(nil).to be_nil
40
+ expect(RSpec::Matchers.generated_description).to eq "should be nil"
41
41
  end
42
42
 
43
- it "should be > n" do
44
- 5.should be > 3
45
- RSpec::Matchers.generated_description.should eq "should be > 3"
43
+ it "expect(...).to be > n" do
44
+ expect(5).to be > 3
45
+ expect(RSpec::Matchers.generated_description).to eq "should be > 3"
46
46
  end
47
47
 
48
- it "should be predicate arg1, arg2 and arg3" do
49
- 5.0.should be_between(0,10)
50
- RSpec::Matchers.generated_description.should eq "should be between 0 and 10"
48
+ it "expect(...).to be predicate arg1, arg2 and arg3" do
49
+ expect(5.0).to be_between(0,10)
50
+ expect(RSpec::Matchers.generated_description).to eq "should be between 0 and 10"
51
51
  end
52
52
 
53
- it "should equal" do
53
+ it "expect(...).to equal" do
54
54
  expected = "expected"
55
- expected.should equal(expected)
56
- RSpec::Matchers.generated_description.should eq "should equal \"expected\""
55
+ expect(expected).to equal(expected)
56
+ expect(RSpec::Matchers.generated_description).to eq "should equal \"expected\""
57
57
  end
58
58
 
59
- it "should_not equal" do
60
- 5.should_not equal(37)
61
- RSpec::Matchers.generated_description.should eq "should not equal 37"
59
+ it "expect(...).not_to equal" do
60
+ expect(5).not_to equal(37)
61
+ expect(RSpec::Matchers.generated_description).to eq "should not equal 37"
62
62
  end
63
63
 
64
- it "should eql" do
65
- "string".should eql("string")
66
- RSpec::Matchers.generated_description.should eq "should eql \"string\""
64
+ it "expect(...).to eql" do
65
+ expect("string").to eql("string")
66
+ expect(RSpec::Matchers.generated_description).to eq "should eql \"string\""
67
67
  end
68
68
 
69
- it "should not eql" do
70
- "a".should_not eql(:a)
71
- RSpec::Matchers.generated_description.should eq "should not eql :a"
69
+ it "expect(...).not_to eql" do
70
+ expect("a").not_to eql(:a)
71
+ expect(RSpec::Matchers.generated_description).to eq "should not eql :a"
72
72
  end
73
73
 
74
- it "should have_key" do
75
- {:a => "a"}.should have_key(:a)
76
- RSpec::Matchers.generated_description.should eq "should have key :a"
74
+ it "expect(...).to have_key" do
75
+ expect({:a => "a"}).to have_key(:a)
76
+ expect(RSpec::Matchers.generated_description).to eq "should have key :a"
77
77
  end
78
78
 
79
- it "should have_some_method" do
79
+ it "expect(...).to have_some_method" do
80
80
  object = Object.new
81
81
  def object.has_eyes_closed?; true; end
82
82
 
83
- object.should have_eyes_closed
84
- RSpec::Matchers.generated_description.should eq 'should have eyes closed'
83
+ expect(object).to have_eyes_closed
84
+ expect(RSpec::Matchers.generated_description).to eq 'should have eyes closed'
85
85
  end
86
86
 
87
- it "should have_some_method(args*)" do
87
+ it "expect(...).to have_some_method(args*)" do
88
88
  object = Object.new
89
89
  def object.has_taste_for?(*args); true; end
90
90
 
91
- object.should have_taste_for("wine", "cheese")
92
- RSpec::Matchers.generated_description.should eq 'should have taste for "wine", "cheese"'
91
+ expect(object).to have_taste_for("wine", "cheese")
92
+ expect(RSpec::Matchers.generated_description).to eq 'should have taste for "wine", "cheese"'
93
93
  end
94
94
 
95
- it "should have n items" do
96
- team.should have(3).players
97
- RSpec::Matchers.generated_description.should eq "should have 3 players"
95
+ it "expect(...).to have n items" do
96
+ expect(team).to have(3).players
97
+ expect(RSpec::Matchers.generated_description).to eq "should have 3 players"
98
98
  end
99
99
 
100
- it "should have at least n items" do
101
- team.should have_at_least(2).players
102
- RSpec::Matchers.generated_description.should eq "should have at least 2 players"
100
+ it "expect(...).to have at least n items" do
101
+ expect(team).to have_at_least(2).players
102
+ expect(RSpec::Matchers.generated_description).to eq "should have at least 2 players"
103
103
  end
104
104
 
105
- it "should have at most n items" do
106
- team.should have_at_most(4).players
107
- RSpec::Matchers.generated_description.should eq "should have at most 4 players"
105
+ it "expect(...).to have at most n items" do
106
+ expect(team).to have_at_most(4).players
107
+ expect(RSpec::Matchers.generated_description).to eq "should have at most 4 players"
108
108
  end
109
109
 
110
- it "should include" do
111
- [1,2,3].should include(3)
112
- RSpec::Matchers.generated_description.should eq "should include 3"
110
+ it "expect(...).to include" do
111
+ expect([1,2,3]).to include(3)
112
+ expect(RSpec::Matchers.generated_description).to eq "should include 3"
113
113
  end
114
114
 
115
- it "array.should =~ [1,2,3]" do
116
- [1,2,3].should =~ [1,2,3]
117
- RSpec::Matchers.generated_description.should eq "should contain exactly 1, 2 and 3"
115
+ it "expect(array).not_to match_array [1,2,3]" do
116
+ expect([1,2,3]).to match_array [1,2,3]
117
+ expect(RSpec::Matchers.generated_description).to eq "should contain exactly 1, 2 and 3"
118
118
  end
119
119
 
120
- it "should match" do
121
- "this string".should match(/this string/)
122
- RSpec::Matchers.generated_description.should eq "should match /this string/"
120
+ it "expect(...).to match" do
121
+ expect("this string").to match(/this string/)
122
+ expect(RSpec::Matchers.generated_description).to eq "should match /this string/"
123
123
  end
124
124
 
125
- it "should raise_error" do
126
- lambda { raise }.should raise_error
127
- RSpec::Matchers.generated_description.should eq "should raise Exception"
125
+ it "expect(...).to raise_error" do
126
+ expect { raise }.to raise_error
127
+ expect(RSpec::Matchers.generated_description).to eq "should raise Exception"
128
128
  end
129
129
 
130
- it "should raise_error with type" do
131
- lambda { raise }.should raise_error(RuntimeError)
132
- RSpec::Matchers.generated_description.should eq "should raise RuntimeError"
130
+ it "expect(...).to raise_error with type" do
131
+ expect { raise }.to raise_error(RuntimeError)
132
+ expect(RSpec::Matchers.generated_description).to eq "should raise RuntimeError"
133
133
  end
134
134
 
135
- it "should raise_error with type and message" do
136
- lambda { raise "there was an error" }.should raise_error(RuntimeError, "there was an error")
137
- RSpec::Matchers.generated_description.should eq "should raise RuntimeError with \"there was an error\""
135
+ it "expect(...).to raise_error with type and message" do
136
+ expect { raise "there was an error" }.to raise_error(RuntimeError, "there was an error")
137
+ expect(RSpec::Matchers.generated_description).to eq "should raise RuntimeError with \"there was an error\""
138
138
  end
139
139
 
140
- it "should respond_to" do
141
- [].should respond_to(:insert)
142
- RSpec::Matchers.generated_description.should eq "should respond to #insert"
140
+ it "expect(...).to respond_to" do
141
+ expect([]).to respond_to(:insert)
142
+ expect(RSpec::Matchers.generated_description).to eq "should respond to #insert"
143
143
  end
144
144
 
145
- it "should throw symbol" do
146
- lambda { throw :what_a_mess }.should throw_symbol
147
- RSpec::Matchers.generated_description.should eq "should throw a Symbol"
145
+ it "expect(...).to throw symbol" do
146
+ expect { throw :what_a_mess }.to throw_symbol
147
+ expect(RSpec::Matchers.generated_description).to eq "should throw a Symbol"
148
148
  end
149
149
 
150
- it "should throw symbol (with named symbol)" do
151
- lambda { throw :what_a_mess }.should throw_symbol(:what_a_mess)
152
- RSpec::Matchers.generated_description.should eq "should throw :what_a_mess"
150
+ it "expect(...).to throw symbol (with named symbol)" do
151
+ expect { throw :what_a_mess }.to throw_symbol(:what_a_mess)
152
+ expect(RSpec::Matchers.generated_description).to eq "should throw :what_a_mess"
153
153
  end
154
154
 
155
155
  def team
@@ -170,7 +170,7 @@ describe "a Matcher with no description" do
170
170
  end
171
171
 
172
172
  it "provides a helpful message when used in a string-less example block" do
173
- 5.should matcher
174
- RSpec::Matchers.generated_description.should =~ /When you call.*description method/m
173
+ expect(5).to matcher
174
+ expect(RSpec::Matchers.generated_description).to match /When you call.*description method/m
175
175
  end
176
176
  end
@@ -15,15 +15,15 @@ describe "a matcher defined using the matcher DSL" do
15
15
  end
16
16
 
17
17
  RSpec::Matchers.define :be_well do
18
- match { |actual| actual.should be_ok }
18
+ match { |actual| expect(actual).to be_ok }
19
19
  end
20
20
 
21
- ok.should be_well
21
+ expect(ok).to be_well
22
22
  end
23
23
 
24
24
  it "has access to methods available in the scope of the example" do
25
25
  RSpec::Matchers::define(:matcher_a) {}
26
- matcher_a.question?.should eq(:answer)
26
+ expect(matcher_a.question?).to eq(:answer)
27
27
  end
28
28
 
29
29
  it "raises when method is missing from local scope as well as matcher" do
@@ -39,19 +39,19 @@ describe "a matcher defined using the matcher DSL" do
39
39
  end
40
40
  end
41
41
 
42
- 3.should be_just_like(3)
43
- 4.should be_just_like(4)
42
+ expect(3).to be_just_like(3)
43
+ expect(4).to be_just_like(4)
44
44
  end
45
45
 
46
46
  describe "#respond_to?" do
47
47
  it "returns true for methods in example scope" do
48
48
  RSpec::Matchers::define(:matcher_c) {}
49
- matcher_c.should respond_to(:question?)
49
+ expect(matcher_c).to respond_to(:question?)
50
50
  end
51
51
 
52
52
  it "returns false for methods not defined in matcher or example scope" do
53
53
  RSpec::Matchers::define(:matcher_d) {}
54
- matcher_d.should_not respond_to(:i_dont_exist)
54
+ expect(matcher_d).not_to respond_to(:i_dont_exist)
55
55
  end
56
56
  end
57
57
  end