@getjones/test-infra 1.0.3

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/README.md ADDED
@@ -0,0 +1,264 @@
1
+ # Package Name: @getjones/test-infra
2
+
3
+ ## Package Goal
4
+
5
+ * Providing an easy and reusable interface for the backend system. Means, both by the OpenAPI, and the internal API.
6
+
7
+ ## Interface
8
+
9
+ ### init
10
+
11
+ * require the package with settled up configuration json
12
+
13
+ ```node
14
+ const { internalAPI } = require('@getjones/test-infra')(conf);
15
+ ```
16
+
17
+ * configuration example
18
+
19
+ ```node
20
+ const dotenv = require('dotenv');
21
+
22
+ dotenv.config();
23
+
24
+ module.exports = {
25
+ backendUrl: process.env.BACKEND_URL,
26
+ credentials: {
27
+ superUser: process.env.CREDENTIALS_SUPER_USER,
28
+ superUserPassword: process.env.CREDENTIALS_SUPER_USER_PASSWORD,
29
+ strongPassword: process.env.CREDENTIALS_STRONG_PASSWORD,
30
+ },
31
+ accountCreationSecret: process.env.ACCOUNT_CREATION_SECRET,
32
+ environment: process.env.ENVIRONMENT,
33
+ email: process.env.EMAIL,
34
+ };
35
+ ```
36
+
37
+ ### internalAPI
38
+
39
+ * internalAPI contains the next services:
40
+ * auth
41
+ * accounts
42
+ * accountSettings
43
+ * projects
44
+
45
+ ```node
46
+ const { auth, accounts, accountSettings, projects } = internalAPI;
47
+ ```
48
+
49
+ ### auth
50
+
51
+ ```node
52
+
53
+ /**
54
+ *
55
+ * @param email (string)
56
+ * @param password (string)
57
+ * @return Auth cookie (string) with given email privileges.
58
+ */
59
+ const getAuthCookie = async (email, password) => {
60
+ };
61
+
62
+ /**
63
+ *
64
+ * Required Configuration: {
65
+ * credentials.superUser,
66
+ * credentials.superUserPassword
67
+ * }
68
+ * @return ICS cookie (String)
69
+ */
70
+ const getIcsCookie = async () => {
71
+ };
72
+ ```
73
+
74
+ ### accounts
75
+
76
+ ```node
77
+
78
+ /**
79
+ *
80
+ * Required Configuration: {
81
+ * accountCreationSecret: accountCreationSecret,
82
+ * }
83
+ *
84
+ * If you want to use default password so
85
+ * 'credentials.strongPassword' is needed
86
+ * to be a part of the configuration.
87
+ *
88
+ * @param email (string)
89
+ * @param accountName (string)
90
+ * @param context (string): Should contain ICS cookie
91
+ * @return Account (object)
92
+ */
93
+
94
+ const createAccount = async (email, accountName, context,
95
+ password = credentials.strongPassword,
96
+ propertyType = PROPERTY_TYPE) => {
97
+ };
98
+
99
+ /**
100
+ *
101
+ * @param accountName (string)
102
+ * @param context (string): Should contains ICS cookie
103
+ * @return Account (object)
104
+ */
105
+ const getAccount = async (accountName, context) => {
106
+ };
107
+
108
+ /**
109
+ *
110
+ * @param email (string)
111
+ * @param accountName (string)
112
+ * @param context (string): Should contain ICS cookie
113
+ * @param password (string)
114
+ * @return Account (object)
115
+ */
116
+ const getOrCreateAccount = async (email, accountName, context, password = credentials.strongPassword) => {
117
+ };
118
+
119
+ /**
120
+ *
121
+ * @param accountName (string)
122
+ * @param context (string): Should contain ICS cookie
123
+ * @return Account ID (String)
124
+ */
125
+ const getAccountId = async (accountName, context) => {
126
+ };
127
+
128
+ /**
129
+ *
130
+ * @param accountName (string)
131
+ * @param context (string): Should contains ICS cookie
132
+ * @return Http Response
133
+ */
134
+ const deleteAccountByName = async (accountName, context) => {
135
+ };
136
+
137
+ /**
138
+ *
139
+ * @param accountId (string)
140
+ * @param context (string): Should contain ICS cookie
141
+ * @return Http Response
142
+ */
143
+ const deleteAccountById = async (accountId, context) => {
144
+ };
145
+ ```
146
+
147
+ ### accountSettings
148
+
149
+ ```node
150
+
151
+ /**
152
+ *
153
+ * @param accountId (string)
154
+ * @param context (string): Should contain ICS cookie
155
+ * @return Account Settings (object)
156
+ */
157
+ const getAccountSettings = async (accountId, context) => {
158
+ };
159
+
160
+ /**
161
+ *
162
+ * @param accountId (string)
163
+ * @param AccountSettings (object) Should Contain:
164
+ * isMultiPropertyTenants (boolean)
165
+ * isHighPriority (boolean)
166
+ * @param context (string): Should contain ICS cookie
167
+ * @return Http Response
168
+ */
169
+ const updateAccountSettings = async (accountId, isMultiPropertyTenants, isHighPriority, context) => {
170
+ };
171
+
172
+ /**
173
+ * Summary: Change account settings to default
174
+ * Description:
175
+ * Update The Next Account Settings:
176
+ * isMultiPropertyTenants: false
177
+ * isHighPriority: false
178
+ * @param accountId (string)
179
+ * @param context (string): Should Contain ICS cookie
180
+ * @return Http Response
181
+ */
182
+ const restoreAccountSettings = async (accountId, context) => {
183
+ };
184
+
185
+ ```
186
+
187
+ ### projects
188
+
189
+ ```node
190
+
191
+ /**
192
+ *
193
+ * @param accountName (string)
194
+ * @param context (string): Should contain cookie
195
+ * User's cookie that is related to this account or ICS cookie
196
+ * @return List of projects ([objects])
197
+ */
198
+ const getProjectsByAccountName = async (accountName, context) => {
199
+ };
200
+
201
+ /**
202
+ *
203
+ * @param accountId (String)
204
+ * @param context (string): Should contain cookie
205
+ * User's cookie that is related to this account or ICS cookie
206
+ * @return List of projects ([objects])
207
+ */
208
+ const getProjectsByAccountId = async (accountId, context) => {
209
+ };
210
+
211
+ /**
212
+ *
213
+ * @param accountId (string)
214
+ * @param projectName (string)
215
+ * @param context (string): Should contain cookie
216
+ * User's cookie that is related to this account or ICS cookie
217
+ * @return List of projects ([objects])
218
+ */
219
+ const getProjectsByName = async (accountId, projectName, context) => {
220
+ };
221
+
222
+ /**
223
+ * Summary: Delete project by given details
224
+ * @param accountId (string)
225
+ * @param projectName (string)
226
+ * @param context (string): Should contain cookie
227
+ * User's cookie that is related to this account or ICS cookie
228
+ * @return List of projects ([objects])
229
+ */
230
+ const deleteProjectByName = async (accountId, projectName, context) => {
231
+ };
232
+
233
+ /**
234
+ *
235
+ * @param project (object)
236
+ * @param accountName (string)
237
+ * @param context (string): Should contain cookie
238
+ * User's cookie that is related to this account or ICS cookie
239
+ * @return object contains generated projectId
240
+ */
241
+
242
+ // Example for project input (Not all of them are required):
243
+ const createProjectInput = {
244
+ 'projectName': project.name,
245
+ 'userId': '',
246
+ 'projectDescription': project.description,
247
+ 'address': project.address,
248
+ 'projectNumber': project.number,
249
+ 'projectStartDate': project.startDate,
250
+ 'projectEndDate': project.endDate,
251
+ 'city': project.city,
252
+ 'state': project.state,
253
+ 'zipCode': project.zipCode,
254
+ 'companyNameForProject': project.companyNameForProject,
255
+ 'certificateHolder': '',
256
+ 'additionalInsured': '',
257
+ 'tenantSolutionEnabled': '',
258
+ 'onboardingEnabled': '',
259
+ 'automaticRenewalEnabled': ''
260
+ };
261
+
262
+ const createProject = async (project, accountName, context) => {
263
+ };
264
+ ```
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@getjones/test-infra",
3
+ "version": "1.0.3",
4
+ "description": "Providing internal and openapi interface",
5
+ "main": "src/index.js",
6
+ "scripts": {
7
+ "test": "mocha \"./tests/**/*.test.js\" --slow 3000 --timeout 10000 --exit --inlineDiffs --bail"
8
+ },
9
+ "author": "",
10
+ "license": "ISC",
11
+ "dependencies": {
12
+ "axios": "^0.21.1",
13
+ "dotenv": "^8.2.0",
14
+ "mocha": "^8.3.2",
15
+ "chai": "^4.3.4",
16
+ "http-status-code": "^2.1.0"
17
+ },
18
+ "devDependencies": {
19
+ "eslint": "^7.22.0",
20
+ "eslint-plugin-import": "^2.22.1",
21
+ "eslint-plugin-node": "^11.1.0"
22
+ },
23
+ "directories": {
24
+ "test": "tests"
25
+ }
26
+ }
package/src/env.js ADDED
@@ -0,0 +1,30 @@
1
+ let privateMembers = {
2
+ backendUrl: null,
3
+ credentials: null,
4
+ environment: null,
5
+ accountCreationSecret: null,
6
+ };
7
+
8
+ const init = conf => {
9
+ privateMembers = Object.assign(privateMembers, conf);
10
+ requiredValidation({ backendUrl: privateMembers.backendUrl, environment: privateMembers.environment });
11
+ };
12
+
13
+ const requiredValidation = object => {
14
+ const invalidKeys = [];
15
+ Object.keys(object).forEach(key => {
16
+ if (!object[key]) {
17
+ invalidKeys.push(key);
18
+ }
19
+ });
20
+
21
+ if (invalidKeys.length > 0) {
22
+ throw `Missing required configuration on your environment variables. The missing env-vars are "${invalidKeys}".`;
23
+ }
24
+ };
25
+
26
+ module.exports = {
27
+ init,
28
+ getEnv: () => privateMembers,
29
+ requiredValidation
30
+ };
@@ -0,0 +1,9 @@
1
+ const { StatusCodes } = require('http-status-code');
2
+
3
+ class NotFoundError extends Error {
4
+ constructor(message) {
5
+ super(message, StatusCodes.NOT_FOUND);
6
+ }
7
+ }
8
+
9
+ module.exports = { NotFoundError };
package/src/index.js ADDED
@@ -0,0 +1,16 @@
1
+ const env = require('./env');
2
+
3
+ const init = conf => {
4
+ env.init(conf);
5
+
6
+ const auth = require('./internal-api/auth/auth.setup');
7
+
8
+ const accounts = require('./internal-api/accounts/accounts.setup');
9
+ const accountSettings = require('./internal-api/accounts/settings/settings.setup');
10
+ const projects = require('./internal-api/projects/projects.setup');
11
+
12
+ const internalAPI = { auth, accounts, accountSettings, projects };
13
+ return { internalAPI };
14
+ };
15
+
16
+ module.exports = init;
@@ -0,0 +1,28 @@
1
+ const requests = require('../common/requests');
2
+ const { backendUrl } = require('../../env').getEnv();
3
+
4
+ const Endpoints = {
5
+ getAccount: `${backendUrl}/saas/accounts`,
6
+ create: `${backendUrl}/saas/createaccount`,
7
+ delete: `${backendUrl}/saas/account`,
8
+ edit: accountId => `${backendUrl}/saas/account/${accountId}/settings`
9
+ };
10
+
11
+ const create = async (account, context) => {
12
+ return requests.postRequestHandler(Endpoints.create, account, context).then(res => res.data);
13
+ };
14
+
15
+ const deleteAccount = async (accountId, context) => {
16
+ return requests.deleteRequestHandler(Endpoints.delete, context, {}, { 'userId': accountId });
17
+ };
18
+
19
+ const updateAccountSettings = async (accountId, settings, context) => {
20
+ return requests.putRequestHandler(Endpoints.edit(accountId), { accountId, ...settings }, context);
21
+ };
22
+
23
+ const getByName = async (accountName, context) => {
24
+ const params = { name: accountName };
25
+ return await requests.getRequestHandler(Endpoints.getAccount, params, context).then(res => res.data);
26
+ };
27
+
28
+ module.exports = { create, getByName, deleteAccount, updateAccountSettings };
@@ -0,0 +1,79 @@
1
+ const env = require('../../env');
2
+ const accountsAPI = require('./accounts.api');
3
+
4
+ const { credentials, accountCreationSecret } = env.getEnv();
5
+ const { NotFoundError } = require('../../exceptions/notFoundError');
6
+ const PROPERTY_TYPE = 'Property Management';
7
+
8
+ const createAccount = async (email, accountName, context,
9
+ password = credentials.strongPassword,
10
+ propertyType = PROPERTY_TYPE) => {
11
+ env.requiredValidation({
12
+ accountCreationSecret: accountCreationSecret,
13
+ 'credentials.strongPassword': password
14
+ });
15
+
16
+ const newAccount = {
17
+ companyName: accountName,
18
+ email: email,
19
+ password: password,
20
+ verifyPassword: password,
21
+ secret: accountCreationSecret,
22
+ userType: propertyType
23
+ };
24
+
25
+ return await accountsAPI.create(newAccount, context);
26
+ };
27
+
28
+ const getAccount = async (accountName, context) => {
29
+ const existingAccounts = await accountsAPI.getByName(accountName, context);
30
+
31
+ if (!existingAccounts || existingAccounts.length === 0) {
32
+ return null;
33
+ }
34
+
35
+ if (existingAccounts.length > 1) {
36
+ throw new Error(`Got more than one account with the name: ${accountName}. IDs: ${existingAccounts.map(item => item.userId).join(', ')}`);
37
+ }
38
+
39
+ return existingAccounts[0];
40
+ };
41
+
42
+ const getOrCreateAccount = async (email, accountName, context, password = credentials.strongPassword) => {
43
+ const existingAccount = await getAccount(accountName, context);
44
+
45
+ if (existingAccount) {
46
+ return existingAccount;
47
+ }
48
+
49
+ return await createAccount(email, accountName, context, password);
50
+ };
51
+
52
+ const getAccountId = async (accountName, context) => {
53
+ const account = await getAccount(accountName, context);
54
+
55
+ if (!account) {
56
+ throw NotFoundError(`Account ${accountName} does not exist`);
57
+ }
58
+
59
+ return account.userId;
60
+ };
61
+
62
+ const deleteAccountByName = async (accountName, context) => {
63
+ const accountId = await getAccountId(accountName, context);
64
+ return accountsAPI.deleteAccount(accountId, context);
65
+ };
66
+
67
+ const deleteAccountById = async (accountId, context) => {
68
+ return accountsAPI.deleteAccount(accountId, context);
69
+ };
70
+
71
+ module.exports = {
72
+ getAccount,
73
+ getOrCreateAccount,
74
+ getAccountId,
75
+ createAccount,
76
+ deleteAccountByName,
77
+ deleteAccountById
78
+ };
79
+
@@ -0,0 +1,20 @@
1
+ const requests = require('../../common/requests');
2
+ const { backendUrl } = require('../../../env').getEnv();
3
+
4
+ const Endpoints = {
5
+ get: accountId => `${backendUrl}/saas/account/${accountId}/settings`,
6
+ edit: accountId => `${backendUrl}/saas/account/${accountId}/settings`
7
+ };
8
+
9
+ const getAccountSettings = async (accountId, context) => {
10
+ return requests.getRequestHandler(Endpoints.get(accountId), {}, context);
11
+ };
12
+
13
+ const updateAccountSettings = async (accountId, settings, context) => {
14
+ return requests.putRequestHandler(Endpoints.edit(accountId), { accountId, ...settings }, context);
15
+ };
16
+
17
+ module.exports = {
18
+ getAccountSettings,
19
+ updateAccountSettings
20
+ };
@@ -0,0 +1,22 @@
1
+ const accountsAPI = require('./settings.api');
2
+
3
+ const getAccountSettings = async (accountId, context) => {
4
+ return accountsAPI.getAccountSettings(accountId, context).then(res => res.data);
5
+ };
6
+
7
+ const updateAccountSettings = async (accountId, { isMultiPropertyTenants, isHighPriority }, context) => {
8
+ return accountsAPI.updateAccountSettings(accountId, { isMultiPropertyTenants, isHighPriority }, context);
9
+ };
10
+
11
+ const restoreAccountSettings = async (accountId, context) => {
12
+ return accountsAPI.updateAccountSettings(accountId, {
13
+ isMultiPropertyTenants: false,
14
+ isHighPriority: false
15
+ }, context);
16
+ };
17
+
18
+ module.exports = {
19
+ getAccountSettings,
20
+ updateAccountSettings,
21
+ restoreAccountSettings
22
+ };
@@ -0,0 +1,12 @@
1
+ const requests = require('../common/requests');
2
+ const { backendUrl } = require('../../env').getEnv();
3
+
4
+ const Endpoints = {
5
+ login: `${backendUrl}/logincontroller`
6
+ };
7
+
8
+ const login = async (email, password) => {
9
+ return await requests.postRequestHandler(Endpoints.login, { email, password }).then(res => res);
10
+ };
11
+
12
+ module.exports = { login };
@@ -0,0 +1,33 @@
1
+ const { getEnv, requiredValidation } = require('../../env');
2
+ const { credentials } = getEnv();
3
+ const authApi = require('./auth.api');
4
+
5
+ const getAuthCookie = async (email, password) => {
6
+ try {
7
+ const res = await authApi.login(email, password);
8
+ const authCookie = res.headers['set-cookie'].find(item => item.startsWith('JonesToken='));
9
+
10
+ return authCookie;
11
+ } catch (error) {
12
+ throw new Error(`Failed to login to email:${email}`, error);
13
+ }
14
+ };
15
+
16
+ const getIcsCookie = async () => {
17
+ requiredValidation({
18
+ 'credentials.superUser': credentials.superUser,
19
+ 'credentials.superUserPassword': credentials.superUserPassword
20
+ });
21
+ return await getAuthCookie(credentials.superUser, credentials.superUserPassword);
22
+ };
23
+
24
+ const auth = {
25
+ getAuthCookie,
26
+ getIcsCookie
27
+ };
28
+
29
+ module.exports = {
30
+ getAuthCookie,
31
+ getIcsCookie
32
+ };
33
+
@@ -0,0 +1,53 @@
1
+ const axios = require('axios');
2
+
3
+ const getRequestHandler = async (url, params = {}, context = null, headers = {}) => {
4
+ enrichCookie(headers, context);
5
+ try {
6
+ const response = await axios.get(url, { params, headers });
7
+ return response;
8
+ } catch (error) {
9
+ throw Error(JSON.stringify(error.response.data));
10
+ }
11
+
12
+ };
13
+
14
+ const postRequestHandler = async (url, body, context = null, headers = {}) => {
15
+ enrichCookie(headers, context);
16
+ try {
17
+ const response = await axios.post(url, body, { headers });
18
+ return response;
19
+ } catch (error) {
20
+ throw Error(JSON.stringify(error.response.data));
21
+ }
22
+
23
+ };
24
+
25
+ const putRequestHandler = async (url, body, context = null, headers = {}) => {
26
+ enrichCookie(headers, context);
27
+ try {
28
+ const response = await axios.put(url, body, { headers });
29
+ return response;
30
+ } catch (error) {
31
+ throw Error(JSON.stringify(error.response.data));
32
+ }
33
+
34
+ };
35
+
36
+ const deleteRequestHandler = async (url, context = null, headers = {}, params = {}) => {
37
+ enrichCookie(headers, context);
38
+ try {
39
+ const response = await axios.delete(url, { params, headers });
40
+ return response;
41
+ } catch (error) {
42
+ throw Error(JSON.stringify(error.response.data));
43
+ }
44
+
45
+ };
46
+
47
+ const enrichCookie = (headers, context) => {
48
+ if (context) {
49
+ headers.Cookie = context;
50
+ }
51
+ };
52
+
53
+ module.exports = { getRequestHandler, postRequestHandler, putRequestHandler, deleteRequestHandler };
@@ -0,0 +1,23 @@
1
+ const requests = require('../common/requests');
2
+ const { backendUrl } = require('../../env').getEnv();
3
+
4
+ const Endpoints = {
5
+ create: `${backendUrl}/saas/project`,
6
+ delete: projectId => `${backendUrl}/saas/project/${projectId}`,
7
+ getByAccountId: `${backendUrl}/saas/project/list`
8
+ };
9
+
10
+ const create = async (project, context) => {
11
+ return requests.putRequestHandler(Endpoints.create, project, context);
12
+ };
13
+
14
+ const getProjectsByAccountId = async (accountId, context) => {
15
+ const params = { userId: accountId };
16
+ return requests.getRequestHandler(Endpoints.getByAccountId, params, context).then(res => res.data);
17
+ };
18
+
19
+ const deleteProjectById = async (projectId, context) => {
20
+ return requests.deleteRequestHandler(Endpoints.delete(projectId), context);
21
+ };
22
+
23
+ module.exports = { create, getProjectsByAccountId, deleteProjectById };
@@ -0,0 +1,35 @@
1
+ const projectsApi = require('./projects.api');
2
+ const accounts = require('../accounts/accounts.setup');
3
+
4
+ const getProjectsByAccountName = async (accountName, context) => {
5
+ const accountId = accounts.getAccountId(accountName, context);
6
+ return getProjectsByAccountId(accountId, context);
7
+ };
8
+
9
+ const getProjectsByAccountId = async (accountId, context) => {
10
+ return projectsApi.getProjectsByAccountId(accountId, context);
11
+ };
12
+
13
+ const getProjectsByName = async (accountId, projectName, context) => {
14
+ const projects = await getProjectsByAccountId(accountId, context);
15
+ const filteredProjects = projects && projects.filter(project => project.projectName === projectName) || [];
16
+ return filteredProjects;
17
+ };
18
+
19
+ const deleteProjectByName = async (accountId, projectName, context) => {
20
+ const projects = await getProjectsByName(accountId, projectName, context);
21
+ projects.map(async project => await projectsApi.deleteProjectById(project.projectId, context)
22
+ );
23
+ };
24
+
25
+ const createProject = async (project, accountName, context) => {
26
+ const accountId = await accounts.getAccountId(accountName, context);
27
+ return await projectsApi.create({ ...project, userId: accountId }, context);
28
+ };
29
+
30
+ module.exports = {
31
+ getProjectsByAccountName,
32
+ getProjectsByAccountId,
33
+ createProject,
34
+ deleteProjectByName
35
+ };
@@ -0,0 +1,39 @@
1
+ const chai = require('chai');
2
+
3
+ const { expect } = chai;
4
+
5
+ const env = require('../src/env');
6
+
7
+ describe('Env | Test Core Logic', async function() {
8
+ const expectedSanityAssignVariables = {
9
+ 'backendUrl': 'Test',
10
+ 'credentials': {
11
+ 'superUser': 'TestSuperUser',
12
+ 'superUserPassword': 'TestSuperUserPassword'
13
+ },
14
+ 'environment': 'dev',
15
+ 'accountCreationSecret': null
16
+ };
17
+
18
+ const expectedValidationError = 'Missing required configuration on your environment variables. The missing env-vars are "backendUrl,environment".';
19
+
20
+ it('Missing Configuration', async function() {
21
+ const badInput = {
22
+ credentials: { superUser: 'TestSuperUser', superUserPassword: 'TestSuperUserPassword' }
23
+ };
24
+
25
+ expect(() => env.init(badInput)).to.throw(expectedValidationError);
26
+ });
27
+
28
+ it('Assign Configuration', async function() {
29
+ env.init({
30
+ backendUrl: 'Test',
31
+ environment: 'dev',
32
+ credentials: { superUser: 'TestSuperUser', superUserPassword: 'TestSuperUserPassword' }
33
+ });
34
+
35
+ const envVariables = env.getEnv();
36
+ expect(envVariables).to.deep.equal(expectedSanityAssignVariables, 'Assign configuration did not work properly');
37
+ });
38
+
39
+ });