mailerlite-ruby 1.0.6 → 2.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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/.envrc +2 -0
  3. data/.github/workflows/main.yml +4 -4
  4. data/.github/workflows/publish_gem.yml +5 -5
  5. data/.gitignore +2 -1
  6. data/.rubocop.yml +1 -1
  7. data/CHANGELOG.md +21 -0
  8. data/README.md +583 -1
  9. data/flake.lock +27 -0
  10. data/flake.nix +25 -0
  11. data/lefthook.yml +14 -0
  12. data/lib/mailerlite/api_response.rb +24 -0
  13. data/lib/mailerlite/automations/automation_emails.rb +57 -0
  14. data/lib/mailerlite/automations/automation_reports.rb +114 -0
  15. data/lib/mailerlite/automations/automation_steps.rb +105 -0
  16. data/lib/mailerlite/automations/automation_templates.rb +34 -0
  17. data/lib/mailerlite/automations/automation_triggers.rb +62 -0
  18. data/lib/mailerlite/automations/automations.rb +177 -8
  19. data/lib/mailerlite/brand_styles/brand_styles.rb +24 -0
  20. data/lib/mailerlite/campaigns/campaigns.rb +33 -1
  21. data/lib/mailerlite/client.rb +15 -5
  22. data/lib/mailerlite/ecommerce/ecommerce.rb +316 -0
  23. data/lib/mailerlite/emails/emails.rb +306 -0
  24. data/lib/mailerlite/errors.rb +88 -0
  25. data/lib/mailerlite/files/files.rb +45 -0
  26. data/lib/mailerlite/groups/groups.rb +16 -8
  27. data/lib/mailerlite/params.rb +58 -0
  28. data/lib/mailerlite/query_params.rb +33 -0
  29. data/lib/mailerlite/request.rb +24 -0
  30. data/lib/mailerlite/segments/segments.rb +10 -10
  31. data/lib/mailerlite/subscribers/subscribers.rb +63 -8
  32. data/lib/mailerlite/version.rb +1 -1
  33. data/lib/mailerlite.rb +14 -0
  34. data/mailerlite-ruby.gemspec +8 -8
  35. data/spec/api_response_rspec.rb +140 -0
  36. data/spec/automation_emails_rspec.rb +40 -0
  37. data/spec/automation_reports_rspec.rb +92 -0
  38. data/spec/automation_steps_rspec.rb +76 -0
  39. data/spec/automation_templates_rspec.rb +24 -0
  40. data/spec/automation_triggers_rspec.rb +48 -0
  41. data/spec/automations_rspec.rb +143 -0
  42. data/spec/brand_styles_rspec.rb +49 -0
  43. data/spec/campaigns_rspec.rb +42 -0
  44. data/spec/ecommerce_rspec.rb +141 -0
  45. data/spec/emails_rspec.rb +692 -0
  46. data/spec/files_rspec.rb +90 -0
  47. data/spec/fixtures/brand_styles.json +50 -0
  48. data/spec/fixtures/campaign_simple_editor.json +24 -0
  49. data/spec/fixtures/email.json +81 -0
  50. data/spec/fixtures/email_block.json +12 -0
  51. data/spec/fixtures/email_block_created.json +12 -0
  52. data/spec/fixtures/email_block_created_rejected.json +15 -0
  53. data/spec/fixtures/email_block_moved.json +12 -0
  54. data/spec/fixtures/email_block_updated.json +9 -0
  55. data/spec/fixtures/email_block_updated_rejected.json +13 -0
  56. data/spec/fixtures/email_block_validation_invalid.json +5 -0
  57. data/spec/fixtures/email_etag.json +1 -0
  58. data/spec/fixtures/email_html.json +1 -0
  59. data/spec/fixtures/email_settings.json +111 -0
  60. data/spec/fixtures/email_settings_validation.json +9 -0
  61. data/spec/fixtures/email_template.json +1 -0
  62. data/spec/fixtures/email_version.json +1 -0
  63. data/spec/fixtures/email_versions.json +26 -0
  64. data/spec/fixtures/files.json +44 -0
  65. data/spec/groups_rspec.rb +21 -0
  66. data/spec/params_rspec.rb +126 -0
  67. data/spec/request_rspec.rb +139 -0
  68. data/spec/segments_rspec.rb +39 -0
  69. data/spec/spec_helper.rb +1 -0
  70. data/spec/subscribers_rspec.rb +57 -0
  71. data/spec/support/json_fixture.rb +27 -0
  72. data/spec/support/request_stub.rb +25 -0
  73. metadata +69 -22
  74. /data/{renovate.json → .github/renovate.json} +0 -0
