feat(modal): add confirm and confirm delete modals with tests

- Implemented ConfirmModalComponent and ConfirmDeleteModalComponent for confirmation dialogs.
- Added modal service methods to open confirm and confirm delete modals.
- Created corresponding HTML and SCSS files for both modal components.
- Updated ReutilizablesTestPageComponent to utilize new modals.
- Enhanced modal service tests to cover new functionality.
- Refactored existing tests to accommodate changes in modal behavior and structure.
This commit is contained in:
2026-07-02 11:45:47 -03:00
parent b3782a6cc1
commit 446d1b8970
14 changed files with 677 additions and 164 deletions

View File

@@ -5,8 +5,18 @@ import {
BrowserTestingModule,
platformBrowserTesting
} from '@angular/platform-browser/testing';
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
import {
afterEach,
beforeAll,
beforeEach,
describe,
expect,
it,
vi
} from 'vitest';
import { ConfirmDeleteModalComponent } from '../../shared/components/confirm-delete-modal/confirm-delete-modal.component';
import { ConfirmModalComponent } from '../../shared/components/confirm-modal/confirm-modal.component';
import {
MODAL_DATA,
ModalRef,
@@ -122,6 +132,59 @@ describe('ModalService', () => {
expect(activeModal?.config.data).toEqual({ amount: 3 });
expect(activeModal?.ref).toBe(ref);
});
it('opens the standard confirm modal with default labels', () => {
const ref = service.openConfirm({
title: 'Confirmar compra',
content: 'Esto confirmara la compra actual.'
});
const activeModal = service.activeModal();
expect(activeModal?.component).toBe(ConfirmModalComponent);
expect(activeModal?.ref).toBe(ref);
expect(activeModal?.config).toEqual({
title: 'Confirmar compra',
data: {
content: 'Esto confirmara la compra actual.',
confirmLabel: 'Confirmar',
cancelLabel: 'Cancelar'
},
size: 'md',
closeOnBackdrop: true,
closeOnEscape: true,
showCloseButton: true
});
});
it('opens the delete confirm modal preserving modal overrides', () => {
service.openConfirmDelete({
title: 'Eliminar producto',
content: 'Se eliminara el producto.',
confirmLabel: 'Eliminar',
cancelLabel: 'Conservar',
size: 'lg',
closeOnBackdrop: false,
closeOnEscape: false,
showCloseButton: false
});
const activeModal = service.activeModal();
expect(activeModal?.component).toBe(ConfirmDeleteModalComponent);
expect(activeModal?.config).toEqual({
title: 'Eliminar producto',
data: {
content: 'Se eliminara el producto.',
confirmLabel: 'Eliminar',
cancelLabel: 'Conservar'
},
size: 'lg',
closeOnBackdrop: false,
closeOnEscape: false,
showCloseButton: false
});
});
});
@Component({

View File

@@ -1,5 +1,7 @@
import { InjectionToken, Injectable, Type, signal } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { ConfirmDeleteModalComponent } from '../../shared/components/confirm-delete-modal/confirm-delete-modal.component';
import { ConfirmModalComponent } from '../../shared/components/confirm-modal/confirm-modal.component';
export type ModalSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';
export type ModalDismissReason =
@@ -28,6 +30,19 @@ export interface NormalizedModalConfig<TData = unknown>
showCloseButton: boolean;
}
export interface ConfirmModalData {
content: string;
confirmLabel: string;
cancelLabel: string;
}
export interface ConfirmModalConfig
extends Omit<ModalConfig<ConfirmModalData>, 'data'> {
content: string;
confirmLabel?: string;
cancelLabel?: string;
}
export interface ActiveModalState<TResult = unknown, TData = unknown> {
component: Type<unknown>;
config: NormalizedModalConfig<TData>;
@@ -46,6 +61,11 @@ const DEFAULT_MODAL_CONFIG: Pick<
showCloseButton: true
};
const DEFAULT_CONFIRM_MODAL_LABELS = {
confirmLabel: 'Confirmar',
cancelLabel: 'Cancelar'
} satisfies Pick<ConfirmModalData, 'confirmLabel' | 'cancelLabel'>;
export class ModalRef<TResult = unknown> {
private readonly afterClosedSubject = new Subject<TResult | undefined>();
private closed = false;
@@ -115,6 +135,17 @@ export class ModalService {
return ref;
}
openConfirm(config: ConfirmModalConfig): ModalRef<boolean> {
return this.open(ConfirmModalComponent, this.buildConfirmModalConfig(config));
}
openConfirmDelete(config: ConfirmModalConfig): ModalRef<boolean> {
return this.open(
ConfirmDeleteModalComponent,
this.buildConfirmModalConfig(config)
);
}
private close<TResult>(ref: ModalRef<TResult>, result?: TResult): void {
if (this.activeModalState()?.ref !== ref) {
return;
@@ -144,4 +175,24 @@ export class ModalService {
...config
};
}
private buildConfirmModalConfig(
config: ConfirmModalConfig
): ModalConfig<ConfirmModalData> {
const {
content,
confirmLabel = DEFAULT_CONFIRM_MODAL_LABELS.confirmLabel,
cancelLabel = DEFAULT_CONFIRM_MODAL_LABELS.cancelLabel,
...modalConfig
} = config;
return {
...modalConfig,
data: {
content,
confirmLabel,
cancelLabel
}
};
}
}