fixturama 0.1.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +99 -0
  3. data/README.md +76 -4
  4. data/lib/fixturama.rb +48 -20
  5. data/lib/fixturama/changes.rb +72 -0
  6. data/lib/fixturama/changes/base.rb +28 -0
  7. data/lib/fixturama/changes/chain.rb +64 -0
  8. data/lib/fixturama/changes/chain/actions.rb +31 -0
  9. data/lib/fixturama/changes/chain/arguments.rb +59 -0
  10. data/lib/fixturama/changes/chain/raise_action.rb +43 -0
  11. data/lib/fixturama/changes/chain/return_action.rb +33 -0
  12. data/lib/fixturama/changes/const.rb +30 -0
  13. data/lib/fixturama/changes/env.rb +35 -0
  14. data/lib/fixturama/changes/request.rb +91 -0
  15. data/lib/fixturama/changes/request/response.rb +62 -0
  16. data/lib/fixturama/changes/request/responses.rb +22 -0
  17. data/lib/fixturama/changes/seed.rb +39 -0
  18. data/lib/fixturama/config.rb +5 -0
  19. data/lib/fixturama/fixture_error.rb +31 -0
  20. data/lib/fixturama/loader.rb +6 -2
  21. data/lib/fixturama/loader/context.rb +14 -5
  22. data/lib/fixturama/loader/value.rb +1 -0
  23. data/lib/fixturama/version.rb +4 -0
  24. metadata +85 -73
  25. data/.gitignore +0 -12
  26. data/.rspec +0 -2
  27. data/.rubocop.yml +0 -22
  28. data/.travis.yml +0 -17
  29. data/Gemfile +0 -9
  30. data/LICENSE.txt +0 -21
  31. data/Rakefile +0 -6
  32. data/fixturama.gemspec +0 -24
  33. data/lib/fixturama/seed.rb +0 -15
  34. data/lib/fixturama/stubs.rb +0 -79
  35. data/lib/fixturama/stubs/chain.rb +0 -90
  36. data/lib/fixturama/stubs/chain/actions.rb +0 -39
  37. data/lib/fixturama/stubs/chain/actions/raise.rb +0 -21
  38. data/lib/fixturama/stubs/chain/actions/return.rb +0 -23
  39. data/lib/fixturama/stubs/chain/arguments.rb +0 -86
  40. data/lib/fixturama/stubs/const.rb +0 -43
  41. data/lib/fixturama/stubs/request.rb +0 -98
  42. data/lib/fixturama/stubs/request/response.rb +0 -43
  43. data/lib/fixturama/stubs/request/responses.rb +0 -20
  44. data/lib/fixturama/utils.rb +0 -39
  45. data/spec/fixturama/load_fixture/_spec.rb +0 -53
  46. data/spec/fixturama/load_fixture/data.json +0 -5
  47. data/spec/fixturama/load_fixture/data.yaml +0 -3
  48. data/spec/fixturama/load_fixture/data.yml +0 -3
  49. data/spec/fixturama/seed_fixture/_spec.rb +0 -36
  50. data/spec/fixturama/seed_fixture/seed.yml +0 -16
  51. data/spec/fixturama/stub_fixture/_spec.rb +0 -120
  52. data/spec/fixturama/stub_fixture/stub.yml +0 -73
  53. data/spec/spec_helper.rb +0 -26
