Skip to content

Commit 2383824

Browse files
committed
test: expand Admin v2 coverage matrix
1 parent 7f551c8 commit 2383824

13 files changed

Lines changed: 476 additions & 28 deletions

docs/ui-development.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,32 @@ docker compose --profile swoole --profile e2e run --rm --no-deps ui-e2e-static
4040
docker compose --profile swoole up -d --force-recreate php-swoole ui
4141
```
4242

43+
Para Admin 2.0 la matriz se ejecuta sin modificar `config/config.json`:
44+
45+
```sh
46+
# Unitarios y cobertura de Angular (reporte V8).
47+
docker exec psfs-ui-1 npm run test:admin:coverage
48+
49+
# Contratos PHP nuevos, incluida la resolución del WebSocket HMR.
50+
docker exec -e XDEBUG_MODE=coverage psfs-php-1 php vendor/bin/phpunit \
51+
--testsuite default --filter 'AdminFrontend|UiDevelopmentProxyResolver|UiDevelopmentWebSocketBridge'
52+
53+
# PHP-FPM + paquete estático: todos los flujos administrativos reales.
54+
docker compose --profile swoole --profile e2e run --rm --no-deps \
55+
-e PSFS_E2E_BASE_URL=http://php:8080 ui-e2e \
56+
sh -lc 'npm ci && npm run test:e2e:admin -- --reporter=line'
57+
58+
# Swoole/watch: HMR del Admin a través del mismo origen PSFS.
59+
docker compose --profile swoole --profile e2e run --rm --no-deps ui-e2e \
60+
sh -lc 'npm ci && npm run test:e2e:admin:hmr -- --reporter=line'
61+
62+
# Swoole/build: deep-link SPA y assets con Node desconectado.
63+
ADMIN_UI_DEV_UPSTREAM= UI_DEV_UPSTREAM= docker compose --profile swoole up -d --force-recreate php-swoole
64+
docker compose --profile swoole --profile e2e run --rm --no-deps ui-e2e \
65+
sh -lc 'npm ci && npx playwright test e2e/admin-v2-static.spec.mjs --reporter=line'
66+
docker compose --profile swoole up -d --force-recreate php-swoole
67+
```
68+
4369
Con `ui.path=/ui` ya configurado, abrir
4470
`http://admin:admin@localhost:8011/ui/`. La URL debe conservar el puerto
4571
`8011` y renderizar `PSFS UI POC · HMR verificado`.

tests/controller/AdminFrontendRoutesControllerTest.php

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,24 @@
33
namespace PSFS\tests\controller;
44

55
use PHPUnit\Framework\TestCase;
6+
use PSFS\base\Router;
67
use PSFS\base\Security;
78
use PSFS\base\exception\ApiException;
89
use PSFS\controller\AdminFrontendRoutesController;
910