@@ -0,0 +1,126 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe MailerLite::Params do
6
+ describe 'error classes' do
7
+ it 'makes the client-side errors subclasses of ArgumentError' do
8
+ expect(MailerLite::EmptyIdError.ancestors).to include(ArgumentError)
9
+ expect(MailerLite::InvalidIdError.ancestors).to include(ArgumentError)
10
+ end
11
+
12
+ it 'has a base error class for the SDK' do
13
+ expect(MailerLite::Error.ancestors).to include(StandardError)
14
+ end
15
+ end
16
+
17
+ describe '.path_id' do
18
+ it 'returns a String of digits as it is' do
19
+ expect(described_class.path_id('123', 'email_id')).to eq '123'
20
+ end
21
+
22
+ it 'returns an Integer as a String' do
23
+ expect(described_class.path_id(123, 'email_id')).to eq '123'
24
+ end
25
+
26
+ it 'raises EmptyIdError for an empty String and for nil' do
27
+ expect { described_class.path_id('', 'email_id') }.to raise_error(MailerLite::EmptyIdError, /`email_id`/)
28
+ expect { described_class.path_id(nil, 'email_id') }.to raise_error(MailerLite::EmptyIdError, /`email_id`/)
29
+ end
30
+
31
+ ['123/html', '123%2Fhtml', "123\n", ' 123', '²', '١٢', '1.5', '-5'].each do |value|
32
+ it "raises InvalidIdError for #{value.inspect}" do
33
+ expect { described_class.path_id(value, 'block_id') }.to raise_error(MailerLite::InvalidIdError, /`block_id`/)
34
+ end
35
+ end
36
+
37
+ it 'raises InvalidIdError for a negative Integer' do
38
+ expect { described_class.path_id(-5, 'email_id') }.to raise_error(MailerLite::InvalidIdError)
39
+ end
40
+
41
+ it 'raises InvalidIdError for a String with invalid bytes' do
42
+ value = (+"12\xFF").force_encoding('UTF-8')
43
+ expect { described_class.path_id(value, 'email_id') }.to raise_error(MailerLite::InvalidIdError)
44
+ end
45
+
46
+ it 'raises InvalidIdError for a String in an encoding that is not ASCII compatible' do
47
+ expect { described_class.path_id('12'.encode('UTF-16LE'), 'email_id') }.to raise_error(MailerLite::InvalidIdError)
48
+ end
49
+
50
+ [true, false, 1.5, :'123', ['1']].each do |value|
51
+ it "raises TypeError for #{value.inspect}" do
52
+ expect { described_class.path_id(value, 'email_id') }.to raise_error(TypeError, /`email_id`/)
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '.require_hash' do
58
+ it 'returns the Hash' do
59
+ value = { 'a' => 1 }
60
+ expect(described_class.require_hash(value, 'settings')).to be value
61
+ end
62
+
63
+ [nil, 'image', [], 1].each do |value|
64
+ it "raises TypeError for #{value.inspect}" do
65
+ expect { described_class.require_hash(value, 'filter') }.to raise_error(TypeError, /`filter`/)
66
+ end
67
+ end
68
+ end
69
+
70
+ describe '.settings' do
71
+ it 'returns the settings' do
72
+ settings = { brand: { mode: 'account' } }
73
+ expect(described_class.settings(settings)).to eq settings
74
+ end
75
+
76
+ it 'raises ArgumentError for an etag key' do
77
+ expect { described_class.settings({ etag: '1' }) }.to raise_error(ArgumentError, /etag/)
78
+ expect { described_class.settings({ 'etag' => '1' }) }.to raise_error(ArgumentError, /etag/)
79
+ end
80
+
81
+ it 'raises TypeError for settings that are not a Hash' do
82
+ expect { described_class.settings(nil) }.to raise_error(TypeError, /`settings`/)
83
+ end
84
+ end
85
+
86
+ describe '.query' do
87
+ it 'returns an empty Hash with no values' do
88
+ expect(described_class.query).to eq({})
89
+ end
90
+
91
+ it 'adds a filter[key] value for each filter key' do
92
+ expect(described_class.query(filter: { name: 'summer sale', type: 'image' }, sort: '-size'))
93
+ .to eq('filter[name]' => 'summer sale', 'filter[type]' => 'image', 'sort' => '-size')
94
+ end
95
+
96
+ it 'drops nil values, also in the filter' do
97
+ expect(described_class.query(filter: { name: nil, type: 'pdf' }, page: nil, limit: 10))
98
+ .to eq('filter[type]' => 'pdf', 'limit' => 10)
99
+ end
100
+
101
+ it 'keeps empty String values' do
102
+ expect(described_class.query(filter: { type: '' }, sort: ''))
103
+ .to eq('filter[type]' => '', 'sort' => '')
104
+ end
105
+
106
+ it 'raises TypeError for a filter that is not a Hash' do
107
+ expect { described_class.query(filter: 'image') }.to raise_error(TypeError, /`filter`/)
108
+ end
109
+ end
110
+
111
+ describe '.idempotency_headers' do
112
+ it 'returns no headers without a key' do
113
+ expect(described_class.idempotency_headers(nil)).to eq({})
114
+ end
115
+
116
+ it 'returns the header for a valid key' do
117
+ expect(described_class.idempotency_headers('key-1')).to eq('Idempotency-Key' => 'key-1')
118
+ end
119
+
120
+ ['', 'a' * 256, 'é', ' k', 'k ', 1].each do |key|
121
+ it "returns the header with the key as given for #{key.inspect[0, 20]}" do
122
+ expect(described_class.idempotency_headers(key)).to eq('Idempotency-Key' => key)
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'webmock/rspec'
5
+ require 'json'
6
+ require_relative 'support/json_fixture'
7
+
8
+ RSpec.describe MailerLite::Request do
9
+ include_context 'with the dummy API token'
10
+
11
+ let(:client) { MailerLite::Client.new }
12
+ let(:api) { MAILERLITE_API_URL }
13
+
14
+ # WebMock normalizes the URI (for example `+` becomes `%20`), so keep the raw URI that http.rb sends.
15
+ def capture_raw_uris
16
+ uris = []
17
+ allow_any_instance_of(HTTP::Client).to receive(:perform).and_wrap_original do |method, request, options|
18
+ uris << request.uri.to_s
19
+ method.call(request, options)
20
+ end
21
+ uris
22
+ end
23
+
24
+ it 'sends a PATCH request with the JSON body' do
25
+ stub = stub_request(:patch, "#{api}/emails/1/settings")
26
+ .with { |req| req.body == '{"layout":{"alignment":"left"},"etag":"42"}' }
27
+ .to_return(status: 200, body: '{}')
28
+
29
+ described_class.call(client, :patch, '/emails/1/settings', json: { 'layout' => { 'alignment' => 'left' }, 'etag' => '42' })
30
+
31
+ expect(stub).to have_been_requested
32
+ end
33
+
34
+ it 'sends a DELETE request with the JSON body' do
35
+ stub = stub_request(:delete, "#{api}/emails/1/blocks/2")
36
+ .with { |req| req.body == '{"etag":"42"}' }
37
+ .to_return(status: 200, body: '{"etag":"43"}')
38
+
39
+ described_class.call(client, :delete, '/emails/1/blocks/2', json: { 'etag' => '42' })
40
+
41
+ expect(stub).to have_been_requested
42
+ end
43
+
44
+ it 'sends no body, not null, when there is no body' do
45
+ stub = stub_request(:post, "#{api}/emails/1/versions")
46
+ .with { |req| req.body == '' }
47
+ .to_return(status: 201, body: '{}')
48
+
49
+ described_class.call(client, :post, '/emails/1/versions')
50
+
51
+ expect(stub).to have_been_requested
52
+ end
53
+
54
+ it 'sends the query and encodes a space as +' do
55
+ uris = capture_raw_uris
56
+ stub = stub_request(:get, "#{api}/files")
57
+ .with(query: { 'filter[name]' => 'summer sale', 'filter[type]' => '', 'page' => '2' })
58
+ .to_return(status: 200, body: '{}')
59
+
60
+ described_class.call(client, :get, '/files', query: { 'filter[name]' => 'summer sale', 'filter[type]' => '', 'page' => 2 })
61
+
62
+ expect(stub).to have_been_requested
63
+ expect(uris).to eq ["#{api}/files?filter%5Bname%5D=summer+sale&filter%5Btype%5D=&page=2"]
64
+ end
65
+
66
+ it 'sends no query for an empty query' do
67
+ uris = capture_raw_uris
68
+ stub_request(:get, "#{api}/emails/1/versions").to_return(status: 200, body: '{}')
69
+
70
+ described_class.call(client, :get, '/emails/1/versions', query: {})
71
+
72
+ expect(uris).to eq ["#{api}/emails/1/versions"]
73
+ end
74
+
75
+ it 'sends the Authorization header and no Idempotency-Key header without a key' do
76
+ stub = stub_request(:post, "#{api}/emails/1/versions")
77
+ .with(headers: { 'Authorization' => 'Bearer dummy_token' })
78
+ .with { |req| !req.headers.key?('Idempotency-Key') }
79
+ .to_return(status: 201, body: '{}')
80
+
81
+ described_class.call(client, :post, '/emails/1/versions')
82
+
83
+ expect(stub).to have_been_requested
84
+ end
85
+
86
+ it 'sends the Idempotency-Key header with a key' do
87
+ stub = stub_request(:post, "#{api}/emails/1/versions")
88
+ .with(headers: { 'Idempotency-Key' => 'key-1' })
89
+ .to_return(status: 201, body: '{}')
90
+
91
+ described_class.call(client, :post, '/emails/1/versions', idempotency_key: 'key-1')
92
+
93
+ expect(stub).to have_been_requested
94
+ end
95
+
96
+ it 'sends a key with a space at the end as given' do
97
+ stub = stub_request(:post, "#{api}/emails/1/versions")
98
+ .with { |req| req.headers['Idempotency-Key'] == 'a b ' }
99
+ .to_return(status: 400, body: '{"message":"The idempotency key is not valid."}')
100
+
101
+ response = described_class.call(client, :post, '/emails/1/versions', idempotency_key: 'a b ')
102
+
103
+ expect(stub).to have_been_requested
104
+ expect(response.api_error.status).to eq 400
105
+ end
106
+
107
+ it 'returns the HTTP::Response with the ApiResponse methods' do
108
+ stub_request(:get, "#{api}/emails/1").to_return(status: 409, body: '{"message":"Conflict.","code":"version_conflict","etag":"9"}')
109
+
110
+ response = described_class.call(client, :get, '/emails/1')
111
+
112
+ expect(response).to be_a(HTTP::Response)
113
+ expect(response.code).to eq 409
114
+ expect(response.api_error.etag).to eq '9'
115
+ expect(response.idempotent_replay?).to be(false)
116
+ end
117
+
118
+ it 'reads the base URL when the request runs' do
119
+ original = MAILERLITE_API_URL
120
+ Object.send(:remove_const, :MAILERLITE_API_URL)
121
+ Object.const_set(:MAILERLITE_API_URL, 'http://api.example.com/api')
122
+ stub = stub_request(:get, 'http://api.example.com/api/emails/1').to_return(status: 200, body: '{}')
123
+
124
+ described_class.call(client, :get, '/emails/1')
125
+
126
+ expect(stub).to have_been_requested
127
+ ensure
128
+ Object.send(:remove_const, :MAILERLITE_API_URL)
129
+ Object.const_set(:MAILERLITE_API_URL, original)
130
+ end
131
+
132
+ it 'does not change the Hashes of the caller' do
133
+ body = { 'etag' => '42' }.freeze
134
+ query = { 'page' => 1 }.freeze
135
+ stub_request(:delete, "#{api}/emails/1/blocks/2?page=1").to_return(status: 200, body: '{}')
136
+
137
+ expect { described_class.call(client, :delete, '/emails/1/blocks/2', json: body, query: query) }.not_to raise_error
138
+ end
139
+ end
@@ -67,4 +67,43 @@ RSpec.describe MailerLite::Segments do
67
67
  end
