-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathapi.test.js
More file actions
156 lines (132 loc) · 5.2 KB
/
api.test.js
File metadata and controls
156 lines (132 loc) · 5.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
const { test } = require('node:test');
const assert = require('node:assert');
const request = require('supertest');
const { app } = require('../src/index.js');
test('GET /health returns 200', async () => {
const res = await request(app).get('/health');
assert.strictEqual(res.status, 200);
assert.deepStrictEqual(res.body, { status: 'ok' });
assert.strictEqual(res.headers['x-powered-by'], undefined);
});
test('POST /v1/chat/completions works with valid data', async () => {
const res = await request(app)
.post('/v1/chat/completions')
.send({
model: 'gpt-4',
messages: [{ role: 'user', content: 'Hello!' }]
});
assert.strictEqual(res.status, 200);
assert.ok(res.body.id.startsWith('chatcmpl-'));
assert.ok(res.body.id.length > 20); // chatcmpl- + UUID length (36)
assert.strictEqual(res.body.object, 'chat.completion');
assert.strictEqual(res.body.model, 'gpt-4');
assert.strictEqual(res.body.choices[0].message.content, 'This is a mock response from the unified API.');
});
test('POST /v1/chat/completions fails without model', async () => {
const res = await request(app)
.post('/v1/chat/completions')
.send({
messages: [{ role: 'user', content: 'Hello!' }]
});
assert.strictEqual(res.status, 400);
assert.strictEqual(res.body.error, 'Missing or invalid model');
});
test('POST /v1/chat/completions fails when messages is not an array', async () => {
const res = await request(app)
.post('/v1/chat/completions')
.send({
model: 'gpt-4',
messages: "Hello!"
});
assert.strictEqual(res.status, 400);
assert.strictEqual(res.body.error, 'Missing or invalid messages');
});
test('POST /v1/chat/completions fails with empty messages array', async () => {
const res = await request(app)
.post('/v1/chat/completions')
.send({
model: 'gpt-4',
messages: []
});
assert.strictEqual(res.status, 400);
assert.strictEqual(res.body.error, 'Missing or invalid messages');
});
test('POST /v1/chat/completions fails with malformed message objects', async () => {
const res = await request(app)
.post('/v1/chat/completions')
.send({
model: 'gpt-4',
messages: [{ role: 'user' }] // missing content
});
assert.strictEqual(res.status, 400);
assert.strictEqual(res.body.error, 'Malformed message object');
});
test('POST /v1/chat/completions fails with invalid JSON gracefully', async () => {
const res = await request(app)
.post('/v1/chat/completions')
.set('Content-Type', 'application/json')
.send('{invalid_json');
assert.strictEqual(res.status, 400);
assert.strictEqual(res.body.error, 'Invalid JSON payload');
});
test('Generic error handler returns 500 without leaking stack traces', async () => {
const crypto = require('crypto');
const originalRandomUUID = crypto.randomUUID;
const originalConsoleError = console.error;
// Mock internal failure
crypto.randomUUID = () => { throw new Error('Mock internal failure'); };
// Suppress expected console.error from the error handler
console.error = () => {};
try {
const res = await request(app)
.post('/v1/chat/completions')
.send({
model: 'gpt-4',
messages: [{ role: 'user', content: 'Hello!' }]
});
assert.strictEqual(res.status, 500);
assert.deepStrictEqual(res.body, { error: 'Internal server error' });
} finally {
// Restore originals
crypto.randomUUID = originalRandomUUID;
console.error = originalConsoleError;
}
});
test('POST /v1/chat/completions fails with more than 1000 messages', async () => {
const res = await request(app)
.post('/v1/chat/completions')
.send({
model: 'gpt-4',
messages: new Array(1001).fill({ role: 'user', content: 'test' })
});
assert.strictEqual(res.status, 400);
assert.strictEqual(res.body.error, 'Too many messages');
});
test('isValidMessage validation helper', () => {
const { isValidMessage } = require('../src/index.js');
assert.strictEqual(isValidMessage({ role: 'user', content: 'hello' }), true);
assert.strictEqual(isValidMessage(null), false);
assert.strictEqual(isValidMessage([]), false);
assert.strictEqual(isValidMessage({ role: 'user' }), false);
});
test('isValidModel validation helper', () => {
const { isValidModel } = require('../src/index.js');
assert.strictEqual(isValidModel('gpt-4'), true);
assert.strictEqual(isValidModel(''), false);
assert.strictEqual(isValidModel(' '), false);
assert.strictEqual(isValidModel(null), false);
assert.strictEqual(isValidModel(123), false);
});
test('isValidMessagesArray validation helper', () => {
const { isValidMessagesArray } = require('../src/index.js');
assert.strictEqual(isValidMessagesArray([{ role: 'user', content: 'hello' }]), true);
assert.strictEqual(isValidMessagesArray([]), false);
assert.strictEqual(isValidMessagesArray(null), false);
assert.strictEqual(isValidMessagesArray("not an array"), false);
});
test('404 handler returns proper JSON and does not leak path', async () => {
const res = await request(app).get('/some-unknown-path');
assert.strictEqual(res.status, 404);
assert.strictEqual(res.headers['content-type'], 'application/json; charset=utf-8');
assert.deepStrictEqual(res.body, { error: 'Not found' });
});