Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Giofelix/Proyecto-automatizacion-Empresa/llms.txt

Use this file to discover all available pages before exploring further.

El proyecto automation-arqc extrae en tres clases reutilizables los patrones de interfaz Angular Material que se repiten en todos los módulos del sistema municipal de impuestos: la navegación por el menú acordeón lateral (MenuNavegacion), los botones de acción de mantenimiento CRUD (AccionesCrud) y los controles de filtrado, paginación y selección de filas de las tablas de datos (ComponentesTabla). Cualquier Page Object de módulo específico instancia estas tres clases en lugar de duplicar locators.

MenuNavegacion

Navega el acordeón lateral Angular Material con animaciones incluidas.

AccionesCrud

Abstrae los botones de iconos Material: add, save, edit, delete, Aceptar y Cancelar.

ComponentesTabla

Controla filtros, paginación y selección de filas en las tablas mat-table.

MenuNavegacion abstrae el menú lateral de la aplicación, construido con componentes mat-expansion-panel (acordeón) de Angular Material. Gestiona automáticamente la apertura de paneles, la asignación de IDs temporales para evitar referencias obsoletas y la espera de las animaciones de expansión.

Importación

const { MenuNavegacion } = require('./pages/common/menu-navegacion');

Constructor

const menu = new MenuNavegacion(page);
El constructor recibe la instancia page de Playwright y establece dos propiedades:
PropiedadValor inicialDescripción
containerpage.locator('.mat-drawer-inner-container')Raíz del menú lateral; contexto de búsqueda inicial
contextoActualthis.containerReferencia al nodo activo; se actualiza en cada seleccionarOpcion()

Métodos

Navega a través de una secuencia de elementos del menú acordeón, procesándolos en orden de izquierda a derecha (de raíz a hoja).
rutaOpciones
string[]
required
Array con los nombres exactos (insensible a mayúsculas) de cada nodo de la ruta, desde el nivel superior hasta el ítem hoja.
Antes de iterar, reinicia contextoActual a container para garantizar una búsqueda limpia independientemente del estado previo. Por cada nombre en el array delega a seleccionarOpcion().

seleccionarOpcion(nombreOpcion)

Localiza y hace clic sobre un elemento del menú dentro del contexto actual.
nombreOpcion
string
required
Texto exacto del ítem (se usa new RegExp('^' + nombreOpcion + '$', 'i')).
Comportamiento interno:
  1. Busca dentro de contextoActual elementos de tipo button, mat-panel-title, .btnMenu, .spanAcordeon o span cuyo texto coincida exactamente con nombreOpcion.
  2. Llama a scrollIntoViewIfNeeded() y verifica visibilidad (timeout 5 s).
  3. Evalúa en el DOM si el elemento está dentro de un mat-expansion-panel-header (acordeón):
    • Si es acordeón: lee o asigna un ID temporal al mat-expansion-panel padre, hace clic, actualiza contextoActual al .mat-expansion-panel-content de ese panel y espera 800 ms para la animación de Angular Material.
    • Si es hoja (no acordeón): hace clic, restaura contextoActual a container y espera networkidle para la carga del módulo destino.
El ID temporal (pw-nav-XXXXXXXXX) se asigna directamente en el DOM mediante evaluate() para evitar el encadenamiento de locators que provocaría errores de tipo “Received: hidden” cuando el panel se anida dentro de otro ya abierto.

Ejemplo

const menu = new MenuNavegacion(page);
await menu.navegar(['Reteica', 'Archivos', 'Terceros']);
// Paso 1: abre el panel acordeón "Reteica"
// Paso 2: abre el sub-panel acordeón "Archivos" dentro de Reteica
// Paso 3: hace clic en el ítem hoja "Terceros" y espera networkidle

AccionesCrud

AccionesCrud envuelve los seis botones de acción estándar que aparecen en la barra de herramientas de todos los formularios de mantenimiento: agregar, guardar, editar, eliminar y los botones de confirmación de diálogo Aceptar/Cancelar.

Importación

const { AccionesCrud } = require('./pages/common/acciones-crud');

Constructor

const crud = new AccionesCrud(page);
PropiedadLocatorIcono MaterialAcción
btnAgregarpage.getByText('add', { exact: true })addAbre formulario de nuevo registro
btnGuardarpage.locator('mat-icon:has-text("save")')savePersiste el registro actual
btnEditarpage.locator('mat-icon:has-text("edit")')editAbre el registro en modo edición
btnEliminarpage.locator('mat-icon:has-text("delete")')deleteElimina el registro seleccionado
btnAceptarpage.getByRole('button', { name: 'Aceptar' })Confirma un diálogo de confirmación
btnCancelarpage.getByRole('button', { name: 'Cancelar' })Cancela/cierra un diálogo

Métodos

