mailshake-ruby 0.1.0 → 0.2.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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +80 -19
  3. data/lib/mailshake/activity.rb +14 -7
  4. data/lib/mailshake/campaigns.rb +10 -5
  5. data/lib/mailshake/client.rb +2 -1
  6. data/lib/mailshake/leads.rb +6 -3
  7. data/lib/mailshake/models/add_recipients_request.rb +8 -0
  8. data/lib/mailshake/models/added_recipients.rb +8 -0
  9. data/lib/mailshake/models/base_model.rb +79 -0
  10. data/lib/mailshake/models/campaign.rb +10 -0
  11. data/lib/mailshake/models/campaign_export.rb +8 -0
  12. data/lib/mailshake/models/campaign_export_request.rb +8 -0
  13. data/lib/mailshake/models/click.rb +11 -0
  14. data/lib/mailshake/models/created_leads.rb +8 -0
  15. data/lib/mailshake/models/lead.rb +11 -0
  16. data/lib/mailshake/models/lead_status.rb +8 -0
  17. data/lib/mailshake/models/list.rb +30 -0
  18. data/lib/mailshake/models/message.rb +8 -0
  19. data/lib/mailshake/models/open.rb +11 -0
  20. data/lib/mailshake/models/recipient.rb +8 -0
  21. data/lib/mailshake/models/reply.rb +11 -0
  22. data/lib/mailshake/models/sender.rb +8 -0
  23. data/lib/mailshake/models/sent_message.rb +11 -0
  24. data/lib/mailshake/models/user.rb +8 -0
  25. data/lib/mailshake/recipients.rb +8 -4
  26. data/lib/mailshake/senders.rb +2 -1
  27. data/lib/mailshake/team.rb +2 -1
  28. data/lib/mailshake.rb +21 -0
  29. data/spec/examples.txt +86 -60
  30. data/spec/mailshake/activity_spec.rb +4 -2
  31. data/spec/mailshake/campaigns_spec.rb +10 -4
  32. data/spec/mailshake/client_spec.rb +1 -0
  33. data/spec/mailshake/leads_spec.rb +5 -2
  34. data/spec/mailshake/models/base_model_spec.rb +118 -0
  35. data/spec/mailshake/models/list_spec.rb +103 -0
  36. data/spec/mailshake/push_spec.rb +1 -0
  37. data/spec/mailshake/recipients_spec.rb +7 -3
  38. data/spec/mailshake/senders_spec.rb +2 -1
  39. data/spec/mailshake/team_spec.rb +2 -1
  40. metadata +24 -2
@@ -3,7 +3,7 @@
3
3
  module Mailshake
4
4
  class Recipients < Base
5
5
  def add(campaign_id:, addresses: nil, list_of_emails: nil, csv_data: nil, add_as_new_list: nil, truncate_extra_fields: nil)