68
68
  end
69
69
  end
70
+
71
+ describe '#list query string' do
72
+ it 'sends the params in the query string with no body' do
73
+ stub = stub_api(:get, '/segments', query: { 'limit' => '10', 'page' => '2', 'sort' => '-created_at' })
74
+
75
+ segments.list(limit: 10, page: 2, sort: '-created_at')
76
+
77
+ expect(stub).to have_been_requested
78
+ end
79
+ end
80
+
81
+ describe '#update with filter' do
82
+ it 'sends name and filter' do
83
+ rules = [[{ 'operator' => 'in_any', 'args' => %w[groups 1] }]]
84
+ stub = stub_api(:put, '/segments/1', body: { 'name' => 'VIP', 'filter' => rules })
85
+
86
+ segments.update(segment_id: 1, name: 'VIP', filter: rules)
87
+
88
+ expect(stub).to have_been_requested
89
+ end
90
+ end
91
+
92
+ describe '#get_subscribers cursor' do
93
+ it 'sends cursor' do
94
+ stub = stub_api(:get, '/segments/1/subscribers', query: { 'filter[status]' => 'active', 'limit' => '10', 'cursor' => 'abc' })
95
+
96
+ segments.get_subscribers(segment_id: 1, filter: { status: 'active' }, limit: 10, cursor: 'abc')
97
+
98
+ expect(stub).to have_been_requested
99
+ end
100
+
101
+ it 'still sends after' do
102
+ stub = stub_api(:get, '/segments/1/subscribers', query: { 'after' => '123' })
103
+
104
+ segments.get_subscribers(segment_id: 1, after: 123)
105
+
106
+ expect(stub).to have_been_requested
107
+ end
108
+ end
70
109
  end
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require 'simplecov'
4
4
  SimpleCov.start
