shoegaze 1.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.
- 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
|