6
- client.post("/recipients/add", camelize_params(
6
+ response = client.post("/recipients/add", camelize_params(
7
7
  campaign_id: campaign_id,
8
8
  addresses: addresses,
9
9
  list_of_emails: list_of_emails,
@@ -11,28 +11,32 @@ module Mailshake
11
11
  add_as_new_list: add_as_new_list,
12
12
  truncate_extra_fields: truncate_extra_fields
13
13
  ))
14
+ Models::AddRecipientsRequest.new(response)
14
15
  end
15
16
 
16
17
  def add_status(status_id:)
17
- client.get("/recipients/add-status", camelize_params(status_id: status_id))
18
+ response = client.get("/recipients/add-status", camelize_params(status_id: status_id))
19
+ Models::AddedRecipients.new(response)
18
20
  end
19
21
 
20
22
  def list(campaign_id:, filter: nil, search: nil, next_token: nil, per_page: nil)
21
- client.get("/recipients/list", camelize_params(
23
+ response = client.get("/recipients/list", camelize_params(
22
24
  campaign_id: campaign_id,
23
25
  filter: filter,
24
26
  search: search,
25
27
  next_token: next_token,
26
28
  per_page: per_page
27
29
  ))
30
+ Models::List.new(response, Models::Recipient)
28
31
  end
29
32
 
30
33
  def get(recipient_id: nil, campaign_id: nil, email_address: nil)
31
- client.get("/recipients/get", camelize_params(
34
+ response = client.get("/recipients/get", camelize_params(
32
35
  recipient_id: recipient_id,
33
36
  campaign_id: campaign_id,
34
37
  email_address: email_address
35
38
  ))
39
+ Models::Recipient.new(response)
36
40
  end
37
41
 
38
42
  def pause(campaign_id:, email_address:)
@@ -3,7 +3,8 @@
3
3
  module Mailshake
4
4
  class Senders < Base
5
5
  def list(search: nil, next_token: nil, per_page: nil)
6
- client.get("/senders/list", camelize_params(search: search, next_token: next_token, per_page: per_page))
6
+ response = client.get("/senders/list", camelize_params(search: search, next_token: next_token, per_page: per_page))
7
+ Models::List.new(response, Models::Sender)
7
8
  end
8
9
  end
9
10
  end
@@ -3,7 +3,8 @@
3
3
  module Mailshake
4
4
  class Team < Base
5
5
  def list_members(search: nil, next_token: nil, per_page: nil)
6
- client.get("/team/list-members", camelize_params(search: search, next_token: next_token, per_page: per_page))
6
+ response = client.get("/team/list-members", camelize_params(search: search, next_token: next_token, per_page: per_page))
7
+ Models::List.new(response, Models::User)
7
8
  end
8
9
  end
9
10
  end
data/lib/mailshake.rb CHANGED
@@ -6,6 +6,27 @@ require 'json'
6
6
  require_relative 'mailshake/version'
7
7
  require_relative 'mailshake/errors'
8
8
  require_relative 'mailshake/configuration'
9
+
10
+ # Models must be loaded before resource classes
11
+ require_relative 'mailshake/models/base_model'
12
+ require_relative 'mailshake/models/list'
13
+ require_relative 'mailshake/models/user'
14
+ require_relative 'mailshake/models/sender'
15
+ require_relative 'mailshake/models/message'
16
+ require_relative 'mailshake/models/campaign'
17
+ require_relative 'mailshake/models/recipient'
18
+ require_relative 'mailshake/models/lead'
19
+ require_relative 'mailshake/models/sent_message'
20
+ require_relative 'mailshake/models/open'
21
+ require_relative 'mailshake/models/click'
22
+ require_relative 'mailshake/models/reply'
23
+ require_relative 'mailshake/models/lead_status'
24
+ require_relative 'mailshake/models/created_leads'
25
+ require_relative 'mailshake/models/add_recipients_request'
26
+ require_relative 'mailshake/models/added_recipients'
27
+ require_relative 'mailshake/models/campaign_export_request'
28
+ require_relative 'mailshake/models/campaign_export'
29
+
9
30
  require_relative 'mailshake/client'
10
31
  require_relative 'mailshake/base'
11
32
  require_relative 'mailshake/campaigns'
data/spec/examples.txt CHANGED
@@ -1,60 +1,86 @@
1
- example_id | status | run_time |
2
- --------------------------------------------- | ------ | --------------- |
3
- ./spec/mailshake/activity_spec.rb[1:1:1] | passed | 0.00026 seconds |
4
- ./spec/mailshake/activity_spec.rb[1:1:2] | passed | 0.00036 seconds |
5
- ./spec/mailshake/activity_spec.rb[1:2:1] | passed | 0.00044 seconds |
6
- ./spec/mailshake/activity_spec.rb[1:3:1] | passed | 0.0004 seconds |
7
- ./spec/mailshake/activity_spec.rb[1:4:1] | passed | 0.00051 seconds |
8
- ./spec/mailshake/activity_spec.rb[1:5:1] | passed | 0.00041 seconds |
9
- ./spec/mailshake/activity_spec.rb[1:6:1] | passed | 0.00034 seconds |
10
- ./spec/mailshake/activity_spec.rb[1:7:1] | passed | 0.00039 seconds |
11
- ./spec/mailshake/campaigns_spec.rb[1:1:1] | passed | 0.00037 seconds |
12
- ./spec/mailshake/campaigns_spec.rb[1:1:2] | passed | 0.00034 seconds |
13
- ./spec/mailshake/campaigns_spec.rb[1:2:1] | passed | 0.00033 seconds |
14
- ./spec/mailshake/campaigns_spec.rb[1:3:1] | passed | 0.00036 seconds |
15
- ./spec/mailshake/campaigns_spec.rb[1:4:1] | passed | 0.00029 seconds |
16
- ./spec/mailshake/campaigns_spec.rb[1:5:1] | passed | 0.00029 seconds |
17
- ./spec/mailshake/campaigns_spec.rb[1:6:1] | passed | 0.00033 seconds |
18
- ./spec/mailshake/campaigns_spec.rb[1:7:1] | passed | 0.00033 seconds |
19
- ./spec/mailshake/client_spec.rb[1:1:1] | passed | 0.00031 seconds |
20
- ./spec/mailshake/client_spec.rb[1:1:2:1] | passed | 0.00054 seconds |
21
- ./spec/mailshake/client_spec.rb[1:2:1] | passed | 0.00022 seconds |
22
- ./spec/mailshake/client_spec.rb[1:2:2] | passed | 0.002 seconds |
23
- ./spec/mailshake/client_spec.rb[1:2:3] | passed | 0.00041 seconds |
24
- ./spec/mailshake/client_spec.rb[1:2:4] | passed | 0.00045 seconds |
25
- ./spec/mailshake/client_spec.rb[1:3:1] | passed | 0.00039 seconds |
26
- ./spec/mailshake/client_spec.rb[1:4:1] | passed | 0.00029 seconds |
27
- ./spec/mailshake/client_spec.rb[1:5:1] | passed | 0.00038 seconds |
28
- ./spec/mailshake/client_spec.rb[1:5:2] | passed | 0.00043 seconds |
29
- ./spec/mailshake/client_spec.rb[1:5:3] | passed | 0.00038 seconds |
30
- ./spec/mailshake/client_spec.rb[1:5:4] | passed | 0.00042 seconds |
31
- ./spec/mailshake/client_spec.rb[1:5:5] | passed | 0.00064 seconds |
32
- ./spec/mailshake/configuration_spec.rb[1:1:1] | passed | 0.00004 seconds |
33
- ./spec/mailshake/configuration_spec.rb[1:1:2] | passed | 0.00004 seconds |
34
- ./spec/mailshake/configuration_spec.rb[1:2:1] | passed | 0.00004 seconds |
35
- ./spec/mailshake/configuration_spec.rb[1:2:2] | passed | 0.00004 seconds |
36
- ./spec/mailshake/configuration_spec.rb[1:2:3] | passed | 0.00005 seconds |
37
- ./spec/mailshake/configuration_spec.rb[1:3:1] | passed | 0.00005 seconds |
38
- ./spec/mailshake/configuration_spec.rb[1:3:2] | passed | 0.00004 seconds |
39
- ./spec/mailshake/leads_spec.rb[1:1:1] | passed | 0.00037 seconds |
40
- ./spec/mailshake/leads_spec.rb[1:1:2] | passed | 0.00043 seconds |
41
- ./spec/mailshake/leads_spec.rb[1:2:1] | passed | 0.00047 seconds |
42
- ./spec/mailshake/leads_spec.rb[1:3:1] | passed | 0.00039 seconds |
43
- ./spec/mailshake/leads_spec.rb[1:4:1] | passed | 0.00035 seconds |
44
- ./spec/mailshake/leads_spec.rb[1:5:1] | passed | 0.00037 seconds |
45
- ./spec/mailshake/leads_spec.rb[1:6:1] | passed | 0.00041 seconds |
46
- ./spec/mailshake/push_spec.rb[1:1:1] | passed | 0.00183 seconds |
47
- ./spec/mailshake/push_spec.rb[1:1:2] | passed | 0.00026 seconds |
48
- ./spec/mailshake/push_spec.rb[1:2:1] | passed | 0.00032 seconds |
49
- ./spec/mailshake/recipients_spec.rb[1:1:1] | passed | 0.00035 seconds |
50
- ./spec/mailshake/recipients_spec.rb[1:2:1] | passed | 0.00074 seconds |
51
- ./spec/mailshake/recipients_spec.rb[1:3:1] | passed | 0.0005 seconds |
52
- ./spec/mailshake/recipients_spec.rb[1:3:2] | passed | 0.00049 seconds |
53
- ./spec/mailshake/recipients_spec.rb[1:4:1] | passed | 0.00112 seconds |
54
- ./spec/mailshake/recipients_spec.rb[1:5:1] | passed | 0.01614 seconds |
55
- ./spec/mailshake/recipients_spec.rb[1:6:1] | passed | 0.00037 seconds |
56
- ./spec/mailshake/recipients_spec.rb[1:7:1] | passed | 0.00035 seconds |
57
- ./spec/mailshake/senders_spec.rb[1:1:1] | passed | 0.00027 seconds |
58
- ./spec/mailshake/senders_spec.rb[1:1:2] | passed | 0.00054 seconds |
59
- ./spec/mailshake/team_spec.rb[1:1:1] | passed | 0.0003 seconds |
60
- ./spec/mailshake/team_spec.rb[1:1:2] | passed | 0.00039 seconds |
1
+ example_id | status | run_time |
2
+ ------------------------------------------------- | ------ | --------------- |
3
+ ./spec/mailshake/activity_spec.rb[1:1:1] | passed | 0.0003 seconds |
4
+ ./spec/mailshake/activity_spec.rb[1:1:2] | passed | 0.00075 seconds |
5
+ ./spec/mailshake/activity_spec.rb[1:2:1] | passed | 0.00038 seconds |
6
+ ./spec/mailshake/activity_spec.rb[1:3:1] | passed | 0.00048 seconds |
7
+ ./spec/mailshake/activity_spec.rb[1:4:1] | passed | 0.00037 seconds |
8
+ ./spec/mailshake/activity_spec.rb[1:5:1] | passed | 0.00037 seconds |
9
+ ./spec/mailshake/activity_spec.rb[1:6:1] | passed | 0.0004 seconds |
10
+ ./spec/mailshake/activity_spec.rb[1:7:1] | passed | 0.0004 seconds |
11
+ ./spec/mailshake/campaigns_spec.rb[1:1:1] | passed | 0.00049 seconds |
12
+ ./spec/mailshake/campaigns_spec.rb[1:1:2] | passed | 0.00082 seconds |
13
+ ./spec/mailshake/campaigns_spec.rb[1:2:1] | passed | 0.01488 seconds |
14
+ ./spec/mailshake/campaigns_spec.rb[1:3:1] | passed | 0.00045 seconds |
15
+ ./spec/mailshake/campaigns_spec.rb[1:4:1] | passed | 0.00039 seconds |
16
+ ./spec/mailshake/campaigns_spec.rb[1:5:1] | passed | 0.0005 seconds |
17
+ ./spec/mailshake/campaigns_spec.rb[1:6:1] | passed | 0.00053 seconds |
18
+ ./spec/mailshake/campaigns_spec.rb[1:7:1] | passed | 0.00066 seconds |
19
+ ./spec/mailshake/client_spec.rb[1:1:1] | passed | 0.00004 seconds |
20
+ ./spec/mailshake/client_spec.rb[1:1:2:1] | passed | 0.00058 seconds |
21
+ ./spec/mailshake/client_spec.rb[1:2:1] | passed | 0.00021 seconds |
22
+ ./spec/mailshake/client_spec.rb[1:2:2] | passed | 0.00042 seconds |
23
+ ./spec/mailshake/client_spec.rb[1:2:3] | passed | 0.00025 seconds |
24
+ ./spec/mailshake/client_spec.rb[1:2:4] | passed | 0.00038 seconds |
25
+ ./spec/mailshake/client_spec.rb[1:3:1] | passed | 0.00028 seconds |
26
+ ./spec/mailshake/client_spec.rb[1:4:1] | passed | 0.00036 seconds |
27
+ ./spec/mailshake/client_spec.rb[1:5:1] | passed | 0.00029 seconds |
28
+ ./spec/mailshake/client_spec.rb[1:5:2] | passed | 0.0003 seconds |
29
+ ./spec/mailshake/client_spec.rb[1:5:3] | passed | 0.00039 seconds |
30
+ ./spec/mailshake/client_spec.rb[1:5:4] | passed | 0.00032 seconds |
31
+ ./spec/mailshake/client_spec.rb[1:5:5] | passed | 0.00036 seconds |
32
+ ./spec/mailshake/configuration_spec.rb[1:1:1] | passed | 0.00003 seconds |
33
+ ./spec/mailshake/configuration_spec.rb[1:1:2] | passed | 0.00004 seconds |
34
+ ./spec/mailshake/configuration_spec.rb[1:2:1] | passed | 0.00003 seconds |
35
+ ./spec/mailshake/configuration_spec.rb[1:2:2] | passed | 0.00003 seconds |
36
+ ./spec/mailshake/configuration_spec.rb[1:2:3] | passed | 0.00003 seconds |
37
+ ./spec/mailshake/configuration_spec.rb[1:3:1] | passed | 0.00003 seconds |
38
+ ./spec/mailshake/configuration_spec.rb[1:3:2] | passed | 0.00004 seconds |
39
+ ./spec/mailshake/leads_spec.rb[1:1:1] | passed | 0.00106 seconds |
40
+ ./spec/mailshake/leads_spec.rb[1:1:2] | passed | 0.00046 seconds |
41
+ ./spec/mailshake/leads_spec.rb[1:2:1] | passed | 0.00159 seconds |
42
+ ./spec/mailshake/leads_spec.rb[1:3:1] | passed | 0.00112 seconds |
43
+ ./spec/mailshake/leads_spec.rb[1:4:1] | passed | 0.00199 seconds |
44
+ ./spec/mailshake/leads_spec.rb[1:5:1] | passed | 0.00145 seconds |
45
+ ./spec/mailshake/leads_spec.rb[1:6:1] | passed | 0.0003 seconds |
46
+ ./spec/mailshake/models/base_model_spec.rb[1:1:1] | passed | 0.00004 seconds |
47
+ ./spec/mailshake/models/base_model_spec.rb[1:1:2] | passed | 0.00004 seconds |
48
+ ./spec/mailshake/models/base_model_spec.rb[1:1:3] | passed | 0.00004 seconds |
49
+ ./spec/mailshake/models/base_model_spec.rb[1:2:1] | passed | 0.00005 seconds |
50
+ ./spec/mailshake/models/base_model_spec.rb[1:2:2] | passed | 0.00004 seconds |
51
+ ./spec/mailshake/models/base_model_spec.rb[1:3:1] | passed | 0.00004 seconds |
52
+ ./spec/mailshake/models/base_model_spec.rb[1:3:2] | passed | 0.00006 seconds |
53
+ ./spec/mailshake/models/base_model_spec.rb[1:3:3] | passed | 0.00003 seconds |
54
+ ./spec/mailshake/models/base_model_spec.rb[1:3:4] | passed | 0.00005 seconds |
55
+ ./spec/mailshake/models/base_model_spec.rb[1:4:1] | passed | 0.00004 seconds |
56
+ ./spec/mailshake/models/base_model_spec.rb[1:4:2] | passed | 0.00004 seconds |
57
+ ./spec/mailshake/models/base_model_spec.rb[1:5:1] | passed | 0.00004 seconds |
58
+ ./spec/mailshake/models/base_model_spec.rb[1:6:1] | passed | 0.0001 seconds |
59
+ ./spec/mailshake/models/base_model_spec.rb[1:6:2] | passed | 0.00003 seconds |
60
+ ./spec/mailshake/models/list_spec.rb[1:1:1] | passed | 0.00006 seconds |
61
+ ./spec/mailshake/models/list_spec.rb[1:1:2] | passed | 0.00003 seconds |
62
+ ./spec/mailshake/models/list_spec.rb[1:1:3] | passed | 0.00003 seconds |
63
+ ./spec/mailshake/models/list_spec.rb[1:2:1] | passed | 0.00004 seconds |
64
+ ./spec/mailshake/models/list_spec.rb[1:2:2] | passed | 0.00134 seconds |
65
+ ./spec/mailshake/models/list_spec.rb[1:3:1] | passed | 0.00005 seconds |
66
+ ./spec/mailshake/models/list_spec.rb[1:3:2] | passed | 0.00005 seconds |
67
+ ./spec/mailshake/models/list_spec.rb[1:3:3] | passed | 0.00004 seconds |
68
+ ./spec/mailshake/models/list_spec.rb[1:3:4] | passed | 0.00005 seconds |
69
+ ./spec/mailshake/models/list_spec.rb[1:3:5] | passed | 0.00004 seconds |
70
+ ./spec/mailshake/models/list_spec.rb[1:4:1] | passed | 0.00004 seconds |
71
+ ./spec/mailshake/models/list_spec.rb[1:5:1] | passed | 0.00004 seconds |
72
+ ./spec/mailshake/push_spec.rb[1:1:1] | passed | 0.00023 seconds |
73
+ ./spec/mailshake/push_spec.rb[1:1:2] | passed | 0.00049 seconds |
74
+ ./spec/mailshake/push_spec.rb[1:2:1] | passed | 0.0003 seconds |
75
+ ./spec/mailshake/recipients_spec.rb[1:1:1] | passed | 0.00054 seconds |
76
+ ./spec/mailshake/recipients_spec.rb[1:2:1] | passed | 0.00036 seconds |
77
+ ./spec/mailshake/recipients_spec.rb[1:3:1] | passed | 0.0004 seconds |
78
+ ./spec/mailshake/recipients_spec.rb[1:3:2] | passed | 0.00192 seconds |
79
+ ./spec/mailshake/recipients_spec.rb[1:4:1] | passed | 0.00038 seconds |
80
+ ./spec/mailshake/recipients_spec.rb[1:5:1] | passed | 0.00039 seconds |
81
+ ./spec/mailshake/recipients_spec.rb[1:6:1] | passed | 0.00032 seconds |
82
+ ./spec/mailshake/recipients_spec.rb[1:7:1] | passed | 0.00038 seconds |
83
+ ./spec/mailshake/senders_spec.rb[1:1:1] | passed | 0.00031 seconds |
84
+ ./spec/mailshake/senders_spec.rb[1:1:2] | passed | 0.0004 seconds |
85
+ ./spec/mailshake/team_spec.rb[1:1:1] | passed | 0.00026 seconds |
86
+ ./spec/mailshake/team_spec.rb[1:1:2] | passed | 0.00045 seconds |
@@ -13,7 +13,8 @@ RSpec.describe Mailshake::Activity do
13
13
  headers: { "Content-Type" => "application/json" })
14
14
 
15
15
  result = activity.sent
16
- expect(result["results"]).to eq([])
16
+ expect(result).to be_a(Mailshake::Models::List)
17
+ expect(result.results).to eq([])
17
18
  end
18
19
 
19
20
  it "passes campaign and pagination params" do
@@ -34,7 +35,8 @@ RSpec.describe Mailshake::Activity do
34
35
  headers: { "Content-Type" => "application/json" })
35
36
 
36
37
  result = activity.opens(campaign_id: "1", exclude_duplicates: "true")
37
- expect(result["results"]).to eq([])
38
+ expect(result).to be_a(Mailshake::Models::List)
39
+ expect(result.results).to eq([])
38
40
  end
39
41
  end
40
42
 
@@ -13,7 +13,8 @@ RSpec.describe Mailshake::Campaigns do
13
13
  headers: { "Content-Type" => "application/json" })
14
14
 
15
15
  result = campaigns.list
16
- expect(result["results"]).to eq([])
16
+ expect(result).to be_a(Mailshake::Models::List)
17
+ expect(result.results).to eq([])
17
18
  end
18
19
 
19
20
  it "passes search and pagination params" do
@@ -34,7 +35,8 @@ RSpec.describe Mailshake::Campaigns do
34
35
  headers: { "Content-Type" => "application/json" })
35
36
 
36
37
  result = campaigns.get(campaign_id: "1")
37
- expect(result["title"]).to eq("Test Campaign")
38
+ expect(result).to be_a(Mailshake::Models::Campaign)
39
+ expect(result.title).to eq("Test Campaign")
38
40
  end
39
41
  end
40
42
 
@@ -46,7 +48,8 @@ RSpec.describe Mailshake::Campaigns do
46
48
  headers: { "Content-Type" => "application/json" })
47
49
 
48
50
  result = campaigns.create(title: "New Campaign", sender_id: 5)
49
- expect(result["title"]).to eq("New Campaign")
51
+ expect(result).to be_a(Mailshake::Models::Campaign)
52
+ expect(result.title).to eq("New Campaign")
50
53
  end
51
54
  end
52
55
 
@@ -80,6 +83,7 @@ RSpec.describe Mailshake::Campaigns do
80
83
  headers: { "Content-Type" => "application/json" })
