Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion infra/k6/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
"test:teams": "k6 run scenarios/teams.js",
"test:projects": "k6 run scenarios/projects.js",
"test:users": "k6 run scenarios/users.js",
"test:board": "k6 run scenarios/board-full.js",
"test:boards:all": "k6 run scenarios/boards.js && k6 run scenarios/boards-columns.js && k6 run scenarios/boards-views.js",
"test:boards": "k6 run scenarios/boards.js",
"test:boards:columns": "k6 run scenarios/boards-columns.js",
"test:boards:views": "k6 run scenarios/boards-views.js",
"test:tasks": "k6 run scenarios/tasks.js",
"smoke": "k6 run smoke.js"
},
Expand Down
134 changes: 134 additions & 0 deletions infra/k6/scenarios/boards-columns.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import { SharedArray } from 'k6/data';
import { sleep, check } from 'k6';
import { GET_OPTIONS } from '../common/config.js';
import getAuthUser from '../shared/get-auth-user.js';

const users = new SharedArray('test users', function () {
return JSON.parse(open('../data/users.json'));
});
const teams = new SharedArray('test teams', function () {
return JSON.parse(open('../data/teams.json'));
});
const randomStr = (len = 8) =>
Math.random()
.toString(36)
.substring(2, 2 + len);
const randomNum = (min = 1, max = 100) => Math.floor(Math.random() * (max - min + 1)) + min;

const baseOptions = GET_OPTIONS();
baseOptions.thresholds = Object.assign({}, baseOptions.thresholds, {
'http_req_duration{name:auth-sign-in}': ['p(95)<333'],
'http_req_duration{name:post-teams-projects}': ['p(95)<333'],
'http_req_duration{name:post-projects-boards}': ['p(95)<333'],
'http_req_duration{name:get-boards-columns}': ['p(95)<333'],
'http_req_duration{name:post-boards-columns}': ['p(95)<333'],
'http_req_duration{name:get-boards-columns-id}': ['p(95)<333'],
'http_req_duration{name:patch-boards-columns}': ['p(95)<333'],
'http_req_duration{name:delete-boards-columns}': ['p(95)<333'],
'http_req_duration{name:delete-teams-projects}': ['p(95)<333'],
});

export const options = baseOptions;

export default function () {
const user = users[(__VU - 1) % users.length];
const team = teams[(__VU - 1) % teams.length];
const { client } = getAuthUser(user);

sleep(1);

// --- create project ---
const project = {
name: `k6_columns_project_${randomStr(6)}`,
key: `K6${randomNum(1000, 9999)}`,
description: 'k6 columns scenario project',
visibility: 'public',
};
const createProjectRes = client.post(`/teams/${team.slug}/projects`, project, {
tags: { name: 'post-teams-projects' },
});
const projectId = createProjectRes.json().projectId;

check(createProjectRes, {
'POST /teams/:slug/projects: has projectId': (r) => r.json().projectId !== undefined,
});

sleep(1);

// --- create board ---
const boardPayload = {
name: `k6_columns_board_${randomStr(6)}`,
position: Date.now(),
};
const createBoardRes = client.post(`/projects/${projectId}/boards`, boardPayload, {
tags: { name: 'post-projects-boards' },
});
const boardId = createBoardRes.json().id;

check(createBoardRes, {
'POST /projects/:id/boards: has id': (r) => r.json().id !== undefined,
});

sleep(1);

// --- get all columns ---
const listRes = client.get(
`/boards/${boardId}/columns`,
{},
{ tags: { name: 'get-boards-columns' } },
);
check(listRes, { 'GET /boards/:id/columns: array': (r) => Array.isArray(r.json()) });

sleep(1);

// --- create column ---
const columnPayload = {
name: `k6_column_${randomStr(6)}`,
position: 4000,
color: '#22c55e',
};
const createColumnRes = client.post(`/boards/${boardId}/columns`, columnPayload, {
tags: { name: 'post-boards-columns' },
});
const columnId = createColumnRes.json().id;

check(createColumnRes, {
'POST /boards/:id/columns: has id': (r) => r.json().id !== undefined,
});

sleep(1);

// --- get column ---
client.get(
`/boards/${boardId}/columns/${columnId}`,
{},
{ tags: { name: 'get-boards-columns-id' } },
);

sleep(1);

// --- update column ---
const updatedColumn = {
name: `k6_column_${randomStr(7)}`,
color: '#3b82f6',
};
client.patch(`/boards/${boardId}/columns/${columnId}`, updatedColumn, {
tags: { name: 'patch-boards-columns' },
});

sleep(1);

// --- delete column ---
client.delete(`/boards/${boardId}/columns/${columnId}`, {
tags: { name: 'delete-boards-columns' },
});

sleep(1);

// --- delete project ---
client.delete(`/teams/${team.slug}/projects/${projectId}`, {
tags: { name: 'delete-teams-projects' },
});

sleep(1);
}
130 changes: 130 additions & 0 deletions infra/k6/scenarios/boards-views.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import { SharedArray } from 'k6/data';
import { sleep, check } from 'k6';
import { GET_OPTIONS } from '../common/config.js';
import getAuthUser from '../shared/get-auth-user.js';

