Skip to content

Commit 983f3fb

Browse files
ThomasKranitsasabhinav-koppula
authored andcommitted
Integrate with the automated API testing framework
1 parent 84384b9 commit 983f3fb

File tree

230 files changed

+27168
-9
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

230 files changed

+27168
-9
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ lib-cov
2222
coverage
2323
*.lcov
2424

25+
# Newman tests
26+
newman
27+
2528
# nyc test coverage
2629
.nyc_output
2730

README.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ To be able to change and test `taas-es-processor` locally you can follow the nex
208208
| `npm run build` | Build source code for production run into `dist` folder. |
209209
| `npm run start` | Start app in the production mode from prebuilt `dist` folder. |
210210
| `npm run dev` | Start app in the development mode using `nodemon`. |
211+
| `npm run start:test` | Start app in the test mode. |
211212
| `npm run test` | Run tests. |
212213
| `npm run init-db` | Initializes Database. |
213214
| `npm run create-index` | Create Elasticsearch indexes. Use `-- --force` flag to skip confirmation |
@@ -230,6 +231,9 @@ To be able to change and test `taas-es-processor` locally you can follow the nex
230231
| `npm run migrate:undo` | Revert most recent migration. |
231232
| `npm run demo-email-notifications` | Listen to the Kafka events of email notification and render all the emails into `./out` folder. See [its readme](scripts/demo-email-notifications/README.md) for details. |
232233
| `npm run emsi-mapping` | mapping EMSI tags to topcoder skills |
234+
| `npm run mock-api` | Starts the mock api |
235+
| `npm test:newman` | Starts E2E tests with newman |
236+
| `npm test:newman:clear` | Clears the data produced during E2E tests |
233237
234238
## Import and Export data
235239
@@ -334,9 +338,73 @@ The following parameters can be set in the config file or via env variables:
334338

335339
## Testing
336340

341+
### Unit Tests
342+
337343
- Run `npm run test` to execute unit tests
338344
- Run `npm run cov` to execute unit tests and generate coverage report.
339345

346+
### E2E Postman Tests
347+
348+
1. In the `taas-apis` root directory create `.env` file with the next environment variables.
349+
350+
```bash
351+
# Auth0 config
352+
AUTH_SECRET=
353+
AUTH0_URL=
354+
AUTH0_AUDIENCE=
355+
AUTH0_AUDIENCE_UBAHN=
356+
AUTH0_CLIENT_ID=
357+
AUTH0_CLIENT_SECRET=
358+
AUTH_V2_URL=
359+
AUTH_V2_CLIENT_ID=
360+
AUTH_V3_URL=
361+
# Following configs are used to generate tokens.
362+
ADMIN_CREDENTIALS_USERNAME=
363+
ADMIN_CREDENTIALS_PASSWORD=
364+
MANAGER_CREDENTIALS_USERNAME=
365+
MANAGER_CREDENTIALS_PASSWORD=
366+
COPILOT_CREDENTIALS_USERNAME=
367+
COPILOT_CREDENTIALS_PASSWORD=
368+
USER_CREDENTIALS_USERNAME=
369+
USER_CREDENTIALS_PASSWORD=
370+
# Locally deployed services
371+
ES_HOST=http://localhost:9200
372+
DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres
373+
BUSAPI_URL=http://localhost:8002/v5
374+
MOCK_API_PORT=4000
375+
API_BASE_URL=http://localhost:3000
376+
TC_API=http://localhost:4000/v5
377+
TOPCODER_USERS_API=http://localhost:4000/v3/users
378+
TOPCODER_MEMBERS_API=http://localhost:4000/v3/members
379+
```
380+
1. Install npm dependencies
381+
```bash
382+
npm install
383+
```
384+
1. Start services and mock api and make sure taas-es-processor started properly by viewing logs.
385+
386+
```bash
387+
npm run services:up
388+
npm run mock-api
389+
```
390+
1. Start taas-api in test mode
391+
```bash
392+
npm run start:test
393+
```
394+
1. Create Database tables and Elasticsearch indexes
395+
```bash
396+
npm run init-db
397+
npm run create-index
398+
```
399+
1. Run tests
400+
```bash
401+
npm run test:newman
402+
```
403+
1. Clear test data produced during tests
404+
```bash
405+
npm run test:newman:clear
406+
```
407+
340408
## 📋 Code Guidelines
341409