81
84
 
82
85
  result = campaigns.export(campaign_ids: [1, 2], export_type: "csv", timezone: "US/Pacific")
86
+ expect(result).to be_a(Mailshake::Models::CampaignExportRequest)
83
87
  expect(result["statusID"]).to eq(42)
84
88
  end
85
89
  end
@@ -92,7 +96,9 @@ RSpec.describe Mailshake::Campaigns do
92
96
  headers: { "Content-Type" => "application/json" })
93
97
 
94
98
  result = campaigns.export_status(status_id: "42")
95
- expect(result["isFinished"]).to be true
99
+ expect(result).to be_a(Mailshake::Models::CampaignExport)
100
+ expect(result.is_finished).to be true
101
+ expect(result.csv_download_url).to eq("https://example.com/file.csv")
96
102
  end
97
103
  end
98
104
  end
@@ -80,6 +80,7 @@ RSpec.describe Mailshake::Client do
80
80
  headers: { "Content-Type" => "application/json" })
81
81
 
82
82
  result = client.me
83
+ expect(result).to be_a(Mailshake::Models::User)
83
84
  expect(result["email"]).to eq("test@example.com")
84
85
  end
85
86
  end
@@ -13,7 +13,8 @@ RSpec.describe Mailshake::Leads do
13
13
  headers: { "Content-Type" => "application/json" })
