107 lines
3.9 KiB
TypeScript
107 lines
3.9 KiB
TypeScript
/**
|
|
* Integration tests — verify Appwrite backend is reachable and configured correctly.
|
|
* These tests make real network calls; they require NUXT_PUBLIC_APPWRITE_* env vars
|
|
* from .env.local and a live Appwrite instance.
|
|
*/
|
|
import { describe, it, expect, beforeAll } from 'vitest';
|
|
import { Client, Account, Databases, AppwriteException } from 'appwrite';
|
|
|
|
const endpoint = process.env.NUXT_PUBLIC_APPWRITE_ENDPOINT;
|
|
const projectId = process.env.NUXT_PUBLIC_APPWRITE_PROJECT_ID;
|
|
|
|
function makeClient(): Client {
|
|
return new Client().setEndpoint(endpoint!).setProject(projectId!);
|
|
}
|
|
|
|
describe('Appwrite configuration', () => {
|
|
it('has NUXT_PUBLIC_APPWRITE_ENDPOINT set', () => {
|
|
expect(endpoint, 'NUXT_PUBLIC_APPWRITE_ENDPOINT is missing from .env.local').toBeTruthy();
|
|
});
|
|
|
|
it('has NUXT_PUBLIC_APPWRITE_PROJECT_ID set', () => {
|
|
expect(projectId, 'NUXT_PUBLIC_APPWRITE_PROJECT_ID is missing from .env.local').toBeTruthy();
|
|
});
|
|
});
|
|
|
|
describe('Appwrite health', () => {
|
|
// Some Appwrite deployments restrict /health to authenticated requests (returns 401).
|
|
// Either 200 or 401 confirms the server is reachable and responding.
|
|
it('health endpoint is reachable', async () => {
|
|
const res = await fetch(`${endpoint}/health`);
|
|
expect([200, 401], `Unexpected status ${res.status} — is ${endpoint} correct?`).toContain(res.status);
|
|
});
|
|
|
|
it('health DB endpoint is reachable', async () => {
|
|
const res = await fetch(`${endpoint}/health/db`);
|
|
expect([200, 401], `Unexpected status ${res.status} — is ${endpoint} correct?`).toContain(res.status);
|
|
});
|
|
});
|
|
|
|
describe('Appwrite account service', () => {
|
|
let client: Client;
|
|
|
|
beforeAll(() => {
|
|
client = makeClient();
|
|
});
|
|
|
|
it('rejects unauthenticated session with 401 (not a network error)', async () => {
|
|
const account = new Account(client);
|
|
await expect(account.get()).rejects.toSatisfy(
|
|
(e: unknown) => e instanceof AppwriteException && e.code === 401
|
|
);
|
|
});
|
|
|
|
it('can request a magic URL token (email delivery not verified here)', async () => {
|
|
const account = new Account(client);
|
|
// Use a clearly synthetic address so no real user is affected.
|
|
// A 429 (rate limit) also confirms the endpoint is reachable.
|
|
try {
|
|
await account.createMagicURLToken('test-probe', 'probe@example.invalid');
|
|
// If it succeeds, the endpoint responded (unusual for a fake address but acceptable)
|
|
} catch (e: unknown) {
|
|
expect(e).toBeInstanceOf(AppwriteException);
|
|
// Any AppwriteException means we reached the server
|
|
expect((e as AppwriteException).code).not.toBe(0);
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('Appwrite database service', () => {
|
|
let client: Client;
|
|
|
|
beforeAll(() => {
|
|
client = makeClient();
|
|
});
|
|
|
|
it('database "bab_prod" exists (unauthenticated returns 401, not 404)', async () => {
|
|
const db = new Databases(client);
|
|
try {
|
|
await db.listDocuments('bab_prod', 'boat');
|
|
// Authenticated session — collection is readable
|
|
} catch (e: unknown) {
|
|
expect(e).toBeInstanceOf(AppwriteException);
|
|
// 401 = reached DB but not authenticated; 403 = authenticated but no permission
|
|
// Either confirms the database and collection exist
|
|
expect((e as AppwriteException).code).not.toBe(404);
|
|
}
|
|
});
|
|
|
|
// task, taskTags, skillTags are parked — not yet implemented in bab_prod
|
|
const collections = ['boat', 'reservation', 'interval', 'intervalTemplate'];
|
|
|
|
it.each(collections)('collection "%s" exists in bab_prod', async (collection) => {
|
|
const db = new Databases(client);
|
|
try {
|
|
await db.listDocuments('bab_prod', collection);
|
|
} catch (e: unknown) {
|
|
expect(e).toBeInstanceOf(AppwriteException);
|
|
expect(
|
|
(e as AppwriteException).code,
|
|
`Collection "${collection}" returned 404. ` +
|
|
`Verify it exists in Appwrite dashboard under database "bab_prod" ` +
|
|
`and that the collection ID matches exactly (case-sensitive).`
|
|
).not.toBe(404);
|
|
}
|
|
});
|
|
});
|