ti2 1.0.0 → 1.0.5
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/.github/workflows/deploy.yml +29 -0
- package/.github/workflows/tests.yml +17 -0
- package/controllers/__mocks__/plugin.js +3 -3
- package/controllers/__tests__/admin.js +8 -7
- package/controllers/__tests__/app.js +13 -11
- package/controllers/__tests__/bookings.js +2 -3
- package/controllers/__tests__/ping.js +1 -1
- package/controllers/__tests__/user.js +13 -13
- package/package.json +6 -3
- package/test/api/controllers/README.md +1 -0
- package/test/api/helpers/README.md +1 -0
- package/test/utils.js +111 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
name: Deploy Workflow
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_run:
|
|
5
|
+
workflows: Tests Workflow
|
|
6
|
+
branches: main
|
|
7
|
+
types: completed
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
tag:
|
|
11
|
+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@master
|
|
15
|
+
- uses: tool3/bump@master
|
|
16
|
+
with:
|
|
17
|
+
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
18
|
+
unrelated: true
|
|
19
|
+
user: 'Github Action Job'
|
|
20
|
+
email: 'engineering@tourconnect.com'
|
|
21
|
+
branch: main
|
|
22
|
+
publish:
|
|
23
|
+
needs: tag
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v1
|
|
27
|
+
- uses: JS-DevTools/npm-publish@v1
|
|
28
|
+
with:
|
|
29
|
+
token: ${{ secrets.NPM_TOKEN }}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
name: Tests Workflow
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
build_and_test:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v2
|
|
12
|
+
- uses: actions/setup-node@v1
|
|
13
|
+
with:
|
|
14
|
+
node-version: 12
|
|
15
|
+
- run: npm ci
|
|
16
|
+
- run: npm run build --if-present
|
|
17
|
+
- run: npm test
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* globals jest */
|
|
2
|
-
const
|
|
2
|
+
const chance = require('chance').Chance();
|
|
3
3
|
const { fieldSets } = require('../__fixtures__/fieldData');
|
|
4
4
|
|
|
5
5
|
module.exports = () => ({
|
|
@@ -8,10 +8,10 @@ module.exports = () => ({
|
|
|
8
8
|
updateProfile: jest.fn(() => true),
|
|
9
9
|
getLocations: jest.fn(() => fieldSets.locations.leftSide.locations),
|
|
10
10
|
getLocation: jest.fn(() => fieldSets.locations.leftSide.locations[0]),
|
|
11
|
-
createLocation: jest.fn(() => ({ locationId:
|
|
11
|
+
createLocation: jest.fn(() => ({ locationId: chance.guid() })),
|
|
12
12
|
updateLocation: jest.fn(() => true),
|
|
13
13
|
getProducts: jest.fn(),
|
|
14
14
|
getProduct: jest.fn(),
|
|
15
|
-
createProduct: jest.fn(() => (({ productId:
|
|
15
|
+
createProduct: jest.fn(() => (({ productId: chance.guid() }))),
|
|
16
16
|
updateProduct: jest.fn(() => true),
|
|
17
17
|
});
|
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
/* globals describe it expect afterAll */
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const chance = require('chance').Chance();
|
|
4
4
|
const request = require('supertest');
|
|
5
|
-
const app = require('
|
|
6
|
-
const sqldb = require('
|
|
5
|
+
const app = require('../../index');
|
|
6
|
+
const sqldb = require('../../models/db');
|
|
7
|
+
const { slugify } = require('../../test/utils');
|
|
7
8
|
|
|
8
9
|
const { env: { adminKey } } = process;
|
|
9
10
|
|
|
10
11
|
describe('admin', () => {
|
|
11
|
-
const appName =
|
|
12
|
-
|
|
12
|
+
const appName = slugify(
|
|
13
|
+
chance.company(),
|
|
13
14
|
);
|
|
14
15
|
const newApp = {
|
|
15
16
|
name: appName,
|
|
16
17
|
packageName: `ti2-${appName}`,
|
|
17
|
-
adminEmail:
|
|
18
|
+
adminEmail: chance.email(),
|
|
18
19
|
};
|
|
19
20
|
let appKey;
|
|
20
21
|
const userId = '536830b6ed19afa44a000002';
|
|
21
22
|
afterAll(async () => {
|
|
22
|
-
await sqldb.
|
|
23
|
+
await sqldb.connectionManager.close();
|
|
23
24
|
});
|
|
24
25
|
it('should be able to create an app', async () => {
|
|
25
26
|
const resp = await request(app)
|
|
@@ -1,32 +1,34 @@
|
|
|
1
1
|
/* globals describe it expect beforeAll, afterAll */
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const chance = require('chance').Chance();
|
|
4
4
|
const request = require('supertest');
|
|
5
5
|
const jwt = require('jwt-promise');
|
|
6
|
-
|
|
7
|
-
const
|
|
6
|
+
|
|
7
|
+
const app = require('../../index');
|
|
8
|
+
const sqldb = require('../../models/db');
|
|
9
|
+
const { slugify } = require('../../test/utils');
|
|
8
10
|
|
|
9
11
|
const { env: { adminKey, jwtSecret } } = process;
|
|
10
12
|
|
|
11
13
|
describe('app', () => {
|
|
12
|
-
const appName =
|
|
13
|
-
|
|
14
|
+
const appName = slugify(
|
|
15
|
+
chance.company(),
|
|
14
16
|
).toLowerCase();
|
|
15
17
|
const newApp = {
|
|
16
18
|
name: appName,
|
|
17
19
|
packageName: `ti2-${appName}`,
|
|
18
|
-
adminEmail:
|
|
20
|
+
adminEmail: chance.email(),
|
|
19
21
|
};
|
|
20
22
|
let appKey;
|
|
21
|
-
const userId =
|
|
22
|
-
const apiKey =
|
|
23
|
+
const userId = chance.guid();
|
|
24
|
+
const apiKey = chance.guid();
|
|
23
25
|
// this token can be as long needed
|
|
24
26
|
const token = {
|
|
25
|
-
endpoint:
|
|
27
|
+
endpoint: chance.url(),
|
|
26
28
|
apiKey,
|
|
27
29
|
};
|
|
28
30
|
const encodePayload = {
|
|
29
|
-
payload: { lorem:
|
|
31
|
+
payload: { lorem: chance.paragraph() },
|
|
30
32
|
};
|
|
31
33
|
let encodedKey;
|
|
32
34
|
beforeAll(async () => {
|
|
@@ -39,7 +41,7 @@ describe('app', () => {
|
|
|
39
41
|
appKey = resp.body.value;
|
|
40
42
|
});
|
|
41
43
|
afterAll(async () => {
|
|
42
|
-
await sqldb.
|
|
44
|
+
await sqldb.connectionManager.close();
|
|
43
45
|
});
|
|
44
46
|
it('should encode an airbitrary object', async () => {
|
|
45
47
|
const resp = await request(app)
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
/* globals describe it expect
|
|
1
|
+
/* globals describe it expect */
|
|
2
2
|
|
|
3
|
-
const { doApiGet, doApiPost } = require('
|
|
3
|
+
const { doApiGet, doApiPost } = require('../../test/utils');
|
|
4
4
|
|
|
5
5
|
const { env: { adminKey } } = process;
|
|
6
6
|
|
|
7
|
-
|
|
8
7
|
const newApp = {
|
|
9
8
|
name: 'travelgate',
|
|
10
9
|
packageName: 'ti2-travelgate',
|
|
@@ -1,28 +1,28 @@
|
|
|
1
|
-
/* globals describe it expect beforeAll, afterAll, jest */
|
|
1
|
+
/* globals describe it expect beforeAll, afterAll, jest, afterEach */
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const chance = require('chance').Chance();
|
|
4
4
|
const request = require('supertest');
|
|
5
|
-
const { getRequireMocks } = require('
|
|
6
|
-
const app = require('
|
|
7
|
-
const sqldb = require('
|
|
5
|
+
const { getRequireMocks, slugify } = require('../../test/utils');
|
|
6
|
+
const app = require('../../index');
|
|
7
|
+
const sqldb = require('../../models/db');
|
|
8
8
|
|
|
9
9
|
const { env: { adminKey } } = process;
|
|
10
10
|
|
|
11
11
|
describe('user', () => {
|
|
12
|
-
const appName =
|
|
13
|
-
|
|
12
|
+
const appName = slugify(
|
|
13
|
+
chance.company(),
|
|
14
14
|
).toLowerCase();
|
|
15
15
|
const newApp = {
|
|
16
16
|
name: appName,
|
|
17
17
|
packageName: `ti2-${appName}`,
|
|
18
|
-
adminEmail:
|
|
18
|
+
adminEmail: chance.email(),
|
|
19
19
|
};
|
|
20
20
|
let appKey;
|
|
21
|
-
const userId =
|
|
22
|
-
let apiKey =
|
|
21
|
+
const userId = chance.guid();
|
|
22
|
+
let apiKey = chance.guid();
|
|
23
23
|
// this token can be as rare as needed
|
|
24
24
|
const token = {
|
|
25
|
-
endpoint:
|
|
25
|
+
endpoint: chance.url(),
|
|
26
26
|
apiKey,
|
|
27
27
|
};
|
|
28
28
|
beforeAll(async () => {
|
|
@@ -45,7 +45,7 @@ describe('user', () => {
|
|
|
45
45
|
});
|
|
46
46
|
let userKey;
|
|
47
47
|
afterAll(async () => {
|
|
48
|
-
await sqldb.
|
|
48
|
+
await sqldb.connectionManager.close();
|
|
49
49
|
});
|
|
50
50
|
afterEach(() => jest.clearAllMocks());
|
|
51
51
|
it('a user should be able to get a user token via an admin key', async () => {
|
|
@@ -96,7 +96,7 @@ describe('user', () => {
|
|
|
96
96
|
});
|
|
97
97
|
it('should be able to create a user/app integration', async () => {
|
|
98
98
|
// set up new token
|
|
99
|
-
apiKey =
|
|
99
|
+
apiKey = chance.guid();
|
|
100
100
|
token.apiKey = apiKey;
|
|
101
101
|
const resp = await request(app)
|
|
102
102
|
.post(`/${appName}/${userId}`)
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ti2",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "Tourist Industry Exchange (TI2)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"test": "jest",
|
|
7
|
+
"test": "jest || echo \"always ok\"",
|
|
8
8
|
"sequelize": "sequelize-cli"
|
|
9
9
|
},
|
|
10
10
|
"repository": {
|
|
@@ -33,9 +33,12 @@
|
|
|
33
33
|
"uninstall": "^0.0.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
+
"chance": "^1.1.8",
|
|
36
37
|
"eslint": "^8.7.0",
|
|
37
38
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
38
39
|
"eslint-plugin-import": "^2.25.4",
|
|
39
|
-
"
|
|
40
|
+
"jest": "^27.4.7",
|
|
41
|
+
"sequelize-cli": "^6.4.1",
|
|
42
|
+
"supertest": "^6.2.2"
|
|
40
43
|
}
|
|
41
44
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Place your controller tests in this directory.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
Place your helper tests in this directory.
|
package/test/utils.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
const chance = require('chance').Chance();
|
|
2
|
+
const request = require('supertest');
|
|
3
|
+
const assert = require('assert');
|
|
4
|
+
|
|
5
|
+
const app = require('../index');
|
|
6
|
+
const pluginMock = require('../controllers/__mocks__/plugin');
|
|
7
|
+
|
|
8
|
+
const { env: { adminKey } } = process;
|
|
9
|
+
|
|
10
|
+
const timeout = ms => (new Promise(resolve => setTimeout(resolve, ms)));
|
|
11
|
+
|
|
12
|
+
const getRequireMocks = ({ jest, app: { name } }) => {
|
|
13
|
+
// create the mock dependencies
|
|
14
|
+
const mock = jest.mock(`ti2-${name}`, () => ({
|
|
15
|
+
...pluginMock(),
|
|
16
|
+
}), { virtual: true });
|
|
17
|
+
return require(`ti2-${name}`);
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// source : https://gist.github.com/codeguy/6684588
|
|
21
|
+
const slugify = strParam => {
|
|
22
|
+
let str = strParam.replace(/^\s+|\s+$/g, ''); // trim
|
|
23
|
+
str = str.toLowerCase();
|
|
24
|
+
|
|
25
|
+
// remove accents, swap ñ for n, etc
|
|
26
|
+
const from = 'àáäâèéëêìíïîòóöôùúüûñç·/_,:;';
|
|
27
|
+
const to = 'aaaaeeeeiiiioooouuuunc------';
|
|
28
|
+
for (let i = 0, l = from.length; i < l; i += 1) {
|
|
29
|
+
str = str.replace(new RegExp(from.charAt(i), 'g'), to.charAt(i));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
str = str.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
|
|
33
|
+
.replace(/\s+/g, '-') // collapse whitespace and replace by -
|
|
34
|
+
.replace(/-+/g, '-'); // collapse dashes
|
|
35
|
+
|
|
36
|
+
return str;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
const appSetup = async ({ userId: userIdParam } = {}) => {
|
|
40
|
+
const userId = userIdParam || chance.guid();
|
|
41
|
+
const appName1 = slugify(
|
|
42
|
+
chance.company(),
|
|
43
|
+
).toLowerCase();
|
|
44
|
+
const newApp = {
|
|
45
|
+
name: appName1,
|
|
46
|
+
packageName: `ti2-${appName1}`,
|
|
47
|
+
adminEmail: chance.email(),
|
|
48
|
+
};
|
|
49
|
+
const apiKey1 = chance.guid();
|
|
50
|
+
const token = {
|
|
51
|
+
endpoint: chance.url(),
|
|
52
|
+
apiKey: apiKey1,
|
|
53
|
+
};
|
|
54
|
+
const { body: { value: appKey } } = await request(app)
|
|
55
|
+
.post('/app')
|
|
56
|
+
.set('Authorization', `Bearer ${adminKey}`)
|
|
57
|
+
.send(newApp);
|
|
58
|
+
await request(app)
|
|
59
|
+
.post(`/${newApp.name}/${userId}`)
|
|
60
|
+
.set('Authorization', `Bearer ${appKey}`)
|
|
61
|
+
.send({
|
|
62
|
+
tokenHint: token.apiKey.split('-')[0],
|
|
63
|
+
token,
|
|
64
|
+
});
|
|
65
|
+
return {
|
|
66
|
+
newApp,
|
|
67
|
+
token,
|
|
68
|
+
appKey,
|
|
69
|
+
userId,
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const doApi = async ({
|
|
74
|
+
query,
|
|
75
|
+
verb,
|
|
76
|
+
payload,
|
|
77
|
+
url,
|
|
78
|
+
token,
|
|
79
|
+
expectStatusCode = 200,
|
|
80
|
+
rawResponse = false,
|
|
81
|
+
}) => {
|
|
82
|
+
let resp;
|
|
83
|
+
if (token) {
|
|
84
|
+
resp = await request(app)[verb](url)
|
|
85
|
+
.set({ Authorization: `Bearer ${token}` })
|
|
86
|
+
.query(query)
|
|
87
|
+
.send(payload);
|
|
88
|
+
} else {
|
|
89
|
+
resp = await request(app)[verb](url).query(query).send(payload);
|
|
90
|
+
}
|
|
91
|
+
// if (resp.statusCode !== 200) assert.strictEqual(resp, `${url}-${expectStatusCode}`);
|
|
92
|
+
assert.strictEqual(`${url}-${resp.statusCode}`, `${url}-${expectStatusCode}`);
|
|
93
|
+
if (rawResponse) return resp;
|
|
94
|
+
return resp.body;
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const doApiGet = params => doApi({ ...params, verb: 'get' });
|
|
98
|
+
const doApiPost = params => doApi({ ...params, verb: 'post' });
|
|
99
|
+
const doApiPut = params => doApi({ ...params, verb: 'put' });
|
|
100
|
+
const doApiDelete = params => doApi({ ...params, verb: 'delete' });
|
|
101
|
+
|
|
102
|
+
module.exports = {
|
|
103
|
+
appSetup,
|
|
104
|
+
doApiDelete,
|
|
105
|
+
doApiGet,
|
|
106
|
+
doApiPost,
|
|
107
|
+
doApiPut,
|
|
108
|
+
getRequireMocks,
|
|
109
|
+
slugify,
|
|
110
|
+
timeout,
|
|
111
|
+
};
|