Skip to content

Commit bc1e92c

Browse files
committed
Create k6 scripts and http to test
1 parent 6aea7b6 commit bc1e92c

File tree

15 files changed

+323
-12
lines changed

15 files changed

+323
-12
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@ yarn-error.log
2020
/.phpstorm.meta.php
2121
/_ide_helper.php
2222
/coverage
23-
/dist
23+
/dist
24+
/k6/node_modules/

docker-compose.yml

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
version: '3.8'
2-
31
services:
42
app:
53
image: ts-restful-api:dev
@@ -11,10 +9,23 @@ services:
119
- /app/node_modules
1210
command: ["npm", "run", "dev"]
1311
ports:
14-
- 3000:3000
12+
- "3000:3000"
1513
depends_on:
1614
- mysql
1715

16+
k6:
17+
image: grafana/k6
18+
working_dir: /app
19+
environment:
20+
K6_WEB_DASHBOARD: true
21+
tty: true
22+
command: >
23+
run src/ping.js
24+
ports:
25+
- "5665:5665"
26+
volumes:
27+
- ./k6:/app
28+
1829
mysql:
1930
image: mysql/mysql-server:8.0
2031
restart: always

k6/node_modules/@types/k6/README.md

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

k6/package-lock.json

Lines changed: 18 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

k6/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"devDependencies": {
3+
"@types/k6": "^0.54.2"
4+
}
5+
}

k6/src/create-contact.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { vu } from 'k6/execution'
2+
import {loginUser} from "./supports/user.js";
3+
import {createContact} from "./supports/contact.js";
4+
5+
export const options = {
6+
vus: 10,
7+
duration: '30s'
8+
}
9+
10+
export function setup() {
11+
const data = []
12+
13+
for (let i = 0; i < 10; i++) {
14+
data.push({
15+
first_name: 'Contact',
16+
last_name: `No ${i}`,
17+
email: `contact${i}@example.com`,
18+
phone: `i`
19+
})
20+
}
21+
22+
return data
23+
}
24+
25+
const getToken = () => {
26+
const username = `kevin${vu.idInInstance}`
27+
const loginRequest = JSON.stringify({
28+
username,
29+
password: 'password'
30+
})
31+
32+
33+
return loginUser(loginRequest)
34+
}
35+
36+
export default function (data) {
37+
const { token } = getToken()
38+
39+
for (const value of data) {
40+
createContact(JSON.stringify(value), token)
41+
}
42+
}

k6/src/ping.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import http from 'k6/http';
2+
import { sleep } from 'k6';
3+
4+
export const options = {
5+
vus: 10,
6+
duration: '30s',
7+
};
8+
9+
export default function() {
10+
http.get('http://app:3000/api/ping');
11+
}

k6/src/register.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import http from 'k6/http';
2+
import {check, fail} from 'k6';
3+
import { uuidv4 } from 'https://jslib.k6.io/k6-utils/1.4.0/index.js';
4+
5+
export const options = {
6+
vus: 10,
7+
duration: '10s',
8+
};
9+
10+
const currentUserCallback = (data, { uniqueId }) => {
11+
const currentUser = http.get('http://app:3000/api/users/current', {
12+
headers: {
13+
'Accept': 'application/json',
14+
'Content-Type': 'application/json',
15+
'X-API-TOKEN': data.token
16+
}
17+
});
18+
19+
const currentUserResponse = currentUser.json()
20+
21+
const currentUserCheck = check(currentUser, {
22+
'Current user response status must 200': currentUser.status === 200,
23+
'Current user response data must not null': currentUserResponse.data !== null ,
24+
})
25+
26+
if (! currentUserCheck) {
27+
fail(`Failed to get current user-${uniqueId}`)
28+
}
29+
30+
return currentUserResponse
31+
}
32+
33+
const loginCallback = (data, { uniqueId, password }) => {
34+
const loginRequest = JSON.stringify({
35+
username: data?.username || '',
36+
password,
37+
})
38+
39+
const login = http.post('http://app:3000/api/login', loginRequest, {
40+
headers: {
41+
'Accept': 'application/json',
42+
'Content-Type': 'application/json'
43+
}
44+
});
45+
46+
const loginResponse = login.json()
47+
48+
const loginCheck = check(login, {
49+
'Login response status must 200': login.status === 200,
50+
'Login response token must not null': (loginResponse.data?.token || null) !== null ,
51+
})
52+
53+
if (! loginCheck) {
54+
fail(`Failed to get user-${uniqueId}`)
55+
}
56+
57+
return loginResponse
58+
}
59+
60+
const registerCallback = ({ uniqueId, password }) => {
61+
const data = JSON.stringify({
62+
username: `user-${uniqueId}`,
63+
password,
64+
name: `user-${uniqueId}`
65+
})
66+
67+
const userRegistered = http.post('http://app:3000/api/users', data, {
68+
headers: {
69+
'Accept': 'application/json',
70+
'Content-Type': 'application/json'
71+
}
72+
})
73+
74+
const userRegisteredResponse = userRegistered.json()
75+
76+
const userRegisteredCheck = check(userRegistered, {
77+
'Register response status must 201': userRegistered.status === 201,
78+
'Register response data must not null': userRegisteredResponse.data !== null ,
79+
})
80+
81+
if (! userRegisteredCheck) {
82+
fail(`Failed to registering user-${uniqueId}`)
83+
}
84+
85+
return userRegisteredResponse
86+
}
87+
88+
export default function() {
89+
const uniqueId = uuidv4()
90+
const password = 'password'
91+
92+
const registerResponse = registerCallback({ uniqueId, password })
93+
94+
const loginResponse = loginCallback(registerResponse.data, { uniqueId, password })
95+
96+
return currentUserCallback(loginResponse.data, { uniqueId })
97+
}

k6/src/stages.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import http from 'k6/http';
2+
3+
export const options = {
4+
stages: [
5+
{
6+
duration: '10s',
7+
target: 20
8+
},
9+
{
10+
duration: '10s',
11+
target: 10
12+
},
13+
{
14+
duration: '10s',
15+
target: 0
16+
},
17+
]
18+
};
19+
20+
export default function() {
21+
http.get('http://app:3000/api/ping');
22+
}

k6/src/supports/contact.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import http from "k6/http";
2+
import {check} from "k6";
3+
4+
export const createContact = (createContactRequest, token) => {
5+
const createContact = http.post('http://app:3000/api/contacts', createContactRequest, {
6+
headers: {
7+
'X-API-TOKEN': token,
8+
'Accept': 'application/json',
9+
'Content-Type': 'application/json'
10+
}
11+
})
12+
13+
const createContactResponse = createContact.json()
14+
15+
check(createContact, {
16+
'response must be 200': createContact.status === 200,
17+
'response contains id': createContactResponse.data.id !== undefined,
18+
})
19+
}

0 commit comments

Comments
 (0)