@@ -1,43 +0,0 @@
1
- module Fixturama
2
- #
3
- # Definition for stubbing a constant
4
- #
5
- class Stubs::Const
6
- attr_reader :const, :value
7
-
8
- #
9
- # Human-readable representation of the chain
10
- # @return [String]
11
- #
12
- def to_s
13
- const.to_s
14
- end
15
- alias to_str to_s
16
- alias key to_s
17
-
18
- #
19
- # Overload the definition for the constant
20
- # @option [Object] value
21
- # @return [self]
22
- #
23
- def update!(value:, **)
24
- @value = value
25
- self
26
- end
27
-
28
- #
29
- # Apply the stub to RSpec example
30
- # @return [self]
31
- #
32
- def apply!(example)
33
- example.send(:stub_const, const, value)
34
- self
35
- end
36
-
37
- private
38
-
39
- def initialize(const:, **)
40
- @const = const.to_s
41
- end
42
- end
43
- end
@@ -1,98 +0,0 @@
1
- #
2
- # Stubbed request
3
- #
4
- class Fixturama::Stubs::Request
5
- require_relative "request/response"
6
- require_relative "request/responses"
7
-
8
- def to_s
9
- "#{http_method.upcase} #{uri.to_s == "" ? "*" : uri}"
10
- end
11
- alias to_str to_s
12
-
13
- # every stub is unique
14
- alias key hash
15
- def update!(_); end
16
-
17
- def apply!(example)
18
- stub = example.stub_request(http_method, uri)
19
- stub = stub.with(request) if request.any?
20
- stub.to_return { |_| responses.next }
21
- end
22
-
23
- private
24
-
25
- attr_reader :options
26
-
27
- def initialize(options)
28
- @options = options
29
- with_error { @options = Hash(options).symbolize_keys }
30
- end
31
-
32
- HTTP_METHODS = %i[get post put patch delete head options any].freeze
33
-
34
- def http_method
35
- value = with_error("method") { options[:method]&.to_sym&.downcase } || :any
36
- return value if HTTP_METHODS.include?(value)
37
-
38
- raise ArgumentError, "Invalid HTTP method #{value} in #{@optons}"
39
- end
40
-
41
- def uri
42
- with_error("uri") { maybe_regexp(options[:uri] || options[:url]) }
43
- end
44
-
45
- def headers
46
- with_error("headers") do
47
- Hash(options[:headers]).transform_keys(&:to_s) if options.key?(:headers)
48
- end
49
- end
50
-
51
- def query
52
- with_error("query") do
53
- Hash(options[:query]).transform_keys(&:to_s) if options.key?(:query)
54
- end
55
- end
56
-
57
- def body
58
- with_error("body") do
59
- case options[:body]
60
- when NilClass then nil
61
- when Hash then options[:body]
62
- else maybe_regexp(options[:body])
63
- end
64
- end
65
- end
66
-
67
- def basic_auth
68
- with_error("basic auth") do
69
- value = options[:auth] || options[:basic_auth]
70
- Hash(value).transform_keys(&:to_s).values_at("user", "pass") if value
71
- end
72
- end
73
-
74
- def request
75
- @request ||= {
76
- headers: headers,
77
- body: body,
78
- query: query,
79
- basic_auth: basic_auth
80
- }.select { |_, val| val }
81
- end
82
-
83
- def responses
84
- @responses ||= Responses.new(options[:response] || options[:responses])
85
- end
86
-
87
- def with_error(part = nil)
88
- yield
89
- rescue RuntimeError
90
- message = ["Cannot extract a request", part, "from #{options}"].join(" ")
91
- raise ArgumentError, message, __FILE__, __LINE__ - 1
92
- end
93
-
94
- def maybe_regexp(str)
95
- str = str.to_s
96
- str[%r{\A/.*/\z}] ? Regexp.new(str[1..-2]) : str
97
- end
98
- end
@@ -1,43 +0,0 @@
1
- class Fixturama::Stubs::Request
2
- class Response
3
- def to_h
4
- { status: status, body: body, headers: headers }.select { |_, val| val }
5
- end
6
-
7
- private
8
-
9
- def initialize(options)
10
- @options = options
11
- @options = with_error { Hash(options).transform_keys(&:to_sym) }
12
- end
13
-
14
- attr_reader :options
15
-
16
- def status
17
- with_error("status") { options[:status]&.to_i } || 200
18
- end
19
-
20
- def body
21
- with_error("body") do
22
- case options[:body]
23
- when NilClass then nil
24
- when Hash then JSON.dump(options[:body])
25
- else options[:body].to_s
26
- end
27
- end
28
- end
29
-
30
- def headers
31
- with_error("headers") do
32
- Hash(options[:headers]).map { |k, v| [k.to_s, v.to_s] }.to_h
33
- end
34
- end
35
-
36
- def with_error(part = nil)
37
- yield
38
- rescue RuntimeError
39
- text = ["Cannot extract a response", part, "from #{options}"].join(" ")
40
- raise ArgumentError, text, __FILE__, __LINE__ - 1
41
- end
42
- end
43
- end
@@ -1,20 +0,0 @@
1
- class Fixturama::Stubs::Request
2
- class Responses
3
- def next
4
- list.count > @count ? list[@count].tap { @count += 1 } : list.last
5
- end
6
-
7
- private
8
-
9
- def initialize(list)
10
- @count = 0
11
- list ||= [{ status: 200 }]
12
- @list = case list
13
- when Array then list.map { |item| Response.new(item).to_h }
14
- else [Response.new(list).to_h]
15
- end
16
- end
17
-
18
- attr_reader :list
19
- end
20
- end
@@ -1,39 +0,0 @@
1
- module Fixturama
2
- module Utils
3
- module_function
4
-
5
- def symbolize(item)
6
- item.to_s.to_sym
7
- end
8
-
9
- def symbolize_hash(data)
10
- Hash(data).transform_keys { |key| symbolize(key)}
11
- end
12
-
13
- def symbolize_array(data)
14
- Array(data).map { |item| symbolize(item) }
15
- end
16
-
17
- def constantize(item)
18
- Kernel.const_get(item.to_s)
19
- end
20
-
21
- def clone(item)
22
- item.respond_to?(:dup) ? item.dup : item
23
- end
24
-
25
- def array(list)
26
- case list
27
- when NilClass then []
28
- when Array then list
29
- else [list]
30
- end
31
- end
32
-
33
- def matched_hash_args?(actual, expected)
34
- return unless actual.is_a?(Hash) && expected.is_a?(Hash)
35
-
36
- expected.all? { |key, val| actual[key] == val }
37
- end
38
- end
39
- end
@@ -1,53 +0,0 @@
1
- RSpec.describe "load_fixture" do
2
- let(:expected) { { "foo" => { "bar" => 42 } } }
3
-
4
- context "YAML" do
5
- subject { load_fixture("#{__dir__}/data.yaml", id: 42) }
6
-
7
- it { is_expected.to eq expected }
8
- end
9
-
10
- context "YML" do
11
- subject { load_fixture("#{__dir__}/data.yml", id: 42) }
12
-
13
- it { is_expected.to eq expected }
14
- end
15
-
16
- context "YAML with ruby object" do
17
- subject { load_fixture("#{__dir__}/data.yaml", id: foobar) }
18
-
19
- before { class Test::Foobar; end }
20
-
21
- let(:foobar) { Test::Foobar.new }
22
- let(:expected) { { "foo" => { "bar" => foobar } } }
23
-
24
- it { is_expected.to eq expected }
25
- end
26
-
27
- context "JSON" do
28
- subject { load_fixture("#{__dir__}/data.json", id: 42) }
29
-
30
- it { is_expected.to eq expected }
31
- end
32
-
33
- context "JSON with ruby object" do
34
- subject { load_fixture("#{__dir__}/data.json", id: foobar) }
35
-
36
- before { class Test::Foobar; end }
37
-
38
- let(:foobar) { Test::Foobar.new }
39
- let(:expected) { { "foo" => { "bar" => foobar } } }
40
-
41
- it { is_expected.to eq expected }
42
- end
43
-
44
- context "with RSpec argument matchers" do
45
- subject { load_fixture("#{__dir__}/data.yaml", id: kind_of(Numeric)) }
46
-
47
- it "loads the matcher", aggregate_failures: true do
48
- expect("foo" => { "bar" => 42 }).to include subject
49
- expect("foo" => { "bar" => 99 }).to include subject
50
- expect("foo" => { "bar" => :a }).not_to include subject
51
- end
52
- end
53
- end
@@ -1,5 +0,0 @@
1
- {
2
- "foo": {
3
- "bar": <%= id %>
4
- }
5
- }
@@ -1,3 +0,0 @@
1
- ---
2
- foo:
3
- bar: <%= id %>
@@ -1,3 +0,0 @@
1
- ---
2
- foo:
3
- bar: <%= id %>
@@ -1,36 +0,0 @@
1
- RSpec.describe "seed_fixture" do
2
- subject { seed_fixture "#{__dir__}/seed.yml" }
3
-
4
- before do
5
- FactoryBot.define do
6
- factory :foo, class: Hash do
7
- transient do
8
- bar { 0 }
9
- baz { 0 }
10
- qux { 0 }
11
- end
12
-
13
- trait :bar do
14
- bar { 99 }
15
- end
16
-
17
- trait :baz do
18
- baz { 77 }
19
- end
20
-
21
- skip_create
22
- initialize_with { { bar: bar, baz: baz, qux: qux } }
23
- end
24
- end
25
- end
26
-
27
- it "runs the factory", aggregate_failures: true do
28
- expect(FactoryBot).to receive(:create_list).with(:foo, 1, :baz, qux: 42)
29
- expect(FactoryBot).to receive(:create_list) do |*args, **opts|
30
- expect(args).to eq [:foo, 3, :bar]
31
- expect(opts).to be_empty
32
- end
33
-
34
- subject
35
- end
36
- end
@@ -1,16 +0,0 @@
1
- ---
2
- - type: foo
3
- traits:
4
- - baz
5
- params:
6
- qux: 42
7
-
8
- - type: foo
9
- count: 3
10
- traits:
11
- - bar
12
-
13
- - type: foo
14
- count: 0
15
- traits:
16
- - baz
@@ -1,120 +0,0 @@
1
- RSpec.describe "stub_fixture" do
2
- subject { arguments.map { |argument| Payment.new.pay(argument) } }
3
-
4
- before do
5
- class Payment
6
- def pay(_)
7
- 5
8
- end
9
- end
10
- end
11
-
12
- context "without stubbing" do
13
- let(:arguments) { [0] }
14
-
15
- it { is_expected.to eq [5] }
16
- end
17
-
18
- context "when message chain stubbed" do
19
- before { stub_fixture "#{__dir__}/stub.yml" }
20
-
21
- context "with a :raise option" do
22
- let(:arguments) { [0] }
23
-
24
- it "raises an exception" do
25
- expect { subject }.to raise_error ArgumentError
26
- end
27
- end
28
-
29
- context "with a :return option" do
30
- let(:arguments) { [1] }
31
-
32
- it "returns stubbed value" do
33
- expect(subject).to eq [8]
34
- end
35
- end
36
-
37
- context "with several actions" do
38
- let(:arguments) { [2] * 4 }
39
-
40
- it "calls the consecutive actions and then repeates the last one" do
41
- expect(subject).to eq [4, 2, 0, 0]
42
- end
43
- end
44
-
45
- context "with multi-count actions" do
46
- let(:arguments) { [3] * 4 }
47
-
48
- it "repeats the action a specified number of times" do
49
- expect(subject).to eq [6, 6, 0, 0]
50
- end
51
- end
52
-
53
- context "with several arguments" do
54
- let(:arguments) { [2, 3, 2, 3, 2, 3] }
55
-
56
- it "counts actions for every stub in isolation from the others" do
57
- expect(subject).to eq [4, 6, 2, 6, 0, 0]
58
- end
59
- end
60
-
61
- context "with partially defined options" do
62
- subject { Payment.new.pay(10, overdraft: true, notiy: true) }
63
-
64
- it "uses the stub" do
65
- expect(subject).to eq(-5)
66
- end
67
- end
68
-
69
- context "when options differ" do
70
- subject { Payment.new.pay(10, overdraft: false) }
71
-
72
- it "uses universal stub" do
73
- expect(subject).to eq(-1)
74
- end
75
- end
76
-
77
- context "with unspecified argument" do
78
- let(:arguments) { [4] }
79
-
80
- it "uses universal stub" do
81
- expect(subject).to eq [-1]
82
- end
83
- end
84
- end
85
-
86
- context "when constant stubbed" do
87
- before do
88
- TIMEOUT = 20
89
- stub_fixture "#{__dir__}/stub.yml"
90
- end
91
-
92
- it "stubs the constant" do
93
- expect(TIMEOUT).to eq 10
94
- end
95
- end
96
-
97
- context "when http request stubbed" do
98
- before { stub_fixture "#{__dir__}/stub.yml" }
99
-
100
- it "stubs the request properly" do
101
- req = Net::HTTP::Get.new("/foo")
102
- res = Net::HTTP.start("www.example.com") { |http| http.request(req) }
103
-
104
- expect(res.code).to eq "200"
105
- expect(res.body).to eq "foo"
106
- expect(res["Content-Length"]).to eq "3"
107
- end
108
-
109
- def delete_request
110
- req = Net::HTTP::Delete.new("/foo")
111
- Net::HTTP.start("www.example.com") { |http| http.request(req) }
112
- end
113
-
114
- it "stubs repetitive requests properly" do
115
- expect(delete_request.code).to eq "200"
116
- expect(delete_request.code).to eq "404"
117
- expect(delete_request.code).to eq "404"
118
- end
119
- end
120
- end