Ajout de tests playwright et correction de tests non passant (pour les tests ajoutés : partie game system ).
All checks were successful
Build & Push Images / build (brain) (push) Successful in 1m36s
Build & Push Images / build (core) (push) Successful in 2m53s
Build & Push Images / build (web) (push) Successful in 2m36s

Correction de plusieurs anomalies : problème de switch entre 2 templates (par exemple si on était sur un template 1 et qu'on voulait passer directement au 2, ce dernier ne chargeait pas) ;
correction du soucis d'apparition de la sidebar à gauche qui disparaissait sans explication ; problème de redirection : lorsqu'on terminait de créer un PJ / PNJ ; on arrivait sur l'accueil de la campagne au lieu de voir le résultat de la création.
Problème de redirection également lors du clique sur un PNJ / PJ sur le coté : on arrivait sur l'édition au lieu de la présentation. Correction de la première lettre stylisée : tout est au même style comme ça plus de probleme de lecture.

Nouveautées : stylisation des modales (notamment suppression, warning.....) avec en prime l'ajout d'un warning lors du changement de système pour avertir que les fiches persos ne sont pas conservées.
Ajout d'une option pour créer un game system directement à la création d'une campagne afin de faciliter la mise en place de cette dernière.
Ajout d'un bouton pour créer un nouveau template directement lorsqu'on créer une page : ça permet de créer un template et de revenir sur la page qu'on était en train de créer sans perdre le titre.

Passage en bêta 0.8.4
This commit is contained in:
2026-05-19 13:37:22 +02:00
parent 7c74c12f3e
commit f24ef0891e
70 changed files with 1908 additions and 495 deletions

View File

@@ -24,10 +24,12 @@ test.describe('Arc delete', () => {
page,
request,
}) => {
page.on('dialog', (dialog) => dialog.accept());
await page.goto(`/campaigns/${campaign.id}/arcs/${arc.id}/edit`);
await page.getByRole('button', { name: /^Supprimer$/i }).click();
await page.getByRole('button', { name: /^Supprimer$/i }).first().click();
const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible();
await dialog.getByRole('button', { name: /^Supprimer$/i }).click();
await expect(page).toHaveURL(new RegExp(`/campaigns/${campaign.id}$`));
@@ -36,10 +38,12 @@ test.describe('Arc delete', () => {
});
test('keeps the arc when confirm is dismissed', async ({ page, request }) => {
page.on('dialog', (dialog) => dialog.dismiss());
await page.goto(`/campaigns/${campaign.id}/arcs/${arc.id}/edit`);
await page.getByRole('button', { name: /^Supprimer$/i }).click();
await page.getByRole('button', { name: /^Supprimer$/i }).first().click();
const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible();
await dialog.getByRole('button', { name: /^Annuler$/i }).click();
await expect(page).toHaveURL(new RegExp(`/campaigns/${campaign.id}/arcs/${arc.id}/edit$`));

View File

@@ -38,6 +38,10 @@ test.describe('Arc edit', () => {
};
await page.goto(`/campaigns/${campaign.id}/arcs/${arc.id}/edit`);
// Attend que le formulaire soit prerempli par le ngOnInit (HTTP async) avant
// de fill — sinon le patchValue du load arrive APRES nos fills et ecrase
// les valeurs, le test echoue alors a la verif persisted.name.
await expect(page.getByLabel(/Titre de l'arc/i)).toHaveValue(arc.name);
await page.getByLabel(/Titre de l'arc/i).fill(newName);
await page.getByLabel(/Synopsis de l'arc/i).fill(values.description);

View File

@@ -16,10 +16,12 @@ test.describe('Campaign delete', () => {
page,
request,
}) => {
page.on('dialog', (dialog) => dialog.accept());
await page.goto(`/campaigns/${campaign.id}`);
await page.getByRole('button', { name: /^Supprimer$/i }).click();
await page.getByRole('button', { name: /^Supprimer$/i }).first().click();
const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible();
await dialog.getByRole('button', { name: /^Supprimer$/i }).click();
await expect(page).toHaveURL(/\/campaigns$/);
@@ -28,10 +30,12 @@ test.describe('Campaign delete', () => {
});
test('keeps the campaign when confirm is dismissed', async ({ page, request }) => {
page.on('dialog', (dialog) => dialog.dismiss());
await page.goto(`/campaigns/${campaign.id}`);
await page.getByRole('button', { name: /^Supprimer$/i }).click();
await page.getByRole('button', { name: /^Supprimer$/i }).first().click();
const dialog = page.getByRole('dialog');
await expect(dialog).toBeVisible();
await dialog.getByRole('button', { name: /^Annuler$/i }).click();
await expect(page).toHaveURL(new RegExp(`/campaigns/${campaign.id}$`));

View File

@@ -17,20 +17,22 @@ test.describe('NPC creation', () => {
if (campaign?.id) await deleteCampaign(request, campaign.id);
});
test('creates an NPC and redirects back to the campaign', async ({ page, request }) => {
test('creates an NPC and redirects to the NPC detail page', async ({ page, request }) => {
// Note : depuis la refonte 2026-04-30 les fiches PNJ utilisent des champs
// templates dynamiques pilotes par le GameSystem (plus de markdownContent
// libre). La campagne seedee n'a pas de GameSystem donc on ne fill que le
// nom — c'est suffisant pour valider la creation + la redirection.
const npcName = `Borin le forgeron ${Date.now()}`;
const markdown = '# Borin\n\n**Faction :** Clan Feuillefer\n\nNain barbu au regard perçant.';
await page.goto(`/campaigns/${campaign.id}/npcs/create`);
await expect(page.getByRole('heading', { name: /Nouveau PNJ/i })).toBeVisible();
await page.getByLabel(/Nom du PNJ/i).fill(npcName);
await page.getByLabel(/Fiche \(markdown\)/i).fill(markdown);
await page.getByRole('button', { name: /^Créer$/i }).click();
// Retour à la page campagne après création
await expect(page).toHaveURL(new RegExp(`/campaigns/${campaign.id}$`));
// Redirection vers la fiche du PNJ après création
await expect(page).toHaveURL(new RegExp(`/campaigns/${campaign.id}/npcs/\\d+$`));
// Persistance vérifiée via API
const npcs = await getNpcsByCampaign(request, campaign.id);
@@ -58,7 +60,7 @@ test.describe('NPC creation', () => {
await page.getByLabel(/Nom du PNJ/i).fill(npcName);
await page.getByRole('button', { name: /^Créer$/i }).click();
await expect(page).toHaveURL(new RegExp(`/campaigns/${campaign.id}$`));
await expect(page).toHaveURL(new RegExp(`/campaigns/${campaign.id}/npcs/\\d+$`));
// Le nœud "PNJ" doit apparaître dans la sidebar avec le nouveau PNJ.
// On clique sur le nœud PNJ pour le déplier au cas où il serait fermé,

View File

@@ -14,19 +14,19 @@ test.describe('NPC edit', () => {
test.beforeEach(async ({ request }) => {
campaign = await seedCampaign(request);
npc = await seedNpc(request, {
campaignId: campaign.id,
markdownContent: '# Initial\n\nFiche de départ.',
});
npc = await seedNpc(request, { campaignId: campaign.id });
});
test.afterEach(async ({ request }) => {
if (campaign?.id) await deleteCampaign(request, campaign.id);
});
test('edits name + markdown content and persists via API', async ({ page, request }) => {
test('edits name and persists via API', async ({ page, request }) => {
// Note : depuis la refonte 2026-04-30 les fiches PNJ utilisent des champs
// templates dynamiques pilotes par le GameSystem, plus le markdownContent
// libre. La campagne seedee n'a pas de GameSystem donc pas de champs
// dynamiques a tester ici — on se contente du nom (champ universel).
const newName = `${npc.name} (renommé)`;
const newMarkdown = '# Borin réécrit\n\n**Statut :** Disparu\n\nDes traces dans la neige...';
await page.goto(`/campaigns/${campaign.id}/npcs/${npc.id}/edit`);
@@ -34,7 +34,6 @@ test.describe('NPC edit', () => {
await expect(page.getByLabel(/Nom du PNJ/i)).toHaveValue(npc.name);
await page.getByLabel(/Nom du PNJ/i).fill(newName);
await page.getByLabel(/Fiche \(markdown\)/i).fill(newMarkdown);
await page.getByRole('button', { name: /^Enregistrer$/i }).click();
@@ -43,7 +42,6 @@ test.describe('NPC edit', () => {
const persisted = await getNpcById(request, npc.id);
expect(persisted.name).toBe(newName);
expect(persisted.markdownContent).toBe(newMarkdown);
});
test('save button is disabled when name is cleared', async ({ page }) => {