5
5
  require 'mailerlite'
6
+ require_relative 'support/request_stub'
6
7
  # This file was generated by the `rspec --init` command. Conventionally, all
7
8
  # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
8
9
  # The generated `.rspec` file contains `--require spec_helper` which will cause
@@ -105,4 +105,61 @@ RSpec.describe MailerLite::Subscribers do
105
105
  end
106
106
  end
107
107
  end
108
+
109
+ describe '#fetch with every filter' do
110
+ it 'sends the documented query params' do
111
+ stub = stub_api(:get, '/subscribers', query: {
112
+ 'filter[status]' => 'active', 'filter[group]' => '1,2', 'filter[automation]' => '3', 'filter[form]' => '4',
113
+ 'filter[site]' => '5', 'filter[page]' => '6', 'filter[import]' => '7', 'filter[post]' => '8',
114
+ 'limit' => '10', 'cursor' => 'abc', 'sort' => '-id', 'include' => 'groups',
115
+ 'start_date' => '2026-01-01', 'end_date' => '2026-01-31', 'with_fields' => '1'
116
+ })
117
+
118
+ subscribers.fetch(
119
+ filter: { status: 'active', group: '1,2', automation: '3', form: '4', site: '5', page: '6', import: '7', post: '8' },
120
+ limit: 10, cursor: 'abc', sort: '-id', include: 'groups', start_date: '2026-01-01', end_date: '2026-01-31', with_fields: true
121
+ )
122
+
123
+ expect(stub).to have_been_requested
124
+ end
125
+
126
+ it 'sends Array filter values comma-separated' do
127
+ stub = stub_api(:get, '/subscribers', query: { 'filter[group]' => '1,2' })
128
+
129
+ subscribers.fetch(filter: { group: %w[1 2] })
130
+
131
+ expect(stub).to have_been_requested
132
+ end
133
+ end
134
+
135
+ describe '#fetch filter order' do
136
+ it 'sends the filter keys in the order the caller gave them' do
137
+ uris = capture_raw_uris
138
+ stub_api(:get, '/subscribers', query: { 'filter[form]' => '4', 'filter[status]' => 'active', 'filter[group]' => '1', 'sort' => 'signup_date' })
139
+
140
+ subscribers.fetch(filter: { form: '4', status: 'active', group: '1' }, sort: 'signup_date')
141
+
142
+ expect(uris).to eq ["#{MAILERLITE_API_URL}/subscribers?filter%5Bform%5D=4&filter%5Bstatus%5D=active&filter%5Bgroup%5D=1&sort=signup_date"]
143
+ end
144
+ end
145
+
146
+ describe '#create with the new body fields' do
147
+ it 'sends resubscribe, double_optin and notes' do
148
+ stub = stub_api(:post, '/subscribers', body: { 'email' => 'a@b.com', 'resubscribe' => false, 'double_optin' => true, 'notes' => ['VIP'] })
149
+
150
+ subscribers.create(email: 'a@b.com', resubscribe: false, double_optin: true, notes: ['VIP'])
151
+
152
+ expect(stub).to have_been_requested
153
+ end
154
+ end
155
+
156
+ describe '#activity_log' do
157
+ it 'sends GET /subscribers/{subscriber}/activity-log with the query' do
158
+ stub = stub_api(:get, '/subscribers/1/activity-log', query: { 'filter[log_name]' => 'email_opened', 'limit' => '10', 'page' => '2' })
159
+
160
+ subscribers.activity_log(subscriber_id: 1, filter: { log_name: 'email_opened' }, limit: 10, page: 2)
161
+
162
+ expect(stub).to have_been_requested
163
+ end
164
+ end
108
165
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ # Reads the JSON fixtures in `spec/fixtures` for the specs that use WebMock.
6
+ module JsonFixture
7
+ FIXTURE_DIR = File.expand_path('../fixtures', __dir__)
8
+
9
+ def load_fixture(name)
10
+ JSON.parse(File.read(File.join(FIXTURE_DIR, "#{name}.json")))
11
+ end
12
+ end
13
+
14
+ if defined?(RSpec)
15
+ RSpec.configure { |config| config.include JsonFixture }
16
+
17
+ # The specs do not depend on the token in the shell.
18
+ RSpec.shared_context 'with the dummy API token' do
19
+ around do |example|
20
+ old_token = ENV.fetch('MAILERLITE_API_TOKEN', nil)
21
+ ENV['MAILERLITE_API_TOKEN'] = 'dummy_token'
22
+ example.run
23
+ ensure
24
+ ENV['MAILERLITE_API_TOKEN'] = old_token
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'webmock/rspec'
4
+
5
+ module RequestStub
6
+ def stub_api(method, path, query: nil, body: nil)
7
+ pattern = {}
8
+ pattern[:query] = query if query
9
+ pattern[:body] = body if body
10
+ stub_request(method, "#{MAILERLITE_API_URL}#{path}")
11
+ .with(**pattern) { |request| body || request.body.to_s.empty? }
12
+ .to_return(status: 200, body: '{}', headers: { 'Content-Type' => 'application/json' })
13
+ end
14
+
15
+ def capture_raw_uris
16
+ uris = []
17
+ allow_any_instance_of(HTTP::Client).to receive(:perform).and_wrap_original do |method, request, options|
18
+ uris << request.uri.to_s
19
+ method.call(request, options)
20
+ end
21
+ uris
22
+ end
23
+ end
24
+
25
+ RSpec.configure { |config| config.include RequestStub }
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mailerlite-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.6
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nikola Milojević
8
8
  - Ahsan Gondal
