Struttura: il sito esistente si sposta sotto apps/sito
Primo passo della separazione sito / piattaforme decisa da Adriano il 03/09: due applicazioni autosufficienti, senza workspace di root, cosi' che ognuna resti un progetto Astro completo ed estraibile. Qui non cambia niente del codice: solo la radice. I pattern del .gitignore che avevano una barra erano ancorati alla radice e dopo lo spostamento non avrebbero piu' coperto niente (data/*.db*, uploads/*): resi validi a qualunque profondita'. Suite: 45 file, 347 test verdi prima e dopo lo spostamento. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EndnceRA5WnA6rvA5iV9WL
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import type Database from 'better-sqlite3';
|
||||
import { createDb } from '../src/lib/db';
|
||||
import {
|
||||
createPost, trashPost, restorePost, deletePost, getPostById, listAllPosts, listByAuthor,
|
||||
listTrashed, listPublished, listRecent, listArchiveMonths, getPublishedBySlug,
|
||||
countPublishedByCategory,
|
||||
} from '../src/lib/posts';
|
||||
|
||||
let db: Database.Database;
|
||||
let id: number;
|
||||
|
||||
const articolo = (slug: string, authorId: number | null = 1) => ({
|
||||
title: `Titolo ${slug}`, slug, category: 'training', excerpt: 'x',
|
||||
body_html: '<p>x</p>', draft: false, author_id: authorId,
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
db = createDb(':memory:');
|
||||
id = createPost(db, articolo('uno'));
|
||||
createPost(db, articolo('due', 2));
|
||||
});
|
||||
|
||||
describe('cestino', () => {
|
||||
it('cestinare non cancella: l\'articolo resta leggibile per id', () => {
|
||||
trashPost(db, id);
|
||||
const p = getPostById(db, id);
|
||||
expect(p).toBeDefined();
|
||||
expect(p!.deleted_at).not.toBeNull();
|
||||
});
|
||||
|
||||
it('lo toglie da tutti gli elenchi del pannello', () => {
|
||||
trashPost(db, id);
|
||||
expect(listAllPosts(db).map((p) => p.slug)).toEqual(['due']);
|
||||
expect(listByAuthor(db, 1)).toEqual([]);
|
||||
expect(listTrashed(db).map((p) => p.slug)).toEqual(['uno']);
|
||||
});
|
||||
|
||||
it('lo toglie dal sito pubblico: elenco, recenti, archivio e pagina singola', () => {
|
||||
trashPost(db, id);
|
||||
expect(listPublished(db).items.map((p) => p.slug)).toEqual(['due']);
|
||||
expect(listPublished(db).total).toBe(1);
|
||||
expect(listPublished(db, { category: 'training' }).total).toBe(1);
|
||||
expect(listRecent(db).map((p) => p.slug)).toEqual(['due']);
|
||||
expect(listArchiveMonths(db).reduce((n, m) => n + m.count, 0)).toBe(1);
|
||||
expect(getPublishedBySlug(db, 'uno')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('il cestino di un autore contiene solo i suoi articoli', () => {
|
||||
trashPost(db, id);
|
||||
expect(listTrashed(db, 1).map((p) => p.slug)).toEqual(['uno']);
|
||||
expect(listTrashed(db, 2)).toEqual([]);
|
||||
});
|
||||
|
||||
it('il ripristino lo rimette dov\'era', () => {
|
||||
trashPost(db, id);
|
||||
restorePost(db, id);
|
||||
expect(getPostById(db, id)!.deleted_at).toBeNull();
|
||||
expect(listTrashed(db)).toEqual([]);
|
||||
expect(listAllPosts(db).map((p) => p.slug)).toContain('uno');
|
||||
expect(getPublishedBySlug(db, 'uno')).toBeDefined();
|
||||
});
|
||||
|
||||
it('i conteggi per categoria escludono cestino e bozze', () => {
|
||||
expect(countPublishedByCategory(db)).toEqual({ training: 2 });
|
||||
trashPost(db, id);
|
||||
expect(countPublishedByCategory(db)).toEqual({ training: 1 });
|
||||
restorePost(db, id);
|
||||
expect(countPublishedByCategory(db)).toEqual({ training: 2 });
|
||||
});
|
||||
|
||||
it('la cancellazione definitiva rimuove davvero la riga', () => {
|
||||
trashPost(db, id);
|
||||
deletePost(db, id);
|
||||
expect(getPostById(db, id)).toBeUndefined();
|
||||
expect(listTrashed(db)).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user