@friggframework/api-module-zoho-crm 1.0.1-canary.332f986.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.
package/.env.example ADDED
@@ -0,0 +1,4 @@
1
+ ZOHO_CRM_CLIENT_ID=
2
+ ZOHO_CRM_CLIENT_SECRET=
3
+ ZOHO_CRM_SCOPE=ZohoCRM.users.ALL,ZohoCRM.org.ALL,ZohoCRM.settings.roles.ALL,ZohoCRM.settings.profiles.ALL
4
+ REDIRECT_URI=http://localhost:3000/redirect
package/LICENSE.md ADDED
@@ -0,0 +1,16 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Left Hook Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
6
+ documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
7
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
8
+ persons to whom the Software is furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or
11
+ substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
14
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
15
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,269 @@
1
+ # Zoho CRM
2
+
3
+ This is the API Module for Zoho CRM that allows the [Frigg](https://friggframework.org) code to talk to the Zoho CRM API.
4
+
5
+ [Link to the Zoho CRM REST API Postman collection.](https://www.postman.com/zohocrmdevelopers/workspace/zoho-crm-developers/collection/8522016-0a15778a-ccb1-4676-98b7-4cf1fe7fc940?ctx=documentation)
6
+
7
+ Read more on the [Frigg documentation site](https://docs.friggframework.org/api-modules/list/zoho-crm
8
+
9
+
10
+ ## Setup a Zoho CRM developer account
11
+
12
+ In order to test this api module, you will need to populate your local `.env` file with a set of credentials (`ZOHO_CRM_CLIENT_ID` and `ZOHO_CRM_CLIENT_SECRET`).
13
+
14
+ To get those, you will need to sign up for a Zoho CRM developer account and [create a new API client](https://www.zoho.com/crm/developer/docs/api/v6/register-client.html), which is explained below.
15
+
16
+ If you've already done this, skip to the next section.
17
+
18
+ 1. Go to https://www.zoho.com/crm/developer/ and click `Sign Up For Free`
19
+ ![alt text](images/image.jpg)
20
+
21
+
22
+ 2. Once you're in, set up your example company. Check the `Load Sample Data` box.
23
+ ![alt text](images/image-1.jpg)
24
+
25
+
26
+ 3. Go to your account's API Console at https://api-console.zoho.com/.
27
+
28
+ * You may be asked to verify your email address before accessing your API Console
29
+ ![alt text](images/image-2.jpg)
30
+
31
+ * You'll receive an email with a verification link
32
+ ![alt text](images/image-3.jpg)
33
+
34
+
35
+ 4. From your API Console, you are able to create client for your account. For our purposes, select `Server-based Applications`.
36
+ ![alt text](images/image-5.jpg)
37
+
38
+
39
+ 5. When filling in the details for your new client, make sure to use `http://localhost:3000/redirect/zoho-crm` in the `Authorized Redirect URIs` field.
40
+ ![alt text](images/image-6.jpg)
41
+
42
+
43
+ 6. After creating the client, you will be sent to the `Client Secret` tab where you can grab your Client ID and Client Secret.
44
+ ![alt text](images/image-7.jpg)
45
+
46
+
47
+ ## Set up your local `.env` file
48
+
49
+ 1. Make a copy of `.env.example` and name it `.env`.
50
+
51
+
52
+ 2. Grab your Client ID and Client Secret from the Zoho CRM API Console and paste them into your local `.env` file. It should look something like this:
53
+ ```shell
54
+ ZOHO_CRM_CLIENT_ID=your_client_id
55
+ ZOHO_CRM_CLIENT_SECRET=your_client_secret
56
+ ZOHO_CRM_SCOPE=ZohoCRM.users.ALL,ZohoCRM.org.ALL,ZohoCRM.settings.roles.ALL,ZohoCRM.settings.profiles.ALL
57
+ REDIRECT_URI=http://localhost:3000/redirect
58
+ ```
59
+
60
+
61
+ ## Using the api module from the terminal
62
+
63
+ With your `.env` in place, you can now open a terminal to play around with the available APIs.
64
+
65
+ 1. Start a `node` terminal in `packages/zoho-crm`
66
+
67
+ 2. Paste the following code into the terminal:
68
+ ```js
69
+ require('dotenv').config();
70
+ const {Authenticator} = require('@friggframework/test');
71
+ const {Api} = require('./api.js');
72
+
73
+ api = new Api({
74
+ client_id: process.env.ZOHO_CRM_CLIENT_ID,
75
+ client_secret: process.env.ZOHO_CRM_CLIENT_SECRET,
76
+ scope: process.env.ZOHO_CRM_SCOPE,
77
+ redirect_uri: `${process.env.REDIRECT_URI}/zoho-crm`,
78
+ });
79
+
80
+ const url = await api.getAuthUri();
81
+ const response = await Authenticator.oauth2(url);
82
+ const baseArr = response.base.split('/');
83
+ response.entityType = baseArr[baseArr.length - 1];
84
+ delete response.base;
85
+
86
+ await api.getTokenFromCode(response.data.code);
87
+
88
+ console.log('api ready!');
89
+
90
+ ```
91
+
92
+ 3. Your browser will open a tab and send you to Zoho CRM to authorize the client. You may need to log in first.
93
+ ![alt text](images/image-9.jpg)
94
+
95
+
96
+ 4. After authorizing, the tokens are returned to your terminal where they are used to create an authenticated instance of the Zoho CRM API module in the `api` variable. From here you can call any of the existing API resources defined in the module.
97
+ * List existing Users:
98
+ ```js
99
+ > await api.listUsers()
100
+ {
101
+ users: [
102
+ {
103
+ country: 'HN',
104
+ name_format__s: 'Salutation,First Name,Last Name',
105
+ language: 'en_US',
106
+ microsoft: false,
107
+ '$shift_effective_from': null,
108
+ id: '6238474000000461001',
109
+ state: 'Francisco Morazan',
110
+ fax: null,
111
+ country_locale: 'en_US',
112
+ sandboxDeveloper: false,
113
+ zip: null,
114
+ decimal_separator: 'Period',
115
+ created_time: '2024-04-20T10:35:36-06:00',
116
+ time_format: 'hh:mm a',
117
+ offset: -21600000,
118
+ profile: [Object],
119
+ created_by: [Object],
120
+ zuid: '851289894',
121
+ full_name: 'Armando Alvarado',
122
+ phone: '32415425',
123
+ dob: null,
124
+ sort_order_preference__s: 'First Name,Last Name',
125
+ status: 'active',
126
+ role: [Object],
127
+ customize_info: [Object],
128
+ city: null,
129
+ signature: null,
130
+ locale: 'en_US',
131
+ personal_account: false,
132
+ Source__s: null,
133
+ Isonline: false,
134
+ default_tab_group: '0',
135
+ Modified_By: [Object],
136
+ street: null,
137
+ '$current_shift': null,
138
+ alias: null,
139
+ theme: [Object],
140
+ first_name: 'Armando Alvarado',
141
+ email: 'aaj2006@hotmail.com',
142
+ status_reason__s: null,
143
+ website: null,
144
+ Modified_Time: '2024-04-20T10:37:55-06:00',
145
+ '$next_shift': null,
146
+ mobile: null,
147
+ last_name: null,
148
+ time_zone: 'America/Tegucigalpa',
149
+ number_separator: 'Comma',
150
+ confirm: true,
151
+ date_format: 'MM-dd-yyyy',
152
+ category: 'regular_user'
153
+ }
154
+ ]
155
+ }
156
+ ```
157
+
158
+ * List existing Roles:
159
+ ```js
160
+ > await api.listRoles()
161
+ {
162
+ roles: [
163
+ {
164
+ display_label: 'CEO',
165
+ created_by__s: null,
166
+ modified_by__s: null,
167
+ forecast_manager: null,
168
+ share_with_peers: true,
169
+ modified_time__s: null,
170
+ name: 'CEO',
171
+ description: 'Users with this role have access to the data owned by all other users.',
172
+ reporting_to: null,
173
+ id: '6238474000000026005',
174
+ created_time__s: null
175
+ },
176
+ {
177
+ display_label: 'Manager',
178
+ created_by__s: null,
179
+ modified_by__s: null,
180
+ forecast_manager: null,
181
+ share_with_peers: false,
182
+ modified_time__s: null,
183
+ name: 'Manager',
184
+ description: 'Users belonging to this role cannot see data for admin users.',
185
+ reporting_to: [Object],
186
+ id: '6238474000000026008',
187
+ created_time__s: null
188
+ }
189
+ ]
190
+ }
191
+ ```
192
+
193
+ ## Using this API module in a Frigg instance
194
+ 1. Run `npm install @friggframework/api-module-zoho-crm`
195
+
196
+ 2. Populate your `.env` file with `ZOHO_CRM_CLIENT_ID`, `ZOHO_CRM_CLIENT_SECRET`, and `ZOHO_CRM_SCOPE`.
197
+
198
+ 3. Create a subclass of `IntegrationBase` from `@friggframework/core` in `src/integrations` and plug in the Zoho CRM API module. Example:
199
+ ```js
200
+ const { IntegrationBase, Options } = require('@friggframework/core');
201
+ const { Definition: ZohoCRMModule } = require('@friggframework/api-module-zoho-crm');
202
+ const _ = require('lodash');
203
+
204
+ class ZohoCRMIntegration extends IntegrationBase {
205
+ static Config = {
206
+ name: 'zoho-crm',
207
+ version: '1.0.0',
208
+ supportedVersions: ['1.0.0'],
209
+ events: ['GET_SOMETHING'],
210
+ };
211
+
212
+ static Options =
213
+ new Options({
214
+ module: ZohoCRMModule,
215
+ integrations: [ZohoCRMModule],
216
+ display: {
217
+ name: 'Zoho CRM',
218
+ description: 'CRM Stuff',
219
+ category: 'CRM',
220
+ detailsUrl: 'https://www.zoho.com/crm/',
221
+ icon: 'https://static.zohocdn.com/crm/images/favicon_cbfca4856ba4bfb37be615b152f95251_.ico',
222
+ }
223
+ });
224
+
225
+ static modules = {
226
+ 'zoho-crm': ZohoCRMModule
227
+ }
228
+
229
+ /**
230
+ * HANDLE EVENTS
231
+ */
232
+ async receiveNotification(notifier, event, object = null) {
233
+ if (event === 'GET_SOMETHING') {
234
+ return this.target.api.getProjects();
235
+ }
236
+ }
237
+
238
+ /**
239
+ * ALL CUSTOM/OPTIONAL METHODS FOR AN INTEGRATION
240
+ */
241
+ async getSampleData() {
242
+ const response = await this.target.api.listRoles();
243
+ const data = response.roles.map(role => ({
244
+ 'Id': role.id,
245
+ 'Name': role.name,
246
+ 'Description': role.description,
247
+ }));
248
+ return {data};
249
+ }
250
+ }
251
+
252
+ module.exports = ZohoCRMIntegration;
253
+ ```
254
+
255
+ 4. Plug your subclass into your app definition's `integrations` array.
256
+ ![alt text](images/image-11.jpg)
257
+
258
+ 5. Zoho CRM should now appear in your list of available integrations
259
+ ![alt text](images/image-12.jpg)
260
+
261
+
262
+ ## Running the tests
263
+
264
+ The API tests verify that the usual CRUD operations against the API resources work as expected. Because of that, you will need to have a valid set of credentials in your local `.env` file.
265
+
266
+ When running `npm run test`, a browser tab will open to ask you for authorization. After you've authorized, the tests will run and produce an output similar to this:
267
+ ![alt text](images/image-10.jpg)
268
+
269
+ **Note:** There is a 30-second timeout for the authorization request. You may need to try again if your browser does not open fast enough.
package/api.js ADDED
@@ -0,0 +1,169 @@
1
+ const FormData = require('form-data');
2
+ const {OAuth2Requester, get} = require('@friggframework/core');
3
+
4
+ class Api extends OAuth2Requester {
5
+ constructor(params) {
6
+ super(params);
7
+ // The majority of the properties for OAuth are default loaded by OAuth2Requester.
8
+ // This includes the `client_id`, `client_secret`, `scopes`, and `redirect_uri`.
9
+ this.baseUrl = 'https://www.zohoapis.com/crm/v6';
10
+ this.authorizationUri = encodeURI(
11
+ `https://accounts.zoho.com/oauth/v2/auth?scope=${this.scope}&client_id=${this.client_id}&redirect_uri=${this.redirect_uri}&response_type=code&access_type=offline`
12
+ );
13
+ this.tokenUri = 'https://accounts.zoho.com/oauth/v2/token';
14
+ this.access_token = get(params, 'access_token', null);
15
+ this.refresh_token = get(params, 'refresh_token', null);
16
+
17
+ this.URLs = {
18
+ // Users
19
+ users: '/users',
20
+ user: (userId) => `/users/${userId}`,
21
+
22
+ // Roles
23
+ roles: '/settings/roles',
24
+ role: (roleId) => `/settings/roles/${roleId}`,
25
+
26
+ // Profiles
27
+ profiles: '/settings/profiles',
28
+ };
29
+ }
30
+
31
+ getAuthUri() {
32
+ return this.authorizationUri;
33
+ }
34
+
35
+ async getTokenFromCode(code) {
36
+ // I had to override OAuth2Requester.getTokenFromCode method so I could send a form-data,
37
+ // as described in the docs: https://www.zoho.com/crm/developer/docs/api/v6/access-refresh.html
38
+ const formData = new FormData();
39
+ formData.append('grant_type', 'authorization_code');
40
+ formData.append('client_id', this.client_id);
41
+ formData.append('client_secret', this.client_secret);
42
+ formData.append('redirect_uri', this.redirect_uri);
43
+ formData.append('scope', this.scope);
44
+ formData.append('code', code);
45
+ const options = {
46
+ body: formData,
47
+ headers: formData.getHeaders(),
48
+ url: this.tokenUri,
49
+ };
50
+ const response = await this._post(options, false);
51
+ await this.setTokens(response);
52
+ return response;
53
+ }
54
+
55
+ addJsonHeaders(options) {
56
+ const jsonHeaders = {
57
+ 'content-type': 'application/json',
58
+ Accept: 'application/json',
59
+ };
60
+ options.headers = {
61
+ ...jsonHeaders,
62
+ ...options.headers,
63
+ }
64
+ }
65
+
66
+ async _get(options, stringify) {
67
+ this.addJsonHeaders(options);
68
+ return super._get(options, stringify);
69
+ }
70
+
71
+ async _post(options, stringify) {
72
+ this.addJsonHeaders(options);
73
+ return super._post(options, stringify);
74
+ }
75
+
76
+ async _put(options, stringify) {
77
+ this.addJsonHeaders(options);
78
+ return super._put(options, stringify);
79
+ }
80
+
81
+ async _delete(options) {
82
+ this.addJsonHeaders(options);
83
+ const response = await super._delete(options);
84
+ return await this.parsedBody(response);
85
+ }
86
+
87
+ // ************************** Users **********************************
88
+ // https://www.zoho.com/crm/developer/docs/api/v6/get-users.html
89
+
90
+ async listUsers(queryParams = {}) {
91
+ return this._get({
92
+ url: this.baseUrl + this.URLs.users,
93
+ query: {...queryParams},
94
+ });
95
+ }
96
+
97
+ async getUser(userId) {
98
+ return this._get({
99
+ url: this.baseUrl + this.URLs.user(userId),
100
+ });
101
+ }
102
+
103
+ async createUser(body = {}) {
104
+ return this._post({
105
+ url: this.baseUrl + this.URLs.users,
106
+ body: body
107
+ });
108
+ }
109
+
110
+ async updateUser(userId, body = {}) {
111
+ return this._put({
112
+ url: this.baseUrl + this.URLs.user(userId),
113
+ body: body,
114
+ });
115
+ }
116
+
117
+ async deleteUser(userId) {
118
+ return this._delete({
119
+ url: this.baseUrl + this.URLs.user(userId),
120
+ });
121
+ }
122
+
123
+ // ************************** Roles **********************************
124
+ // https://www.zoho.com/crm/developer/docs/api/v6/get-roles.html
125
+
126
+ async listRoles() {
127
+ return this._get({
128
+ url: this.baseUrl + this.URLs.roles
129
+ });
130
+ }
131
+
132
+ async getRole(roleId) {
133
+ return this._get({
134
+ url: this.baseUrl + this.URLs.role(roleId)
135
+ });
136
+ }
137
+
138
+ async createRole(body = {}) {
139
+ return this._post({
140
+ url: this.baseUrl + this.URLs.roles,
141
+ body: body
142
+ });
143
+ }
144
+
145
+ async updateRole(roleId, body = {}) {
146
+ return this._put({
147
+ url: this.baseUrl + this.URLs.role(roleId),
148
+ body: body,
149
+ });
150
+ }
151
+
152
+ async deleteRole(roleId, queryParams = {}) {
153
+ return this._delete({
154
+ url: this.baseUrl + this.URLs.role(roleId),
155
+ query: {...queryParams},
156
+ });
157
+ }
158
+
159
+ // ************************** Profiles **********************************
160
+ // https://www.zoho.com/crm/developer/docs/api/v6/get-profiles.html
161
+
162
+ async listProfiles() {
163
+ return this._get({
164
+ url: this.baseUrl + this.URLs.profiles
165
+ });
166
+ }
167
+ }
168
+
169
+ module.exports = {Api};
@@ -0,0 +1,13 @@
1
+ {
2
+ "name": "zoho-crm",
3
+ "label": "Zoho CRM",
4
+ "productUrl": "https://www.zoho.com/crm/",
5
+ "apiDocs": "https://www.zoho.com/crm/developer/docs/",
6
+ "logoUrl": "https://friggframework.org/assets/img/zoho-crm-512.png",
7
+ "categories": [
8
+ "Sales",
9
+ "Marketing",
10
+ "CRM"
11
+ ],
12
+ "description": "Zoho CRM acts as a single repository to bring your sales, marketing, and customer support activities together, and streamline your process, policy, and people in one platform."
13
+ }
package/definition.js ADDED
@@ -0,0 +1,51 @@
1
+ require('dotenv').config();
2
+ const {Api} = require('./api');
3
+ const {get} = require('@friggframework/core');
4
+ const config = require('./defaultConfig.json')
5
+
6
+ const Definition = {
7
+ API: Api,
8
+ getName: function() {
9
+ return config.name
10
+ },
11
+ moduleName: config.name,
12
+ requiredAuthMethods: {
13
+ getToken: async function(api, params) {
14
+ const code = get(params.data, 'code');
15
+ await api.getTokenFromCode(code);
16
+ },
17
+ apiPropertiesToPersist: {
18
+ credential: ['access_token', 'refresh_token'],
19
+ entity: [],
20
+ },
21
+ getCredentialDetails: async function (api, userId) {
22
+ const response = await api.listUsers({type: 'CurrentUser'});
23
+ const currentUser = response.users[0];
24
+ return {
25
+ identifiers: {externalId: currentUser.id, user: userId},
26
+ details: {},
27
+ };
28
+ },
29
+ getEntityDetails: async function (api, callbackParams, tokenResponse, userId) {
30
+ const response = await api.listUsers({type: 'CurrentUser'});
31
+ const currentUser = response.users[0];
32
+ return {
33
+ identifiers: {externalId: currentUser.id, user: userId},
34
+ details: {
35
+ name: currentUser.email
36
+ },
37
+ }
38
+ },
39
+ testAuthRequest: async function(api) {
40
+ return await api.listUsers();
41
+ },
42
+ },
43
+ env: {
44
+ client_id: process.env.ZOHO_CRM_CLIENT_ID,
45
+ client_secret: process.env.ZOHO_CRM_CLIENT_SECRET,
46
+ scope: process.env.ZOHO_CRM_SCOPE,
47
+ redirect_uri: `${process.env.REDIRECT_URI}/zoho-crm`,
48
+ }
49
+ };
50
+
51
+ module.exports = {Definition};
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/index.js ADDED
@@ -0,0 +1,9 @@
1
+ const {Api} = require('./api');
2
+ const Config = require('./defaultConfig');
3
+ const {Definition} = require('./definition');
4
+
5
+ module.exports = {
6
+ Api,
7
+ Config,
8
+ Definition,
9
+ };
package/jest-setup.js ADDED
@@ -0,0 +1,3 @@
1
+ const {globalSetup} = require('@friggframework/test');
2
+ require('dotenv').config();
3
+ module.exports = globalSetup;
@@ -0,0 +1,2 @@
1
+ const {globalTeardown} = require('@friggframework/test');
2
+ module.exports = globalTeardown;
package/jest.config.js ADDED
@@ -0,0 +1,22 @@
1
+ /*
2
+ * For a detailed explanation regarding each configuration property, visit:
3
+ * https://jestjs.io/docs/configuration
4
+ */
5
+ module.exports = {
6
+ // preset: '@friggframework/test-environment',
7
+ coverageThreshold: {
8
+ global: {
9
+ statements: 13,
10
+ branches: 0,
11
+ functions: 1,
12
+ lines: 13,
13
+ },
14
+ },
15
+ // A path to a module which exports an async function that is triggered once before all test suites
16
+ globalSetup: './jest-setup.js',
17
+
18
+ // A path to a module which exports an async function that is triggered once after all test suites
19
+ globalTeardown: './jest-teardown.js',
20
+
21
+ testTimeout: 30000,
22
+ };
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@friggframework/api-module-zoho-crm",
3
+ "version": "1.0.1-canary.332f986.0",
4
+ "prettier": "@friggframework/prettier-config",
5
+ "description": "Zoho CRM API module that lets the Frigg Framework interact with Zoho CRM",
6
+ "main": "index.js",
7
+ "scripts": {
8
+ "lint:fix": "prettier --write --loglevel error . && eslint . --fix",
9
+ "test": "jest"
10
+ },
11
+ "author": "",
12
+ "license": "MIT",
13
+ "devDependencies": {
14
+ "@friggframework/devtools": "^1.1.2",
15
+ "@friggframework/test": "^1.1.2",
16
+ "dotenv": "^16.0.3",
17
+ "eslint": "^8.22.0",
18
+ "jest": "^28.1.3",
19
+ "jest-environment-jsdom": "^28.1.3",
20
+ "prettier": "^2.7.1"
21
+ },
22
+ "dependencies": {
23
+ "@friggframework/core": "^1.1.2"
24
+ },
25
+ "publishConfig": {
26
+ "access": "public"
27
+ },
28
+ "gitHead": "332f9863623e74ea29795607ac3df0120dc1bc3f"
29
+ }
@@ -0,0 +1,195 @@
1
+ const {Authenticator} = require('@friggframework/test');
2
+ const {Api} = require('../api');
3
+ const config = require('../defaultConfig.json');
4
+ const { FetchError } = require('@friggframework/core');
5
+
6
+ const api = new Api({
7
+ client_id: process.env.ZOHO_CRM_CLIENT_ID,
8
+ client_secret: process.env.ZOHO_CRM_CLIENT_SECRET,
9
+ scope: process.env.ZOHO_CRM_SCOPE,
10
+ redirect_uri: `${process.env.REDIRECT_URI}/zoho-crm`,
11
+ });
12
+
13
+ beforeAll(async () => {
14
+ const url = api.getAuthUri();
15
+ const response = await Authenticator.oauth2(url);
16
+ const baseArr = response.base.split('/');
17
+ response.entityType = baseArr[baseArr.length - 1];
18
+ delete response.base;
19
+ await api.getTokenFromCode(response.data.code);
20
+ });
21
+
22
+ describe(`${config.label} API tests`, () => {
23
+ let existingRoleId;
24
+ describe('Test Role resource', () => {
25
+ it('should list all Roles', async () => {
26
+ const response = await api.listRoles();
27
+ expect(response).toHaveProperty('roles');
28
+ expect(response.roles).toBeInstanceOf(Array);
29
+ existingRoleId = response.roles[0].id; // needed later, to delete a Role
30
+ });
31
+
32
+ let newRoleId;
33
+ it('should create a new Role', async () => {
34
+ const response = await api.createRole({
35
+ roles: [
36
+ {'name': 'Test Role 1000', 'description': 'Just testing stuff'}
37
+ ]
38
+ });
39
+ expect(response).toHaveProperty('roles');
40
+ expect(response.roles[0].code).toBe('SUCCESS');
41
+ expect(response.roles[0].message).toBe('Role added');
42
+ newRoleId = response.roles[0].details.id; // store the id of the newly created Role
43
+ });
44
+
45
+ it('should get the newly created Role by ID', async () => {
46
+ const response = await api.getRole(newRoleId);
47
+ expect(response).toHaveProperty('roles');
48
+ expect(response.roles[0].id).toBe(newRoleId);
49
+ expect(response.roles[0].name).toBe('Test Role 1000');
50
+ expect(response.roles[0].description).toBe('Just testing stuff');
51
+ });
52
+
53
+ let updatedName = 'Foo';
54
+ let updatedDescription = 'Bar';
55
+ it('should update the newly created Role by ID', async () => {
56
+ const response = await api.updateRole(
57
+ newRoleId,
58
+ {roles: [{'name': updatedName, 'description': updatedDescription}]},
59
+ );
60
+ expect(response).toHaveProperty('roles');
61
+ expect(response.roles[0].code).toBe('SUCCESS');
62
+ expect(response.roles[0].message).toBe('Role updated');
63
+ });
64
+
65
+ it('should receive the updated values when getting the newly created User by ID', async () => {
66
+ const response = await api.getRole(newRoleId);
67
+ expect(response).toHaveProperty('roles');
68
+ expect(response.roles[0].id).toBe(newRoleId);
69
+ expect(response.roles[0].name).toBe(updatedName);
70
+ expect(response.roles[0].description).toBe(updatedDescription);
71
+ });
72
+
73
+ it('should delete the newly created Role by ID', async () => {
74
+ // To delete a Role, the api requires that we send it the ID of
75
+ // another Role, to which all users will be transfered after the delete.
76
+ // We rely on one of the existing Roles, whose ID we saved earlier.
77
+ const response = await api.deleteRole(
78
+ newRoleId,
79
+ {'transfer_to_id': existingRoleId}
80
+ );
81
+ expect(response).toHaveProperty('roles');
82
+ expect(response.roles[0].code).toBe('SUCCESS');
83
+ expect(response.roles[0].message).toBe('Role Deleted');
84
+ });
85
+
86
+ it('should throw FetchError when trying to create with empty params', () => {
87
+ expect(async () => await api.createRole()).rejects.toThrow(FetchError)
88
+ });
89
+ });
90
+
91
+ describe('Test User resource', () => {
92
+ it('should list all Users', async () => {
93
+ const response = await api.listUsers();
94
+ expect(response).toHaveProperty('users');
95
+ expect(response.users).toBeInstanceOf(Array);
96
+ });
97
+
98
+ let newUserId;
99
+ it('should create a new User', async () => {
100
+ // To create a new User in Zoho CRM, we need to specify their
101
+ // Role and Profile by providing the relevant IDs in the request.
102
+ // So we first need to fetch an existing Role and Profile.
103
+ const rolesResponse = await api.listRoles();
104
+ const role = rolesResponse.roles[0];
105
+ const profilesResponse = await api.listProfiles();
106
+ const profile = profilesResponse.profiles[0];
107
+
108
+ const response = await api.createUser({
109
+ users: [{
110
+ first_name: 'Test User 1000',
111
+ email: 'test@friggframework.org',
112
+ role: role.id,
113
+ profile: profile.id,
114
+ }]
115
+ });
116
+
117
+ expect(response).toHaveProperty('users');
118
+ expect(response.users[0].code).toBe('SUCCESS');
119
+ expect(response.users[0].message).toBe('User added');
120
+ newUserId = response.users[0].details.id; // store the id of the newly created User
121
+ });
122
+
123
+ it('should get the newly created User by ID', async () => {
124
+ const response = await api.getUser(newUserId);
125
+ expect(response).toHaveProperty('users');
126
+ expect(response.users[0].id).toBe(newUserId);
127
+ expect(response.users[0].first_name).toBe('Test User 1000');
128
+ expect(response.users[0].email).toBe('test@friggframework.org');
129
+ });
130
+
131
+ let updatedFirstName = 'Elon';
132
+ let updatedEmail = 'musk@friggframework.com';
133
+ it('should update the newly created User by ID', async () => {
134
+ const response = await api.updateUser(
135
+ newUserId,
136
+ {users: [{'first_name': updatedFirstName, 'email': updatedEmail}]},
137
+ );
138
+ expect(response).toHaveProperty('users');
139
+ expect(response.users[0].code).toBe('SUCCESS');
140
+ expect(response.users[0].message).toBe('User updated');
141
+ });
142
+
143
+ it('should receive the updated values when getting the newly created User by ID', async () => {
144
+ const response = await api.getUser(newUserId);
145
+ expect(response).toHaveProperty('users');
146
+ expect(response.users[0].id).toBe(newUserId);
147
+ expect(response.users[0].first_name).toBe(updatedFirstName);
148
+ expect(response.users[0].email).toBe(updatedEmail);
149
+ });
150
+
151
+ it('should delete the newly created User by ID', async () => {
152
+ const response = await api.deleteUser(newUserId);
153
+ expect(response).toHaveProperty('users');
154
+ expect(response.users[0].code).toBe('SUCCESS');
155
+ expect(response.users[0].message).toBe('User deleted');
156
+ });
157
+
158
+ it('should throw FetchError when trying to create with empty params', () => {
159
+ expect(async () => await api.createUser()).rejects.toThrow(FetchError)
160
+ });
161
+ });
162
+
163
+ describe('Test Profile resource', () => {
164
+ it('should list all Profiles', async () => {
165
+ const response = await api.listProfiles();
166
+ expect(response).toHaveProperty('profiles');
167
+ expect(response.profiles).toBeInstanceOf(Array);
168
+ });
169
+
170
+ it.skip('should create a new Profile', async () => {
171
+ // TODO
172
+ });
173
+
174
+ it.skip('should get the newly created Profile by ID', async () => {
175
+ // TODO
176
+ });
177
+
178
+ it.skip('should update the newly created Profile by ID', async () => {
179
+ // TODO
180
+ });
181
+
182
+ it.skip('should receive the updated values when getting the newly created Profile by ID', async () => {
183
+ // TODO
184
+ });
185
+
186
+ it.skip('should delete the newly created Profile by ID', async () => {
187
+ // TODO
188
+ });
189
+
190
+ it.skip('should throw FetchError when trying to create with empty params', () => {
191
+ // TODO
192
+ });
193
+ });
194
+
195
+ });