97 lines
4.3 KiB
TypeScript
97 lines
4.3 KiB
TypeScript
import { provideHttpClient } from '@angular/common/http';
|
|
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
|
|
import { type ComponentFixture, TestBed } from '@angular/core/testing';
|
|
import { beforeEach, describe, expect, it } from 'vitest';
|
|
import { SessionStore } from '../../core/auth/session.store';
|
|
import { PermissionsPage } from './permissions.page';
|
|
|
|
describe('PermissionsPage', () => {
|
|
let fixture: ComponentFixture<PermissionsPage>;
|
|
let ctrl: HttpTestingController;
|
|
const el = () => fixture.nativeElement as HTMLElement;
|
|
const tick = async () => {
|
|
fixture.detectChanges();
|
|
await new Promise((r) => setTimeout(r));
|
|
fixture.detectChanges();
|
|
};
|
|
const click = async (selector: string, index = 0) => {
|
|
(el().querySelectorAll(selector)[index] as HTMLElement).click();
|
|
await tick();
|
|
};
|
|
const byText = (selector: string, text: string) =>
|
|
[...el().querySelectorAll<HTMLElement>(selector)].find((e) => e.textContent?.trim().startsWith(text))!;
|
|
|
|
beforeEach(async () => {
|
|
await TestBed.configureTestingModule({
|
|
imports: [PermissionsPage],
|
|
providers: [provideHttpClient(), provideHttpClientTesting()],
|
|
}).compileComponents();
|
|
TestBed.inject(SessionStore); // sin sesión: solo necesitamos que exista
|
|
ctrl = TestBed.inject(HttpTestingController);
|
|
fixture = TestBed.createComponent(PermissionsPage);
|
|
await tick();
|
|
ctrl.expectOne('/api/permissions').flush([
|
|
{ webUser: 'ana', paths: ['/ventas/*', '/socios/clientes'] },
|
|
{ webUser: 'luis', paths: ['*'] },
|
|
]);
|
|
await tick();
|
|
});
|
|
|
|
it('lista los usuarios con permisos', () => {
|
|
expect([...el().querySelectorAll('.users li button')].map((b) => b.textContent?.trim())).toEqual(['ana', 'luis']);
|
|
});
|
|
|
|
it('al elegir un usuario marca sus pantallas (el módulo completo por /ventas/*)', async () => {
|
|
await click('.users li button', 0);
|
|
const checked = [...el().querySelectorAll<HTMLInputElement>('fieldset .items input')].filter((i) => i.checked);
|
|
expect(checked.length).toBe(10); // 9 de ventas + Clientes
|
|
expect(el().querySelector<HTMLButtonElement>('.actions .main')!.disabled).toBe(true); // sin cambios
|
|
});
|
|
|
|
it('el acceso total oculta las casillas y no ofrece Administración como casilla', async () => {
|
|
await click('.users li button', 1);
|
|
expect(el().querySelector('fieldset')).toBeNull();
|
|
await click('.users li button', 0);
|
|
expect(byText('legend label', 'Administración')).toBeUndefined();
|
|
});
|
|
|
|
it('guarda los patrones resultantes con PUT', async () => {
|
|
await click('.users li button', 0);
|
|
const inv = byText('legend label', 'Inventario').querySelector('input')!;
|
|
inv.click();
|
|
await tick();
|
|
expect(el().querySelector<HTMLButtonElement>('.actions .main')!.disabled).toBe(false);
|
|
await click('.actions .main');
|
|
const req = ctrl.expectOne((r) => r.method === 'PUT');
|
|
expect(req.request.url).toBe('/api/permissions/ana');
|
|
expect(req.request.body).toEqual({ paths: ['/ventas/*', '/inventario/*', '/socios/clientes'] });
|
|
req.flush({ webUser: 'ana', paths: [] });
|
|
await tick();
|
|
ctrl.expectOne('/api/permissions').flush([{ webUser: 'ana', paths: ['/ventas/*', '/inventario/*', '/socios/clientes'] }]);
|
|
await tick();
|
|
expect(el().querySelector('.msg')?.textContent).toContain('Permisos de ana guardados');
|
|
});
|
|
|
|
it('muestra el error del servidor, por ejemplo al quitar el último administrador', async () => {
|
|
await click('.users li button', 1);
|
|
await click('.actions .danger');
|
|
ctrl.expectOne((r) => r.method === 'DELETE' && r.url === '/api/permissions/luis').flush(
|
|
{ message: 'No se puede quitar al último administrador' },
|
|
{ status: 409, statusText: 'Conflict' },
|
|
);
|
|
await tick();
|
|
expect(el().querySelector('.msg.err')?.textContent).toContain('último administrador');
|
|
});
|
|
|
|
it('agregar un usuario lo selecciona sin guardar hasta pulsar Guardar', async () => {
|
|
const input = el().querySelector<HTMLInputElement>('.add input')!;
|
|
input.value = 'marta';
|
|
input.dispatchEvent(new Event('input'));
|
|
await tick();
|
|
await click('.add .btn');
|
|
expect([...el().querySelectorAll('.users li button')].map((b) => b.textContent?.trim())).toContain('marta');
|
|
expect(el().querySelector('.detail h2')?.textContent).toBe('marta');
|
|
ctrl.expectNone((r) => r.method === 'PUT');
|
|
});
|
|
});
|