shoegaze 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +190 -0
- data/lib/shoegaze.rb +15 -0
- data/lib/shoegaze/datastore.rb +36 -0
- data/lib/shoegaze/implementation.rb +71 -0
- data/lib/shoegaze/mock.rb +34 -0
- data/lib/shoegaze/model.rb +165 -0
- data/lib/shoegaze/proxy.rb +24 -0
- data/lib/shoegaze/proxy/interface.rb +169 -0
- data/lib/shoegaze/proxy/template.rb +61 -0
- data/lib/shoegaze/scenario.rb +100 -0
- data/lib/shoegaze/scenario/mock.rb +52 -0
- data/lib/shoegaze/scenario/orchestrator.rb +167 -0
- data/lib/shoegaze/version.rb +3 -0
- data/spec/features/basic_class_method_spec.rb +55 -0
- data/spec/features/basic_instance_method_spec.rb +53 -0
- data/spec/features/class_default_scenario_spec.rb +51 -0
- data/spec/features/class_method_block_argument_spec.rb +61 -0
- data/spec/features/data_store_spec.rb +73 -0
- data/spec/features/instance_customized_initializer.rb +24 -0
- data/spec/features/instance_default_scenario_spec.rb +51 -0
- data/spec/features/instance_method_block_argument_spec.rb +60 -0
- data/spec/features/nested_class_method_spec.rb +47 -0
- data/spec/features/nested_instance_method_spec.rb +47 -0
- data/spec/shoegaze/datastore_spec.rb +38 -0
- data/spec/shoegaze/implementation_spec.rb +97 -0
- data/spec/shoegaze/mock_spec.rb +42 -0
- data/spec/shoegaze/proxy/interface_spec.rb +88 -0
- data/spec/shoegaze/proxy/template_spec.rb +36 -0
- data/spec/shoegaze/proxy_spec.rb +18 -0
- data/spec/shoegaze/scenario/mock_spec.rb +31 -0
- data/spec/shoegaze/scenario/orchestrator_spec.rb +145 -0
- data/spec/shoegaze/scenario_spec.rb +74 -0
- metadata +133 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class NestedInstanceMethodSubclass
|
4
|
+
def another_instance_method(arg1, arg2)
|
5
|
+
raise "should never see this"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class NestedInstanceMethod
|
10
|
+
def nested_instance_method(arg1, arg2)
|
11
|
+
return NestedInstanceMethodSubclass.new(*args)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class FakeNestedInstanceMethod < Shoegaze::Mock
|
16
|
+
mock "NestedInstanceMethod"
|
17
|
+
|
18
|
+
implement_instance_method :nested_instance_method do
|
19
|
+
scenario :good do
|
20
|
+
datasource do |arg1, arg2|
|
21
|
+
implement :another_instance_method do
|
22
|
+
default do
|
23
|
+
datasource do
|
24
|
+
:perfect_socks
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe FakeNestedInstanceMethod do
|
34
|
+
let!(:mock){ FakeNestedInstanceMethod.proxy }
|
35
|
+
|
36
|
+
describe "good scenario" do
|
37
|
+
let!(:args){ [:wool, :cotton] }
|
38
|
+
|
39
|
+
before do
|
40
|
+
FakeNestedInstanceMethod.instance_call(:nested_instance_method).with(*args).yields(:good)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "runs the :good scenario datasource and chains into its nested scenario" do
|
44
|
+
expect(mock.new.nested_instance_method(*args).another_instance_method).to eq(:perfect_socks)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoegaze::Datastore do
|
4
|
+
include SpecHelpers
|
5
|
+
|
6
|
+
before :all do
|
7
|
+
@klass = random_named_class
|
8
|
+
@klass.extend(Shoegaze::Datastore)
|
9
|
+
|
10
|
+
@klass.datastore("Pony") do
|
11
|
+
id { 123 }
|
12
|
+
hoofs { 5 }
|
13
|
+
name { "Jeff" }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#datastore" do
|
18
|
+
let!(:created_class){ @klass.const_get("Pony") }
|
19
|
+
|
20
|
+
describe "created model class" do
|
21
|
+
it "creates a TopModel class with the specified name inside the class' namespace" do
|
22
|
+
expect(created_class.ancestors[1]).to eq Shoegaze::Model
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "factory" do
|
27
|
+
let!(:model_instance) do
|
28
|
+
FactoryBot.create(created_class.name.underscore, id: 5, name: "Carlos")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "creates persisted instances" do
|
32
|
+
expect(model_instance.hoofs).to eq(5)
|
33
|
+
expect(model_instance.name).to eq("Carlos")
|
34
|
+
expect(created_class.find(5)).to eq(model_instance)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoegaze::Implementation do
|
4
|
+
include ImplementationSpecHelpers
|
5
|
+
|
6
|
+
let!(:subject){ Shoegaze::Implementation }
|
7
|
+
let!(:mock_class){ double }
|
8
|
+
|
9
|
+
let!(:mock_double) do
|
10
|
+
mock_double = double
|
11
|
+
|
12
|
+
Shoegaze::Mock.send(:extend_double_with_extra_methods, mock_double)
|
13
|
+
mock_double
|
14
|
+
end
|
15
|
+
|
16
|
+
let!(:scope){ :instance }
|
17
|
+
let!(:method_name){ :bicycle }
|
18
|
+
let!(:implementation){ subject.new(mock_class, mock_double, scope, method_name){} }
|
19
|
+
|
20
|
+
describe "#initialize" do
|
21
|
+
describe "instance variables" do
|
22
|
+
it "are assigned" do
|
23
|
+
expect(implementation.instance_variable_get(:@_mock_class)).to eq(mock_class)
|
24
|
+
expect(implementation.instance_variable_get(:@_mock_double)).to eq(mock_double)
|
25
|
+
expect(implementation.instance_variable_get(:@_scope)).to eq(scope)
|
26
|
+
expect(implementation.instance_variable_get(:@_method_name)).to eq(method_name)
|
27
|
+
expect(implementation.instance_variable_get(:@scenarios)).to eq({})
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "block" do
|
32
|
+
it "is called in the scope of the implementation instance" do
|
33
|
+
expect_any_instance_of(subject).to receive(:booyah)
|
34
|
+
subject.new(mock_class, mock_double, scope, method_name){ booyah }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "#scenario" do
|
40
|
+
let!(:fake_block){ proc { } }
|
41
|
+
let!(:fake_scenario){ double }
|
42
|
+
|
43
|
+
it "creates a Scenario with the method name and the block, keyed as the scenario name within scenarios" do
|
44
|
+
expect(Shoegaze::Scenario).to receive(:new).with(method_name) do |name, &block|
|
45
|
+
expect(block).to eq(fake_block)
|
46
|
+
expect(name).to eq(method_name)
|
47
|
+
|
48
|
+
fake_scenario
|
49
|
+
end
|
50
|
+
|
51
|
+
implementation.scenario(:dude_wheres_my_car, &fake_block)
|
52
|
+
|
53
|
+
scenario = implementation.scenarios[:dude_wheres_my_car]
|
54
|
+
expect(scenario).to eq(fake_scenario)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "#default" do
|
59
|
+
let!(:fake_block){ proc { } }
|
60
|
+
let!(:fake_scenario){ double }
|
61
|
+
let!(:fake_scenario_orchestrator){ double }
|
62
|
+
let!(:fake_method_args){ ["chainring", "braze-on"] }
|
63
|
+
|
64
|
+
before :each do
|
65
|
+
allow(mock_double).to receive(:define_method)
|
66
|
+
allow(Shoegaze::Scenario).to receive(:new).with(method_name).and_return(fake_scenario)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "creates a Scenario with the method name and the block, keyed as :default within scenarios" do
|
70
|
+
expect(Shoegaze::Scenario).to receive(:new).with(method_name) do |name, &block|
|
71
|
+
expect(block).to eq(fake_block)
|
72
|
+
expect(name).to eq(method_name)
|
73
|
+
|
74
|
+
fake_scenario
|
75
|
+
end
|
76
|
+
|
77
|
+
implementation.default(&fake_block)
|
78
|
+
|
79
|
+
scenario = implementation.scenarios[:default]
|
80
|
+
expect(scenario).to eq(fake_scenario)
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "with an :instance scope" do
|
84
|
+
it "creates a named method that ultimately triggers :execute_scenario on a Scenario::Orchestrator" do
|
85
|
+
expect_default_scenario_to_be_defined_for_scope(scope)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
describe "with a :class scope" do
|
90
|
+
let!(:scope){ :class }
|
91
|
+
|
92
|
+
it "creates a named singleton method that ultimately triggers :execute_scenario on a Scenario::Orchestrator" do
|
93
|
+
expect_default_scenario_to_be_defined_for_scope(scope)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoegaze::Mock do
|
4
|
+
include SpecHelpers
|
5
|
+
|
6
|
+
subject{ Shoegaze::Mock }
|
7
|
+
|
8
|
+
describe "included modules" do
|
9
|
+
it "includes Proxy::Interface" do
|
10
|
+
expect(subject).to respond_to :implement_class_method
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#self.mock" do
|
15
|
+
let!(:test_class){ random_named_class }
|
16
|
+
let!(:mocked){ subject.mock(test_class.name) }
|
17
|
+
|
18
|
+
it "sets empty implementations" do
|
19
|
+
expect(Shoegaze::Mock.implementations).to eq({class: {}, instance: {}})
|
20
|
+
end
|
21
|
+
|
22
|
+
it "creates class and instance doubles of the provided class" do
|
23
|
+
# hork
|
24
|
+
expect(
|
25
|
+
Shoegaze::Mock.instance_variable_get(:@mock_class_double).
|
26
|
+
instance_variable_get(:@doubled_module).
|
27
|
+
instance_variable_get(:@const_name)
|
28
|
+
).to eq(test_class.name)
|
29
|
+
|
30
|
+
expect(
|
31
|
+
Shoegaze::Mock.instance_variable_get(:@mock_instance_double).
|
32
|
+
instance_variable_get(:@doubled_module).
|
33
|
+
instance_variable_get(:@const_name)
|
34
|
+
).to eq(test_class.name)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "returns a mock proxy anonymous class" do
|
38
|
+
expect(mocked).to respond_to :class_double
|
39
|
+
expect(mocked).to respond_to :instance_double
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoegaze::Proxy::Interface do
|
4
|
+
include SpecHelpers
|
5
|
+
|
6
|
+
let!(:test_class){ random_named_class }
|
7
|
+
let!(:method_name){ :jiu_jitsu }
|
8
|
+
let!(:test_block){ proc { } }
|
9
|
+
let!(:mock_class_double){ double }
|
10
|
+
let!(:mock_instance_double){ double }
|
11
|
+
let!(:fake_implementation){ double }
|
12
|
+
|
13
|
+
before do
|
14
|
+
test_class.include(Shoegaze::Proxy::Interface)
|
15
|
+
test_class.instance_variable_set(:@mock_class_double, mock_class_double)
|
16
|
+
test_class.instance_variable_set(:@mock_instance_double, mock_instance_double)
|
17
|
+
test_class.instance_variable_set(:@implementations, {class: {}, instance: {}})
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#self.implement_class_method" do
|
21
|
+
it "stores a class implementation keyed by the method name" do
|
22
|
+
expect(Shoegaze::Implementation).to receive(:new).with(test_class, mock_class_double, :class, method_name) do |*args, &block|
|
23
|
+
expect(block).to eq(test_block)
|
24
|
+
|
25
|
+
fake_implementation
|
26
|
+
end
|
27
|
+
|
28
|
+
test_class.implement_class_method(method_name, &test_block)
|
29
|
+
expect(test_class.implementations[:class][method_name]).to eq(fake_implementation)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "#self.implement_instance_method" do
|
34
|
+
it "stores an instance implementation keyed by the method name" do
|
35
|
+
expect(Shoegaze::Implementation).to receive(:new).with(test_class, mock_instance_double, :instance, method_name) do |*args, &block|
|
36
|
+
expect(block).to eq(test_block)
|
37
|
+
|
38
|
+
fake_implementation
|
39
|
+
end
|
40
|
+
|
41
|
+
test_class.implement_instance_method(method_name, &test_block)
|
42
|
+
expect(test_class.implementations[:instance][method_name]).to eq(fake_implementation)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#self.implement" do
|
47
|
+
it "is an alias of :implement_instance_method" do
|
48
|
+
expect(test_class.method(:implement)).to eq(test_class.method(:implement_instance_method))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "#self.instance_call" do
|
53
|
+
let!(:fake_scenario_orchestrator){ double }
|
54
|
+
|
55
|
+
it "returns an instance Scenario::Orchestrator" do
|
56
|
+
expect(Shoegaze::Scenario::Orchestrator).to receive(:new).with(test_class, mock_instance_double, :instance, method_name).and_return(fake_scenario_orchestrator)
|
57
|
+
expect(test_class.instance_call(method_name)).to eq(fake_scenario_orchestrator)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#self.class_call" do
|
62
|
+
let!(:fake_scenario_orchestrator){ double }
|
63
|
+
|
64
|
+
it "returns a class Scenario::Orchestrator" do
|
65
|
+
expect(Shoegaze::Scenario::Orchestrator).to receive(:new).with(test_class, mock_class_double, :class, method_name).and_return(fake_scenario_orchestrator)
|
66
|
+
expect(test_class.class_call(method_name)).to eq(fake_scenario_orchestrator)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#self.calling" do
|
71
|
+
it "is an alias to :instance_call" do
|
72
|
+
expect(test_class.method(:calling)).to eq(test_class.method(:instance_call))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "#self.proxy" do
|
77
|
+
let!(:fake_proxy){ double }
|
78
|
+
|
79
|
+
it "returns and caches a Shoegaze::Proxy" do
|
80
|
+
expect(Shoegaze::Proxy).to receive(:new).with(mock_class_double, mock_instance_double).and_return(fake_proxy)
|
81
|
+
expect(test_class.proxy).to eq(fake_proxy)
|
82
|
+
|
83
|
+
# test caching
|
84
|
+
allow(Shoegaze::Proxy).to receive(:new).with(mock_class_double, mock_instance_double).and_return(:should_not_see_this)
|
85
|
+
expect(test_class.proxy).to eq(fake_proxy)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoegaze::Proxy::Template do
|
4
|
+
let!(:instance_double) do
|
5
|
+
mock_double = double
|
6
|
+
|
7
|
+
Shoegaze::Mock.send(:extend_double_with_extra_methods, mock_double)
|
8
|
+
mock_double
|
9
|
+
end
|
10
|
+
|
11
|
+
let!(:class_double) do
|
12
|
+
mock_double = double
|
13
|
+
|
14
|
+
Shoegaze::Mock.send(:extend_double_with_extra_methods, mock_double)
|
15
|
+
mock_double
|
16
|
+
end
|
17
|
+
|
18
|
+
before :each do
|
19
|
+
Shoegaze::Proxy::Template.class_double = class_double
|
20
|
+
Shoegaze::Proxy::Template.instance_double = instance_double
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "instance method calls" do
|
24
|
+
it "get delegated to the instance double" do
|
25
|
+
expect(instance_double).to receive(:rights).and_return(:liberties)
|
26
|
+
expect(Shoegaze::Proxy::Template.new.rights).to eq(:liberties)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "class method calls" do
|
31
|
+
it "get delegated to the class double" do
|
32
|
+
expect(class_double).to receive(:government).and_return(:nothing_of_value)
|
33
|
+
expect(Shoegaze::Proxy::Template.government).to eq(:nothing_of_value)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoegaze::Proxy do
|
4
|
+
describe "#new" do
|
5
|
+
let!(:mock_class_double){ double }
|
6
|
+
let!(:mock_instance_double){ double }
|
7
|
+
let!(:proxy){ Shoegaze::Proxy.new(mock_class_double, mock_instance_double) }
|
8
|
+
|
9
|
+
it "returns a new anonymous class inherited from Shoegaze::Proxy::Template" do
|
10
|
+
expect(proxy.ancestors[1]).to eq(Shoegaze::Proxy::Template)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "sets the proxy class and instance doubles" do
|
14
|
+
expect(proxy.class_double).to eq(mock_class_double)
|
15
|
+
expect(proxy.instance_double).to eq(mock_instance_double)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoegaze::Scenario::Mock do
|
4
|
+
include SpecHelpers
|
5
|
+
|
6
|
+
subject{ Shoegaze::Scenario::Mock }
|
7
|
+
|
8
|
+
describe "included modules" do
|
9
|
+
it "includes Proxy::Interface" do
|
10
|
+
expect(subject).to respond_to :implement_class_method
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "#self.mock" do
|
15
|
+
let!(:mocked){ subject.mock }
|
16
|
+
|
17
|
+
it "sets empty implementations" do
|
18
|
+
expect(Shoegaze::Scenario::Mock.implementations).to eq({class: {}, instance: {}})
|
19
|
+
end
|
20
|
+
|
21
|
+
it "creates class and instance doubles" do
|
22
|
+
expect(Shoegaze::Scenario::Mock.instance_variable_get(:@mock_class_double)).to be_a RSpec::Mocks::Double
|
23
|
+
expect(Shoegaze::Scenario::Mock.instance_variable_get(:@mock_instance_double)).to be_a RSpec::Mocks::Double
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns a mock proxy anonymous class" do
|
27
|
+
expect(mocked).to respond_to :class_double
|
28
|
+
expect(mocked).to respond_to :instance_double
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Shoegaze::Scenario::Orchestrator do
|
4
|
+
include SpecHelpers
|
5
|
+
|
6
|
+
let!(:scope){ :instance }
|
7
|
+
let!(:mock_class){ double }
|
8
|
+
let!(:mock_double){ double }
|
9
|
+
let!(:method_name){ :techno_viking }
|
10
|
+
let!(:scenario_orchestrator){ Shoegaze::Scenario::Orchestrator.new(mock_class, mock_double, scope, method_name) }
|
11
|
+
|
12
|
+
describe "#initialize" do
|
13
|
+
it "sets instance variables" do
|
14
|
+
expect(scenario_orchestrator.instance_variable_get(:@_scope)).to eq(scope)
|
15
|
+
expect(scenario_orchestrator.instance_variable_get(:@_mock_class)).to eq(mock_class)
|
16
|
+
expect(scenario_orchestrator.instance_variable_get(:@_mock_double)).to eq(mock_double)
|
17
|
+
expect(scenario_orchestrator.instance_variable_get(:@_method_name)).to eq(method_name)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#with" do
|
22
|
+
let!(:args){ [:boy, :howdy] }
|
23
|
+
|
24
|
+
it "sets the args and returns self" do
|
25
|
+
expect(scenario_orchestrator.with(*args)).to eq(scenario_orchestrator)
|
26
|
+
expect(scenario_orchestrator.instance_variable_get(:@_args)).to eq(args)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "#yields" do
|
31
|
+
let!(:test_class){
|
32
|
+
random_named_class do
|
33
|
+
def self.techno_viking(arg1, arg2)
|
34
|
+
end
|
35
|
+
|
36
|
+
def techno_viking(arg1, arg2)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
}
|
40
|
+
let!(:args){ [:one, :two] }
|
41
|
+
let!(:scenario_name){ :invisible_pickles }
|
42
|
+
let!(:fake_scenario){ double }
|
43
|
+
let!(:fake_implementation){ double(scenarios: {invisible_pickles: fake_scenario}) }
|
44
|
+
|
45
|
+
describe "for an instance" do
|
46
|
+
let!(:mock_double){ instance_double(test_class.name) }
|
47
|
+
let!(:scenario_orchestrator){ Shoegaze::Scenario::Orchestrator.new(mock_class, mock_double, :instance, method_name) }
|
48
|
+
|
49
|
+
describe "with a scenario" do
|
50
|
+
before :each do
|
51
|
+
allow(mock_class).to receive(:implementations).and_return(
|
52
|
+
{instance: {techno_viking: fake_implementation}}
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "sets up the specific scenario with rspec" do
|
57
|
+
scenario_orchestrator.with(*args).yields(scenario_name)
|
58
|
+
|
59
|
+
expect(scenario_orchestrator).to receive(:execute_scenario).with(fake_scenario)
|
60
|
+
mock_double.send(:techno_viking, *args)
|
61
|
+
|
62
|
+
expect{
|
63
|
+
mock_double.send(:techno_viking, :wrong, :args)
|
64
|
+
}.to raise_exception RSpec::Mocks::MockExpectationError
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "for a class" do
|
69
|
+
let!(:mock_double){ class_double(test_class.name) }
|
70
|
+
let!(:scenario_orchestrator){ Shoegaze::Scenario::Orchestrator.new(mock_class, mock_double, :class, method_name) }
|
71
|
+
|
72
|
+
describe "with a scenario" do
|
73
|
+
before :each do
|
74
|
+
allow(mock_class).to receive(:implementations).and_return(
|
75
|
+
{class: {techno_viking: fake_implementation}}
|
76
|
+
)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "sets up the scenario with rspec" do
|
80
|
+
scenario_orchestrator.with(*args).yields(scenario_name)
|
81
|
+
|
82
|
+
expect(scenario_orchestrator).to receive(:execute_scenario).with(fake_scenario)
|
83
|
+
mock_double.send(:techno_viking, *args)
|
84
|
+
|
85
|
+
expect{
|
86
|
+
mock_double.send(:techno_viking, :wrong, :args)
|
87
|
+
}.to raise_exception RSpec::Mocks::MockExpectationError
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "with no scenario" do
|
94
|
+
let!(:scenario_orchestrator){ Shoegaze::Scenario::Orchestrator.new(mock_class, mock_double, :class, method_name) }
|
95
|
+
let!(:fake_implementation){ double(scenarios: {}) }
|
96
|
+
|
97
|
+
before :each do
|
98
|
+
allow(mock_class).to receive(:implementations).and_return(
|
99
|
+
{class: {techno_viking: fake_implementation}}
|
100
|
+
)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "raises a NoImplementationError" do
|
104
|
+
expect{ scenario_orchestrator.with(*args).yields(scenario_name) }.to raise_exception Shoegaze::Scenario::Orchestrator::NoImplementationError
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
describe "#execute_scenario" do
|
110
|
+
let!(:test_block){ proc { } }
|
111
|
+
let!(:fake_scenario){ double }
|
112
|
+
let!(:fake_args){ [:one, :two] }
|
113
|
+
|
114
|
+
before :each do
|
115
|
+
scenario_orchestrator.with(*fake_args)
|
116
|
+
|
117
|
+
# FIXME: this is a big fugly
|
118
|
+
allow(fake_scenario).to receive(:to_proc).
|
119
|
+
and_return(
|
120
|
+
proc do |*args|
|
121
|
+
raise "bogus" unless args == [:one, :two]
|
122
|
+
|
123
|
+
|
124
|
+
:some_data
|
125
|
+
end
|
126
|
+
)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "runs the block with the args and passes the result to #represent" do
|
130
|
+
expect(scenario_orchestrator).to receive(:represent).with(:some_data, fake_scenario)
|
131
|
+
|
132
|
+
scenario_orchestrator.execute_scenario(fake_scenario)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
describe "#implement" do
|
137
|
+
let!(:proxy_interface){ scenario_orchestrator.send(:proxy_interface) }
|
138
|
+
let!(:test_block){ proc { } }
|
139
|
+
|
140
|
+
it "calls #implement_class_method on the implementation proxy and returns the proxy" do
|
141
|
+
expect(proxy_interface).to receive(:implement_class_method).with(method_name, &test_block)
|
142
|
+
expect(scenario_orchestrator.implement(method_name, &test_block)).to eq(proxy_interface.proxy)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|