9
- autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2024-12-06 00:00:00.000000000 Z
11
+ date: 1980-01-02 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
@@ -17,98 +16,98 @@ dependencies:
17
16
  requirements:
18
17
  - - "~>"
19
18
  - !ruby/object:Gem::Version
20
- version: 2.4.1
19
+ version: '2.5'
21
20
  type: :development
22
21
  prerelease: false
23
22
  version_requirements: !ruby/object:Gem::Requirement
24
23
  requirements:
25
24
  - - "~>"
26
25
  - !ruby/object:Gem::Version
27
- version: 2.4.1
26
+ version: '2.5'
28
27
  - !ruby/object:Gem::Dependency
29
28
  name: rake
30
29
  requirement: !ruby/object:Gem::Requirement
31
30
  requirements:
32
31
  - - "~>"
33
32
  - !ruby/object:Gem::Version
34
- version: '13.0'
33
+ version: '13.2'
35
34
  type: :development
36
35
  prerelease: false
37
36
  version_requirements: !ruby/object:Gem::Requirement
38
37
  requirements:
39
38
  - - "~>"
40
39
  - !ruby/object:Gem::Version
41
- version: '13.0'
40
+ version: '13.2'
42
41
  - !ruby/object:Gem::Dependency
43
42
  name: rubocop
