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,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class BasicClassMethod
|
4
|
+
class << self
|
5
|
+
def basic_class_method(arg1, arg2)
|
6
|
+
raise "should never see this"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class FakeBasicClassMethod < Shoegaze::Mock
|
12
|
+
mock "BasicClassMethod"
|
13
|
+
|
14
|
+
implement_class_method :basic_class_method do
|
15
|
+
scenario :good do
|
16
|
+
datasource do |arg1, arg2|
|
17
|
+
:perfect_socks
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
scenario :bad do
|
22
|
+
datasource do |arg1, arg2|
|
23
|
+
:terrible_socks
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe FakeBasicClassMethod do
|
30
|
+
let!(:mock){ FakeBasicClassMethod.proxy }
|
31
|
+
|
32
|
+
describe "good scenario" do
|
33
|
+
let!(:args){ [:wool, :cotton] }
|
34
|
+
|
35
|
+
before do
|
36
|
+
FakeBasicClassMethod.class_call(:basic_class_method).with(*args).yields(:good)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "runs the :good scenario datasource" do
|
40
|
+
expect(mock.basic_class_method(*args)).to eq(:perfect_socks)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "bad scenario" do
|
45
|
+
let!(:args){ [:burlap, :fiberglass] }
|
46
|
+
|
47
|
+
before do
|
48
|
+
FakeBasicClassMethod.class_call(:basic_class_method).with(*args).yields(:bad)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "runs the :bad scenario datasource" do
|
52
|
+
expect(mock.basic_class_method(*args)).to eq(:terrible_socks)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class BasicInstanceMethod
|
4
|
+
def basic_instance_method(arg1, arg2)
|
5
|
+
raise "should never see this"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class FakeBasicInstanceMethod < Shoegaze::Mock
|
10
|
+
mock "BasicInstanceMethod"
|
11
|
+
|
12
|
+
implement_instance_method :basic_instance_method do
|
13
|
+
scenario :good do
|
14
|
+
datasource do |arg1, arg2|
|
15
|
+
:perfect_socks
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
scenario :bad do
|
20
|
+
datasource do |arg1, arg2|
|
21
|
+
:terrible_socks
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe FakeBasicInstanceMethod do
|
28
|
+
let!(:mock){ FakeBasicInstanceMethod.proxy }
|
29
|
+
|
30
|
+
describe "good scenario" do
|
31
|
+
let!(:args){ [:wool, :cotton] }
|
32
|
+
|
33
|
+
before do
|
34
|
+
FakeBasicInstanceMethod.instance_call(:basic_instance_method).with(*args).yields(:good)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "runs the :good scenario datasource" do
|
38
|
+
expect(mock.new.basic_instance_method(*args)).to eq(:perfect_socks)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "bad scenario" do
|
43
|
+
let!(:args){ [:burlap, :fiberglass] }
|
44
|
+
|
45
|
+
before do
|
46
|
+
FakeBasicInstanceMethod.instance_call(:basic_instance_method).with(*args).yields(:bad)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "runs the :bad scenario datasource" do
|
50
|
+
expect(mock.new.basic_instance_method(*args)).to eq(:terrible_socks)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class ClassDefaultScenario
|
4
|
+
class << self
|
5
|
+
def basic_class_method(arg1, arg2)
|
6
|
+
raise "should never see this"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class FakeClassDefaultScenario < Shoegaze::Mock
|
12
|
+
mock "ClassDefaultScenario"
|
13
|
+
|
14
|
+
implement_class_method :basic_class_method do
|
15
|
+
default do
|
16
|
+
datasource do |arg1, arg2|
|
17
|
+
:perfect_socks
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
scenario :bad do
|
22
|
+
datasource do |arg1, arg2|
|
23
|
+
:terrible_socks
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe FakeClassDefaultScenario do
|
30
|
+
let!(:mock){ FakeClassDefaultScenario.proxy }
|
31
|
+
|
32
|
+
describe "with no specific scenario orchestrated and a default scenario implemented" do
|
33
|
+
let!(:args){ [:wool, :cotton] }
|
34
|
+
|
35
|
+
it "the :default scenario is run" do
|
36
|
+
expect(mock.basic_class_method(*args)).to eq(:perfect_socks)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "with the bad scenario orchestrated" do
|
41
|
+
let!(:args){ [:burlap, :fiberglass] }
|
42
|
+
|
43
|
+
before do
|
44
|
+
FakeClassDefaultScenario.class_call(:basic_class_method).with(*args).yields(:bad)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "runs the :bad scenario datasource" do
|
48
|
+
expect(mock.basic_class_method(*args)).to eq(:terrible_socks)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class BlockClassMethod
|
4
|
+
class << self
|
5
|
+
def class_method_that_takes_a_block(&block)
|
6
|
+
block.call + " the grass"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class FakeBlockClassMethod < Shoegaze::Mock
|
12
|
+
mock "BlockClassMethod"
|
13
|
+
|
14
|
+
implement_class_method :class_method_that_takes_a_block do
|
15
|
+
default do
|
16
|
+
datasource do |*args, &block|
|
17
|
+
block.call + " my hair"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
scenario :cheesy do
|
22
|
+
datasource do |*args, &block|
|
23
|
+
block.call + " the cheese"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe FakeBlockClassMethod do
|
30
|
+
let!(:mock){ FakeBlockClassMethod.proxy }
|
31
|
+
|
32
|
+
describe "good scenario" do
|
33
|
+
let!(:block) do
|
34
|
+
proc do
|
35
|
+
"Cut"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
it "runs the default scenario datasource, passing in the block" do
|
40
|
+
result = mock.class_method_that_takes_a_block(&block)
|
41
|
+
expect(result).to eq("Cut my hair")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "cheesy scenario" do
|
46
|
+
let!(:block) do
|
47
|
+
proc do
|
48
|
+
"Cut"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
before do
|
53
|
+
FakeBlockClassMethod.class_call(:class_method_that_takes_a_block).with(no_args).yields(:cheesy)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "runs the :cheesy scenario datasource, passing in the block" do
|
57
|
+
result = mock.class_method_that_takes_a_block(&block)
|
58
|
+
expect(result).to eq("Cut the cheese")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class DataStoreMethod
|
4
|
+
class << self
|
5
|
+
def create_sock(sock_data)
|
6
|
+
raise "should never see this"
|
7
|
+
end
|
8
|
+
|
9
|
+
def find_sock(sock_id)
|
10
|
+
raise "should never see this"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class SockRepresenter < Representable::Decorator
|
16
|
+
include Representable::JSON
|
17
|
+
|
18
|
+
property :id
|
19
|
+
property :created_at
|
20
|
+
property :material, exec_context: :decorator
|
21
|
+
|
22
|
+
def material
|
23
|
+
represented.material.reverse
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class FakeDataStoreMethod < Shoegaze::Mock
|
28
|
+
extend Shoegaze::Datastore
|
29
|
+
|
30
|
+
mock "DataStoreMethod"
|
31
|
+
|
32
|
+
datastore :Sock do
|
33
|
+
id{ (Random.rand * 100).ceil }
|
34
|
+
material{ [:wool, :carpet, :seal_whiskers].sample }
|
35
|
+
created_at{ Time.now }
|
36
|
+
end
|
37
|
+
|
38
|
+
implement_class_method :create_sock do
|
39
|
+
default do
|
40
|
+
representer SockRepresenter
|
41
|
+
represent_method :as_json
|
42
|
+
|
43
|
+
datasource do |sock_data|
|
44
|
+
FactoryBot.create("fake_data_store_method/sock", sock_data)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
implement_class_method :find_sock do
|
50
|
+
default do
|
51
|
+
representer SockRepresenter
|
52
|
+
represent_method :as_json
|
53
|
+
|
54
|
+
datasource do |id|
|
55
|
+
Sock.find(id)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe FakeDataStoreMethod do
|
62
|
+
let!(:mock){ FakeDataStoreMethod.proxy }
|
63
|
+
|
64
|
+
describe "persistence" do
|
65
|
+
it "can store and retrieve objects from the datastore" do
|
66
|
+
created_sock_data = mock.create_sock({:material => "latex"})
|
67
|
+
expect(created_sock_data["material"]).to eq("xetal")
|
68
|
+
|
69
|
+
found_sock_data = mock.find_sock(created_sock_data["id"])
|
70
|
+
expect(created_sock_data).to eq(found_sock_data)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class InstanceWithInitializer
|
4
|
+
def initialize(_arg1, _arg2)
|
5
|
+
raise "should not see this because we're mocking it"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class FakeInstanceWithInitializer < Shoegaze::Mock
|
10
|
+
mock "InstanceWithInitializer"
|
11
|
+
end
|
12
|
+
|
13
|
+
describe FakeInstanceWithInitializer do
|
14
|
+
let!(:mock){ FakeInstanceWithInitializer.proxy }
|
15
|
+
|
16
|
+
describe "mock a class with an initializer that takes arguments" do
|
17
|
+
it "supports instantiation" do
|
18
|
+
# we just want to prove that mocks based on objects with initializers can be
|
19
|
+
# instantiated
|
20
|
+
instance = mock.new("arg1", "arg2")
|
21
|
+
expect(instance).to be_kind_of Shoegaze::Proxy::Template
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class InstanceDefaultScenario
|
4
|
+
def basic_instance_method(arg1, arg2)
|
5
|
+
raise "should never see this"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class FakeInstanceDefaultScenario < Shoegaze::Mock
|
10
|
+
mock "InstanceDefaultScenario"
|
11
|
+
|
12
|
+
implement_instance_method :basic_instance_method do
|
13
|
+
default do
|
14
|
+
datasource do |arg1, arg2|
|
15
|
+
:perfect_socks
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
scenario :bad do
|
20
|
+
datasource do |arg1, arg2|
|
21
|
+
:terrible_socks
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe FakeInstanceDefaultScenario do
|
28
|
+
let!(:mock){ FakeInstanceDefaultScenario.proxy }
|
29
|
+
|
30
|
+
describe "with no specific scenario orchestrated and a default scenario implemented" do
|
31
|
+
let!(:args){ [:wool, :cotton] }
|
32
|
+
|
33
|
+
it "the :default scenario is run" do
|
34
|
+
instance = mock.new
|
35
|
+
|
36
|
+
expect(instance.basic_instance_method(*args)).to eq(:perfect_socks)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "with the bad scenario orchestrated" do
|
41
|
+
let!(:args){ [:burlap, :fiberglass] }
|
42
|
+
|
43
|
+
before do
|
44
|
+
FakeInstanceDefaultScenario.instance_call(:basic_instance_method).with(*args).yields(:bad)
|
45
|
+
end
|
46
|
+
|
47
|
+
it "runs the :bad scenario datasource" do
|
48
|
+
expect(mock.new.basic_instance_method(*args)).to eq(:terrible_socks)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class BlockInstanceMethod
|
4
|
+
def instance_method_that_takes_a_block(&block)
|
5
|
+
block.call + " the grass"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class FakeBlockInstanceMethod < Shoegaze::Mock
|
10
|
+
mock "BlockInstanceMethod"
|
11
|
+
|
12
|
+
implement_instance_method :instance_method_that_takes_a_block do
|
13
|
+
default do
|
14
|
+
datasource do |*args, &block|
|
15
|
+
block.call + " my hair"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
scenario :cheesy do
|
20
|
+
datasource do |*args, &block|
|
21
|
+
block.call + " the cheese"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe FakeBlockInstanceMethod do
|
28
|
+
let!(:mock){ FakeBlockInstanceMethod.proxy }
|
29
|
+
|
30
|
+
describe "default scenario" do
|
31
|
+
let!(:block) do
|
32
|
+
proc do
|
33
|
+
"Cut"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
it "runs the default scenario datasource, passing in the block" do
|
38
|
+
result = mock.new.instance_method_that_takes_a_block(&block)
|
39
|
+
expect(result).to eq("Cut my hair")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "cheesy scenario" do
|
44
|
+
let!(:block) do
|
45
|
+
proc do
|
46
|
+
"Cut"
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
before do
|
51
|
+
FakeBlockInstanceMethod.instance_call(:instance_method_that_takes_a_block).with(no_args).yields(:cheesy)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "runs the :cheesy scenario datasource, passing in the block" do
|
55
|
+
result = mock.new.instance_method_that_takes_a_block(&block)
|
56
|
+
|
57
|
+
expect(result).to eq("Cut the cheese")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class NestedClassMethodSubclass
|
4
|
+
def self.another_class_method(arg1, arg2)
|
5
|
+
raise "should never see this"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
class NestedClassMethod
|
10
|
+
def self.nested_class_method(arg1, arg2)
|
11
|
+
return NestedClassMethodSubclass.new(*args)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class FakeNestedClassMethod < Shoegaze::Mock
|
16
|
+
mock "NestedClassMethod"
|
17
|
+
|
18
|
+
implement_class_method :nested_class_method do
|
19
|
+
scenario :good do
|
20
|
+
datasource do |arg1, arg2|
|
21
|
+
implement :another_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 FakeNestedClassMethod do
|
34
|
+
let!(:mock){ FakeNestedClassMethod.proxy }
|
35
|
+
|
36
|
+
describe "good scenario" do
|
37
|
+
let!(:args){ [:wool, :cotton] }
|
38
|
+
|
39
|
+
before do
|
40
|
+
FakeNestedClassMethod.class_call(:nested_class_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.nested_class_method(*args).another_method).to eq(:perfect_socks)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|