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