relateiq_client 0.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.
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'Update a list item for a contact' do
4
+ let(:accounts_url) { 'https://test.relateiq.com/accounts' }
5
+ let(:contacts_url) { 'https://test.relateiq.com/contacts' }
6
+ let(:lists_url) { 'https://test.relateiq.com/lists' }
7
+ let(:email) { 'gulgowski.devyn@example.com' }
8
+
9
+ before do
10
+ stub_request(:get, lists_url)
11
+ .to_return(body: File.readlines('spec/fixtures/lists.json').join)
12
+
13
+ stub_request(:get, "#{lists_url}/list2id/listitems/?contactIds=contactid")
14
+ .to_return(body: File.readlines('spec/fixtures/list_items_by_contact_id.json').join)
15
+
16
+ stub_request(:post, "#{lists_url}/list2id/listitems")
17
+ .to_return(body: File.readlines('spec/fixtures/list_item.json').join)
18
+
19
+ stub_request(:post, "#{accounts_url}")
20
+ .to_return(body: File.readlines('spec/fixtures/account_by_id.json').join)
21
+
22
+ stub_request(:get, "#{contacts_url}/?properties.email=#{email}")
23
+ .to_return(body: File.readlines('spec/fixtures/contacts_by_email.json').join)
24
+
25
+ stub_request(:put, "#{lists_url}/list2id/listitems/listitem1")
26
+ .to_return(body: File.readlines('spec/fixtures/list_item.json').join)
27
+
28
+ stub_request(:put, "#{lists_url}/list2id/listitems/listitem2")
29
+ .to_return(body: File.readlines('spec/fixtures/list_item.json').join)
30
+ end
31
+
32
+ it 'finds list by name, creates an account and creates a list item for that list and account' do
33
+ list = RelateIq::List.find_by_title('Burundi')
34
+ account = RelateIq::Account.create(name: 'Simple Company')
35
+ list_item = list.upsert_item(
36
+ name: 'Simple Name',
37
+ account_id: account.id,
38
+ field_values: [
39
+ { 'sint' => 'Administrator, Civil Service' },
40
+ { 'status' => 'Homeopath' },
41
+ { 'maiores' => 'test123' }
42
+ ]
43
+ )
44
+
45
+ expect(list_item.id).to eq('listitemid')
46
+ expect(list_item.account_id).to eq('accountid')
47
+ end
48
+
49
+ it 'can find a list items by contact id and update their status' do
50
+ contacts = RelateIq::Contact.find_by_email(email)
51
+ list = RelateIq::List.find_by_title('Burundi')
52
+ contacts.each do |contact|
53
+ list_items = list.items_by_contact_id(contact.id)
54
+ list_items.each do |list_item|
55
+ list_item.field_values << { 'status' => 'Homeopath' }
56
+ list_item.save
57
+ end
58
+ end
59
+
60
+ expect(WebMock).to have_requested(:put, "#{lists_url}/list2id/listitems/listitem1")
61
+ .with(body: '{"listId":"list2id","id":"listitem1","name":"hello+test@example.com",' \
62
+ '"contactIds":["contactid"],"fieldValues":{"0":[{"raw":"3"}],"44":[' \
63
+ '{"raw":"3"}]}}')
64
+ expect(WebMock).to have_requested(:put, "#{lists_url}/list2id/listitems/listitem2")
65
+ .with(body: '{"listId":"list2id","id":"listitem2","name":"hello@example.com",' \
66
+ '"contactIds":["contactid"],"fieldValues":{"0":[{"raw":"2"}],"' \
67
+ '44":[{"raw":"3"}]}}')
68
+ end
69
+ end
@@ -0,0 +1,66 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RelateIq::Account do
4
+ let(:account) { RelateIq::Account.new(id: 'accountid', name: 'account_name') }
5
+ let(:accounts_url) { 'https://test.relateiq.com/accounts' }
6
+ let(:json) { '{ "id": "accountid", "name": "account_name" }' }
7
+
8
+ before do
9
+ stub_request(:get, "#{accounts_url}/accountid")
10
+ .to_return(body: File.readlines('spec/fixtures/account_by_id.json').join)
11
+ stub_request(:put, "#{accounts_url}/accountid")
12
+ .to_return(body: File.readlines('spec/fixtures/account_by_id.json').join)
13
+ stub_request(:post, "#{accounts_url}")
14
+ .to_return(body: File.readlines('spec/fixtures/account_by_id.json').join)
15
+ end
16
+
17
+ context '#initiazlie' do
18
+ it 'sets account id and name from initializer' do
19
+ expect(account.id).to eq('accountid')
20
+ expect(account.name).to eq('account_name')
21
+ end
22
+ end
23
+
24
+ context '#to_json' do
25
+ it 'returns a properly serialized account' do
26
+ expect(JSON.parse(account.to_json)).to eq(JSON.parse(json))
27
+ end
28
+ end
29
+
30
+ context '#save' do
31
+ it 'calls correct save url with account serialized to JSON' do
32
+ RelateIq::Account.new(id: 'accountid', name: 'Testing Account').save
33
+ expect(WebMock).to have_requested(:put, "#{accounts_url}/accountid")
34
+ .with(body: '{"name":"Testing Account","id":"accountid"}')
35
+ end
36
+ end
37
+
38
+ context '.find' do
39
+ it 'returns a single account by id' do
40
+ account = RelateIq::Account.find('accountid')
41
+ expect(account.id).to eq('accountid')
42
+ expect(account.name).to eq('Bolstr, Inc.')
43
+ end
44
+ end
45
+
46
+ context '.from_json' do
47
+ it 'returns an account object from json representation' do
48
+ account_from_json = RelateIq::Account.from_json(json)
49
+ expect(account_from_json.id).to eq('accountid')
50
+ expect(account_from_json.name).to eq('account_name')
51
+ end
52
+ end
53
+
54
+ context '.create' do
55
+ it 'creates an account and returns its id' do
56
+ account = RelateIq::Account.create(name: 'Testing Account')
57
+ expect(account.id).to eq('accountid')
58
+ end
59
+
60
+ it 'calls the correct url with body params' do
61
+ RelateIq::Account.create(name: 'Testing Account')
62
+ expect(WebMock).to have_requested(:post, accounts_url)
63
+ .with(body: '{"name":"Testing Account"}').once
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,161 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RelateIq::Contact do
4
+ let(:contacts_url) { 'https://test.relateiq.com/contacts' }
5
+ let(:email) { 'gulgowski.devyn@example.com' }
6
+ let(:id) { 'contactid' }
7
+ before do
8
+ stub_request(:get, "#{contacts_url}/?properties.email=#{email}")
9
+ .to_return(body: File.readlines('spec/fixtures/contacts_by_email.json').join)
10
+
11
+ stub_request(:get, "#{contacts_url}/#{id}")
12
+ .to_return(body: File.readlines('spec/fixtures/contact.json').join)
13
+
14
+ stub_request(:post, "#{contacts_url}")
15
+ .to_return(body: File.readlines('spec/fixtures/contact.json').join)
16
+
17
+ stub_request(:put, "#{contacts_url}/#{id}")
18
+ .to_return(body: File.readlines('spec/fixtures/contact.json').join)
19
+ end
20
+
21
+ context '.find_by_email' do
22
+ it 'returns a Contact with a matching title' do
23
+ contacts = RelateIq::Contact.find_by_email(email)
24
+ expect(contacts[0].id).to eq(id)
25
+ end
26
+
27
+ it 'requests the correct url' do
28
+ RelateIq::Contact.find_by_email(email)
29
+ url = "#{contacts_url}/?properties.email=gulgowski.devyn@example.com"
30
+ expect(WebMock).to have_requested(:get, url).once
31
+ end
32
+ end
33
+
34
+ context '.find' do
35
+ let(:contact) { RelateIq::Contact.find(id) }
36
+
37
+ it 'requests the correct url' do
38
+ RelateIq::Contact.find(id)
39
+ url = "#{contacts_url}/#{id}"
40
+ expect(WebMock).to have_requested(:get, url).once
41
+ end
42
+
43
+ it 'assigns relateiq properties to returned contact' do
44
+ expect(contact.email).to eq(email)
45
+ end
46
+ end
47
+
48
+ context '#initialize' do
49
+ let(:contact_from_api) do
50
+ RelateIq::Contact.new(
51
+ id: 'someid',
52
+ properties: {
53
+ email: [{ value: 'hello@hello.com' }],
54
+ company: [
55
+ { value: 'Bolstr' },
56
+ { value: 'Bolstr, Inc.' }
57
+ ],
58
+ liurl: [{ value: 'https://www.linkedin.com/in/doriankarter' }],
59
+ twhan: [{ value: '@test' }]
60
+ }
61
+ )
62
+ end
63
+
64
+ let(:contact) do
65
+ RelateIq::Contact.new(
66
+ id: 'someid',
67
+ email: 'hello@hello.com',
68
+ first_name: 'Little',
69
+ last_name: 'Wuckert',
70
+ company: ['Bolstr', 'Bolstr, Inc.'],
71
+ linkedin: 'https://www.linkedin.com/in/doriankarter'
72
+ )
73
+ end
74
+
75
+ it 'can have mutltiple values on contact' do
76
+ expect(contact_from_api.company).to eq(['Bolstr', 'Bolstr, Inc.'])
77
+ expect(contact.company).to eq(['Bolstr', 'Bolstr, Inc.'])
78
+ end
79
+
80
+ it 'translates and cleans up relateiq keys' do
81
+ expect(contact_from_api.linkedin).to eq('https://www.linkedin.com/in/doriankarter')
82
+ expect(contact_from_api.twitter).to eq('@test')
83
+ expect(contact_from_api).to_not respond_to(:liurl)
84
+ expect(contact_from_api).to_not respond_to(:twhan)
85
+ end
86
+
87
+ it 'allows initializing by user' do
88
+ expect(contact.id).to eq('someid')
89
+ expect(contact.email).to eq('hello@hello.com')
90
+ expect(contact.first_name).to eq('Little')
91
+ expect(contact.last_name).to eq('Wuckert')
92
+ expect(contact.linkedin).to eq('https://www.linkedin.com/in/doriankarter')
93
+ end
94
+
95
+ it 'assigns relateiq properties contact object' do
96
+ expect(contact_from_api.email).to eq('hello@hello.com')
97
+ end
98
+ end
99
+
100
+ context '#save' do
101
+ let(:contact_to_update) do
102
+ RelateIq::Contact.new(
103
+ id: id,
104
+ email: 'hello@hello.com',
105
+ company: ['Bolstr', 'Bolstr, Inc.'],
106
+ linkedin: 'https://www.linkedin.com/in/doriankarter'
107
+ )
108
+ end
109
+
110
+ let(:contact_to_create) do
111
+ RelateIq::Contact.new(
112
+ email: 'hello@hello.com',
113
+ company: ['Bolstr', 'Bolstr, Inc.'],
114
+ linkedin: 'https://www.linkedin.com/in/doriankarter'
115
+ )
116
+ end
117
+
118
+ it 'executes update when contact has no id' do
119
+ contact_to_create.save
120
+ url = "#{contacts_url}"
121
+ expect(WebMock).to have_requested(:post, url).once
122
+ end
123
+
124
+ it 'executes create (post) when contact has id' do
125
+ contact_to_update.save
126
+ url = "#{contacts_url}/#{contact_to_update.id}"
127
+ expect(WebMock).to have_requested(:put, url).once
128
+ end
129
+ end
130
+
131
+ context '#to_json' do
132
+ let(:contact) do
133
+ RelateIq::Contact.new(
134
+ id: 'someid',
135
+ first_name: 'Little',
136
+ last_name: 'Wuckert',
137
+ email: 'hello@hello.com',
138
+ company: ['Bolstr', 'Bolstr, Inc.'],
139
+ linkedin: 'https://www.linkedin.com/in/doriankarter',
140
+ twitter: '@test'
141
+ )
142
+ end
143
+
144
+ it 'should return a proper relateiq json contact and not include unset attributes' do
145
+ expected_json_hash = {
146
+ id: 'someid',
147
+ properties: {
148
+ name: [{ value: 'Little Wuckert' }],
149
+ email: [{ value: 'hello@hello.com' }],
150
+ company: [
151
+ { value: 'Bolstr' },
152
+ { value: 'Bolstr, Inc.' }
153
+ ],
154
+ liurl: [{ value: 'https://www.linkedin.com/in/doriankarter' }],
155
+ twhan: [{ value: '@test' }]
156
+ }
157
+ }
158
+ expect(JSON.parse(contact.to_json, symbolize_names: true)).to eq(expected_json_hash)
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,133 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RelateIq::ListItem do
4
+ let(:lists_url) { 'https://test.relateiq.com/lists' }
5
+
6
+ before do
7
+ stub_request(:get, lists_url)
8
+ .to_return(body: File.readlines('spec/fixtures/lists.json').join)
9
+
10
+ stub_request(:get, "#{lists_url}/list2id/listitems/?contactIds=contactid")
11
+ .to_return(body: File.readlines('spec/fixtures/list_items_by_contact_id.json').join)
12
+
13
+ stub_request(:put, "#{lists_url}/list2id/listitems/listitemid")
14
+ .to_return(body: File.readlines('spec/fixtures/list_item.json').join)
15
+
16
+ stub_request(:post, "#{lists_url}/list2id/listitems")
17
+ .to_return(body: File.readlines('spec/fixtures/list_item.json').join)
18
+ end
19
+
20
+ context '.create' do
21
+ it 'requests correct url with all parameters' do
22
+ RelateIq::ListItem.create(name: 'itemname', list_id: 'list2id')
23
+ url = "#{lists_url}/list2id/listitems"
24
+ expect(WebMock).to have_requested(:post, url)
25
+ .with(body: '{"listId":"list2id","name":"itemname"}')
26
+ end
27
+
28
+ it 'returns the id of the list item' do
29
+ item = RelateIq::ListItem.create(name: 'itemname', list_id: 'list2id')
30
+ expect(item.id).to eq('listitemid')
31
+ end
32
+ end
33
+
34
+ context '.find_by_contact' do
35
+ let(:list_items) do
36
+ RelateIq::ListItem.find_by_contact('list2id', 'contactid')
37
+ end
38
+
39
+ it 'requests correct url with all parameters' do
40
+ RelateIq::ListItem.find_by_contact('list2id', 'contactid')
41
+ expect(WebMock).to have_requested(:get, "#{lists_url}/list2id/listitems/?contactIds=contactid")
42
+ end
43
+
44
+ it 'returns 2 list items' do
45
+ expect(list_items.count).to eq(2)
46
+ expect(list_items[0].is_a? RelateIq::ListItem).to eq(true)
47
+ expect(list_items[1].is_a? RelateIq::ListItem).to eq(true)
48
+ end
49
+ end
50
+
51
+ context '.from_json' do
52
+ it 'returns an instance of ListItem containing all properties specified in json' do
53
+ json = '{ "listId": "list2id", "name": "test" }'
54
+ deserialized_list_item = RelateIq::ListItem.from_json(json)
55
+ expect(deserialized_list_item.list_id).to eq('list2id')
56
+ end
57
+ end
58
+
59
+ context '#to_json' do
60
+ it 'returns a full representation of list item in relateiq json format' do
61
+ list_item = RelateIq::ListItem.new(
62
+ name: 'itemname',
63
+ list_id: 'list2id',
64
+ field_values: [{ 'nobis' => 'Dancer' }],
65
+ contact_ids: ['contactid1', 'contactid2'],
66
+ account_id: 'accountid'
67
+ )
68
+ json_hash = {
69
+ 'listId' => 'list2id',
70
+ 'name' => 'itemname',
71
+ 'accountId' => 'accountid',
72
+ 'contactIds' => ['contactid1', 'contactid2'],
73
+ 'fieldValues' => {
74
+ '0' => [{ 'raw' => '17' }]
75
+ }
76
+ }
77
+ expect(list_item.to_json).to eq(json_hash.to_json)
78
+ end
79
+
80
+ it 'does not render an account id to a contact type list' do
81
+ list_item = RelateIq::ListItem.new(
82
+ list_id: 'list1id',
83
+ contact_ids: ['contactid1', 'contactid2'],
84
+ account_id: 'accountid'
85
+ )
86
+ json_hash = {
87
+ 'listId' => 'list1id',
88
+ 'contactIds' => ['contactid1', 'contactid2'],
89
+ }
90
+ expect(list_item.to_json).to eq(json_hash.to_json)
91
+ end
92
+
93
+ it 'omits properties that are not filled' do
94
+ list_item = RelateIq::ListItem.new(
95
+ name: 'itemname',
96
+ list_id: 'list2id',
97
+ field_values: [{ 'nobis' => 'Dancer' }]
98
+ )
99
+ json_hash = {
100
+ 'listId' => 'list2id',
101
+ 'name' => 'itemname',
102
+ 'fieldValues' => {
103
+ '0' => [{ 'raw' => '17' }]
104
+ }
105
+ }
106
+ expect(list_item.to_json).to eq(json_hash.to_json)
107
+ end
108
+ end
109
+
110
+ context '#save' do
111
+ it 'saves existing list item' do
112
+ RelateIq::ListItem.new(
113
+ id: 'listitemid',
114
+ name: 'itemname',
115
+ list_id: 'list2id',
116
+ field_values: nil
117
+ ).save
118
+ url = "#{lists_url}/list2id/listitems/listitemid"
119
+ expect(WebMock).to have_requested(:put, url)
120
+ .with(body: '{"listId":"list2id","id":"listitemid","name":"itemname"}')
121
+ end
122
+
123
+ it 'creates new item when no id is supplied' do
124
+ RelateIq::ListItem.new(
125
+ name: 'itemname',
126
+ list_id: 'list2id'
127
+ ).save
128
+ url = "#{lists_url}/list2id/listitems"
129
+ expect(WebMock).to have_requested(:post, url)
130
+ .with(body: '{"listId":"list2id","name":"itemname"}')
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,145 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RelateIq::List do
4
+ let(:lists_url) { 'https://test.relateiq.com/lists' }
5
+ let(:list_class) { RelateIq::List }
6
+ let(:list_2) { RelateIq::List.find_by_title('Burundi') }
7
+ let(:list_hash) do
8
+ {
9
+ id: 'someid',
10
+ title: 'List Title',
11
+ listType: 'contact',
12
+ modifiedDate: 12345678,
13
+ fields: [
14
+ {
15
+ id: '5',
16
+ name: 'unde',
17
+ listOptions: [],
18
+ isMultiSelect: false,
19
+ isEditable: false,
20
+ dataType: 'DateTime'
21
+ },
22
+ {
23
+ id: '9',
24
+ name: 'porro',
25
+ listOptions: [
26
+ {
27
+ id: '0',
28
+ display: 'Teacher, special educational needs'
29
+ },
30
+ {
31
+ id: '1',
32
+ display: 'Applications developer'
33
+ }
34
+ ],
35
+ isMultiSelect: false,
36
+ isEditable: true,
37
+ dataType: 'List'
38
+ }
39
+ ]
40
+ }
41
+ end
42
+ let(:list_json) { list_hash.to_json }
43
+
44
+ before do
45
+ stub_request(:get, lists_url)
46
+ .to_return(body: File.readlines('spec/fixtures/lists.json').join)
47
+
48
+ stub_request(:get, "#{lists_url}/list2id/listitems/?contactIds=contactid")
49
+ .to_return(body: File.readlines('spec/fixtures/list_items_by_contact_id.json').join)
50
+ end
51
+
52
+ context '.all' do
53
+ it 'returns an array of lists' do
54
+ expect(list_class.all.count).to eq(6)
55
+ list_class.all.each do |item|
56
+ expect(item.is_a? list_class).to eq(true)
57
+ end
58
+ end
59
+
60
+ it 'returns field list_options as an array' do
61
+ status_field = RelateIq::List.all[0].fields.find { |f| f[:name] == 'status' }
62
+ status_field[:listOptions].is_a? Array
63
+ end
64
+
65
+ it 'caches a copy in memory and does not call web method more than once' do
66
+ list_class.clean_cache
67
+ list_class.all
68
+ list_class.all
69
+ expect(WebMock).to have_requested(:get, lists_url).once
70
+ end
71
+ end
72
+
73
+ context '.find_by_title' do
74
+ it 'returns a List with a matching title' do
75
+ expect(list_class.find_by_title('Swaziland')).to eq(list_class.all[2])
76
+ end
77
+
78
+ it 'is case insensitive' do
79
+ expect(list_class.find_by_title('swaziland')).to eq(list_class.all[2])
80
+ end
81
+ end
82
+
83
+ context '.from_json' do
84
+ it 'can create an array of lists from json' do
85
+ lists_from_json = RelateIq::List.from_json(File.readlines('spec/fixtures/lists.json').join)
86
+ lists_from_json.each do |l|
87
+ expect(l.is_a?(RelateIq::List)).to eq(true)
88
+ end
89
+ expect(lists_from_json.count).to eq(6)
90
+ end
91
+
92
+ it 'can create a single list from json' do
93
+ list_from_json = RelateIq::List.from_json(list_json)
94
+ expect(list_from_json.id).to eq('someid')
95
+ end
96
+ end
97
+
98
+ context '#initialize' do
99
+ let(:list_from_api) do
100
+ RelateIq::List.new(list_hash)
101
+ end
102
+
103
+ let(:list) do
104
+ RelateIq::List.new(
105
+ id: 'someid',
106
+ title: 'List Title',
107
+ list_type: 'contact'
108
+ )
109
+ end
110
+
111
+ it 'translates and cleans up relateiq keys' do
112
+ expect(list_from_api.list_type).to eq('contact')
113
+ expect(list_from_api.modified_date).to eq(12345678)
114
+ end
115
+
116
+ it 'allows setting attributes directly through the constructor' do
117
+ expect(list.list_type).to eq('contact')
118
+ end
119
+ end
120
+
121
+ context '#items_by_contact_id' do
122
+ it 'can accept a single contact id' do
123
+ list_item_class = RelateIq::ListItem
124
+ allow(list_item_class).to receive(:find_by_contact)
125
+ list_2.items_by_contact_id('contactid')
126
+ expect(list_item_class).to have_received(:find_by_contact).with('list2id', 'contactid')
127
+ end
128
+ end
129
+
130
+ context '#upsert_item' do
131
+ before do
132
+ stub_request(:put, "#{lists_url}/list2id/listitems/listitemid")
133
+ .to_return(body: File.readlines('spec/fixtures/list_item.json').join)
134
+
135
+ stub_request(:post, "#{lists_url}/list2id/listitems")
136
+ .to_return(body: File.readlines('spec/fixtures/list_item.json').join)
137
+ end
138
+
139
+ it 'creates a post request if no id is provided includes current list id' do
140
+ list_2.upsert_item(name: 'test')
141
+ expect(WebMock).to have_requested(:post, "#{lists_url}/list2id/listitems")
142
+ .with(body: '{"listId":"list2id","name":"test"}')
143
+ end
144
+ end
145
+ end