Skip to content

Commit 9504748

Browse files
AgileIndustrialComplexkelsos
authored andcommitted
add skeleton for frontend backed api testing
adds new entrypoint for mocked rotki server which returns OK response for any valid request
1 parent e11750b commit 9504748

File tree

13 files changed

+232
-3
lines changed

13 files changed

+232
-3
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
COMMON_LINT_PATHS = rotkehlchen/ package.py
1+
COMMON_LINT_PATHS = rotkehlchen/ rotkehlchen_mock/ package.py
22
TOOLS_LINT_PATH = tools/
33
ALL_LINT_PATHS = $(COMMON_LINT_PATHS) $(TOOLS_LINT_PATH)
44
ISORT_PARAMS = --ignore-whitespace --skip-glob '*/node_modules/*' $(ALL_LINT_PATHS)

frontend/app/.env.contract

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
CODE_COVERAGE=true
2+
VITE_BACKEND_URL=http://127.0.0.1:22221
3+
VITE_TEST=true
4+
VITE_SILENT_TRANSLATION_WARN=true

frontend/app/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,6 @@ rotki_config.json
3838
package-lock.json
3939
components.d.ts
4040
.e2e
41+
.contract
4142

4243
src/data/external-links.js

frontend/app/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"postuninstall": "electron-builder install-app-deps",
2626
"serve": "node scripts/serve.js --web",
2727
"serve:backend": "node scripts/start-backend.js",
28+
"test:contract": "node scripts/contract.js",
2829
"test:integration": "node scripts/e2e.js",
2930
"test:integration-ci": "node scripts/e2e.js --ci",
3031
"test:unit": "cross-env TZ=UTC VITE_TEST=true vitest --dir tests/unit --coverage",

