From 8e8737e130e56a9d975ed8e1a7d08b098a1fa2fb Mon Sep 17 00:00:00 2001 From: shikanime Date: Wed, 26 Aug 2026 01:22:58 +0200 Subject: [PATCH 1/3] test(playwright): user-acceptance gap-fill secrets journeys Co-authored-by: Automata --- playwright/e2e-tests/secrets.spec.ts | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 playwright/e2e-tests/secrets.spec.ts diff --git a/playwright/e2e-tests/secrets.spec.ts b/playwright/e2e-tests/secrets.spec.ts new file mode 100644 index 0000000000..26550726f9 --- /dev/null +++ b/playwright/e2e-tests/secrets.spec.ts @@ -0,0 +1,55 @@ +import { expect, test } from '@playwright/test' +import { clientURL, signInCloudPiNative, testUser } from 'config/console' +import { createProject, deleteProject } from 'helpers/project' + +/** + * Cahier de tests fonctionnels — SECR-001 / SECR-003 + * SECR-001: Affichage des secrets de projet (toggle "Afficher les secrets des services") + * SECR-003: Bouton indisponible (projet verrouillé) — covered indirectly here by the + * visibility contract on a fresh project; the locked-project variant requires an + * archived/locked fixture the CI stack does not provision (see skip below). + */ +test.describe('Secrets du projet (SECR)', { tag: '@e2e' }, () => { + let projectName: string + + test.beforeEach(async ({ page }) => { + await page.goto(clientURL) + await signInCloudPiNative({ page, credentials: testUser }) + const { name } = await createProject({ page }) + projectName = name + }) + + test('SECR-001: the secrets toggle is visible on a fresh project dashboard', async ({ page }) => { + await page.getByTestId('menuMyProjects').click() + await page.getByRole('link', { name: projectName }).click() + + // The toggle button exists and defaults to the hidden state + const toggle = page.getByRole('button', { name: 'Afficher les secrets des services' }) + await expect(toggle).toBeVisible() + }) + + test('SECR-001: toggling switches the label between show/hide', async ({ page }) => { + await page.getByTestId('menuMyProjects').click() + await page.getByRole('link', { name: projectName }).click() + + const toggle = page.getByRole('button', { name: 'Afficher les secrets des services' }) + await toggle.click() + await expect(page.getByRole('button', { name: 'Cacher les secrets des services' })).toBeVisible() + // toggle back for state cleanliness + await page.getByRole('button', { name: 'Cacher les secrets des services' }).click() + await expect(page.getByRole('button', { name: 'Afficher les secrets des services' })).toBeVisible() + }) + + test.skip('SECR-003: secrets button unavailable on a locked project', async () => { + // Requires provisioning a project with status locked/archived plus its plugin stack. + // The merge-queue CI stack does not seed locked projects; to enable, seed a locked + // project via admin API in beforeEach and assert the toggle is not rendered. + }) + + test.afterEach(async ({ page }) => { + if (!projectName) + return + await deleteProject({ page, projectName }) + projectName = '' + }) +}) From 9ba1d9a90802b79d67a6a2b4e135ec7e3d513d98 Mon Sep 17 00:00:00 2001 From: William Phetsinorath Date: Fri, 28 Aug 2026 17:03:26 +0200 Subject: [PATCH 2/3] test(playwright): trim project secrets journey spec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Retire le test redondant (visibilité du toggle, déjà couvert par 'Should show project secrets' dans dashboard.spec.ts), le skip verrouillé (0 assertion) et le guard afterEach superflu (deleteProject gère sa navigation). Un seul test conserve le contrat : libellé Afficher/Cacher. Signed-off-by: William Phetsinorath Change-Id: I0e1156816ab0c44aebbbdfbf7be968576a6a6964 --- playwright/e2e-tests/secrets.spec.ts | 32 ++++++---------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/playwright/e2e-tests/secrets.spec.ts b/playwright/e2e-tests/secrets.spec.ts index 26550726f9..b5c1530f19 100644 --- a/playwright/e2e-tests/secrets.spec.ts +++ b/playwright/e2e-tests/secrets.spec.ts @@ -1,15 +1,12 @@ import { expect, test } from '@playwright/test' import { clientURL, signInCloudPiNative, testUser } from 'config/console' +import { openMyProjects } from 'helpers/navigation' import { createProject, deleteProject } from 'helpers/project' -/** - * Cahier de tests fonctionnels — SECR-001 / SECR-003 - * SECR-001: Affichage des secrets de projet (toggle "Afficher les secrets des services") - * SECR-003: Bouton indisponible (projet verrouillé) — covered indirectly here by the - * visibility contract on a fresh project; the locked-project variant requires an - * archived/locked fixture the CI stack does not provision (see skip below). - */ -test.describe('Secrets du projet (SECR)', { tag: '@e2e' }, () => { +// Parcours secrets du projet : bascule du bouton « Afficher/Cacher les secrets +// des services ». Le cas projet verrouillé (bouton indisponible) n'est pas +// couvert — la stack CI ne provisionne pas de projet verrouillé. +test.describe('Secrets du projet', { tag: '@e2e' }, () => { let projectName: string test.beforeEach(async ({ page }) => { @@ -19,33 +16,18 @@ test.describe('Secrets du projet (SECR)', { tag: '@e2e' }, () => { projectName = name }) - test('SECR-001: the secrets toggle is visible on a fresh project dashboard', async ({ page }) => { - await page.getByTestId('menuMyProjects').click() + test('toggling switches the label between show/hide', async ({ page }) => { + await openMyProjects({ page }) await page.getByRole('link', { name: projectName }).click() - // The toggle button exists and defaults to the hidden state const toggle = page.getByRole('button', { name: 'Afficher les secrets des services' }) await expect(toggle).toBeVisible() - }) - - test('SECR-001: toggling switches the label between show/hide', async ({ page }) => { - await page.getByTestId('menuMyProjects').click() - await page.getByRole('link', { name: projectName }).click() - - const toggle = page.getByRole('button', { name: 'Afficher les secrets des services' }) await toggle.click() await expect(page.getByRole('button', { name: 'Cacher les secrets des services' })).toBeVisible() - // toggle back for state cleanliness await page.getByRole('button', { name: 'Cacher les secrets des services' }).click() await expect(page.getByRole('button', { name: 'Afficher les secrets des services' })).toBeVisible() }) - test.skip('SECR-003: secrets button unavailable on a locked project', async () => { - // Requires provisioning a project with status locked/archived plus its plugin stack. - // The merge-queue CI stack does not seed locked projects; to enable, seed a locked - // project via admin API in beforeEach and assert the toggle is not rendered. - }) - test.afterEach(async ({ page }) => { if (!projectName) return From fd35bba62d23a1c94be9ac38b432fc445357e377 Mon Sep 17 00:00:00 2001 From: William Phetsinorath Date: Thu, 10 Sep 2026 17:30:09 +0200 Subject: [PATCH 3/3] test(playwright): assert project secrets existence in integration flow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le parcours d'intégration vérifie désormais l'existence des secrets du projet via la modale : section GITLAB avec les clés GIT_MIRROR_PROJECT_ID / GIT_MIRROR_TOKEN (valeur non vide), section VAULT présente. Clés seulement — les valeurs tournent avec le provisionnement du projet. Signed-off-by: William Phetsinorath Change-Id: If822346c7f6fbf9df8d1ee3b0a44a13c6a6a6964 --- playwright/integration-tests/user-flow.spec.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/playwright/integration-tests/user-flow.spec.ts b/playwright/integration-tests/user-flow.spec.ts index a27b10139b..7cc2ff733f 100644 --- a/playwright/integration-tests/user-flow.spec.ts +++ b/playwright/integration-tests/user-flow.spec.ts @@ -95,6 +95,21 @@ test.describe('Integration tests user flow: first checks', { tag: '@integ' }, () await expect(page1.getByRole('link', { name: 'forge-dso' })).not.toBeVisible() }) + test('Check project secrets', { tag: '@replayable' }, async ({ page }) => { + await page.goto(clientURL) + await signInCloudPiNative({ page, credentials: testUser }) + await page.getByTestId('menuMyProjects').click() + await page.getByRole('link', { name: projectName }).click() + await page.getByTestId('showSecretsBtn').click() + const modal = page.getByTestId('projectSecretsZone') + // Keys only — secret values rotate with the project's provisioning. + await expect(modal.getByRole('heading', { name: 'GITLAB' })).toBeVisible() + await expect(modal.getByText('GIT_MIRROR_PROJECT_ID')).toBeVisible() + await expect(modal.getByText('GIT_MIRROR_TOKEN')).toBeVisible() + await expect(modal.locator('pre').first()).not.toBeEmpty() + await expect(modal.getByRole('heading', { name: 'VAULT' })).toBeVisible() + }) + test('Project permissions', async ({ page }) => { await page.goto(clientURL) await signInCloudPiNative({ page, credentials: testUser })