fixturama 0.1.0 → 0.5.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 +4 -4
- data/CHANGELOG.md +99 -0
- data/README.md +76 -4
- data/lib/fixturama.rb +48 -20
- data/lib/fixturama/changes.rb +72 -0
- data/lib/fixturama/changes/base.rb +28 -0
- data/lib/fixturama/changes/chain.rb +64 -0
- data/lib/fixturama/changes/chain/actions.rb +31 -0
- data/lib/fixturama/changes/chain/arguments.rb +59 -0
- data/lib/fixturama/changes/chain/raise_action.rb +43 -0
- data/lib/fixturama/changes/chain/return_action.rb +33 -0
- data/lib/fixturama/changes/const.rb +30 -0
- data/lib/fixturama/changes/env.rb +35 -0
- data/lib/fixturama/changes/request.rb +91 -0
- data/lib/fixturama/changes/request/response.rb +62 -0
- data/lib/fixturama/changes/request/responses.rb +22 -0
- data/lib/fixturama/changes/seed.rb +39 -0
- data/lib/fixturama/config.rb +5 -0
- data/lib/fixturama/fixture_error.rb +31 -0
- data/lib/fixturama/loader.rb +6 -2
- data/lib/fixturama/loader/context.rb +14 -5
- data/lib/fixturama/loader/value.rb +1 -0
- data/lib/fixturama/version.rb +4 -0
- metadata +85 -73
- data/.gitignore +0 -12
- data/.rspec +0 -2
- data/.rubocop.yml +0 -22
- data/.travis.yml +0 -17
- data/Gemfile +0 -9
- data/LICENSE.txt +0 -21
- data/Rakefile +0 -6
- data/fixturama.gemspec +0 -24
- data/lib/fixturama/seed.rb +0 -15
- data/lib/fixturama/stubs.rb +0 -79
- data/lib/fixturama/stubs/chain.rb +0 -90
- data/lib/fixturama/stubs/chain/actions.rb +0 -39
- data/lib/fixturama/stubs/chain/actions/raise.rb +0 -21
- data/lib/fixturama/stubs/chain/actions/return.rb +0 -23
- data/lib/fixturama/stubs/chain/arguments.rb +0 -86
- data/lib/fixturama/stubs/const.rb +0 -43
- data/lib/fixturama/stubs/request.rb +0 -98
- data/lib/fixturama/stubs/request/response.rb +0 -43
- data/lib/fixturama/stubs/request/responses.rb +0 -20
- data/lib/fixturama/utils.rb +0 -39
- data/spec/fixturama/load_fixture/_spec.rb +0 -53
- data/spec/fixturama/load_fixture/data.json +0 -5
- data/spec/fixturama/load_fixture/data.yaml +0 -3
- data/spec/fixturama/load_fixture/data.yml +0 -3
- data/spec/fixturama/seed_fixture/_spec.rb +0 -36
- data/spec/fixturama/seed_fixture/seed.yml +0 -16
- data/spec/fixturama/stub_fixture/_spec.rb +0 -120
- data/spec/fixturama/stub_fixture/stub.yml +0 -73
- 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
|
data/lib/fixturama/utils.rb
DELETED
@@ -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,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,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
|