const users = new SharedArray('test users', function () {
return JSON.parse(open('../data/users.json'));
});
const teams = new SharedArray('test teams', function () {
return JSON.parse(open('../data/teams.json'));
});
const randomStr = (len = 8) =>
Math.random()
.toString(36)
.substring(2, 2 + len);
const randomNum = (min = 1, max = 100) => Math.floor(Math.random() * (max - min + 1)) + min;

const baseOptions = GET_OPTIONS();
baseOptions.thresholds = Object.assign({}, baseOptions.thresholds, {
'http_req_duration{name:auth-sign-in}': ['p(95)<333'],
'http_req_duration{name:post-teams-projects}': ['p(95)<333'],
'http_req_duration{name:post-projects-boards}': ['p(95)<333'],
'http_req_duration{name:get-boards-views}': ['p(95)<333'],
'http_req_duration{name:post-boards-views}': ['p(95)<333'],
'http_req_duration{name:get-boards-views-id}': ['p(95)<333'],
'http_req_duration{name:patch-boards-views}': ['p(95)<333'],
'http_req_duration{name:delete-boards-views}': ['p(95)<333'],
'http_req_duration{name:delete-teams-projects}': ['p(95)<333'],
});

export const options = baseOptions;

export default function () {
const user = users[(__VU - 1) % users.length];
const team = teams[(__VU - 1) % teams.length];
const { client } = getAuthUser(user);

sleep(1);

// --- create project ---
const project = {
name: `k6_views_project_${randomStr(6)}`,
key: `K6${randomNum(1000, 9999)}`,
description: 'k6 views scenario project',
visibility: 'public',
};
const createProjectRes = client.post(`/teams/${team.slug}/projects`, project, {
tags: { name: 'post-teams-projects' },
});
const projectId = createProjectRes.json().projectId;

check(createProjectRes, {
'POST /teams/:slug/projects: has projectId': (r) => r.json().projectId !== undefined,
});

sleep(1);

// --- create board ---
const boardPayload = {
name: `k6_views_board_${randomStr(6)}`,
position: Date.now(),
};
const createBoardRes = client.post(`/projects/${projectId}/boards`, boardPayload, {
tags: { name: 'post-projects-boards' },
});
const boardId = createBoardRes.json().id;

check(createBoardRes, {
'POST /projects/:id/boards: has id': (r) => r.json().id !== undefined,
});

sleep(1);

// --- get all views ---
const listRes = client.get(
`/boards/${boardId}/views`,
{},
{ tags: { name: 'get-boards-views' } },
);
check(listRes, { 'GET /boards/:id/views: array': (r) => Array.isArray(r.json()) });

sleep(1);

// --- create view ---
const viewPayload = {
type: 'kanban',
name: `k6_view_${randomStr(6)}`,
position: 4000,
settings: { mock: 'k6' },
};
const createViewRes = client.post(`/boards/${boardId}/views`, viewPayload, {
tags: { name: 'post-boards-views' },
});
const viewId = createViewRes.json().id;

check(createViewRes, {
'POST /boards/:id/views: has id': (r) => r.json().id !== undefined,
});

sleep(1);

// --- get view ---
client.get(`/boards/${boardId}/views/${viewId}`, {}, { tags: { name: 'get-boards-views-id' } });

sleep(1);

// --- update view ---
const updatedView = {
name: `k6_view_${randomStr(7)}`,
};
client.patch(`/boards/${boardId}/views/${viewId}`, updatedView, {
tags: { name: 'patch-boards-views' },
});

sleep(1);

// --- delete view ---
client.delete(`/boards/${boardId}/views/${viewId}`, {
tags: { name: 'delete-boards-views' },
});

sleep(1);

// --- delete project ---
client.delete(`/teams/${team.slug}/projects/${projectId}`, {
tags: { name: 'delete-teams-projects' },
});

sleep(1);
}
115 changes: 115 additions & 0 deletions infra/k6/scenarios/boards.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { SharedArray } from 'k6/data';
import { sleep, check } from 'k6';
import { GET_OPTIONS } from '../common/config.js';
import getAuthUser from '../shared/get-auth-user.js';