342410
### General Requirements

config/test.js

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,24 @@
11
module.exports = {
22
LOG_LEVEL: process.env.LOG_LEVEL || 'info',
3-
AUTH0_URL: 'http://example.com',
4-
AUTH0_AUDIENCE: 'http://example.com',
5-
AUTH0_AUDIENCE_UBAHN: 'http://example.com',
6-
AUTH0_CLIENT_ID: 'fake_id',
7-
AUTH0_CLIENT_SECRET: 'fake_secret'
3+
AUTH_V2_URL: process.env.AUTH_V2_URL,
4+
AUTH_V2_CLIENT_ID: process.env.AUTH_V2_CLIENT_ID,
5+
AUTH_V3_URL: process.env.AUTH_V3_URL,
6+
MOCK_API_PORT: process.env.MOCK_API_PORT || 4000,
7+
ADMIN_CREDENTIALS_USERNAME: process.env.ADMIN_CREDENTIALS_USERNAME,
8+
ADMIN_CREDENTIALS_PASSWORD: process.env.ADMIN_CREDENTIALS_PASSWORD,
9+
MANAGER_CREDENTIALS_USERNAME: process.env.MANAGER_CREDENTIALS_USERNAME,
10+
MANAGER_CREDENTIALS_PASSWORD: process.env.MANAGER_CREDENTIALS_PASSWORD,
11+
COPILOT_CREDENTIALS_USERNAME: process.env.COPILOT_CREDENTIALS_USERNAME,
12+
COPILOT_CREDENTIALS_PASSWORD: process.env.COPILOT_CREDENTIALS_PASSWORD,
13+
USER_CREDENTIALS_USERNAME: process.env.USER_CREDENTIALS_USERNAME,
14+
USER_CREDENTIALS_PASSWORD: process.env.USER_CREDENTIALS_PASSWORD,
15+
WAIT_TIME: 6000,
16+
AUTOMATED_TESTING_REPORTERS_FORMAT: process.env.AUTOMATED_TESTING_REPORTERS_FORMAT
17+
? process.env.AUTOMATED_TESTING_REPORTERS_FORMAT.split(',')
18+
: ['cli', 'html'],
19+
AUTOMATED_TESTING_NAME_PREFIX: process.env.AUTOMATED_TESTING_NAME_PREFIX || 'POSTMANE2E-',
20+
API_BASE_URL: process.env.API_BASE_URL || 'http://localhost:3000',
21+
TC_API: process.env.TC_API || 'http://localhost:4000/v5',
22+
TOPCODER_USERS_API: process.env.TOPCODER_USERS_API || 'http://localhost:4000/v3/users',
23+
TOPCODER_MEMBERS_API: process.env.TOPCODER_MEMBERS_API || 'http://localhost:4000/v3/members'
824
}

