gladwords 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.circleci/config.yml +34 -0
- data/.gitignore +4 -0
- data/.projections.json +5 -0
- data/.rspec +1 -0
- data/.rubocop.yml +57 -0
- data/.rubocop_todo.yml +32 -0
- data/.vim/coc-settings.json +12 -0
- data/.vim/install.sh +38 -0
- data/.vscode/launch.json +13 -0
- data/.vscode/settings.json +9 -0
- data/.vscode/tasks.json +21 -0
- data/Gemfile +20 -0
- data/Gemfile.lock +200 -0
- data/LICENSE.txt +21 -0
- data/README.md +71 -0
- data/Rakefile +15 -0
- data/bin/rake +31 -0
- data/bin/rspec +31 -0
- data/bin/solargraph +29 -0
- data/config/environment.rb +3 -0
- data/gladwords.code-workspace +11 -0
- data/gladwords.gemspec +27 -0
- data/lib/ext/rom/inflector.rb +8 -0
- data/lib/gladwords.rb +22 -0
- data/lib/gladwords/associations.rb +7 -0
- data/lib/gladwords/associations/many_to_many.rb +18 -0
- data/lib/gladwords/associations/many_to_one.rb +22 -0
- data/lib/gladwords/associations/one_to_many.rb +19 -0
- data/lib/gladwords/associations/one_to_one.rb +10 -0
- data/lib/gladwords/associations/one_to_one_through.rb +8 -0
- data/lib/gladwords/commands.rb +7 -0
- data/lib/gladwords/commands/core.rb +76 -0
- data/lib/gladwords/commands/create.rb +18 -0
- data/lib/gladwords/commands/delete.rb +22 -0
- data/lib/gladwords/commands/error_wrapper.rb +25 -0
- data/lib/gladwords/commands/update.rb +17 -0
- data/lib/gladwords/errors.rb +7 -0
- data/lib/gladwords/gateway.rb +48 -0
- data/lib/gladwords/inflector.rb +20 -0
- data/lib/gladwords/relation.rb +197 -0
- data/lib/gladwords/relation/association_methods.rb +29 -0
- data/lib/gladwords/relation/joined_relation.rb +52 -0
- data/lib/gladwords/schema.rb +26 -0
- data/lib/gladwords/schema/attributes_inferrer.rb +171 -0
- data/lib/gladwords/schema/dsl.rb +28 -0
- data/lib/gladwords/schema/inferrer.rb +19 -0
- data/lib/gladwords/selector_fields_db.rb +30 -0
- data/lib/gladwords/selector_fields_db/v201806.json +3882 -0
- data/lib/gladwords/selector_fields_db/v201809.json +4026 -0
- data/lib/gladwords/struct.rb +24 -0
- data/lib/gladwords/types.rb +27 -0
- data/lib/gladwords/version.rb +5 -0
- data/rakelib/generate_selector_fields_db.rake +72 -0
- data/spec/integration/commands/create_spec.rb +24 -0
- data/spec/integration/commands/delete_spec.rb +47 -0
- data/spec/integration/commands/update_spec.rb +24 -0
- data/spec/shared/campaigns.rb +56 -0
- data/spec/shared/labels.rb +17 -0
- data/spec/spec_helper.rb +33 -0
- data/spec/support/adwords_helpers.rb +41 -0
- data/spec/unit/commands/create_spec.rb +85 -0
- data/spec/unit/commands/delete_spec.rb +32 -0
- data/spec/unit/commands/update_spec.rb +96 -0
- data/spec/unit/inflector_spec.rb +11 -0
- data/spec/unit/relation/association_methods_spec.rb +91 -0
- data/spec/unit/relation_spec.rb +187 -0
- data/spec/unit/schema/attributes_inferrer_spec.rb +83 -0
- data/spec/unit/selector_fields_db_spec.rb +29 -0
- data/spec/unit/types_spec.rb +49 -0
- metadata +190 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Gladwords::Commands::Delete do
|
4
|
+
include_context 'labels'
|
5
|
+
|
6
|
+
subject(:command) do
|
7
|
+
relation.command(:delete)
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:service) { label_service }
|
11
|
+
let(:relation) { labels }
|
12
|
+
|
13
|
+
before do
|
14
|
+
allow(service).to receive(:get).and_return(entries: [{ id: '1' }])
|
15
|
+
allow(service).to receive(:mutate).and_return(value: [{ id: '1' }])
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'mutates the service with the correct operations' do
|
19
|
+
expect(service).to receive(:mutate).with(
|
20
|
+
[
|
21
|
+
{
|
22
|
+
operator: 'REMOVE',
|
23
|
+
operand: { id: '1' }
|
24
|
+
}
|
25
|
+
]
|
26
|
+
)
|
27
|
+
|
28
|
+
rel = relation.where(id: 1)
|
29
|
+
delete_command = rel.command(:delete)
|
30
|
+
delete_command.call
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'securerandom'
|
4
|
+
|
5
|
+
RSpec.describe Gladwords::Commands::Update do
|
6
|
+
include_context 'campaigns'
|
7
|
+
|
8
|
+
subject(:command) do
|
9
|
+
relation.command(:update)
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:service) { campaign_service }
|
13
|
+
let(:relation) { campaigns }
|
14
|
+
|
15
|
+
context 'when provided a single tuple' do
|
16
|
+
before do
|
17
|
+
allow(service).to receive(:mutate).and_return(
|
18
|
+
value: [{ name: 'updated name', id: '1', end_date: '01012017' }]
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'mutates the service with the correct operations' do
|
23
|
+
expect(service).to receive(:mutate).with(
|
24
|
+
[
|
25
|
+
{
|
26
|
+
operator: 'SET',
|
27
|
+
operand: {
|
28
|
+
name: 'updated name',
|
29
|
+
id: '1'
|
30
|
+
}
|
31
|
+
}
|
32
|
+
]
|
33
|
+
)
|
34
|
+
|
35
|
+
subject.call(name: 'updated name', id: '1')
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'returns a struct' do
|
39
|
+
result = subject.call(name: 'updated name', id: '1')
|
40
|
+
|
41
|
+
expect(result).to be_a(Gladwords::Struct::Campaign)
|
42
|
+
expect(result.id).to eq '1'
|
43
|
+
expect(result.name).to eq 'updated name'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when provided multiple tuples' do
|
48
|
+
subject(:command) do
|
49
|
+
relation.command(:update, result: :many)
|
50
|
+
end
|
51
|
+
|
52
|
+
before do
|
53
|
+
allow(service).to(
|
54
|
+
receive(:mutate).and_return(
|
55
|
+
value: [
|
56
|
+
{ name: 'updated name', id: '1', end_date: '01012017' },
|
57
|
+
{ name: 'updated name 2', id: '2', end_date: '01012018' }
|
58
|
+
]
|
59
|
+
)
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'mutates the service with the correct operations' do
|
64
|
+
expect(service).to receive(:mutate).with(
|
65
|
+
[
|
66
|
+
{
|
67
|
+
operator: 'SET',
|
68
|
+
operand: {
|
69
|
+
name: 'updated name',
|
70
|
+
id: '1'
|
71
|
+
}
|
72
|
+
},
|
73
|
+
{
|
74
|
+
operator: 'SET',
|
75
|
+
operand: {
|
76
|
+
name: 'updated name 2',
|
77
|
+
id: '2'
|
78
|
+
}
|
79
|
+
}
|
80
|
+
]
|
81
|
+
)
|
82
|
+
|
83
|
+
subject.call([{ name: 'updated name', id: '1' }, { name: 'updated name 2', id: '2' }])
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'returns an array of structs' do
|
87
|
+
result = subject.call(
|
88
|
+
[{ name: 'updated name', id: '1' }, { name: 'updated name 2', id: '2' }]
|
89
|
+
)
|
90
|
+
|
91
|
+
expect(result.count).to eq 2
|
92
|
+
|
93
|
+
expect(result).to all be_a(Gladwords::Struct::Campaign)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Gladwords::Inflector do
|
4
|
+
it 'correctly pluralizes criterion' do
|
5
|
+
expect(described_class.pluralize('criterion')).to eq 'criteria'
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'correctly singularizes criteria' do
|
9
|
+
expect(described_class.singularize('criteria')).to eq 'criterion'
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gladwords
|
4
|
+
RSpec.describe Relation::AssociationMethods do
|
5
|
+
include_context 'campaigns'
|
6
|
+
|
7
|
+
context 'when the relation is one-to-many' do
|
8
|
+
subject { campaigns }
|
9
|
+
|
10
|
+
describe '#join' do
|
11
|
+
let(:campaign_id) { 1_338_164_832 }
|
12
|
+
let(:filtered_relation) { subject.select(:id).where(id: campaign_id).join(:ad_groups) }
|
13
|
+
|
14
|
+
it 'filters the target relation' do
|
15
|
+
returned_ids = filtered_relation.call.flat_map(&:ad_groups).map(&:campaign_id)
|
16
|
+
|
17
|
+
expect(returned_ids).to all eq(campaign_id)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'returns the filtered combined relationship' do
|
21
|
+
ad_groups = filtered_relation.ad_groups.call
|
22
|
+
|
23
|
+
aggregate_failures do
|
24
|
+
expect(ad_groups).to all be_a(Gladwords::Struct::AdGroup)
|
25
|
+
expect(ad_groups.pluck(:campaign_id)).to all eq(campaign_id)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'can query on the combined node' do
|
30
|
+
scope = filtered_relation.node(:ad_groups) { |n| n.select(:campaign_id) }
|
31
|
+
ad_group = scope.one.ad_groups.first
|
32
|
+
expect(ad_group.to_h).to eql(campaign_id: campaign_id)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'when the relation is many-to-one' do
|
38
|
+
subject { rom.relations[:ad_groups] }
|
39
|
+
|
40
|
+
describe '#combine' do
|
41
|
+
let(:campaign_id) { 1_338_164_832 }
|
42
|
+
let(:filtered_relation) { subject.combine(:campaign) }
|
43
|
+
|
44
|
+
it 'filters the target relation' do
|
45
|
+
scope = filtered_relation.where(campaign_id: campaign_id)
|
46
|
+
ad_group = scope.limit(1).call.one
|
47
|
+
expect(ad_group.campaign.id).to eql(campaign_id)
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'can query on the combined node' do
|
51
|
+
scope = filtered_relation.where(campaign_id: campaign_id)
|
52
|
+
scope = scope.node(:campaign) { |n| n.select(:id) }
|
53
|
+
campaign = scope.call.one.campaign
|
54
|
+
expect(campaign.to_h).to eql(id: campaign_id)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'when the relation is has-many through' do
|
60
|
+
subject { campaigns }
|
61
|
+
|
62
|
+
describe '#combine' do
|
63
|
+
let(:campaign_id) { 1_338_164_832 }
|
64
|
+
|
65
|
+
context 'when the combine is nested' do
|
66
|
+
let(:filtered_relation) { subject.combine(ad_groups: [:ad_group_ads]) }
|
67
|
+
|
68
|
+
it 'includes the nested has_many through' do
|
69
|
+
scope = filtered_relation.where(campaign_id: campaign_id).one
|
70
|
+
ads = scope.ad_groups.flat_map(&:ad_group_ads)
|
71
|
+
expect(ads).not_to be_empty
|
72
|
+
expect(ads.map(&:base_campaign_id)).to all eq(campaign_id)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when the combine is direct' do
|
77
|
+
let(:filtered_relation) { subject.combine(:ad_group_ads) }
|
78
|
+
|
79
|
+
it 'includes the nested has_many through' do
|
80
|
+
pending 'Combine is not working for direct has many through'
|
81
|
+
scope = filtered_relation.where(campaign_id: campaign_id).one
|
82
|
+
|
83
|
+
ads = scope.ad_group_ads
|
84
|
+
expect(ads).not_to be_empty
|
85
|
+
expect(ads.map(&:base_campaign_id)).to all eq(campaign_id)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,187 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Gladwords::Relation do
|
4
|
+
include_context 'campaigns'
|
5
|
+
|
6
|
+
subject { campaigns }
|
7
|
+
|
8
|
+
describe '#by_pk' do
|
9
|
+
it 'loads the resource by id and limits the result' do
|
10
|
+
new_scope = subject.by_pk('123')
|
11
|
+
predicates = new_scope.options.dig(:selector, :predicates)
|
12
|
+
paging = new_scope.options.dig(:selector, :paging)
|
13
|
+
|
14
|
+
expect(predicates).to eql([{ field: 'Id', operator: 'IN', values: ['123'] }])
|
15
|
+
expect(paging).to eql(number_results: 1)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe '#where' do
|
20
|
+
it 'chains where clauses' do
|
21
|
+
old_scope = subject.select(:id, :name).where(id: '123')
|
22
|
+
new_scope = old_scope.where(name: 'TestName')
|
23
|
+
expected = [{ field: 'Id', operator: 'IN', values: ['123'] },
|
24
|
+
{ field: 'Name', operator: 'IN', values: ['TestName'] }]
|
25
|
+
predicates = new_scope.options.dig(:selector, :predicates)
|
26
|
+
|
27
|
+
expect(predicates).to match_array(expected)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'de-duplicates where clauses' do
|
31
|
+
old_scope = subject.select(:id, :name).where(id: '123')
|
32
|
+
new_scope = old_scope.where(id: '123')
|
33
|
+
expected = [{ field: 'Id', operator: 'IN', values: ['123'] }]
|
34
|
+
predicates = new_scope.options.dig(:selector, :predicates)
|
35
|
+
|
36
|
+
expect(predicates).to match_array(expected)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe '#total_count' do
|
41
|
+
it 'shows the total_count' do
|
42
|
+
scope = subject.select(:id, :name).where(name: 'Test Campaign 2')
|
43
|
+
|
44
|
+
expect(scope.total_count).to eq 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#offset' do
|
49
|
+
it 'offsets the start_index' do
|
50
|
+
scope = subject.offset(10)
|
51
|
+
|
52
|
+
expect(scope.options.dig(:selector, :paging, :start_index)).to eq 10
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#limit' do
|
57
|
+
it 'sets the paging[:number_results]' do
|
58
|
+
scope = subject.limit(3)
|
59
|
+
|
60
|
+
expect(scope.options.dig(:selector, :paging, :number_results)).to eq 3
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#select' do
|
65
|
+
it 'camelcases the fields' do
|
66
|
+
scope = subject.select(:base_campaign_id, :name)
|
67
|
+
fields = scope.options.dig(:selector, :fields)
|
68
|
+
|
69
|
+
expect(fields).to contain_exactly 'BaseCampaignId', 'Name'
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'only selects unique fields' do
|
73
|
+
scope = subject.select(:name).select(:name)
|
74
|
+
fields = scope.options.dig(:selector, :fields)
|
75
|
+
|
76
|
+
expect(fields).to contain_exactly 'Name'
|
77
|
+
end
|
78
|
+
|
79
|
+
it 'limits requested fields when using #select' do
|
80
|
+
repo = Class.new(ROM::Repository[:campaigns]).new(rom)
|
81
|
+
result = repo.campaigns.select(:name).limit(1).one
|
82
|
+
|
83
|
+
expect(result.to_h.keys).to contain_exactly(:name)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '#pluck' do
|
88
|
+
it 'returns an array of the ids' do
|
89
|
+
ids = subject.pluck(:id).call
|
90
|
+
|
91
|
+
expect(ids).not_to be_empty
|
92
|
+
expect(ids).to all be_a(Integer)
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'only requests the plucked field' do
|
96
|
+
expect(campaign_service)
|
97
|
+
.to receive(:get)
|
98
|
+
.with(a_hash_including(fields: ['Id']))
|
99
|
+
.and_return({})
|
100
|
+
|
101
|
+
scope = subject.pluck(:id)
|
102
|
+
|
103
|
+
expect(scope.options.dig(:selector, :fields)).to eql(['Id'])
|
104
|
+
scope.call
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'by default selects all selectable fields' do
|
109
|
+
repo = Class.new(ROM::Repository[:campaigns]).new(rom)
|
110
|
+
scope = repo.campaigns.where(name: 'Test Campaign 2')
|
111
|
+
result = scope.call
|
112
|
+
|
113
|
+
expected = {
|
114
|
+
id: 1_338_164_832,
|
115
|
+
status: 'ENABLED',
|
116
|
+
serving_status: 'SERVING',
|
117
|
+
ad_serving_optimization_status: 'OPTIMIZE',
|
118
|
+
advertising_channel_type: 'SEARCH',
|
119
|
+
advertising_channel_sub_type: nil,
|
120
|
+
campaign_trial_type: 'BASE',
|
121
|
+
campaign_group_id: nil,
|
122
|
+
name: 'Test Campaign 2',
|
123
|
+
start_date: '20180329',
|
124
|
+
end_date: '20371230',
|
125
|
+
universal_app_campaign_info: nil,
|
126
|
+
final_url_suffix: nil,
|
127
|
+
budget: {
|
128
|
+
budget_id: 1_391_080_779,
|
129
|
+
name: 'Test Campaign 2',
|
130
|
+
amount: a_hash_including(micro_amount: 999_000_000),
|
131
|
+
delivery_method: 'STANDARD',
|
132
|
+
reference_count: 1,
|
133
|
+
is_explicitly_shared: false,
|
134
|
+
status: 'ENABLED'
|
135
|
+
},
|
136
|
+
conversion_optimizer_eligibility: {
|
137
|
+
eligible: false,
|
138
|
+
rejection_reasons: ['NOT_ENOUGH_CONVERSIONS']
|
139
|
+
},
|
140
|
+
frequency_cap: nil,
|
141
|
+
settings: [{
|
142
|
+
setting_type: 'GeoTargetTypeSetting',
|
143
|
+
positive_geo_target_type: 'LOCATION_OF_PRESENCE',
|
144
|
+
negative_geo_target_type: 'DONT_CARE',
|
145
|
+
xsi_type: 'GeoTargetTypeSetting'
|
146
|
+
}],
|
147
|
+
network_setting: {
|
148
|
+
target_google_search: true,
|
149
|
+
target_search_network: true,
|
150
|
+
target_content_network: false,
|
151
|
+
target_partner_search_network: false
|
152
|
+
},
|
153
|
+
labels: [],
|
154
|
+
bidding_strategy_configuration: {
|
155
|
+
bidding_strategy_id: nil,
|
156
|
+
bidding_strategy_name: nil,
|
157
|
+
bidding_strategy_type: 'MANUAL_CPC',
|
158
|
+
bidding_strategy_source: nil,
|
159
|
+
bidding_scheme: {
|
160
|
+
bidding_scheme_type: 'ManualCpcBiddingScheme',
|
161
|
+
enhanced_cpc_enabled: false,
|
162
|
+
xsi_type: 'ManualCpcBiddingScheme'
|
163
|
+
},
|
164
|
+
bids: [],
|
165
|
+
target_roas_override: nil
|
166
|
+
},
|
167
|
+
base_campaign_id: 1_338_164_832,
|
168
|
+
forward_compatibility_map: [],
|
169
|
+
tracking_url_template: nil,
|
170
|
+
url_custom_parameters: nil,
|
171
|
+
vanity_pharma: nil,
|
172
|
+
selective_optimization: nil
|
173
|
+
}
|
174
|
+
|
175
|
+
entries = result.map(&:to_h)
|
176
|
+
|
177
|
+
expect(entries.first).to match(expected)
|
178
|
+
expect(entries).to contain_exactly(expected)
|
179
|
+
end
|
180
|
+
|
181
|
+
describe '#request' do
|
182
|
+
it 'raises when the method does not exist' do
|
183
|
+
expect { subject.request(:bad_method) }
|
184
|
+
.to raise_error described_class::InvalidRequestMethodError
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'adwords_api/v201809/campaign_service_registry'
|
4
|
+
|
5
|
+
module Gladwords
|
6
|
+
RSpec.describe Schema::AttributesInferrer do
|
7
|
+
let(:schema) { double(name: :campaigns, options: { shitlist: [] }) }
|
8
|
+
let(:registry) { AdwordsApi::V201809::CampaignService::CampaignServiceRegistry }
|
9
|
+
let(:gateway) { double(service_registry: registry) }
|
10
|
+
|
11
|
+
describe '#call' do
|
12
|
+
declarations = {
|
13
|
+
String => %i[
|
14
|
+
name
|
15
|
+
status
|
16
|
+
serving_status
|
17
|
+
start_date
|
18
|
+
end_date
|
19
|
+
ad_serving_optimization_status
|
20
|
+
advertising_channel_type
|
21
|
+
advertising_channel_sub_type
|
22
|
+
campaign_trial_type
|
23
|
+
tracking_url_template
|
24
|
+
final_url_suffix
|
25
|
+
],
|
26
|
+
Integer => %i[id base_campaign_id campaign_group_id]
|
27
|
+
}
|
28
|
+
|
29
|
+
declarations.each do |primitive, fields|
|
30
|
+
it "maps to #{primitive.name}", skip: fields.delete(skip: true) do
|
31
|
+
types, _missing = subject.call(schema, gateway)
|
32
|
+
attrs = types.select { |a| a.type.primitive == primitive }
|
33
|
+
|
34
|
+
expect(attrs.map(&:name)).to match_array(fields)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'maps nested types to hashes' do
|
39
|
+
types, _missing = subject.call(schema, gateway)
|
40
|
+
hash_field = types.find { |t| t.name == :budget }
|
41
|
+
member_types = hash_field.type.options[:member_types]
|
42
|
+
|
43
|
+
aggregate_failures do
|
44
|
+
expect(member_types[:budget_id].primitive).to eq(Integer)
|
45
|
+
expect(member_types[:name].primitive).to eq(String)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'includes read types for known nested hashes' do
|
50
|
+
types, _missing = subject.call(schema, gateway)
|
51
|
+
hash_field = types.find { |t| t.name == :budget }
|
52
|
+
|
53
|
+
read_type = hash_field.meta[:read]
|
54
|
+
|
55
|
+
expect(read_type).to be_a(Dry::Types::Constructor)
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'removes shitlist attributes from schema' do
|
59
|
+
allow(schema).to receive(:options).and_return(shitlist: [:end_date])
|
60
|
+
types, _missing = subject.call(schema, gateway)
|
61
|
+
|
62
|
+
expect(types.find { |t| t.name == :end_date }).to be_nil
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'created enumerated types' do
|
66
|
+
types, _missing = subject.call(schema, gateway)
|
67
|
+
status = types.find { |t| t.name == :status }
|
68
|
+
type = status.type
|
69
|
+
|
70
|
+
expect(type).to be_a(Dry::Types::Enum)
|
71
|
+
expect(type.options).to eql(values: %w[UNKNOWN ENABLED PAUSED REMOVED])
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'creates enumerated type arrays' do
|
75
|
+
types, _missing = subject.call(schema, gateway)
|
76
|
+
status = types.find { |t| t.name == :conversion_optimizer_eligibility }
|
77
|
+
type = status.type.member_types[:rejection_reasons].type
|
78
|
+
|
79
|
+
expect(type).to be_a(Dry::Types::Array)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|