const users = new SharedArray('test users', function () {
return JSON.parse(open('../data/users.json'));
});
const teams = new SharedArray('test teams', function () {
return JSON.parse(open('../data/teams.json'));
});
const randomStr = (len = 8) =>
Math.random()
.toString(36)
.substring(2, 2 + len);
const randomNum = (min = 1, max = 100) => Math.floor(Math.random() * (max - min + 1)) + min;

const baseOptions = GET_OPTIONS();
baseOptions.thresholds = Object.assign({}, baseOptions.thresholds, {
'http_req_duration{name:auth-sign-in}': ['p(95)<333'],
'http_req_duration{name:post-teams-projects}': ['p(95)<333'],
'http_req_duration{name:post-projects-boards}': ['p(95)<333'],
'http_req_duration{name:get-projects-boards}': ['p(95)<333'],
'http_req_duration{name:get-projects-boards-id}': ['p(95)<333'],
'http_req_duration{name:patch-projects-boards}': ['p(95)<333'],
'http_req_duration{name:delete-projects-boards}': ['p(95)<333'],
'http_req_duration{name:delete-teams-projects}': ['p(95)<333'],
});

export const options = baseOptions;

export default function () {
const user = users[(__VU - 1) % users.length];
const team = teams[(__VU - 1) % teams.length];
const { client } = getAuthUser(user);

sleep(1);

// --- create project ---
const project = {
name: `k6_board_project_${randomStr(6)}`,
key: `K6${randomNum(1000, 9999)}`,
description: 'k6 boards scenario project',
visibility: 'public',
};
const createProjectRes = client.post(`/teams/${team.slug}/projects`, project, {
tags: { name: 'post-teams-projects' },
});
const projectId = createProjectRes.json().projectId;

check(createProjectRes, {
'POST /teams/:slug/projects: has projectId': (r) => r.json().projectId !== undefined,
});

sleep(1);

// --- create board ---
const boardPayload = {
name: `k6_board_${randomStr(6)}`,
position: Date.now(),
};
const createBoardRes = client.post(`/projects/${projectId}/boards`, boardPayload, {
tags: { name: 'post-projects-boards' },
});
const boardId = createBoardRes.json().id;

check(createBoardRes, {
'POST /projects/:id/boards: has id': (r) => r.json().id !== undefined,
});

sleep(1);

// --- get all boards ---
const listRes = client.get(
`/projects/${projectId}/boards`,
{},
{ tags: { name: 'get-projects-boards' } },
);
check(listRes, { 'GET /projects/:id/boards: array': (r) => Array.isArray(r.json()) });

sleep(1);

// --- get board ---
client.get(
`/projects/${projectId}/boards/${boardId}`,
{},
{ tags: { name: 'get-projects-boards-id' } },
);

sleep(1);

// --- update board ---
const updatedBoard = {
name: `k6_board_${randomStr(7)}`,
};
client.patch(`/projects/${projectId}/boards/${boardId}`, updatedBoard, {
tags: { name: 'patch-projects-boards' },
});

sleep(1);

// --- delete board ---
client.delete(`/projects/${projectId}/boards/${boardId}`, {
tags: { name: 'delete-projects-boards' },
});

sleep(1);

// --- delete project ---
client.delete(`/teams/${team.slug}/projects/${projectId}`, {
tags: { name: 'delete-teams-projects' },
});

sleep(1);
}
Loading
Loading