shoegaze 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +190 -0
  3. data/lib/shoegaze.rb +15 -0
  4. data/lib/shoegaze/datastore.rb +36 -0
  5. data/lib/shoegaze/implementation.rb +71 -0
  6. data/lib/shoegaze/mock.rb +34 -0
  7. data/lib/shoegaze/model.rb +165 -0
  8. data/lib/shoegaze/proxy.rb +24 -0
  9. data/lib/shoegaze/proxy/interface.rb +169 -0
  10. data/lib/shoegaze/proxy/template.rb +61 -0
  11. data/lib/shoegaze/scenario.rb +100 -0
  12. data/lib/shoegaze/scenario/mock.rb +52 -0
  13. data/lib/shoegaze/scenario/orchestrator.rb +167 -0
  14. data/lib/shoegaze/version.rb +3 -0
  15. data/spec/features/basic_class_method_spec.rb +55 -0
  16. data/spec/features/basic_instance_method_spec.rb +53 -0
  17. data/spec/features/class_default_scenario_spec.rb +51 -0
  18. data/spec/features/class_method_block_argument_spec.rb +61 -0
  19. data/spec/features/data_store_spec.rb +73 -0
  20. data/spec/features/instance_customized_initializer.rb +24 -0
  21. data/spec/features/instance_default_scenario_spec.rb +51 -0
  22. data/spec/features/instance_method_block_argument_spec.rb +60 -0
  23. data/spec/features/nested_class_method_spec.rb +47 -0
  24. data/spec/features/nested_instance_method_spec.rb +47 -0
  25. data/spec/shoegaze/datastore_spec.rb +38 -0
  26. data/spec/shoegaze/implementation_spec.rb +97 -0
  27. data/spec/shoegaze/mock_spec.rb +42 -0
  28. data/spec/shoegaze/proxy/interface_spec.rb +88 -0
  29. data/spec/shoegaze/proxy/template_spec.rb +36 -0
  30. data/spec/shoegaze/proxy_spec.rb +18 -0
  31. data/spec/shoegaze/scenario/mock_spec.rb +31 -0
  32. data/spec/shoegaze/scenario/orchestrator_spec.rb +145 -0
  33. data/spec/shoegaze/scenario_spec.rb +74 -0
  34. metadata +133 -0
@@ -0,0 +1,3 @@
1
+ module Shoegaze
2
+ VERSION = "1.1.0".freeze
3
+ end
@@ -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