Flesh out payment stuff
This commit is contained in:
parent
b0dcdd6438
commit
acfed861ab
27 changed files with 938 additions and 173 deletions
|
|
@ -2159,6 +2159,126 @@ console.log('\n=== Game Session Tests ===');
|
|||
}
|
||||
});
|
||||
|
||||
await test('GET /api/payments/status returns expected generation limit for access type', async () => {
|
||||
const { data } = await request('GET', '/api/payments/status');
|
||||
const status = data as Record<string, unknown>;
|
||||
const accessType = status.accessType as string;
|
||||
const limit = status.generationLimit as number | null;
|
||||
|
||||
if (accessType === 'group') {
|
||||
if (limit !== null) throw new Error('Expected null generationLimit for group access');
|
||||
return;
|
||||
}
|
||||
|
||||
if (accessType === 'subscription') {
|
||||
if (limit !== 250) throw new Error(`Expected generationLimit 250, got ${limit}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (accessType === 'none') {
|
||||
if (limit !== 5) throw new Error(`Expected free tier generationLimit 5, got ${limit}`);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error(`Unexpected accessType: ${accessType}`);
|
||||
});
|
||||
|
||||
await test('POST /api/generate with two documents blocks free tier users', async () => {
|
||||
const statusRes = await request('GET', '/api/payments/status');
|
||||
const status = statusRes.data as Record<string, unknown>;
|
||||
const accessType = status.accessType as string;
|
||||
|
||||
const res = await fetch(`${API_URL}/api/generate`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${TOKEN}`,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
topic: 'Document content',
|
||||
documents: [
|
||||
{ type: 'text', content: 'Doc A' },
|
||||
{ type: 'text', content: 'Doc B' }
|
||||
],
|
||||
questionCount: 2
|
||||
}),
|
||||
});
|
||||
|
||||
if (accessType === 'none') {
|
||||
if (res.status !== 403) throw new Error(`Expected 403 for free tier, got ${res.status}`);
|
||||
const data = await res.json();
|
||||
if (!data.error || !String(data.error).toLowerCase().includes('document')) {
|
||||
throw new Error('Expected document limit error message');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const VALID_STATUSES = [200, 503];
|
||||
if (!VALID_STATUSES.includes(res.status)) {
|
||||
throw new Error(`Expected one of ${VALID_STATUSES.join('/')}, got ${res.status}`);
|
||||
}
|
||||
});
|
||||
|
||||
await test('POST /api/upload with OCR blocks free tier users', async () => {
|
||||
const statusRes = await request('GET', '/api/payments/status');
|
||||
const status = statusRes.data as Record<string, unknown>;
|
||||
const accessType = status.accessType as string;
|
||||
|
||||
const formData = new FormData();
|
||||
const blob = new Blob(['test content'], { type: 'text/plain' });
|
||||
formData.append('document', blob, 'test.txt');
|
||||
formData.append('useOcr', 'true');
|
||||
|
||||
const res = await fetch(`${API_URL}/api/upload`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
Authorization: `Bearer ${TOKEN}`,
|
||||
},
|
||||
body: formData,
|
||||
});
|
||||
|
||||
if (accessType === 'none') {
|
||||
if (res.status !== 403) throw new Error(`Expected 403 for free tier OCR, got ${res.status}`);
|
||||
const data = await res.json();
|
||||
if (!data.error || !String(data.error).toLowerCase().includes('ocr')) {
|
||||
throw new Error('Expected OCR access error message');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const VALID_STATUSES = [200, 400];
|
||||
if (!VALID_STATUSES.includes(res.status)) {
|
||||
throw new Error(`Expected one of ${VALID_STATUSES.join('/')}, got ${res.status}`);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('\nPayments Refund Tests:');
|
||||
|
||||
await test('POST /api/payments/refund without token returns 401', async () => {
|
||||
const res = await fetch(`${API_URL}/api/payments/refund`, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ paymentIntentId: 'pi_test' }),
|
||||
});
|
||||
if (res.status !== 401) throw new Error(`Expected 401, got ${res.status}`);
|
||||
});
|
||||
|
||||
await test('POST /api/payments/refund with non-admin returns 403 or 503', async () => {
|
||||
const res = await fetch(`${API_URL}/api/payments/refund`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
Authorization: `Bearer ${TOKEN}`,
|
||||
},
|
||||
body: JSON.stringify({ paymentIntentId: 'pi_test' }),
|
||||
});
|
||||
|
||||
const VALID_STATUSES = [403, 503];
|
||||
if (!VALID_STATUSES.includes(res.status)) {
|
||||
throw new Error(`Expected one of ${VALID_STATUSES.join('/')}, got ${res.status}`);
|
||||
}
|
||||
});
|
||||
|
||||
console.log('\n=== Quiz Sharing Tests ===');
|
||||
|
||||
let shareTestQuizId: string | null = null;
|
||||
|
|
|
|||
|
|
@ -36,14 +36,14 @@ async function getTokenWithServiceAccount(): Promise<string> {
|
|||
|
||||
const tokenUrl = `${AUTHENTIK_URL}/application/o/token/`;
|
||||
const params = new URLSearchParams({
|
||||
grant_type: 'client_credentials',
|
||||
grant_type: 'password',
|
||||
client_id: CLIENT_ID,
|
||||
username: USERNAME,
|
||||
password: PASSWORD,
|
||||
scope: 'openid profile email',
|
||||
});
|
||||
|
||||
console.log(` Trying client_credentials with username/password...`);
|
||||
console.log(` Trying password grant with username/password...`);
|
||||
const response = await fetch(tokenUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
|
|
|
|||
|
|
@ -4,10 +4,34 @@ import { dirname, join } from 'path';
|
|||
|
||||
const AUTHENTIK_URL = process.env.AUTHENTIK_URL || 'http://localhost:9000';
|
||||
const CLIENT_ID = process.env.CLIENT_ID || 'kaboot-spa';
|
||||
const CLIENT_SECRET = process.env.CLIENT_SECRET || '';
|
||||
const USERNAME = process.env.TEST_USERNAME || '';
|
||||
const PASSWORD = process.env.TEST_PASSWORD || '';
|
||||
const TEST_TOKEN = process.env.TEST_TOKEN || '';
|
||||
|
||||
async function getToken(): Promise<string> {
|
||||
const tokenUrl = `${AUTHENTIK_URL}/application/o/token/`;
|
||||
|
||||
if (CLIENT_SECRET) {
|
||||
const params = new URLSearchParams({
|
||||
grant_type: 'client_credentials',
|
||||
client_id: CLIENT_ID,
|
||||
client_secret: CLIENT_SECRET,
|
||||
scope: 'openid profile email',
|
||||
});
|
||||
|
||||
const response = await fetch(tokenUrl, {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
body: params.toString(),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const data = await response.json();
|
||||
return data.access_token;
|
||||
}
|
||||
}
|
||||
|
||||
if (!USERNAME || !PASSWORD) {
|
||||
throw new Error(
|
||||
'TEST_USERNAME and TEST_PASSWORD must be set in .env.test\n' +
|
||||
|
|
@ -15,9 +39,8 @@ async function getToken(): Promise<string> {
|
|||
);
|
||||
}
|
||||
|
||||
const tokenUrl = `${AUTHENTIK_URL}/application/o/token/`;
|
||||
const params = new URLSearchParams({
|
||||
grant_type: 'client_credentials',
|
||||
grant_type: 'password',
|
||||
client_id: CLIENT_ID,
|
||||
username: USERNAME,
|
||||
password: PASSWORD,
|
||||
|
|
@ -65,14 +88,19 @@ async function main() {
|
|||
console.log('Kaboot API Test Runner');
|
||||
console.log('======================\n');
|
||||
|
||||
console.log('Obtaining access token from Authentik...');
|
||||
let token: string;
|
||||
try {
|
||||
token = await getToken();
|
||||
console.log(' Token obtained successfully.\n');
|
||||
} catch (error) {
|
||||
console.error(` Failed: ${error instanceof Error ? error.message : error}`);
|
||||
process.exit(1);
|
||||
if (TEST_TOKEN) {
|
||||
console.log('Using TEST_TOKEN from environment.\n');
|
||||
token = TEST_TOKEN;
|
||||
} else {
|
||||
console.log('Obtaining access token from Authentik...');
|
||||
try {
|
||||
token = await getToken();
|
||||
console.log(' Token obtained successfully.\n');
|
||||
} catch (error) {
|
||||
console.error(` Failed: ${error instanceof Error ? error.message : error}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Running API tests...\n');
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue