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,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
|