env.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
export AUTH_SECRET="UgL4(SEAM*~yc7L~vWrKKN&GHrwyc9N[@nVxm,X?#b4}7:xbzM"
3+
export AUTH0_URL=https://topcoder-dev.auth0.com/oauth/token
4+
export AUTH0_AUDIENCE=https://m2m.topcoder-dev.com/
5+
export AUTH0_AUDIENCE_UBAHN=https://u-bahn.topcoder.com
6+
export AUTH0_CLIENT_ID=gZ6jt50HYHLBf4vhxjUhXPZOR7Q5lk4k
7+
export AUTH0_CLIENT_SECRET=zb-OV1Rl3QpUkt4BexJ-Rs58jYMazCre1_97aU4PJIvQdVB-DmQIs61W3gCfPyP4
8+
export BUSAPI_URL=http://localhost:8002/v5
9+
export AUTH_V2_URL=https://topcoder-dev.auth0.com/oauth/ro
10+
export AUTH_V2_CLIENT_ID=JFDo7HMkf0q2CkVFHojy3zHWafziprhT
11+
export AUTH_V3_URL=https://api.topcoder-dev.com/v3/authorizations
12+
export ADMIN_CREDENTIALS_USERNAME=jcori
13+
export ADMIN_CREDENTIALS_PASSWORD=appirio123
14+
export MANAGER_CREDENTIALS_USERNAME=TonyJ
15+
export MANAGER_CREDENTIALS_PASSWORD=appirio123
16+
export COPILOT_CREDENTIALS_USERNAME=TCConnCopilot
17+
export COPILOT_CREDENTIALS_PASSWORD=appirio123
18+
export USER_CREDENTIALS_USERNAME=isbilir
19+
export USER_CREDENTIALS_PASSWORD=@Topcoder123
20+
export ES_HOST=http://localhost:9200
21+
export DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres
22+
export MOCK_API_PORT=4000
23+
export API_BASE_URL=http://localhost:3000
24+
export TC_API=http://localhost:4000/v5
25+
export TOPCODER_USERS_API=http://localhost:4000/v3/users
26+
export TOPCODER_MEMBERS_API=http://localhost:4000/v3/members

