gladwords 1.0.1
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 +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
|