14
14
 
15
15
  result = leads.list
16
- expect(result["results"]).to eq([])
16
+ expect(result).to be_a(Mailshake::Models::List)
17
+ expect(result.results).to eq([])
17
18
  end
18
19
 
19
20
  it "passes filter params" do
@@ -34,7 +35,8 @@ RSpec.describe Mailshake::Leads do
34
35
  headers: { "Content-Type" => "application/json" })
35
36
 
36
37
  result = leads.get(lead_id: "42")
37
- expect(result["status"]).to eq("open")
38
+ expect(result).to be_a(Mailshake::Models::Lead)
39
+ expect(result.status).to eq("open")
38
40
  end
39
41
  end
40
42
 
@@ -46,6 +48,7 @@ RSpec.describe Mailshake::Leads do
46
48
  headers: { "Content-Type" => "application/json" })
47
49
 
48
50
  result = leads.create(campaign_id: 1, email_addresses: ["john@example.com"])
51
+ expect(result).to be_a(Mailshake::Models::CreatedLeads)
49
52
  expect(result["results"].length).to eq(1)
50
53
  end
51
54
  end
@@ -0,0 +1,118 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe Mailshake::Models::BaseModel do
6
+ describe "creating from hash with camelCase keys" do
7
+ it "creates a model from a hash" do
8
+ model = described_class.new("firstName" => "John", "lastName" => "Doe")
9
+ expect(model.first_name).to eq("John")
10
+ expect(model.last_name).to eq("Doe")
11
+ end
12
+
13
+ it "handles single-word keys" do
14
+ model = described_class.new("id" => 42, "title" => "Test")
15
+ expect(model.id).to eq(42)
16
+ expect(model.title).to eq("Test")
17
+ end
18
+
19
+ it "handles keys with multiple capitals" do
20
+ model = described_class.new("emailAddress" => "test@example.com", "teamID" => 5)
21
+ expect(model.email_address).to eq("test@example.com")
22
+ expect(model.team_id).to eq(5)
23
+ end
24
+ end
25
+
26
+ describe "snake_case accessor methods" do
27
+ it "defines accessor methods for all keys" do
28
+ model = described_class.new("isArchived" => true, "createdDate" => "2026-01-01")
29
+ expect(model.is_archived).to be true
30
+ expect(model.created_date).to eq("2026-01-01")
31
+ end
32
+
33
+ it "responds to accessor methods" do
34
+ model = described_class.new("firstName" => "John")
35
+ expect(model.respond_to?(:first_name)).to be true
36
+ expect(model.respond_to?(:nonexistent)).to be false
37
+ end
38
+ end
39
+
40
+ describe "nested model hydration" do
41
+ it "hydrates has_one associations" do
42
+ campaign = Mailshake::Models::Campaign.new(
43
+ "id" => 1,
44
+ "title" => "Test",
45
+ "sender" => { "id" => 10, "emailAddress" => "sender@example.com" }
46
+ )
47
+ expect(campaign.sender).to be_a(Mailshake::Models::Sender)
48
+ expect(campaign.sender.id).to eq(10)
49
+ expect(campaign.sender.email_address).to eq("sender@example.com")
50
+ end
51
+
52
+ it "hydrates has_many associations" do
53
+ campaign = Mailshake::Models::Campaign.new(
54
+ "id" => 1,
55
+ "title" => "Test",
56
+ "messages" => [
57
+ { "id" => 1, "subject" => "Hello" },
58
+ { "id" => 2, "subject" => "Follow up" }
59
+ ]
60
+ )
61
+ expect(campaign.messages).to be_an(Array)
62
+ expect(campaign.messages.length).to eq(2)
63
+ expect(campaign.messages.first).to be_a(Mailshake::Models::Message)
64
+ expect(campaign.messages.first.subject).to eq("Hello")
65
+ end
66
+
67
+ it "handles nil nested values" do
68
+ campaign = Mailshake::Models::Campaign.new("id" => 1, "sender" => nil)
69
+ expect(campaign.sender).to be_nil
70
+ end
71
+
72
+ it "handles deeply nested models" do
73
+ lead = Mailshake::Models::Lead.new(
74
+ "id" => 1,
75
+ "campaign" => {
76
+ "id" => 10,
77
+ "sender" => { "id" => 20, "emailAddress" => "sender@example.com" }
78
+ }
79
+ )
80
+ expect(lead.campaign).to be_a(Mailshake::Models::Campaign)
81
+ expect(lead.campaign.sender).to be_a(Mailshake::Models::Sender)
82
+ expect(lead.campaign.sender.email_address).to eq("sender@example.com")
83
+ end
84
+ end
85
+
86
+ describe "[] backwards compatibility" do
87
+ it "accesses original hash keys via []" do
88
+ model = described_class.new("firstName" => "John", "emailAddress" => "john@example.com")
89
+ expect(model["firstName"]).to eq("John")
90
+ expect(model["emailAddress"]).to eq("john@example.com")
91
+ end
92
+
93
+ it "returns nil for missing keys" do
94
+ model = described_class.new("id" => 1)
95
+ expect(model["missing"]).to be_nil
96
+ end
97
+ end
98
+
99
+ describe "#to_h" do
100
+ it "returns the original hash" do
101
+ data = { "id" => 1, "firstName" => "John", "emailAddress" => "john@example.com" }
102
+ model = described_class.new(data)
103
+ expect(model.to_h).to eq(data)
104
+ end
105
+ end
106
+
107
+ describe "with empty hash" do
108
+ it "handles empty hash" do
109
+ model = described_class.new({})
110
+ expect(model.to_h).to eq({})
111
+ end
112
+
113
+ it "handles nil" do
114
+ model = described_class.new(nil)
115
+ expect(model.to_h).to eq({})
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ RSpec.describe Mailshake::Models::List do
6
+ describe "results array with model objects" do
7
+ it "wraps results in model objects" do
8
+ data = {
9
+ "results" => [
10
+ { "id" => 1, "title" => "Campaign 1" },
11
+ { "id" => 2, "title" => "Campaign 2" }
12
+ ],
13
+ "nextToken" => "abc123"
14
+ }
15
+
16
+ list = described_class.new(data, Mailshake::Models::Campaign)
17
+ expect(list.results.length).to eq(2)
18
+ expect(list.results.first).to be_a(Mailshake::Models::Campaign)
19
+ expect(list.results.first.title).to eq("Campaign 1")
20
+ expect(list.results.last.title).to eq("Campaign 2")
21
+ end
22
+
23
+ it "handles empty results" do
24
+ data = { "results" => [] }
25
+ list = described_class.new(data, Mailshake::Models::Campaign)
26
+ expect(list.results).to eq([])
27
+ end
28
+
29
+ it "handles missing results key" do
30
+ list = described_class.new({}, Mailshake::Models::Campaign)
31
+ expect(list.results).to eq([])
32
+ end
33
+ end
34
+
35
+ describe "next_token" do
36
+ it "exposes next_token from response" do
37
+ data = { "results" => [], "nextToken" => "page2" }
38
+ list = described_class.new(data, Mailshake::Models::Campaign)
39
+ expect(list.next_token).to eq("page2")
40
+ end
41
+
42
+ it "returns nil when no next_token" do
43
+ data = { "results" => [] }
44
+ list = described_class.new(data, Mailshake::Models::Campaign)
45
+ expect(list.next_token).to be_nil
46
+ end
47
+ end
48
+
49
+ describe "Enumerable methods" do
50
+ let(:data) do
51
+ {
52
+ "results" => [
53
+ { "id" => 1, "title" => "First" },
54
+ { "id" => 2, "title" => "Second" },
55
+ { "id" => 3, "title" => "Third" }
56
+ ]
57
+ }
58
+ end
59
+ let(:list) { described_class.new(data, Mailshake::Models::Campaign) }
60
+
61
+ it "supports each" do
62
+ titles = []
63
+ list.each { |campaign| titles << campaign.title }
64
+ expect(titles).to eq(["First", "Second", "Third"])
65
+ end
66
+
67
+ it "supports map" do
68
+ ids = list.map(&:id)
69
+ expect(ids).to eq([1, 2, 3])
70
+ end
71
+
72
+ it "supports select" do
73
+ selected = list.select { |c| c.id > 1 }
74
+ expect(selected.length).to eq(2)
75
+ end
76
+
77
+ it "supports first" do
78
+ expect(list.first).to be_a(Mailshake::Models::Campaign)
79
+ expect(list.first.id).to eq(1)
80
+ end
81
+
82
+ it "supports count" do
83
+ expect(list.count).to eq(3)
84
+ end
85
+ end
86
+
87
+ describe "[] backwards compatibility" do
88
+ it "accesses original hash keys" do
89
+ data = { "results" => [{ "id" => 1 }], "nextToken" => "abc" }
90
+ list = described_class.new(data, Mailshake::Models::Campaign)
91
+ expect(list["results"]).to eq([{ "id" => 1 }])
92
+ expect(list["nextToken"]).to eq("abc")
93
+ end
94
+ end
95
+
96
+ describe "#to_h" do
97
+ it "returns the original data hash" do
98
+ data = { "results" => [{ "id" => 1 }], "nextToken" => "abc" }
99
+ list = described_class.new(data, Mailshake::Models::Campaign)
100
+ expect(list.to_h).to eq(data)
101
+ end
102
+ end
103
+ end
@@ -14,6 +14,7 @@ RSpec.describe Mailshake::Push do
14
14
  headers: { "Content-Type" => "application/json" })