1011
class AdminFrontendRoutesControllerTest extends TestCase
1112
{
13+
protected function setUp(): void
14+
{
15+
Router::dropInstance();
16+
Router::getInstance()->hydrateRouting();
17+
}
18+
1219
protected function tearDown(): void
1320
{
1421
Security::setTest(false);
1522
Security::dropInstance();
23+
Router::dropInstance();
1624
}
1725

1826
public function testRoutesEndpointReturnsTheRouterCatalogWithoutHtml(): void
@@ -26,21 +34,13 @@ public function testRoutesEndpointReturnsTheRouterCatalogWithoutHtml(): void
2634

2735
public function testDocumentationIndexReturnsTheKnownDomainsAsAnEnvelope(): void
2836
{
29-
$response = (new AdminFrontendRoutesControllerProbe())->documentation();
30-
31-
self::assertStringContainsString('"ok":true', $response);
32-
self::assertStringContainsString('"domains"', $response);
33-
self::assertStringContainsString('"documentPaths"', $response);
34-
self::assertStringContainsString('/CLIENT/api/doc', $response);
35-
self::assertStringNotContainsString('<html', strtolower($response));
36-
}
37-
38-
public function testDocumentationDomainAcceptsTheDomainPublishedByTheIndex(): void
39-
{
40-
$response = (new AdminFrontendRoutesControllerProbe())->documentationDomain('client');
37+
$response = json_decode((new AdminFrontendRoutesControllerProbe())->documentation(), true, 512, JSON_THROW_ON_ERROR);
4138

42-
self::assertStringContainsString('"ok":true', $response);
43-
self::assertStringContainsString('"openapi"', $response);
39+
self::assertTrue($response['ok']);
40+
self::assertNotEmpty($response['data']['domains']);
41+
foreach ($response['data']['domains'] as $domain) {
42+
self::assertSame('/' . strtoupper($domain) . '/api/doc', $response['data']['documentPaths'][$domain]);
43+
}
4444
}
4545

4646
public function testDocumentationDomainReturnsTheV2EnvelopeForAnUnknownDomain(): void

ui/e2e/admin-v2-config.spec.mjs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ test('carga la configuración segura, conserva el secreto vacío y bloquea un re
55
await page.goto('/admin-v2/config');
66
await config;
77

8-
await expect(page.getByRole('heading', { name: 'Configuración general' })).toBeVisible();
8+
await expect(page.getByRole('heading', { name: /^(Configuración general|General configuration)$/ })).toBeVisible();
99
await expect(page.locator('iframe')).toHaveCount(0);
1010
await expect(page.locator('input[type="password"]')).toHaveCount(1);
1111
await expect(page.locator('input[type="password"]')).toHaveValue('');
12-
await page.getByRole('button', { name: 'Añadir parámetro' }).click();
12+
await page.getByRole('button', { name: /^(Añadir parámetro|Add parameter)$/ }).click();
1313
const extraKey = page.locator('input[list="config-suggestions"]');
14-
const extraValue = page.getByLabel('Valor del parámetro');
14+
const extraValue = page.getByLabel(/^(Valor del parámetro|Parameter value)$/);
1515
await expect(extraKey).toBeVisible();
1616
await extraKey.fill('custom.runtime.flag');
1717
await expect(extraKey).toHaveValue('custom.runtime.flag');
@@ -20,6 +20,6 @@ test('carga la configuración segura, conserva el secreto vacío y bloquea un re
2020
await expect(extraValue).toBeFocused();
2121

2222
await page.locator('input#db\\.host').fill('');
23-
await page.getByRole('button', { name: 'Guardar configuración' }).click();
23+
await page.locator('form.dynamic-form .button--primary').click();
2424
await expect(page.locator('input#db\\.host')).toHaveClass(/ng-invalid/);
2525
});

ui/e2e/admin-v2-modules.spec.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,5 @@ test('carga el generador nativo y rechaza una generación inválida sin escribir
2424
});
2525
await page.locator('a[href="/admin-v2/config"]').click();
2626
await config;
27-
await expect(page.getByRole('heading', { name: 'Configuración general' })).toBeVisible();
27+
await expect(page.getByRole('heading', { name: /^(Configuración general|General configuration)$/ })).toBeVisible();
2828
});

ui/e2e/admin-v2.spec.mjs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ test('regenera rutas desde Admin 2.0 sin responder con error de servidor', async
5757
const response = await regenerated;
5858

5959
expect(response.status()).toBe(200);
60-
await expect(page.locator('.notice--success')).toContainText('Rutas regeneradas.');
60+
await expect(page.locator('.notice--success')).toContainText(/^(Rutas regeneradas\.|Routes generated successfully)$/);
6161
});
6262

6363
test('mantiene una configuración usable y estilizada en móvil', async ({ page }) => {
@@ -66,13 +66,13 @@ test('mantiene una configuración usable y estilizada en móvil', async ({ page
6666
await page.goto('/admin-v2/config');
6767
await config;
6868

69-
const navigationToggle = page.getByRole('button', { name: 'Abrir navegación' });
69+
const navigationToggle = page.getByRole('button', { name: /^(Abrir navegación|Open navigation)$/ });
7070
await expect(navigationToggle).toBeVisible();
7171
await navigationToggle.click();
72-
await expect(page.getByRole('button', { name: 'Cerrar navegación' })).toHaveAttribute('aria-expanded', 'true');
72+
await expect(page.getByRole('button', { name: /^(Cerrar navegación|Close navigation)$/ })).toHaveAttribute('aria-expanded', 'true');
7373
await expect(page.locator('.admin-sidebar')).toHaveClass(/admin-sidebar--open/);
74-
await page.getByRole('button', { name: 'Cerrar navegación' }).click();
75-
await expect(page.getByRole('button', { name: 'Abrir navegación' })).toHaveAttribute('aria-expanded', 'false');
74+
await page.getByRole('button', { name: /^(Cerrar navegación|Close navigation)$/ }).click();
75+
await expect(page.getByRole('button', { name: /^(Abrir navegación|Open navigation)$/ })).toHaveAttribute('aria-expanded', 'false');
7676

7777
await expect(page.locator('.page')).toBeVisible();
7878
await expect(page.locator('.page-header')).toBeVisible();

ui/package-lock.json

Lines changed: 174 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)