frontend/app/scripts/contract.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
#!/usr/bin/env node
2+
3+
const path = require('node:path');
4+
const { startAndTest } = require('start-server-and-test');
5+
const { ArgumentParser } = require('argparse');
6+
7+
function info(msg) {
8+
console.info(`\n\u001B[32m${msg}\u001B[0m\n`);
9+
};
10+
11+
const parser = new ArgumentParser({
12+
description: 'contract tests, this checks compliance between frontend and backend',
13+
});
14+
parser.add_argument('--spec', { help: 'specific spec to run ' });
15+
16+
const { spec } = parser.parse_args();
17+
18+
require('dotenv').config({
19+
path: path.join(process.cwd(), '.env.contract'),
20+
});
21+
22+
const backendUrl = process.env.VITE_BACKEND_URL;
23+
24+
const services = [
25+
{
26+
start: 'node scripts/start-mocked-backend.js',
27+
url: `${backendUrl}/api/1/ping`,
28+
},
29+
];
30+
31+
const testCmd = 'cross-env TZ=UTC VITE_TEST=true vitest run --dir tests/contract --coverage';
32+
33+
let test = testCmd;
34+
if (spec)
35+
test += ` --spec **/${spec}`;
36+
37+
async function run() {
38+
startAndTest({
39+
services,
40+
test,
41+
namedArguments: { expect: 200 },
42+
})
43+
.then(() => {
44+
info('Execution completed successfully');
45+
process.exit(0);
46+
})
47+
.catch(() => {
48+
console.error('Command execution failed');
49+
process.exit(1);
50+
});
51+
}
52+
53+
// re-evaluate after moving to mjs or ts
54+
// eslint-disable-next-line unicorn/prefer-top-level-await
55+
run();
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
const { spawn } = require('node:child_process');
2+
const fs = require('node:fs');
3+
const path = require('node:path');
4+
5+
if (!(process.env.CI || process.env.VIRTUAL_ENV)) {
6+
process.stdout.write(`\u001B[31mError\u001B[0m: Not CI or VIRTUAL_ENV\n\n`);
7+
process.exit(1);
8+
}
9+
10+
const testDir = path.join(process.cwd(), '.contract');
11+
const dataDir = path.join(testDir, 'data');
12+
13+
process.stdout.write(`Using ${dataDir} to start tests\n`);
14+
15+
function cleanupData() {
16+
const contents = fs.readdirSync(dataDir);
17+
for (const name of contents) {
18+
if (['images', 'global'].includes(name))
19+
continue;
20+
21+
const currentPath = path.join(dataDir, name);
22+
if (fs.statSync(currentPath).isDirectory())
23+
fs.rmSync(currentPath, { recursive: true });
24+
}
25+
};
26+
27+
if (!fs.existsSync(dataDir))
28+
fs.mkdirSync(dataDir, { recursive: true });
29+
else
30+
cleanupData();
31+
32+
const logDir = path.join(testDir, 'logs');
33+
34+
process.stdout.write(`Using ${logDir} to output backend logs\n`);
35+
36+
if (!fs.existsSync(logDir))
37+
fs.mkdirSync(logDir, { recursive: true });
38+
39+
const args = [
40+
'-m',
41+
'rotkehlchen_mock',
42+
'--rest-api-port',
43+
'22221',
44+
'--websockets-api-port',
45+
'22222',
46+
'--api-cors',
47+
'http://localhost:*',
48+
'--data-dir',
49+
dataDir,
50+
'--logfile',
51+
`${path.join(logDir, 'contract.log')}`,
52+
];
53+
54+
let backend;
55+
56+
process.on('SIGTERM', () => {
57+
if (backend)
58+
backend.kill();
59+
60+
cleanupData();
61+
process.stdout.write('Cleanup: complete\n');
62+
process.exit(0);
63+
});
64+
65+
backend = spawn('python', args, {
66+
stdio: [process.stdin, process.stdout, process.stderr],
67+
cwd: path.join('..', '..'),
68+
});
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
rules: {
3+
'max-lines': 'off',
4+
},
5+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/*
2+
grep "const use.*Api" ./app/src/auto-imports.d.ts | cut -d ' ' -f4 | tr -d ':'
3+
*/
4+
5+
describe('test compliance with User Api', () => {
6+
const api = useUsersApi();
7+
it('gets user profiles', async () => {
8+
await api.getUserProfiles();
9+
});
10+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"extends": "../../tsconfig.json",
3+
"compilerOptions": {
4+
"types": ["vuetify", "vitest/globals"]
5+
},
6+
"include": ["**/*.ts", "../../src/auto-imports.d.ts"],
7+
"exclude": ["node_modules/**", "**/.*"],
8+
"compileOnSave": false
9+
}

frontend/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818
"lint": "eslint --cache . && pnpm run -r lint:style",
1919
"lint:fix": "eslint --cache . --fix",
2020
"check": "pnpm run lint && pnpm run build && pnpm run test:unit",
21-
"check:all": "pnpm run lint && pnpm run build && pnpm run --filter @rotki/common test:unit --w app && pnpm run --filter rotki test:integration-ci",
21+
"check:all": "pnpm run lint && pnpm run build && pnpm run --filter @rotki/common test:unit --w app && pnpm run --filter rotki test:integration-ci && pnpm run --filter rotki test:contract",
2222
"check:return-type": "eslint --no-eslintrc --env \"node\" --parser \"@typescript-eslint/parser\" --plugin \"@typescript-eslint\",\"import\" --rule \"{@typescript-eslint/explicit-function-return-type:warn}\" '{app,common}/src/**/*.ts'",
2323
"clean:modules": "rimraf node_modules app/node_modules common/node_modules dev-proxy/node_modules app/dist app/electron-build app/.e2e common/lib",
2424
"dev": "node scripts/start-dev.js",
2525
"preview": "pnpm run --filter rotki preview",
26-
"test": "pnpm run test:unit && pnpm run test:integration-ci",
26+
"test": "pnpm run test:unit && pnpm run test:integration-ci && pnpm run test:contract",
2727
"test:unit": "pnpm run --filter rotki test:unit:run",
2828
"test:unit:watch": "pnpm run --filter rotki test:unit",
29+
"test:contract": "pnpm run --filter rotki test:contract",
2930
"test:integration": " pnpm run --filter rotki test:integration",
3031
"test:integration-ci": " pnpm run --filter rotki test:integration-ci",
3132
"dev:web": "node scripts/start-dev.js --web",

0 commit comments

Comments
 (0)