15
15
 
16
16
  result = push.create(target_url: "https://example.com/webhook", event: "reply")
17
+ expect(result).to be_a(Hash)
17
18
  expect(result["id"]).to eq(1)
18
19
  end
19
20
 
@@ -14,6 +14,7 @@ RSpec.describe Mailshake::Recipients do
14
14
  headers: { "Content-Type" => "application/json" })
15
15
 
16
16
  result = recipients.add(campaign_id: 1, addresses: [{ emailAddress: "john@example.com" }])
17
+ expect(result).to be_a(Mailshake::Models::AddRecipientsRequest)
17
18
  expect(result["statusID"]).to eq(10)
18
19
  end
19
20
  end
@@ -26,7 +27,8 @@ RSpec.describe Mailshake::Recipients do
26
27
  headers: { "Content-Type" => "application/json" })
27
28
 
28
29
  result = recipients.add_status(status_id: "10")
29
- expect(result["isFinished"]).to be true
30
+ expect(result).to be_a(Mailshake::Models::AddedRecipients)
31
+ expect(result.is_finished).to be true
30
32
  end
31
33
  end
32
34
 
@@ -38,7 +40,8 @@ RSpec.describe Mailshake::Recipients do
38
40
  headers: { "Content-Type" => "application/json" })
39
41
 