44
43
  requirement: !ruby/object:Gem::Requirement
45
44
  requirements:
46
45
  - - "~>"
47
46
  - !ruby/object:Gem::Version
48
- version: '1.7'
47
+ version: '1.69'
49
48
  type: :development
50
49
  prerelease: false
51
50
  version_requirements: !ruby/object:Gem::Requirement
52
51
  requirements:
53
52
  - - "~>"
54
53
  - !ruby/object:Gem::Version
55
- version: '1.7'
54
+ version: '1.69'
56
55
  - !ruby/object:Gem::Dependency
57
56
  name: dotenv
58
57
  requirement: !ruby/object:Gem::Requirement
59
58
  requirements:
60
59
  - - "~>"
61
60
  - !ruby/object:Gem::Version
62
- version: '2.7'
61
+ version: '3.1'
63
62
  type: :runtime
64
63
  prerelease: false
65
64
  version_requirements: !ruby/object:Gem::Requirement
66
65
  requirements:
67
66
  - - "~>"
68
67
  - !ruby/object:Gem::Version
69
- version: '2.7'
68
+ version: '3.1'
70
69
  - !ruby/object:Gem::Dependency
71
70
  name: http
72
71
  requirement: !ruby/object:Gem::Requirement
73
72
  requirements:
74
73
  - - "~>"