Cada método simplemente hace click() sobre el locator correspondiente:
MétodoLocator invocado
agregar()btnAgregar
guardar()btnGuardar
editar()btnEditar
eliminar()btnEliminar
aceptar()btnAceptar
cancelar()btnCancelar

Ejemplo

const crud = new AccionesCrud(page);

// Crear un registro nuevo
await crud.agregar();
// ... llenar formulario ...
await crud.guardar();

// Editar el registro seleccionado en la tabla
await crud.editar();
// ... modificar campos ...
await crud.guardar();

// Eliminar con confirmación
await crud.eliminar();
await crud.aceptar();   // confirma el diálogo de eliminación
btnAgregar usa getByText con exact: true porque el icono mat-icon renderiza el texto add sin etiqueta ARIA en este proyecto. Si en algún formulario el botón tiene aria-label, usa page.getByRole('button', { name: 'Agregar' }) directamente.

ComponentesTabla

ComponentesTabla abstrae los controles de la capa de tabla de datos del sistema: el botón de filtro que abre un diálogo, los botones de paginación, el selector de cantidad de filas por página y la selección de filas por contenido de celda.

Importación

const { ComponentesTabla } = require('./pages/common/componentes-tabla');

Constructor

const tabla = new ComponentesTabla(page);

Locators fijos

PropiedadLocatorDescripción
btnRefrescarpage.locator('mat-icon:has-text("refresh")')Recarga la tabla desde el servidor
btnFiltrarpage.locator('mat-icon:has-text("filter_list")')Abre el diálogo de filtro de la tabla
selectorFilaspage.locator('div.mat-select-arrow')Desplegable de registros por página
btnPrimeraPaginapage.locator('.divtable').getByRole('button', { name: 'Primer registro' })Salta a la primera página
btnPaginaAnteriorpage.locator('.divtable').getByRole('button', { name: 'Anterior' })Página anterior
btnPaginaSiguientepage.locator('.divtable').getByRole('button', { name: 'Siguiente' })Página siguiente
btnUltimaPaginapage.locator('.divtable').getByRole('button', { name: 'Último registro' })Salta a la última página

Locators dinámicos (funciones)

FunciónRetornaDescripción
checkboxSeleccion(textoFila)Checkbox de la fila que contiene una gridcell con texto exactamente igual a textoFilaEvita seleccionar filas cuyo NIT es prefijo de otro
celdaDato(textoFila)page.getByRole('row', { name: textoFila }).getByRole('gridcell').nth(1)Segunda celda de una fila — usada para abrir el detalle

Métodos

filtrar()

Hace clic en btnFiltrar y espera hasta 15 s a que el diálogo de búsqueda sea visible antes de retornar.
await tabla.filtrar();
// El diálogo de filtro ya está visible; puedes interactuar con sus campos
await page.getByRole('dialog').getByRole('textbox', { name: 'Nit' }).fill('900516574');

seleccionarFila(textoFila)

textoFila
string
required
Texto exacto de la celda que identifica la fila (normalmente el NIT o código del registro).
Espera hasta 20 s a que la fila sea visible y luego hace clic (con force: true) en su checkbox. El uso de coincidencia exacta de celda (getByRole('gridcell', { name: textoFila, exact: true })) evita seleccionar accidentalmente filas cuyo identificador contiene como subcadena el valor buscado.

seleccionarCantidadFilas(cantidad)

cantidad
number
required
Número de filas por página a mostrar (debe coincidir exactamente con una opción del mat-select).
Hace clic en selectorFilas para abrir el desplegable y luego selecciona la opción cuyo texto coincide exactamente con cantidad.toString().

irAPaginaSiguiente() / irAPaginaAnterior()

Hacen clic en los botones de navegación de página correspondientes.

abrirDetalle(textoFila)

textoFila
string
required
Texto de cualquier celda de la fila destino.
Hace clic en la segunda celda (nth(1)) de la fila identificada por textoFila, que en los módulos del sistema equivale al campo principal del registro y abre su vista de detalle.

refrescar()

Hace clic en btnRefrescar y espera el estado networkidle (timeout 30 s) para garantizar que la tabla se haya recargado completamente.

Ejemplo completo

const crud = new AccionesCrud(page);
const tabla = new ComponentesTabla(page);

// Filtrar la tabla por NIT
await tabla.filtrar();
await page.getByRole('dialog').getByRole('textbox', { name: 'Nit' }).fill('900516574');
await crud.aceptar();

// Seleccionar la fila encontrada y editar el registro
await tabla.seleccionarFila('900516574');
await crud.editar();

// Después de editar, refrescar la tabla
await crud.guardar();
await tabla.refrescar();
seleccionarFila usa force: true para que el clic en el checkbox funcione aunque un overlay de Angular Material tenga temporalmente los pointer events interceptados. Esto es un patrón recurrente con mat-bottom-sheet y cdk-global-overlay-wrapper en este proyecto.

Build docs developers (and LLMs) love