Skip to content

Commit 0a4c3bd

Browse files
author
CodeJudge
committed
feat: PWA manifest + API 测试套件
1 parent 0dcbd48 commit 0a4c3bd

4 files changed

Lines changed: 92 additions & 1 deletion

File tree

backend/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
"main": "src/app.js",
66
"scripts": {
77
"start": "node src/app.js",
8-
"dev": "nodemon src/app.js"
8+
"dev": "nodemon src/app.js",
9+
"test": "node --test tests/*.test.js",
10+
"test:watch": "node --watch --test tests/*.test.js"
911
},
1012
"dependencies": {
1113
"bcryptjs": "^2.4.3",

backend/tests/api.test.js

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
const { describe, it, before, after } = require('node:test');
2+
const assert = require('assert');
3+
4+
const BASE = 'http://localhost:3001/api';
5+
6+
describe('CodeJudge API Tests', () => {
7+
let token;
8+
9+
it('GET /health returns ok', async () => {
10+
const res = await fetch(`${BASE}/../api/health`);
11+
const data = await res.json();
12+
assert.equal(data.status, 'ok');
13+
});
14+
15+
it('GET /problems/stats returns numbers', async () => {
16+
const res = await fetch(`${BASE}/problems/stats`);
17+
const data = await res.json();
18+
assert.ok(typeof data.total === 'number');
19+
assert.ok(data.total >= 10000);
20+
});
21+
22+
it('POST /auth/login with valid credentials returns token', async () => {
23+
const res = await fetch(`${BASE}/auth/login`, {
24+
method: 'POST',
25+
headers: { 'Content-Type': 'application/json' },
26+
body: JSON.stringify({ email: 'admin@oj.com', password: 'admin123' }),
27+
});
28+
const data = await res.json();
29+
assert.ok(data.token);
30+
assert.equal(data.user.role, 'admin');
31+
token = data.token;
32+
});
33+
34+
it('GET /auth/profile requires auth', async () => {
35+
const res = await fetch(`${BASE}/auth/profile`);
36+
assert.equal(res.status, 401);
37+
});
38+
39+
it('GET /auth/profile with token returns user', async () => {
40+
const res = await fetch(`${BASE}/auth/profile`, {
41+
headers: { Authorization: `Bearer ${token}` },
42+
});
43+
const data = await res.json();
44+
assert.equal(data.role, 'admin');
45+
});
46+
47+
it('GET /problems returns paginated list', async () => {
48+
const res = await fetch(`${BASE}/problems?limit=5&page=1`);
49+
const data = await res.json();
50+
assert.equal(data.problems.length, 5);
51+
assert.ok(data.total >= 10000);
52+
});
53+
54+
it('GET /problems/:id returns problem', async () => {
55+
const res = await fetch(`${BASE}/problems/1`);
56+
const data = await res.json();
57+
assert.ok(data.title);
58+
});
59+
60+
it('GET /auth/leaderboard returns array', async () => {
61+
const res = await fetch(`${BASE}/auth/leaderboard`);
62+
const data = await res.json();
63+
assert.ok(Array.isArray(data));
64+
});
65+
66+
it('POST /submissions choice answer works', async () => {
67+
const res = await fetch(`${BASE}/submissions`, {
68+
method: 'POST',
69+
headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${token}` },
70+
body: JSON.stringify({ problem_id: 5000, answer: 0 }),
71+
});
72+
const data = await res.json();
73+
assert.ok(['accepted', 'wrong_answer'].includes(data.status));
74+
});
75+
});

frontend/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
<meta property="og:description" content="编程、选择、填空三种题型,在线编写代码实时判题" />
1010
<meta property="og:type" content="website" />
1111
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
12+
<link rel="manifest" href="/manifest.json" />
13+
<meta name="theme-color" content="#020617" />
1214
<title>CodeJudge - 在线评测系统</title>
1315
<link rel="preconnect" href="https://fonts.googleapis.com" />
1416
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />

frontend/public/manifest.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"name": "CodeJudge - 在线评测系统",
3+
"short_name": "CodeJudge",
4+
"description": "在线编写代码、答题判题,支持编程/选择/填空三种题型",
5+
"start_url": "/",
6+
"display": "standalone",
7+
"background_color": "#020617",
8+
"theme_color": "#3b82f6",
9+
"icons": [
10+
{ "src": "/vite.svg", "sizes": "any", "type": "image/svg+xml", "purpose": "any maskable" }
11+
]
12+
}

0 commit comments

Comments
 (0)