40
42
  result = recipients.list(campaign_id: "1")
41
- expect(result["results"]).to eq([])
43
+ expect(result).to be_a(Mailshake::Models::List)
44
+ expect(result.results).to eq([])
42
45
  end
43
46
 
44
47
  it "passes filter and pagination params" do
@@ -59,7 +62,8 @@ RSpec.describe Mailshake::Recipients do
59
62
  headers: { "Content-Type" => "application/json" })
60
63
 
61
64
  result = recipients.get(recipient_id: "100")
62
- expect(result["emailAddress"]).to eq("john@example.com")
65
+ expect(result).to be_a(Mailshake::Models::Recipient)
66
+ expect(result.email_address).to eq("john@example.com")
63
67
  end
64
68
  end
65
69
 
@@ -13,7 +13,8 @@ RSpec.describe Mailshake::Senders do
13
13
  headers: { "Content-Type" => "application/json" })
14
14
 
15
15
  result = senders.list
16
- expect(result["results"]).to eq([])
16
+ expect(result).to be_a(Mailshake::Models::List)
17
+ expect(result.results).to eq([])
17
18
  end
18
19
 
19
20
  it "passes search and pagination params" do
@@ -13,7 +13,8 @@ RSpec.describe Mailshake::Team do
13
13
  headers: { "Content-Type" => "application/json" })
14
14
 
15
15
  result = team.list_members
16
- expect(result["results"]).to eq([])
16
+ expect(result).to be_a(Mailshake::Models::List)
17
+ expect(result.results).to eq([])
17
18
  end
18
19
 
19
20
  it "passes search and pagination params" do