mock-api/mock-api.js

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/**
2+
* The mock APIs.
3+
*/
4+
5+
const config = require('config')
6+
const express = require('express')
7+
const cors = require('cors')
8+
const logger = require('../src/common/logger')
9+
const _ = require('lodash')
10+
11+
const skills = [{ name: 'EJB', id: '23e00d92-207a-4b5b-b3c9-4c5662644941' },
12+
{ name: 'Dropwizard', id: '7d076384-ccf6-4e43-a45d-1b24b1e624aa' },
13+
{ name: 'NGINX', id: 'cbac57a3-7180-4316-8769-73af64893158' },
14+
{ name: 'Machine Learning', id: 'a2b4bc11-c641-4a19-9eb7-33980378f82e' },
15+
{ name: 'Force.com', id: '94eae221-1158-4aa9-a6a4-50ecb0bbb8b6' },
16+
{ name: 'Database', id: '2742759c-d0f9-4456-9482-e558aa960969' },
17+
{ name: 'Winforms', id: 'b81859b6-4c50-45d8-afcb-71b35d16ea1e' },
18+
{ name: 'User Interface (Ui)', id: '17b61c7a-98dc-498d-ba8d-c52b6677d73c' },
19+
{ name: 'Photoshop', id: '30d01540-ebed-46b6-88e7-4c210de63862' },
20+
{ name: 'Docker', id: 'bd417c10-d81a-45b6-85a9-d79efe86b9bb' },
21+
{ name: '.NET', id: '4fce6ced-3610-443c-92eb-3f6d76b34f5c' }]
22+
23+
const projects = [
24+
25+
{ id: 111, name: 'Project-111', invites: 1, members: [{ userId: 40158994 }, { userId: 88774634 }] },
26+
{ id: 112, name: 'Project-112', invites: 1, members: [{ userId: 40158994 }, { userId: 88774634 }] },
27+
{ id: 113, name: 'Project-113', invites: 1, members: [{ userId: 40158994 }, { userId: 88774634 }] },
28+
{ id: 222, name: 'Project-222', invites: 1, members: [] }
29+
]
30+
31+
const app = express()
32+
app.set('port', config.MOCK_API_PORT || 4000)
33+
app.use(cors())
34+
app.use(express.json())
35+
app.use((req, res, next) => {
36+
logger.info({ component: 'Mock Api', message: `${req.method} ${req.url}` })
37+
next()
38+
})
39+
40+
app.get('/v5/projects', (req, res) => {
41+
let results = _.cloneDeep(projects)
42+
if (req.query.name) {
43+
results = _.filter(results, ['name', req.query.name])
44+
}
45+
res.status(200).json(results)
46+
})
47+
48+
app.get('/v5/projects/:projectId', (req, res) => {
49+
const project = _.find(projects, project => project.id.toString() === req.params.projectId)
50+
if (project) {
51+
res.json(project)
52+
} else {
53+
res.status(404).end()
54+
}
55+
})
56+
57+
app.post('/v5/projects/:projectId/members', (req, res) => {
58+
res.status(200).json(req.body)
59+
})
60+
61+
app.get('/v5/projects/:projectId/members', (req, res) => {
62+
const project = _.find(projects, project => project.id.toString() === req.params.projectId)
63+
res.status(200).json(project.members)
64+
})
65+
66+
app.delete('/v5/projects/:projectId/members/:memberId', (req, res) => {
67+
const project = _.find(projects, project => project.id.toString() === req.params.projectId)
68+
const member = _.find(project.members, member => member.userId.toString() === req.params.memberId)
69+
if (member) {
70+
res.status(204).end()
71+
} else { res.status(404).end() }
72+
})
73+
74+
app.get('/v5/projects/:projectId/invites', (req, res) => {
75+
const project = _.find(projects, project => project.id.toString() === req.params.projectId)
76+
res.status(200).json({ invites: project.invites })
77+
})
78+
79+
app.get('/v5/skills/:skillId', (req, res) => {
80+
const foundSkill = _.find(skills, ['id', req.params.skillId])
81+
if (foundSkill) {
82+
res.status(200).json(foundSkill)
83+
} else {
84+
res.status(404).end()
85+
}
86+
})
87+
88+
app.get('/v5/skills', (req, res) => {
89+
res.status(200).json(skills)
90+
})
91+
92+
app.get('/v5/users', (req, res) => {
93+
res.status(200).json([{ id: '00000000-0000-0000-0000-000000000000' }])
94+
})
95+
96+
app.get('/v5/users/:userId', (req, res) => {
97+
if (_.includes(['99999999-9999-9999-9999-999999999999'], req.params.userId)) {
98+
res.status(404).end()
99+
} else {
100+
res.status(200).json({ id: req.params.userId, userId: req.params.userId, handle: 'userHandle', firstName: 'firstName', lastName: 'lastName' })
101+
}
102+
})
103+
104+
app.get('/v5/members/:userHandle', (req, res) => {
105+
res.status(200).json({ email: '[email protected]', handle: req.params.userHandle })
106+
})
107+
108+
app.get('/v5/members', (req, res) => {
109+
res.status(200).json([{ handleLower: 'userhandle' }])
110+
})
111+
112+
app.get('/v3/users', (req, res) => {
113+
res.status(200).json({ result: { content: [{ email: '[email protected]', firstName: 'firstName', lastName: 'lastName', handle: 'userhandle', id: 1 }] } })
114+
})
115+
116+
app.get('/v3/members/_search', (req, res) => {
117+
res.status(200).json({ result: { content: [{ email: '[email protected]', firstName: 'firstName', lastName: 'lastName', handle: 'userhandle', userId: 1 }] } })
118+
})
119+
120+
app.use((req, res) => {
121+
res.status(404).json({ error: 'route not found' })
122+
})
123+
124+
app.use((err, req, res, next) => {
125+
logger.logFullError(err, { component: 'Mock Api', signature: `${req.method}_${req.url}` })
126+
res.status(500).json({
127+
error: err.message
128+
})
129+
})
130+
131+
app.listen(app.get('port'), '0.0.0.0', () => {
132+
logger.info({ component: 'Mock Api', message: `Mock Api listening on port ${app.get('port')}` })
133+
})

0 commit comments

Comments
 (0)