Smarter failed pre-conditions
[gitorious:use_case.git] / test / use_case_test.rb
1 # encoding: utf-8
2 # --
3 # The MIT License (MIT)
4 #
5 # Copyright (C) 2013 Gitorious AS
6 #
7 # Permission is hereby granted, free of charge, to any person obtaining a copy
8 # of this software and associated documentation files (the "Software"), to deal
9 # in the Software without restriction, including without limitation the rights
10 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 # copies of the Software, and to permit persons to whom the Software is
12 # furnished to do so, subject to the following conditions:
13 #
14 # The above copyright notice and this permission notice shall be included in all
15 # copies or substantial portions of the Software.
16 #
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 # SOFTWARE.
24 #++
25 require "test_helper"
26 require "use_case"
27 require "sample_use_case"
28
29 describe UseCase do
30   before do
31     @logged_in_user = User.new(42, "Christian")
32     @logged_in_user.can_admin = true
33   end
34
35   it "fails first pre-condition; no user logged in" do
36     outcome = CreateRepository.new(nil).execute({})
37
38     outcome.pre_condition_failed do |f|
39       assert_equal UserLoggedInPrecondition, f.pre_condition.class
40     end
41   end
42
43   it "fails second pre-condition; user cannot admin" do
44     @logged_in_user.can_admin = false
45     outcome = CreateRepository.new(@logged_in_user).execute({})
46
47     outcome.pre_condition_failed do |f|
48       assert_equal ProjectAdminPrecondition, f.pre_condition.class
49     end
50   end
51
52   it "fails with error if pre-condition raises" do
53     def @logged_in_user.id; raise "Oops!"; end
54     outcome = CreateRepository.new(@logged_in_user).execute({})
55
56     outcome.pre_condition_failed do |f|
57       assert_equal RuntimeError, f.pre_condition.class
58     end
59   end
60
61   it "fails on input validation" do
62     outcome = CreateRepository.new(@logged_in_user).execute({})
63
64     validation = outcome.failure do |v|
65       refute v.valid?
66       assert_equal 1, v.errors.count
67       assert v.errors[:name]
68     end
69
70     refute_nil validation
71   end
72
73   it "executes command" do
74     outcome = CreateRepository.new(@logged_in_user).execute({ :name => "My repository" })
75
76     result = outcome.success do |res|
77       assert_equal "My repository", res.name
78       assert res.is_a?(Repository)
79     end
80
81     refute_nil result
82   end
83
84   it "raises if command raises" do
85     use_case = ExplodingRepository.new(@logged_in_user)
86
87     assert_raises RuntimeError do
88       use_case.execute(nil)
89     end
90   end
91
92   it "fails when builder processed inputs fail validation" do
93     outcome = CreateRepositoryWithBuilder.new(@logged_in_user).execute({ :name => "invalid" })
94
95     validation = outcome.failure do |v|
96       refute v.valid?
97       assert_equal 1, v.errors.count
98       assert v.errors[:name]
99     end
100
101     refute_nil validation
102   end
103
104   it "passes builder processed inputs to command" do
105     outcome = CreateRepositoryWithBuilder.new(@logged_in_user).execute({ :name => "Dude" })
106
107     assert outcome.success?, outcome.failure && outcome.failure.full_messages.join("\n")
108     assert_equal "Dude!", outcome.result.name
109   end
110
111   it "treats builder error as failed pre-condition" do
112     outcome = CreateRepositoryWithExplodingBuilder.new(@logged_in_user).execute({ :name => "Dude" })
113
114     assert outcome.pre_condition_failed?
115   end
116
117   it "chains two commands" do
118     outcome = CreatePimpedRepository.new(@logged_in_user).execute({ :name => "Mr" })
119
120     assert_equal 1349, outcome.result.id
121     assert_equal "Mr (Pimped)", outcome.result.name
122   end
123
124   it "chains two commands with individual builders" do
125     outcome = CreatePimpedRepository2.new(@logged_in_user).execute({ :name => "Mr" })
126
127     assert_equal 42, outcome.result.id
128     assert_equal "Mr! (Pimped)", outcome.result.name
129   end
130
131   it "fails one of three validators" do
132     outcome = CreatePimpedRepository3.new(@logged_in_user).execute({ :name => "Mr" })
133
134     refute outcome.success?
135     assert_equal "You cannot win", outcome.failure.errors[:name].join
136   end
137
138   it "calls command lambda" do
139     outcome = InlineCommand.new.execute({ :name => "Dissection" })
140
141     assert outcome.success?
142     assert_equal "Dissection", outcome.result
143   end
144
145   it "implicitly uses command as builder" do
146     outcome = ImplicitBuilder.new(@logged_in_user).execute({ :name => "Mr" })
147
148     assert_equal 42, outcome.result.id
149     assert_equal "Mr! (Pimped)", outcome.result.name
150   end
151 end