task(F2-backend): global block favorites - is_favorite column, adapter mapping, PATCH validation

This commit is contained in:
Agent Zero
2026-08-28 13:27:50 +02:00
parent 8ab816667b
commit 83a94e4f42
5 changed files with 111 additions and 7 deletions
+87
View File
@@ -525,3 +525,90 @@ describe('Global Blocks API F1 export/import', () => {
expect(res.statusCode).toBe(400);
});
});
// ─── Task F2: Block-Favoriten ─────────────────────────────
describe('Global Blocks API F2 favorite', () => {
let app: FastifyInstance;
let db: SqliteAdapter;
let authToken: string;
let blockId: string;
beforeAll(async () => {
db = new SqliteAdapter(':memory:');
await db.init();
app = await createServer({ db, port: 0 });
await app.ready();
const regRes = await app.inject({
method: 'POST',
url: '/api/auth/register',
payload: { email: 'fav-test@example.com', password: 'Password123!', name: 'Fav Test', role: 'admin' },
});
authToken = JSON.parse(regRes.body).session.token;
const blockRes = await app.inject({
method: 'POST',
url: '/api/global-blocks',
headers: { authorization: `Bearer ${authToken}` },
payload: { name: 'Fav-Block', block_data: '{"type":"block"}' },
});
blockId = JSON.parse(blockRes.body).id;
});
afterAll(async () => {
await app.close();
db.close();
});
it('neuer Block startet mit is_favorite=false', async () => {
const res = await app.inject({
method: 'GET',
url: `/api/global-blocks/${blockId}`,
headers: { authorization: `Bearer ${authToken}` },
});
expect(res.statusCode).toBe(200);
expect(JSON.parse(res.body).is_favorite).toBe(false);
});
it('PATCH is_favorite:true setzt Favorit', async () => {
const res = await app.inject({
method: 'PATCH',
url: `/api/global-blocks/${blockId}`,
headers: { authorization: `Bearer ${authToken}` },
payload: { is_favorite: true },
});
expect(res.statusCode).toBe(200);
expect(JSON.parse(res.body).is_favorite).toBe(true);
});
it('is_favorite ist persistent nach GET', async () => {
const res = await app.inject({
method: 'GET',
url: `/api/global-blocks/${blockId}`,
headers: { authorization: `Bearer ${authToken}` },
});
expect(res.statusCode).toBe(200);
expect(JSON.parse(res.body).is_favorite).toBe(true);
});
it('PATCH is_favorite:false hebt Favorit auf', async () => {
const res = await app.inject({
method: 'PATCH',
url: `/api/global-blocks/${blockId}`,
headers: { authorization: `Bearer ${authToken}` },
payload: { is_favorite: false },
});
expect(res.statusCode).toBe(200);
expect(JSON.parse(res.body).is_favorite).toBe(false);
});
it('PATCH mit nicht-boolean is_favorite liefert 400', async () => {
const res = await app.inject({
method: 'PATCH',
url: `/api/global-blocks/${blockId}`,
headers: { authorization: `Bearer ${authToken}` },
payload: { is_favorite: 'yes' },
});
expect(res.statusCode).toBe(400);
});
});