merge: combine all features from both codebases - mobile dashboard + layer panel + notifications + shares + all fixes
This commit is contained in:
@@ -12,6 +12,7 @@ describe('Elements API', () => {
|
||||
let drawingId: string;
|
||||
let layerId: string;
|
||||
let createdElementId: string;
|
||||
let authToken: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
db = new SqliteAdapter(':memory:');
|
||||
@@ -19,10 +20,18 @@ describe('Elements API', () => {
|
||||
app = await createServer({ db, port: 0 });
|
||||
await app.ready();
|
||||
|
||||
const regRes = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/auth/register',
|
||||
payload: { email: 'admin-test@example.com', password: 'Password123!', name: 'Admin Test', role: 'admin' },
|
||||
});
|
||||
authToken = JSON.parse(regRes.body).session.token;
|
||||
|
||||
// Create project → drawing → layer hierarchy
|
||||
const projRes = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/projects',
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
payload: { name: 'Elements Test Project' },
|
||||
});
|
||||
const projectId = JSON.parse(projRes.body).id;
|
||||
@@ -30,6 +39,7 @@ describe('Elements API', () => {
|
||||
const drawRes = await app.inject({
|
||||
method: 'POST',
|
||||
url: `/api/projects/${projectId}/drawings`,
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
payload: { name: 'Elements Test Drawing' },
|
||||
});
|
||||
drawingId = JSON.parse(drawRes.body).id;
|
||||
@@ -37,6 +47,7 @@ describe('Elements API', () => {
|
||||
const layerRes = await app.inject({
|
||||
method: 'POST',
|
||||
url: `/api/drawings/${drawingId}/layers`,
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
payload: { name: 'Elements Layer' },
|
||||
});
|
||||
layerId = JSON.parse(layerRes.body).id;
|
||||
@@ -47,6 +58,18 @@ describe('Elements API', () => {
|
||||
db.close();
|
||||
});
|
||||
|
||||
// ─── Auth Check ──────────────────────────────────────
|
||||
|
||||
describe('Authentication', () => {
|
||||
it('should return 401 without authorization header', async () => {
|
||||
const response = await app.inject({
|
||||
method: 'GET',
|
||||
url: `/api/drawings/${drawingId}/elements`,
|
||||
});
|
||||
expect(response.statusCode).toBe(401);
|
||||
});
|
||||
});
|
||||
|
||||
// ─── Create ─────────────────────────────────────────
|
||||
|
||||
describe('POST /api/drawings/:drawingId/elements', () => {
|
||||
@@ -54,6 +77,7 @@ describe('Elements API', () => {
|
||||
const response = await app.inject({
|
||||
method: 'POST',
|
||||
url: `/api/drawings/${drawingId}/elements`,
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
payload: { layer_id: layerId, type: 'rect', x: 10, y: 20, width: 100, height: 50 },
|
||||
});
|
||||
expect(response.statusCode).toBe(201);
|
||||
@@ -73,6 +97,7 @@ describe('Elements API', () => {
|
||||
const response = await app.inject({
|
||||
method: 'POST',
|
||||
url: `/api/drawings/${drawingId}/elements`,
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
payload: { layer_id: layerId, type: 'circle' },
|
||||
});
|
||||
expect(response.statusCode).toBe(201);
|
||||
@@ -93,6 +118,7 @@ describe('Elements API', () => {
|
||||
const response = await app.inject({
|
||||
method: 'GET',
|
||||
url: `/api/drawings/${drawingId}/elements`,
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
});
|
||||
expect(response.statusCode).toBe(200);
|
||||
const body = JSON.parse(response.body);
|
||||
@@ -105,12 +131,14 @@ describe('Elements API', () => {
|
||||
const projRes = await app.inject({
|
||||
method: 'POST',
|
||||
url: '/api/projects',
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
payload: { name: 'Empty Elements Project' },
|
||||
});
|
||||
const projId = JSON.parse(projRes.body).id;
|
||||
const drawRes = await app.inject({
|
||||
method: 'POST',
|
||||
url: `/api/projects/${projId}/drawings`,
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
payload: { name: 'Empty Drawing' },
|
||||
});
|
||||
const emptyDrawId = JSON.parse(drawRes.body).id;
|
||||
@@ -118,6 +146,7 @@ describe('Elements API', () => {
|
||||
const response = await app.inject({
|
||||
method: 'GET',
|
||||
url: `/api/drawings/${emptyDrawId}/elements`,
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
});
|
||||
expect(response.statusCode).toBe(200);
|
||||
const body = JSON.parse(response.body);
|
||||
@@ -133,6 +162,7 @@ describe('Elements API', () => {
|
||||
const response = await app.inject({
|
||||
method: 'PATCH',
|
||||
url: `/api/elements/${createdElementId}`,
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
payload: { x: 100, y: 200 },
|
||||
});
|
||||
expect(response.statusCode).toBe(200);
|
||||
@@ -145,6 +175,7 @@ describe('Elements API', () => {
|
||||
const response = await app.inject({
|
||||
method: 'PATCH',
|
||||
url: `/api/elements/${createdElementId}`,
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
payload: { width: 300, height: 150 },
|
||||
});
|
||||
expect(response.statusCode).toBe(200);
|
||||
@@ -157,6 +188,7 @@ describe('Elements API', () => {
|
||||
const response = await app.inject({
|
||||
method: 'PATCH',
|
||||
url: `/api/elements/${createdElementId}`,
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
payload: { properties_json: '{"color":"red"}' },
|
||||
});
|
||||
expect(response.statusCode).toBe(200);
|
||||
@@ -168,6 +200,7 @@ describe('Elements API', () => {
|
||||
const response = await app.inject({
|
||||
method: 'PATCH',
|
||||
url: '/api/elements/non-existent-id',
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
payload: { x: 0 },
|
||||
});
|
||||
expect(response.statusCode).toBe(404);
|
||||
@@ -182,6 +215,7 @@ describe('Elements API', () => {
|
||||
const createRes = await app.inject({
|
||||
method: 'POST',
|
||||
url: `/api/drawings/${drawingId}/elements`,
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
payload: { layer_id: layerId, type: 'line' },
|
||||
});
|
||||
const elemId = JSON.parse(createRes.body).id;
|
||||
@@ -189,6 +223,7 @@ describe('Elements API', () => {
|
||||
const response = await app.inject({
|
||||
method: 'DELETE',
|
||||
url: `/api/elements/${elemId}`,
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
});
|
||||
expect(response.statusCode).toBe(204);
|
||||
|
||||
@@ -196,6 +231,7 @@ describe('Elements API', () => {
|
||||
const listRes = await app.inject({
|
||||
method: 'GET',
|
||||
url: `/api/drawings/${drawingId}/elements`,
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
});
|
||||
const elements = JSON.parse(listRes.body);
|
||||
expect(elements.find((e: any) => e.id === elemId)).toBeUndefined();
|
||||
@@ -205,6 +241,7 @@ describe('Elements API', () => {
|
||||
const response = await app.inject({
|
||||
method: 'DELETE',
|
||||
url: '/api/elements/non-existent-id',
|
||||
headers: { authorization: `Bearer ${authToken}` },
|
||||
});
|
||||
expect(response.statusCode).toBe(404);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user