75
74
  - !ruby/object:Gem::Version
76
- version: '5.0'
75
+ version: '5.2'
77
76
  type: :runtime
78
77
  prerelease: false
79
78
  version_requirements: !ruby/object:Gem::Requirement
80
79
  requirements:
81
80
  - - "~>"
82
81
  - !ruby/object:Gem::Version
83
- version: '5.0'
82
+ version: '5.2'
84
83
  - !ruby/object:Gem::Dependency
85
84
  name: json
86
85
  requirement: !ruby/object:Gem::Requirement
87
86
  requirements:
88
87
  - - "~>"
89
88
  - !ruby/object:Gem::Version
90
- version: '2.5'
89
+ version: '2.9'
91
90
  type: :runtime
92
91
  prerelease: false
93
92
  version_requirements: !ruby/object:Gem::Requirement
94
93
  requirements:
95
94
  - - "~>"
96
95
  - !ruby/object:Gem::Version
97
- version: '2.5'
96
+ version: '2.9'
98
97
  - !ruby/object:Gem::Dependency
99
98
  name: uri
100
99
  requirement: !ruby/object:Gem::Requirement
101
100
  requirements:
102
101
  - - "~>"
103
102
  - !ruby/object:Gem::Version
104
- version: 0.13.0
103
+ version: '1.0'
105
104
  type: :runtime
106
105
  prerelease: false
107
106
  version_requirements: !ruby/object:Gem::Requirement
108
107
  requirements:
109
108
  - - "~>"
110
109
  - !ruby/object:Gem::Version
111
- version: 0.13.0
110
+ version: '1.0'
112
111
  - !ruby/object:Gem::Dependency
113
112
  name: rspec
114
113
  requirement: !ruby/object:Gem::Requirement
@@ -190,6 +189,8 @@ extensions: []
190
189
  extra_rdoc_files: []
191
190
  files:
192
191
  - ".env.example"
192
+ - ".envrc"
193
+ - ".github/renovate.json"
193
194
  - ".github/workflows/main.yml"
194
195
  - ".github/workflows/publish_gem.yml"
195
196
  - ".gitignore"
@@ -247,31 +248,79 @@ files:
247
248
  - fixtures/webhooks/get.yml
248
249
  - fixtures/webhooks/list.yml
249
250
  - fixtures/webhooks/update.yml
251
+ - flake.lock
252
+ - flake.nix
253
+ - lefthook.yml
250
254
  - lib/mailerlite-ruby.rb
251
255
  - lib/mailerlite.rb
256
+ - lib/mailerlite/api_response.rb
257
+ - lib/mailerlite/automations/automation_emails.rb
258
+ - lib/mailerlite/automations/automation_reports.rb
259
+ - lib/mailerlite/automations/automation_steps.rb
260
+ - lib/mailerlite/automations/automation_templates.rb
261
+ - lib/mailerlite/automations/automation_triggers.rb
252
262
  - lib/mailerlite/automations/automations.rb
253
263
  - lib/mailerlite/batch/batch.rb
264
+ - lib/mailerlite/brand_styles/brand_styles.rb
254
265
  - lib/mailerlite/campaigns/campaigns.rb
255
266
  - lib/mailerlite/client.rb
267
+ - lib/mailerlite/ecommerce/ecommerce.rb
268
+ - lib/mailerlite/emails/emails.rb
269
+ - lib/mailerlite/errors.rb
256
270
  - lib/mailerlite/fields/fields.rb
271
+ - lib/mailerlite/files/files.rb
257
272
  - lib/mailerlite/forms/forms.rb
258
273
  - lib/mailerlite/groups/groups.rb
274
+ - lib/mailerlite/params.rb
275
+ - lib/mailerlite/query_params.rb
276
+ - lib/mailerlite/request.rb
259
277
  - lib/mailerlite/segments/segments.rb
260
278
  - lib/mailerlite/subscribers/subscribers.rb
261
279
  - lib/mailerlite/timezones/timezones.rb
262
280
  - lib/mailerlite/version.rb
263
281
  - lib/mailerlite/webhooks/webhooks.rb
264
282
  - mailerlite-ruby.gemspec
265
- - renovate.json
283
+ - spec/api_response_rspec.rb
284
+ - spec/automation_emails_rspec.rb
285
+ - spec/automation_reports_rspec.rb
286
+ - spec/automation_steps_rspec.rb
287
+ - spec/automation_templates_rspec.rb
288
+ - spec/automation_triggers_rspec.rb
266
289
  - spec/automations_rspec.rb
267
290
  - spec/batches_rspec.rb
291
+ - spec/brand_styles_rspec.rb
268
292
  - spec/campaigns_rspec.rb
293
+ - spec/ecommerce_rspec.rb
294
+ - spec/emails_rspec.rb
269
295
  - spec/fields_rspec.rb
296
+ - spec/files_rspec.rb
297
+ - spec/fixtures/brand_styles.json
298
+ - spec/fixtures/campaign_simple_editor.json
299
+ - spec/fixtures/email.json
300
+ - spec/fixtures/email_block.json
301
+ - spec/fixtures/email_block_created.json
302
+ - spec/fixtures/email_block_created_rejected.json
303
+ - spec/fixtures/email_block_moved.json
304
+ - spec/fixtures/email_block_updated.json
305
+ - spec/fixtures/email_block_updated_rejected.json
306
+ - spec/fixtures/email_block_validation_invalid.json
307
+ - spec/fixtures/email_etag.json
308
+ - spec/fixtures/email_html.json
309
+ - spec/fixtures/email_settings.json
310
+ - spec/fixtures/email_settings_validation.json
311
+ - spec/fixtures/email_template.json
312
+ - spec/fixtures/email_version.json
313
+ - spec/fixtures/email_versions.json
314
+ - spec/fixtures/files.json
270
315
  - spec/forms_rspec.rb
271
316
  - spec/groups_rspec.rb
317
+ - spec/params_rspec.rb
318
+ - spec/request_rspec.rb
272
319
  - spec/segments_rspec.rb
273
320
  - spec/spec_helper.rb
274
321
  - spec/subscribers_rspec.rb
322
+ - spec/support/json_fixture.rb
323
+ - spec/support/request_stub.rb
275
324
  - spec/timezones_rspec.rb
276
325
  - spec/webhooks_rspec.rb
277
326
  homepage: https://www.MailerLite.com
@@ -283,7 +332,6 @@ metadata:
283
332
  source_code_uri: https://github.com/mailerlite/mailerlite-ruby
284
333
  changelog_uri: https://github.com/mailerlite/mailerlite-ruby/blob/main/CHANGELOG.md
285
334
  rubygems_mfa_required: 'true'
286
- post_install_message:
287
335
  rdoc_options: []
288
336
  require_paths:
289
337
  - lib
@@ -291,15 +339,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
291
339
  requirements:
292
340
  - - ">="
293
341
  - !ruby/object:Gem::Version
294
- version: 2.5.0
342
+ version: '3.1'
295
343
  required_rubygems_version: !ruby/object:Gem::Requirement
296
344
  requirements:
297
345
  - - ">="
298
346
  - !ruby/object:Gem::Version
299
347
  version: '0'
300
348
  requirements: []
301
- rubygems_version: 3.5.22
302
- signing_key:
349
+ rubygems_version: 3.6.9
303
350
  specification_version: 4
304
351
  summary: MailerLite's official Ruby SDK
305
352
  test_files: []
File without changes