@m4l/testing 0.0.22 → 0.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/e2e/commands/components/Accordions/commands.d.ts +4 -0
  2. package/e2e/commands/components/Accordions/commands.js +19 -0
  3. package/e2e/commands/components/Accordions/types.d.ts +63 -0
  4. package/e2e/commands/components/CommonActions/commands.d.ts +4 -0
  5. package/e2e/commands/components/CommonActions/commands.js +11 -0
  6. package/e2e/commands/components/CommonActions/types.d.ts +20 -0
  7. package/e2e/commands/components/DataGrid/commands.d.ts +1 -1
  8. package/e2e/commands/components/DataGrid/commands.js +29 -29
  9. package/e2e/commands/components/DataGrid/types.d.ts +109 -24
  10. package/e2e/commands/components/DynamicFilter/commands.d.ts +1 -1
  11. package/e2e/commands/components/DynamicFilter/types.d.ts +10 -3
  12. package/e2e/commands/components/DynamicSort/commands.d.ts +1 -1
  13. package/e2e/commands/components/DynamicSort/types.d.ts +17 -1
  14. package/e2e/commands/components/Filters/commands.d.ts +4 -0
  15. package/e2e/commands/components/Filters/commands.js +24 -0
  16. package/e2e/commands/components/Filters/types.d.ts +91 -0
  17. package/e2e/commands/components/MenuActions/commands.d.ts +1 -1
  18. package/e2e/commands/components/MenuActions/commands.js +2 -2
  19. package/e2e/commands/components/MenuActions/types.d.ts +16 -1
  20. package/e2e/commands/components/Popover/commands.d.ts +1 -1
  21. package/e2e/commands/components/Popover/types.d.ts +6 -0
  22. package/e2e/commands/components/PropertyValue/commands.d.ts +1 -1
  23. package/e2e/commands/components/PropertyValue/types.d.ts +9 -4
  24. package/e2e/commands/components/Tab/commands.d.ts +1 -1
  25. package/e2e/commands/components/Tab/commands.js +3 -2
  26. package/e2e/commands/components/Tab/types.d.ts +19 -4
  27. package/e2e/commands/components/WindowBase/commands.d.ts +1 -1
  28. package/e2e/commands/components/WindowBase/commands.js +4 -0
  29. package/e2e/commands/components/WindowBase/types.d.ts +71 -5
  30. package/e2e/commands/components/index.d.ts +3 -0
  31. package/e2e/commands/index.d.ts +3 -0
  32. package/e2e/commands/register.d.ts +1 -2
  33. package/e2e/commands/register.js +10 -7
  34. package/e2e/cypress.d.js +1 -0
  35. package/e2e/cypress.d.ts +4 -1
  36. package/index.d.ts +1 -0
  37. package/package.json +36 -47
  38. package/testComponents/DataGrid/helpers.js +52 -30
  39. package/testComponents/DataGrid/types.d.ts +15 -3
  40. package/e2e/commands/components/DataGrid/export.d.ts +0 -7
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Registers Accordions commands
3
+ */
4
+ export declare const registerDynamicAccordionsCommands: () => void;
@@ -0,0 +1,19 @@
1
+ const t = () => {
2
+ Cypress.Commands.add(
3
+ "m4lDynamicAccordionsValidate",
4
+ (e, o, r, a) => {
5
+ cy.get('[class*="M4LAccordion-accordionRoot"]').eq(r).as("currentAccordion"), cy.get("@currentAccordion").find('[class*="M4LAccordion-accordionSummary"]').should("have.text", a).click(), cy.get("@currentAccordion").within(() => {
6
+ cy.get('[class*="MuiCollapse-hidden"]').should("exist");
7
+ }), cy.get("@currentAccordion").find('[class*="M4LAccordion-accordionSummary"]').click(), cy.get("@currentAccordion").within(() => {
8
+ cy.get('[class*="MuiCollapse-entered"]').should("exist");
9
+ }), e(o).forEach((c) => {
10
+ cy.get("@currentAccordion").find('[class*="M4LAccordion-accordionDetails"]').find('[role="property-value-form-role"]').eq(c.index).within(() => {
11
+ cy.log(`Validating name ${c.key}`), cy.get('[class*="M4LPropertyValue-name"]').should("have.text", c.key), cy.log(`Validating value ${c.value}`), cy.get('[role="property-value-value-role"][class*="M4LPropertyValue-value"]').should("contain.text", c.value);
12
+ });
13
+ });
14
+ }
15
+ );
16
+ };
17
+ export {
18
+ t as r
19
+ };
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Property values accordion configuration
3
+ */
4
+ export type M4lPropertyValuesAccordionsConfig = {
5
+ /**
6
+ * @param title - The accordion title
7
+ */
8
+ title: string;
9
+ /**
10
+ * @param key - The property key
11
+ */
12
+ key: string;
13
+ /**
14
+ * @param value - The property value
15
+ */
16
+ value: any;
17
+ /**
18
+ * @param index - The property index
19
+ */
20
+ index: number;
21
+ };
22
+
23
+ declare global {
24
+ namespace Cypress {
25
+ interface Chainable {
26
+ /**
27
+ * Validates the accordions using the dynamic accordions hook.
28
+ * Collapses/expands by title and checks each property key-value.
29
+ * @example
30
+ * const mockAccordions: M4lPropertyValuesAccordionsConfig[] = [
31
+ * { title: 'Details', key: 'Name', value: 'Item 1', index: 0 },
32
+ * { title: 'Details', key: 'Status', value: 'Active', index: 1 },
33
+ * ];
34
+ * cy.m4lDynamicAccordionsValidate(
35
+ * (acc) => acc,
36
+ * mockAccordions,
37
+ * 0,
38
+ * 'Details'
39
+ * );
40
+ */
41
+ m4lDynamicAccordionsValidate(
42
+ /**
43
+ * @param accordions - Function that returns the accordion configurations
44
+ */
45
+ accordions: (mockAccordions: M4lPropertyValuesAccordionsConfig[]) => M4lPropertyValuesAccordionsConfig[],
46
+ /**
47
+ * @param mockAccordions - The accordion configurations
48
+ */
49
+ mockAccordions: M4lPropertyValuesAccordionsConfig[],
50
+ /**
51
+ * @param index - The accordion index
52
+ */
53
+ index: number,
54
+ /**
55
+ * @param title - The accordion title
56
+ */
57
+ title: string,
58
+ ): Chainable<Element>;
59
+ }
60
+ }
61
+ }
62
+
63
+ export {};
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Registers CommonActions commands
3
+ */
4
+ export declare const registerCommonActionsCommands: () => void;
@@ -0,0 +1,11 @@
1
+ const n = () => {
2
+ Cypress.Commands.add(
3
+ "m4lConfirmActionIntro",
4
+ (o) => {
5
+ cy.get('[class*="M4LActionsContainer"]').should("contain", o).click();
6
+ }
7
+ );
8
+ };
9
+ export {
10
+ n as r
11
+ };
@@ -0,0 +1,20 @@
1
+ declare global {
2
+ namespace Cypress {
3
+ interface Chainable {
4
+ /**
5
+ * Finds the dialog action container, asserts it contains the option text, and clicks it.
6
+ * @example
7
+ * cy.m4lActionIntro('Accept');
8
+ * cy.m4lActionIntro('Cancel');
9
+ */
10
+ m4lConfirmActionIntro(
11
+ /**
12
+ * Button option
13
+ */
14
+ option: string,
15
+ ): Chainable<Element>;
16
+ }
17
+ }
18
+ }
19
+
20
+ export {};
@@ -1,4 +1,4 @@
1
1
  /**
2
- * Registra los comandos de DataGrid
2
+ * Registers DataGrid commands
3
3
  */
4
4
  export declare const registerDataGridCommands: () => void;
@@ -1,42 +1,42 @@
1
- const u = () => {
2
- Cypress.Commands.add("m4lDataGrid", (e) => {
3
- cy.get(e).find('[class^="M4LDataGrid-root"]');
4
- }), Cypress.Commands.add("m4lDataGridValidateVisibleColumns", (e, d, l, r = 1) => {
5
- let a = 0, i = r;
6
- d(l).forEach((n) => {
7
- n.visible && (cy.log(`Validando columna visible: ${n.headerText} , index: ${i}`), i++, cy.m4lDataGrid(e).find("[role=row]").find(`[role=columnheader][aria-colindex=${i}]`).should("have.text", n.headerText), cy.m4lDataGrid(e).find("[role=row]").find(`[role=gridcell][aria-colindex=${i}]`).should("contain", n.value), cy.m4lDataGrid(e).find("[role=row]").find(`[role=columnheader][aria-colindex=${i}]`).then((s) => {
8
- const o = s.width();
9
- o !== void 0 && (a += o), cy.m4lDataGrid(e).find("[role=grid]").scrollTo(a, 0, { duration: 100, ensureScrollable: !1 });
1
+ const f = () => {
2
+ Cypress.Commands.add("m4lDataGrid", (i) => cy.get(i).find('[class^="M4LDataGrid-root"]').filter(":visible").first()), Cypress.Commands.add("m4lDataGridValidateVisibleColumns", (i, n, a, o = 1) => {
3
+ let l = 0, t = o;
4
+ n(a).forEach((r) => {
5
+ r.visible && (cy.log(`Validating visible column: ${r.headerText} , index: ${t}`), t++, cy.m4lDataGrid(i).find("[role=row]").find(`[role=columnheader][aria-colindex=${t}]`).should("have.text", r.headerText), cy.m4lDataGrid(i).find("[role=row]").find(`[role=gridcell][aria-colindex=${t}]`).should("contain", r.value), cy.m4lDataGrid(i).find("[role=row]").find(`[role=columnheader][aria-colindex=${t}]`).then((s) => {
6
+ const d = s.width();
7
+ d !== void 0 && (l += d), cy.m4lDataGrid(i).find("[role=grid]").scrollTo(l, 0, { duration: 100, ensureScrollable: !1 });
10
8
  }));
11
9
  });
12
- }), Cypress.Commands.add("m4lDataGridRow", (e, d, l) => {
13
- let r = 0, a = 0;
14
- const i = 10, n = d + 1;
10
+ }), Cypress.Commands.add("m4lDataGridRow", (i, n, a) => {
11
+ let o = 0, l = 0;
12
+ const t = 10, r = n + 1;
15
13
  function s() {
16
- return cy.m4lDataGrid(e).find("[role=row]").not('[aria-rowindex="1"]').filter(`[aria-rowindex="${n}"]`).then((o) => {
17
- if (o.length > 0) {
18
- const t = o[0].getBoundingClientRect();
19
- if (t.top >= 0 && t.left >= 0 && t.bottom <= (window.innerHeight || document.documentElement.clientHeight) && t.right <= (window.innerWidth || document.documentElement.clientWidth))
20
- return cy.wrap(o);
14
+ return cy.m4lDataGrid(i).find("[role=row]").not('[aria-rowindex="1"]').filter(`[aria-rowindex="${r}"]`).then((d) => {
15
+ if (d.length > 0) {
16
+ const e = d[0].getBoundingClientRect();
17
+ if (e.top >= 0 && e.left >= 0 && e.bottom <= (window.innerHeight || document.documentElement.clientHeight) && e.right <= (window.innerWidth || document.documentElement.clientWidth))
18
+ return cy.wrap(d);
21
19
  }
22
- if (a >= i)
23
- throw new Error(`No se encontró la fila ${n} después de ${i} intentos`);
24
- return a++, cy.m4lDataGrid(e).find("[role=row]").not('[aria-rowindex="1"]').filter((m, t) => {
25
- const c = t.getBoundingClientRect();
20
+ if (l >= t)
21
+ throw new Error(`Row ${r} was not found after ${t} attempts`);
22
+ return l++, cy.m4lDataGrid(i).find("[role=row]").not('[aria-rowindex="1"]').filter((m, e) => {
23
+ const c = e.getBoundingClientRect();
26
24
  return c.top >= 0 && c.left >= 0 && c.bottom <= (window.innerHeight || document.documentElement.clientHeight) && c.right <= (window.innerWidth || document.documentElement.clientWidth);
27
25
  }).first().then((m) => {
28
- const t = m.height() || 0;
29
- return r += t, cy.m4lDataGrid(e).find("[role=grid]").scrollTo(0, r, { duration: 100, ensureScrollable: !1 }).then(() => s());
26
+ const e = m.height() || 0;
27
+ return o += e, cy.m4lDataGrid(i).find("[role=grid]").scrollTo(0, o, { duration: 100, ensureScrollable: !1 }).then(() => s());
30
28
  });
31
29
  });
32
30
  }
33
- return s().find(`[role=gridcell][aria-colindex="${l}"]`);
34
- }), Cypress.Commands.add("m4lDataGridRowAction", (e, d, l = 1, r = 1) => {
35
- cy.m4lDataGridRow(e, l, r).find("button").eq(0).should("be.visible", { timeout: 1e4 }).click(), cy.m4lMenuActionsItem(d);
36
- }), Cypress.Commands.add("m4lDataGridFindAllColumns", (e) => {
37
- cy.m4lDataGrid(e).find('[class^="M4LDataGrid-actionsConfigContainer"]').find("button").eq(2).click();
31
+ return s().find(`[role=gridcell][aria-colindex="${a}"]`);
32
+ }), Cypress.Commands.add("m4lDataGridRowAction", (i, n, a = 1, o = 1) => {
33
+ cy.m4lDataGridRow(i, a, o).find("button").eq(0).should("be.visible", { timeout: 1e4 }).click(), cy.m4lMenuActionsItem(n);
34
+ }), Cypress.Commands.add("m4lDataGridFindAllColumns", (i) => {
35
+ cy.m4lDataGrid(i).find('[class^="M4LDataGrid-actionsConfigContainer"]').find("button").eq(2).click();
36
+ }), Cypress.Commands.add("m4lDataGridOrCardViewMode", (i, n) => {
37
+ cy.m4lDataGrid(i).find('[class*="M4LDataGrid-actionsConfigContainer"]').find('[class*="M4LDataGrid-containerLeftActions"]').find('button[aria-label="view-mode"]').click(), cy.get("[role=presentation]").find('[class^="MuiPaper-root"]').find("[role=button]").eq(n).click();
38
38
  });
39
39
  };
40
40
  export {
41
- u as r
41
+ f as r
42
42
  };
@@ -1,53 +1,138 @@
1
- import { M4LGetCypressDataGridColumnsConfig } from './export';
1
+ /**
2
+ * Column configuration for DataGrid in Cypress
3
+ */
4
+ export type M4LDataGridCypressColumn = {
5
+ /**
6
+ * @param key - The column key
7
+ */
8
+ key: string;
9
+ /**
10
+ * @param value - The column value
11
+ */
12
+ value: any;
13
+ /**
14
+ * @param headerText - The column header text
15
+ */
16
+ headerText: string;
17
+ /**
18
+ * @param visible - Indicates whether the column is visible
19
+ */
20
+ visible: boolean;
21
+ };
22
+
23
+ /**
24
+ * Function that gets the DataGrid column configuration
25
+ */
26
+ export type M4LGetCypressDataGridColumnsConfig<T> = (data: T) => M4LDataGridCypressColumn[];
27
+
2
28
  declare global {
3
29
  namespace Cypress {
4
30
  interface Chainable {
5
31
  /**
6
- * Obtiene el grid
7
- * @param selector selector del grid
8
- * @returns el grid
32
+ * Gets the grid. Returns the first visible M4LDataGrid under the selector.
33
+ * @param selector grid selector
34
+ * @returns the grid
35
+ * @example
36
+ * cy.m4lDataGrid('[class*="M4LDataGrid-root"]').find('[role=row]').should('have.length.at.least', 1);
9
37
  */
10
- m4lDataGrid(selector: string): Chainable<Element>
38
+ m4lDataGrid(selector: string ): Chainable<JQuery<HTMLElement>>
11
39
  /**
12
- * Valida las columnas visibles del grid
13
- * @param selector selector del grid
14
- * @param getColumnsConfig función que obtiene las columnas visibles del grid
15
- * @param mockData datos del grid
16
- * @param baseColumnIndex índice de la columna a obtener
40
+ * Validates the visible columns of the grid. Scrolls horizontally as needed for each column.
41
+ * @example
42
+ * const getColumns = (data: MockItem) => [
43
+ * { key: 'name', headerText: 'Name', value: data.name, visible: true },
44
+ * { key: 'code', headerText: 'Code', value: data.code, visible: true },
45
+ * ];
46
+ * cy.m4lDataGridValidateVisibleColumns('[class*="M4LDataGrid-root"]', getColumns, mockItem, 1);
17
47
  */
18
48
  m4lDataGridValidateVisibleColumns<T>(
49
+ /**
50
+ * Grid selector
51
+ */
19
52
  selector: string,
53
+ /**
54
+ * Function that gets the visible columns of the grid
55
+ */
20
56
  getColumnsConfig: M4LGetCypressDataGridColumnsConfig<T>,
57
+ /**
58
+ * Grid data
59
+ */
21
60
  mockData: T,
61
+ /**
62
+ * Column index to get
63
+ */
22
64
  baseColumnIndex?: number
23
65
  ): Chainable<void>;
24
66
  /**
25
- * Obtiene la fila del grid especificada por el índice de base 1, garantizando que esté visible en el viewport
26
- * @param selector selector del grid
27
- * @param targetRowBaseOneIndex índice de la fila a obtener
28
- * @param baseOneColumnIndex índice de la columna a obtener
29
- * @returns la fila del grid
67
+ * Gets the grid row specified by 1-based index, ensuring it is visible in the viewport.
68
+ * @example
69
+ * cy.m4lDataGridRow('[class*="M4LDataGrid-root"]', 2, 1).click(); // row 2, column 1
30
70
  */
31
- m4lDataGridRow(selector: string, targetRowBaseOneIndex: number, baseOneColumnIndex: number): Chainable<JQuery<HTMLElement>>;
71
+ m4lDataGridRow(
72
+ /**
73
+ * Grid selector
74
+ */
75
+ selector: string,
76
+ /**
77
+ * Row index to get
78
+ */
79
+ targetRowBaseOneIndex: number,
80
+ /**
81
+ * Column index to get
82
+ */
83
+ baseOneColumnIndex: number
84
+ ): Chainable<JQuery<HTMLElement>>;
32
85
  /**
33
- * Obtiene el rowAction del menuActions asociado a la fila del grid especificada por el índice de base 1
34
- * @param selector selector del grid
35
- * @param menuItemIndex índice del item del menuActions
36
- * @param baseOneTargetRowIndex índice de la fila a obtener
37
- * @param baseColbaseOneColumnIndexumnIndex índice de la columna a obtener
38
- * @returns el rowAction del menuActions asociado a la fila del grid
86
+ * Opens the row actions menu for the given row and selects the menu item by index.
87
+ * @example
88
+ * cy.m4lDataGridRowAction('[class*="M4LDataGrid-root"]', 0, 2, 1); // row 2, column 1, first menu item
39
89
  */
40
90
  m4lDataGridRowAction(
91
+ /**
92
+ * Grid selector
93
+ */
41
94
  selector: string,
95
+ /**
96
+ * menuActions item index
97
+ */
42
98
  menuItemIndex: number,
99
+ /**
100
+ * Row index to get
101
+ */
43
102
  baseOnetargetRowIndex?: number,
103
+ /**
104
+ * Column index to get
105
+ */
44
106
  baseOneColumnIndex?: number,
45
107
  ): Chainable<Element>
46
108
 
47
109
  /**
48
- * Busca y muestra todas las columnas del grid principal
110
+ * Finds and shows all columns of the main grid by opening the configurator (third button).
111
+ * @example
112
+ * cy.m4lDataGridFindAllColumns('[class*="M4LDataGrid-root"]');
113
+ */
114
+ m4lDataGridFindAllColumns(
115
+ /**
116
+ * Grid selector
117
+ */
118
+ selector: string,
119
+ ): Chainable<Element>
120
+ /**
121
+ * Switches the grid view mode (e.g. Card vs Grid). Clicks the view-mode button and selects option by index.
122
+ * @example
123
+ * cy.m4lDataGridViewMode('[class*="M4LDataGrid-root"]', 0);
124
+ * cy.m4lDataGridViewMode('[class*="M4LDataGrid-root"]', 1);
49
125
  */
50
- m4lDataGridFindAllColumns(selector: string): Chainable<Element>
126
+ m4lDataGridOrCardViewMode(
127
+ /**
128
+ * Selector for the section to validate
129
+ */
130
+ section: string,
131
+ /**
132
+ * Card or Grid view mode
133
+ */
134
+ viewMode: number,
135
+ ): Chainable<Element>;
51
136
  }
52
137
  }
53
138
  }
@@ -1,4 +1,4 @@
1
1
  /**
2
- * Registra los comandos de DynamicFilter
2
+ * Registers DynamicFilter commands
3
3
  */
4
4
  export declare const registerDynamicFilterCommands: () => void;
@@ -2,15 +2,22 @@ declare global {
2
2
  namespace Cypress {
3
3
  interface Chainable {
4
4
  /**
5
- * Click en el input de filtro
5
+ * Clicks on the filter input to open the filter popover.
6
+ * @example
7
+ * cy.m4lDynamicFilterInputClick();
8
+ * cy.m4lPopover().find('li').first().click();
6
9
  */
7
10
  m4lDynamicFilterInputClick(): Chainable<Element>;
8
11
  /**
9
- * Aplicar el filtro de fecha
12
+ * Applies the date filter: opens filter input, selects the date field by label, then confirms.
13
+ * @example
14
+ * cy.m4lDynamicFilterApplyedDateField('Created at');
10
15
  */
11
16
  m4lDynamicFilterApplyedDateField(dateFieldLabel: string): Chainable<Element>;
12
17
  /**
13
- * Obtiene el botón de refrescar
18
+ * Gets the refresh button (second button in the filter actions area).
19
+ * @example
20
+ * cy.m4lDynamicFilterRefreshButton('[class*="M4LSplitLayout-splitDetail"]').click();
14
21
  */
15
22
  m4lDynamicFilterRefreshButton(selector: string): Chainable<Element>;
16
23
  }
@@ -1,4 +1,4 @@
1
1
  /**
2
- * Registra los comandos de DynamicSort
2
+ * Registers DynamicSort commands
3
3
  */
4
4
  export declare const registerDynamicSortCommands: () => void;
@@ -1,8 +1,24 @@
1
1
  declare global {
2
2
  namespace Cypress {
3
3
  interface Chainable {
4
+ /**
5
+ * Clicks on the sort input to open the sort popover.
6
+ * @example
7
+ * cy.m4lDynamicSortInputClick();
8
+ * cy.m4lPopover().find('li').contains('Name').click();
9
+ */
4
10
  m4lDynamicSortInputClick(): Chainable<Element>
5
- m4lDynamicSortApplyedField(dateFieldLabel: string): Chainable<Element>
11
+ /**
12
+ * Applies the sort for a field: opens sort input, selects the field by label, then confirms.
13
+ * @example
14
+ * cy.m4lDynamicSortApplyedField('Created at');
15
+ */
16
+ m4lDynamicSortApplyedField(
17
+ /**
18
+ * Date field label
19
+ */
20
+ dateFieldLabel: string,
21
+ ): Chainable<Element>
6
22
  }
7
23
  }
8
24
  }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Registers Filters and Sorts commands
3
+ */
4
+ export declare const registerFiltersCommands: () => void;
@@ -0,0 +1,24 @@
1
+ const I = '[class*="M4LSplitLayout-splitDetail"]', y = () => {
2
+ Cypress.Commands.add(
3
+ "m4lFiltersAndSortsOptionsValidation",
4
+ (i, t, n, s, c, l) => {
5
+ const o = () => cy.get('[role="presentation"]', { timeout: 1e3 }).should("exist"), r = (e) => {
6
+ o(), cy.get('[role="presentation"]', { timeout: 1e3 }).find("li").contains(e.key).click(), cy.get('[role="presentation"]', { timeout: 1e3 }).find('[class*="MuiPaper-root-MuiPopover-paper"]').should("be.visible").find("input").eq(e.inputIndex).click({ force: !0 });
7
+ }, T = () => {
8
+ cy.get("[role=presentation]").find("button").contains("N_D:[common_actions.intro]").click({ force: !0 });
9
+ }, d = (e) => {
10
+ ["select", "selectAsync", "boolean"].includes(e.type) ? (o(), cy.get('[role="presentation"]', { timeout: 1e3 }).find("li").eq(0).click({ force: !0 }), cy.get("[role=presentation]").find('[class*="MuiPaper-root-MuiPopover-paper"]').find('[class*="M4LWindowBase-headerWindowComponent"]').dblclick({ force: !0 })) : ["string", "number"].includes(e.type) && (o(), cy.get('[role="presentation"]', { timeout: 1e3 }).find("input").eq(1).type(e.value));
11
+ }, a = (e, p, u, E) => {
12
+ cy.log(`Validating filter ${e.key}`), cy.get(p, { timeout: 1e3 }).find(u).eq(E).click(), r(e), d(e), T();
13
+ };
14
+ i(t).forEach((e) => {
15
+ l ? (a(e, n, s, c), cy.get(`${I} [class*="M4LDynamicFilter-actions"] button`).eq(1).click(), cy.wait(e.endpoint, { timeout: 1e3 })) : (a(e, n, s, c), cy.wait(e.endpoint, { timeout: 1e3 }).wait("@getList", { timeout: 1e3 }));
16
+ });
17
+ }
18
+ ), Cypress.Commands.add("m4lFiltersAndSortsPersistValidation", (i, t, n) => {
19
+ cy.get(i).find(`[class*="M4LDynamic${t}-applied${t}s"]`).find(`[class*="M4LDynamic${t}-applied${t}InnerContainer"]`).find("[role=button-chip]").should("have.length", n);
20
+ });
21
+ };
22
+ export {
23
+ y as r
24
+ };
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Filter and sort configuration for Filters
3
+ */
4
+ export type M4lFiltersAndSortsConfig = {
5
+ /**
6
+ * Filter type for string, number, select, selectAsync and boolean types
7
+ */
8
+ type: string;
9
+ /**
10
+ * Filter key for select, selectAsync and boolean types
11
+ */
12
+ key: string;
13
+ /**
14
+ * Filter value for string and number types
15
+ */
16
+ value: string;
17
+ /**
18
+ * Filter endpoint to wait for
19
+ */
20
+ endpoint: string;
21
+ /**
22
+ * Filter input index
23
+ */
24
+ inputIndex: number;
25
+ };
26
+
27
+ declare global {
28
+ namespace Cypress {
29
+ interface Chainable {
30
+ /**
31
+ * Validates filter and sort options for DynamicFilter. For each filter, selects it, applies value by type, sends input.
32
+ * @example
33
+ * const mockFilters: M4lDynamicFilterConfig[] = [
34
+ * { type: 'string', key: 'Name', value: 'test', endpoint: '@getList', inputIndex: 1 },
35
+ * ];
36
+ * cy.intercept('GET', '/api/items*').as('getList');
37
+ * cy.m4lDynamicFilterValidateFilterAndSortOptions(
38
+ * (f) => f,
39
+ * mockFilters,
40
+ * '[class*="M4LDynamicFilter-root"]',
41
+ * '[class*="M4LDynamicFilter-filterChip"]',
42
+ * 0
43
+ * );
44
+ */
45
+ m4lFiltersAndSortsOptionsValidation(
46
+ filters: (mockFilters: M4lFiltersAndSortsConfig[]) => M4lFiltersAndSortsConfig[],
47
+ /**
48
+ * Mock of the filters to validate
49
+ */
50
+ mockFilters: M4lFiltersAndSortsConfig[],
51
+ /**
52
+ * Selector for the filters or sort to validate
53
+ */
54
+ filtersOrSort: string,
55
+ /**
56
+ * Selector for the section to validate
57
+ */
58
+ section: string,
59
+ /**
60
+ * Index of the filters or sort to validate
61
+ */
62
+ index: number,
63
+ /**
64
+ * If true, validates the filter in the logs tab
65
+ */
66
+ logs?: boolean,
67
+ ): Chainable<Element>;
68
+ /**
69
+ * Asserts that the number of applied filter/sort chips matches the expected length.
70
+ * @example
71
+ * cy.m4lDynamicFilterAndSortsPersist('[class*="M4LSplitLayout-splitDetail"]', 'Filter', 2);
72
+ */
73
+ m4lFiltersAndSortsPersistValidation(
74
+ /**
75
+ * Selector for the section to validate
76
+ */
77
+ section: string,
78
+ /**
79
+ * Filter or sort type
80
+ */
81
+ type: 'Filter' | 'Sort',
82
+ /**
83
+ * Length of applied filters and sorts
84
+ */
85
+ length: number,
86
+ ): Chainable<Element>;
87
+ }
88
+ }
89
+ }
90
+
91
+ export {};
@@ -1,4 +1,4 @@
1
1
  /**
2
- * Registra los comandos de MenuActions
2
+ * Registers MenuActions commands
3
3
  */
4
4
  export declare const registerMenuActionsCommands: () => void;
@@ -1,6 +1,6 @@
1
1
  const o = () => {
2
- Cypress.Commands.add("m4lMenuActionsItem", (e) => {
3
- cy.m4lPopover().find("[role=menuitem]").eq(e).should("be.visible", { timeout: 1e4 });
2
+ Cypress.Commands.add("m4lMenuActionsItem", (e, s) => {
3
+ cy.m4lPopover().find("[role=menuitem]").eq(e), s ? cy.should("have.attr", "aria-disabled", "true") : cy.should("be.visible", { timeout: 1e4 });
4
4
  });
5
5
  };
6
6
  export {
@@ -1,7 +1,22 @@
1
1
  declare global {
2
2
  namespace Cypress {
3
3
  interface Chainable {
4
- m4lMenuActionsItem(menuItemIndex: number): Chainable<Element>
4
+ /**
5
+ * Gets the MenuItem of a MenuAction at the specified position. Optionally asserts disabled state.
6
+ * @example
7
+ * cy.m4lMenuActionsItem(0); // first item, expect visible
8
+ * cy.m4lMenuActionsItem(1, 'isDisabled'); // second item, expect disabled
9
+ */
10
+ m4lMenuActionsItem(
11
+ /**
12
+ * menuActions item index
13
+ */
14
+ menuItemIndex: number,
15
+ /**
16
+ * Indicates whether the menuActions item is disabled
17
+ */
18
+ isDisabled?: 'isDisabled',
19
+ ): Chainable<Element>
5
20
  }
6
21
  }
7
22
  }
@@ -1,4 +1,4 @@
1
1
  /**
2
- * Registra los comandos de Popover
2
+ * Registers Popover commands
3
3
  */
4
4
  export declare const registerPopoverCommands: () => void;
@@ -1,6 +1,12 @@
1
1
  declare global {
2
2
  namespace Cypress {
3
3
  interface Chainable {
4
+ /**
5
+ * Gets the currently open popover (MUI Paper with role=presentation).
6
+ * @example
7
+ * cy.m4lDynamicFilterInputClick();
8
+ * cy.m4lPopover().find('li').contains('Name').click();
9
+ */
4
10
  m4lPopover(): Chainable<Element>
5
11
  }
6
12
  }
@@ -1,4 +1,4 @@
1
1
  /**
2
- * Registra los comandos de PropertyValue
2
+ * Registers PropertyValue commands
3
3
  */
4
4
  export declare const registerPropertyValueCommands: () => void;
@@ -2,11 +2,16 @@ declare global {
2
2
  namespace Cypress {
3
3
  interface Chainable {
4
4
  /**
5
- * Obtiene el PropertyValue
6
- * @param selector selector de la propiedad
7
- * @returns el valor de la propiedad
5
+ * Gets the PropertyValue element (value part) within the given selector.
6
+ * @example
7
+ * cy.m4lPropertyValue('[class*="M4LPropertyValue-root"]').should('have.text', '123');
8
8
  */
9
- m4lPropertyValue(selector: string): Chainable<Element>
9
+ m4lPropertyValue(
10
+ /**
11
+ * Property selector
12
+ */
13
+ selector: string,
14
+ ): Chainable<Element>
10
15
  }
11
16
  }
12
17
  }
@@ -1,4 +1,4 @@
1
1
  /**
2
- * Registra los comandos de Tab
2
+ * Registers Tab commands
3
3
  */
4
4
  export declare const registerTabCommands: () => void;
@@ -1,6 +1,7 @@
1
1
  const a = () => {
2
- Cypress.Commands.add("m4lTabButton", (t, s) => {
3
- cy.get(t).find("[role=tablist]").find("button").eq(s);
2
+ Cypress.Commands.add("m4lTabButton", (o, s, t) => {
3
+ const n = cy.get(o).find("[role=tablist]").find("button").eq(s);
4
+ t !== void 0 && n.should("have.text", t);
4
5
  });
5
6
  };
6
7
  export {
@@ -2,11 +2,26 @@ declare global {
2
2
  namespace Cypress {
3
3
  interface Chainable {
4
4
  /**
5
- * Obtiene el botón de la pestaña indicada
6
- * @param tabIndex índice de la pestaña a obtener
7
- * @returns el botón de la pestaña indicada
5
+ * Gets the tab button at the given index and asserts its text equals tabTitle.
6
+ * @example
7
+ * cy.m4lTabButton('[class*="M4LTab-root"]', 0); // Without title
8
+ * cy.m4lTabButton('[class*="M4LTab-root"]', 0, 'Details');
9
+ * cy.m4lTabButton('[class*="M4LTab-root"]', 1, 'History');
8
10
  */
9
- m4lTabButton(selector: string, tabIndex: number): Chainable<Element>
11
+ m4lTabButton(
12
+ /**
13
+ * @param selector - The component selector to get the tab button
14
+ */
15
+ selector: string,
16
+ /**
17
+ * @param tabIndex - The tab index to get the button
18
+ */
19
+ tabIndex: number,
20
+ /**
21
+ * @param tabTitle - The tab title to validate
22
+ */
23
+ tabTitle?: string,
24
+ ): Chainable<Element>
10
25
  }
11
26
  }
12
27
  }
@@ -1,4 +1,4 @@
1
1
  /**
2
- * Registra los comandos de WindowBase
2
+ * Registers WindowBase commands
3
3
  */
4
4
  export declare const registerWindowBaseCommands: () => void;
@@ -9,6 +9,10 @@ const a = () => {
9
9
  cy.m4lWindowBaseHeader().find('[class*="M4LMenuActions-root-M4LWindowBase-menuActionsWindowBase"]').find("button").eq(0).click(), cy.get("[role=presentation]").find('[class^="MuiPaper-root"]').find("[role=menuitem]").eq(e);
10
10
  }), Cypress.Commands.add("m4lWindowBaseMenuActionDisabled", (e) => {
11
11
  cy.m4lWindowBaseMenuAction(e).should("have.attr", "aria-disabled", "true");
12
+ }), Cypress.Commands.add("m4lDialogWindowActions", (e) => {
13
+ cy.get('[class^="MuiDialog-container"]').find('[class^="M4LWindowBase-root"]').should("contain", e);
14
+ }), Cypress.Commands.add("m4lDialogWindowActionsValidateTitle", (e) => {
15
+ cy.get('[class^="M4LGridLayout-root"]').find('[class*="M4LPopupsViewer-root"]').find('[class*="M4LDragResizeWindowRND-draggableHandle"]').find('[class*="M4LTypography-root"]').should("have.text", e);
12
16
  });
13
17
  };
14
18
  export {
@@ -1,12 +1,78 @@
1
1
  declare global {
2
2
  namespace Cypress {
3
3
  interface Chainable {
4
+ /**
5
+ * Gets the module header (draggable handle area).
6
+ * @example
7
+ * cy.m4lWindowBaseHeader().find('button').first().click();
8
+ */
4
9
  m4lWindowBaseHeader(): Chainable<Element>
5
- m4lWindowBaseLeftAction(buttonPosition: number): Chainable<Element>
6
- m4lWindowBaseLeftActionClick(buttonPosition: number): Chainable<Element>
7
- m4lWindowBaseMenuAction(menuItemPosition: number): Chainable<Element>
8
- m4lWindowBaseMenuActionDisabled(menuItemPosition: number): Chainable<Element>
9
-
10
+ /**
11
+ * Gets a button on the left side of the module by 0-based index.
12
+ * @example
13
+ * cy.m4lWindowBaseLeftAction(0).click(); // first left button
14
+ */
15
+ m4lWindowBaseLeftAction(
16
+ /**
17
+ * Button position
18
+ */
19
+ buttonPosition: number,
20
+ ): Chainable<Element>
21
+ /**
22
+ * Clicks on the left button of the module by 0-based index.
23
+ * @example
24
+ * cy.m4lWindowBaseLeftActionClick(0);
25
+ */
26
+ m4lWindowBaseLeftActionClick(
27
+ /**
28
+ * Button position
29
+ */
30
+ buttonPosition: number,
31
+ ): Chainable<Element>
32
+ /**
33
+ * Opens the header menu and returns the menu item at the given 0-based position.
34
+ * @example
35
+ * cy.m4lWindowBaseMenuAction(0).click(); // click first menu item
36
+ */
37
+ m4lWindowBaseMenuAction(
38
+ /**
39
+ * Button position
40
+ */
41
+ menuItemPosition: number,
42
+ ): Chainable<Element>
43
+ /**
44
+ * Asserts that the menu item at the given position is disabled.
45
+ * @example
46
+ * cy.m4lWindowBaseMenuActionDisabled(2);
47
+ */
48
+ m4lWindowBaseMenuActionDisabled(
49
+ /**
50
+ * Button position
51
+ */
52
+ menuItemPosition: number,
53
+ ): Chainable<Element>
54
+ /**
55
+ * Finds the dialog by title and returns the container (e.g. to then find and click accept).
56
+ * @example
57
+ * cy.m4lDialogWindowActions('Confirm').find('button').contains('Accept').click();
58
+ */
59
+ m4lDialogWindowActions(
60
+ /**
61
+ * Dialog title
62
+ */
63
+ title: string,
64
+ ): Chainable<Element>
65
+ /**
66
+ * Asserts that a popup window has the given title.
67
+ * @example
68
+ * cy.m4lDialogWindowActionsValidateTitle('Edit item');
69
+ */
70
+ m4lDialogWindowActionsValidateTitle(
71
+ /**
72
+ * Dialog title
73
+ */
74
+ title: string,
75
+ ): Chainable<Element>
10
76
  // login(email: string, password: string): Chainable<void>
11
77
  // drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
12
78
  // dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
@@ -1,3 +1,4 @@
1
+ export * from './Accordions/commands';
1
2
  export * from './DataGrid/commands';
2
3
  export * from './DynamicFilter/commands';
3
4
  export * from './DynamicSort/commands';
@@ -6,3 +7,5 @@ export * from './Popover/commands';
6
7
  export * from './PropertyValue/commands';
7
8
  export * from './Tab/commands';
8
9
  export * from './WindowBase/commands';
10
+ export * from './CommonActions/commands';
11
+ export * from './Filters/commands';
@@ -1 +1,4 @@
1
1
  export { registerCommands } from './register';
2
+ export type { M4lFiltersAndSortsConfig } from './components/Filters/types';
3
+ export type { M4lPropertyValuesAccordionsConfig } from './components/Accordions/types';
4
+ export type { M4LDataGridCypressColumn, M4LGetCypressDataGridColumnsConfig } from './components/DataGrid/types';
@@ -1,5 +1,4 @@
1
- import { Rute } from '../types';
2
1
  /**
3
2
  * Registra los comandos de la aplicación
4
3
  */
5
- export declare const registerCommands: (_props?: Rute) => void;
4
+ export declare const registerCommands: () => void;
@@ -1,15 +1,18 @@
1
+ import { r } from "./components/Accordions/commands.js";
1
2
  import { r as m } from "./components/DataGrid/commands.js";
2
3
  import { r as o } from "./components/DynamicFilter/commands.js";
3
4
  import { r as s } from "./components/DynamicSort/commands.js";
4
5
  import { r as e } from "./components/MenuActions/commands.js";
5
- import { r as t } from "./components/Popover/commands.js";
6
- import { r as a } from "./components/PropertyValue/commands.js";
7
- import { r as i } from "./components/Tab/commands.js";
6
+ import { r as i } from "./components/Popover/commands.js";
7
+ import { r as t } from "./components/PropertyValue/commands.js";
8
+ import { r as a } from "./components/Tab/commands.js";
8
9
  import { r as n } from "./components/WindowBase/commands.js";
9
- import { r as p } from "./intercepts/noPrivileges/interceptCommands.js";
10
- const u = (r = {}) => {
11
- m(), o(), s(), e(), t(), a(), i(), n(), p(r);
10
+ import { r as d } from "./components/CommonActions/commands.js";
11
+ import { r as p } from "./components/Filters/commands.js";
12
+ import { r as g } from "./intercepts/noPrivileges/interceptCommands.js";
13
+ const w = () => {
14
+ r(), m(), o(), s(), e(), i(), t(), a(), n(), d(), p(), g();
12
15
  };
13
16
  export {
14
- u as r
17
+ w as r
15
18
  };
@@ -0,0 +1 @@
1
+
package/e2e/cypress.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ /// <reference path="./commands/components/Accordions/types.d.ts" />
1
2
  /// <reference path="./commands/components/DataGrid/types.d.ts" />
2
3
  /// <reference path="./commands/components/DynamicFilter/types.d.ts" />
3
4
  /// <reference path="./commands/components/DynamicSort/types.d.ts" />
@@ -6,9 +7,9 @@
6
7
  /// <reference path="./commands/components/Popover/types.d.ts" />
7
8
  /// <reference path="./commands/components/PropertyValue/types.d.ts" />
8
9
  /// <reference path="./commands/components/Tab/types.d.ts" />
10
+ /// <reference path="./commands/components/CommonActions/types.d.ts" />
9
11
  /// <reference path="./commands/intercepts/noPrivileges/types.d.ts" />
10
12
 
11
- export type { M4LGetCypressDataGridColumnsConfig , M4LDataGridCypressColumn } from './commands/components/DataGrid/export';
12
13
 
13
14
  declare global {
14
15
  namespace Cypress {
@@ -18,3 +19,5 @@ declare global {
18
19
  }
19
20
  }
20
21
  }
22
+
23
+ export {};
package/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export * from './e2e/cypress.d';
1
2
  export * from './e2e/commands';
2
3
  export * from './testComponents';
3
4
  export * from './testTools';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@m4l/testing",
3
3
  "description": "Shared testing utilities for MFs",
4
- "version": "0.0.22",
4
+ "version": "0.0.23",
5
5
  "license": "UNLICENSED",
6
6
  "author": "M4L Team",
7
7
  "scripts": {
@@ -29,89 +29,78 @@
29
29
  "*.{js,ts,tsx}": "eslint --fix --max-warnings 0"
30
30
  },
31
31
  "dependencies": {
32
- "@storybook/addon-designs": "^8.0.3",
33
- "@storybook/addon-essentials": "^8.3.4",
34
- "@storybook/addon-interactions": "^8.3.4",
35
- "@storybook/addon-links": "^8.3.4",
32
+ "@storybook/addon-designs": "^8.0.0",
33
+ "@storybook/addon-essentials": "8.3.4",
34
+ "@storybook/addon-interactions": "8.3.4",
35
+ "@storybook/addon-links": "8.3.4",
36
36
  "@storybook/addon-onboarding": "^8.3.4",
37
37
  "@storybook/blocks": "^8.3.4",
38
- "@storybook/react": "^8.3.4",
39
- "@storybook/react-vite": "^8.3.4",
40
- "@storybook/test": "^8.3.4",
38
+ "@storybook/react": "8.3.4",
39
+ "@storybook/react-vite": "8.3.4",
40
+ "@storybook/test": "8.3.4",
41
41
  "@testing-library/dom": "^10.4.0",
42
42
  "@testing-library/jest-dom": "^6.5.0",
43
43
  "@testing-library/react": "^16.0.0",
44
44
  "@testing-library/react-hooks": "^8.0.1",
45
45
  "@testing-library/user-event": "^14.5.2",
46
- "@types/cypress": "^1.1.6",
47
46
  "@types/jest": "^29.5.10",
48
47
  "@vitejs/plugin-react": "^4.0.0",
49
- "@vitest/coverage-istanbul": "^3.1.1",
50
- "@vitest/coverage-v8": "^3.1.1",
48
+ "@vitest/coverage-istanbul": "3.1.1",
49
+ "@vitest/coverage-v8": "3.1.1",
51
50
  "@vitest/ui": "^3.1.1",
52
51
  "cypress": "^14.1.0",
53
- "cypress-vite": "^1.5.0",
52
+ "cypress-vite": "1.6.0",
54
53
  "happy-dom": "^17.1.9",
55
- "jest-environment-jsdom": "^29.7.0",
54
+ "jest-environment-jsdom": "29.7.0",
56
55
  "jsdom": "^25.0.1",
57
56
  "storybook": "^8.3.4"
58
57
  },
59
58
  "peerDependencies": {
60
- "@types/react": "^18.0.0",
61
- "react": "^18.0.0",
62
- "vitest": "^3.1.1"
59
+ "@types/react": "18.3.23",
60
+ "react": "18.3.1",
61
+ "vitest": "3.1.1"
63
62
  },
64
63
  "devDependencies": {
65
64
  "@m4l/components": "^9.0.0",
66
65
  "@m4l/config": "^1.1.2",
67
66
  "@m4l/vite-plugins": "^1.1.5",
68
67
  "@types/node": "^22.7.3",
69
- "@types/react": "^18.0.0",
70
- "@types/react-dom": "^18.0.0",
71
- "eslint": "^9.0.0",
72
- "lefthook": "^1.7.18",
73
- "lint-staged": "^15.2.10",
74
- "react": "^18.0.0",
75
- "react-dom": "^18.0.0",
76
- "typescript": "^5.4.5",
77
- "vite": "^6.3.5",
68
+ "@types/react": "18.3.23",
69
+ "@types/react-dom": "18.3.7",
70
+ "eslint": "9.28.0",
71
+ "lefthook": "1.11.13",
72
+ "lint-staged": "15.5.2",
73
+ "react": "18.3.1",
74
+ "react-dom": "18.3.1",
75
+ "typescript": "5.8.3",
76
+ "vite": "6.3.5",
78
77
  "vite-plugin-dts": "^4.2.1",
79
- "vitest": "^3.1.1"
78
+ "vitest": "3.1.1"
80
79
  },
81
80
  "resolutions": {
82
81
  "glob": "^10.4.5",
83
- "react": "^18.0.0",
84
- "@types/react": "^18.0.0",
85
- "@types/react-dom": "^18.0.0",
86
- "react-dom": "^18.0.0",
82
+ "react": "18.3.1",
83
+ "@types/react": "18.3.23",
84
+ "@types/react-dom": "18.3.7",
85
+ "react-dom": "18.3.1",
87
86
  "@vitejs/plugin-react": "^4.0.0"
88
87
  },
89
88
  "overrides": {
90
89
  "glob": "^10.4.5",
91
- "eslint": "^9.0.0",
92
- "react": "^18.0.0",
93
- "@types/react": "^18.0.0",
94
- "@types/react-dom": "^18.0.0",
95
- "react-dom": "^18.0.0"
90
+ "eslint": "9.28.0",
91
+ "react": "18.3.1",
92
+ "@types/react": "18.3.23",
93
+ "@types/react-dom": "18.3.7",
94
+ "react-dom": "18.3.1"
96
95
  },
97
96
  "files": [
98
97
  "*"
99
98
  ],
99
+ "type": "module",
100
100
  "source": "./index.js",
101
- "main": "src/index.ts",
101
+ "main": "./index.js",
102
102
  "module": "./index.js",
103
- "type": "module",
104
103
  "types": "./index.d.ts",
105
- "exports": {
106
- ".": {
107
- "types": "./index.d.ts",
108
- "import": "./index.js",
109
- "require": null
110
- },
111
- "./cypress": {
112
- "types": "./e2e/cypress.d.ts"
113
- }
114
- },
115
104
  "sideEffects": false,
116
105
  "publishConfig": {
117
106
  "access": "public"
@@ -1,73 +1,95 @@
1
- import { expect as t } from "vitest";
2
- const n = (o) => o?.type === "nested", h = (o) => o?.type === "date", d = (o) => o?.type === "boolean", k = (o) => o?.type === "setCheck", C = (o) => o?.type === "price", p = (o) => o?.type === "points", y = (o) => o?.type === "uncertainty", f = (o) => o?.type === "concatenated", m = (o) => o?.type === "chipStatus", V = (o, a) => {
3
- t(o).toHaveLength(a.length), a.forEach((e, s) => {
4
- const l = o[s], u = e.hookCall?.type ?? "none";
5
- describe(`Column ${s + 1}: ${e.key} (${u})`, () => {
1
+ import { expect as l } from "vitest";
2
+ const i = (t) => t?.type === "nested", k = (t) => t?.type === "date", C = (t) => t?.type === "boolean", d = (t) => t?.type === "setCheck", n = (t) => t?.type === "price", p = (t) => t?.type === "points", y = (t) => t?.type === "uncertainty", f = (t) => t?.type === "concatenated", m = (t) => t?.type === "chipStatus", V = (t) => t?.type === "tags", I = (t) => t?.type === "icon", P = (t) => t?.type === "color", E = (t) => t?.type === "image", B = (t, r) => {
3
+ l(t).toHaveLength(r.length), r.forEach((e, u) => {
4
+ const o = t[u], h = e.hookCall?.type ?? "none";
5
+ describe(`Column ${u + 1}: ${e.key} (${h})`, () => {
6
6
  if (it("should have the correct basic properties", () => {
7
- t(l.key).toBe(e.key), t(l.name).toBe(e.name), t(l.type).toBe(e.type), t(l.align).toBe(e.align), t(l.width).toBe(e.width), t(l.visible).toBe(e.visible), e.fixed && t(l.fixed).toBe(e.fixed);
7
+ l(o.key).toBe(e.key), l(o.name).toBe(e.name), l(o.type).toBe(e.type), l(o.align).toBe(e.align), l(o.width).toBe(e.width), l(o.visible).toBe(e.visible), e.fixed && l(o.fixed).toBe(e.fixed);
8
8
  }), e.hookCall) {
9
- let r = !0, i = !0;
9
+ let a = !0, s = !0;
10
10
  it("should have the correct hook call properties", () => {
11
- if (n(e.hookCall))
12
- t(l.testProps).toEqual({
13
- fieldValue: e.hookCall.fieldValue
11
+ if (i(e.hookCall))
12
+ l(o.testProps).toEqual({
13
+ fieldValue: e.hookCall.fieldValue,
14
+ defaultValue: e.hookCall.defaultValue,
15
+ Component: e.hookCall.Component
14
16
  });
15
- else if (h(e.hookCall))
16
- t(l.testProps).toEqual({
17
+ else if (k(e.hookCall))
18
+ l(o.testProps).toEqual({
17
19
  fieldValue: e.hookCall.fieldValue,
18
20
  presentationType: e.hookCall.presentationType
19
21
  });
20
- else if (d(e.hookCall))
21
- t(l.testProps).toEqual({
22
+ else if (C(e.hookCall))
23
+ l(o.testProps).toEqual({
22
24
  fieldValue: e.hookCall.fieldValue,
23
25
  presentationType: e.hookCall.presentationType
24
26
  });
25
- else if (k(e.hookCall))
26
- t(l.testProps).toEqual({
27
+ else if (d(e.hookCall))
28
+ l(o.testProps).toEqual({
27
29
  field: e.hookCall.field,
28
- disabledGetter: t.any(Function),
29
- rowKeyGetter: t.any(Function),
30
- useHook: t.any(Function)
31
- }), r = !1, i = !1;
32
- else if (C(e.hookCall))
33
- t(l.testProps).toEqual({
30
+ disabledGetter: l.any(Function),
31
+ rowKeyGetter: l.any(Function),
32
+ useHook: l.any(Function)
33
+ }), a = !1, s = !1;
34
+ else if (n(e.hookCall))
35
+ l(o.testProps).toEqual({
34
36
  fieldValue: e.hookCall.fieldValue
35
37
  });
36
38
  else if (p(e.hookCall))
37
- t(l.testProps).toEqual({
39
+ l(o.testProps).toEqual({
38
40
  fieldValue: e.hookCall.fieldValue,
39
41
  fieldUnit: e.hookCall.fieldUnit
40
42
  });
41
43
  else if (y(e.hookCall))
42
- t(l.testProps).toEqual({
44
+ l(o.testProps).toEqual({
43
45
  fieldValue: e.hookCall.fieldValue,
44
46
  fieldUnit: e.hookCall.fieldUnit,
45
47
  fieldSymbol: e.hookCall.fieldSymbol
46
48
  });
47
49
  else if (f(e.hookCall))
48
- t(l.testProps).toEqual({
50
+ l(o.testProps).toEqual({
49
51
  fieldValue: e.hookCall.fieldValue,
50
52
  fieldSeparator: e.hookCall.fieldSeparator
51
53
  });
52
54
  else if (m(e.hookCall))
53
- t(l.testProps).toEqual({
54
- fieldLabel: typeof e.hookCall.fieldLabel == "function" ? t.any(Function) : e.hookCall.fieldLabel,
55
+ l(o.testProps).toEqual({
56
+ fieldLabel: typeof e.hookCall.fieldLabel == "function" ? l.any(Function) : e.hookCall.fieldLabel,
55
57
  fieldStatus: e.hookCall.fieldStatus,
56
58
  statusesColors: e.hookCall.statusesColors,
57
59
  fallbackColor: e.hookCall.fallbackColor
58
60
  });
61
+ else if (V(e.hookCall))
62
+ l(o.testProps).toEqual({
63
+ fieldValue: e.hookCall.fieldValue
64
+ });
65
+ else if (I(e.hookCall))
66
+ l(o.testProps).toEqual({
67
+ getIconProps: l.any(Function)
68
+ }), a = !1, s = !1;
69
+ else if (P(e.hookCall))
70
+ l(o.testProps).toEqual({
71
+ fieldValue: e.hookCall.fieldValue
72
+ }), a = !1, s = !1;
73
+ else if (E(e.hookCall))
74
+ l(o.testProps).toEqual({
75
+ fieldValue: e.hookCall.fieldValue,
76
+ fieldText: e.hookCall.fieldText,
77
+ cover: e.hookCall.cover,
78
+ width: e.hookCall.width,
79
+ height: e.hookCall.height
80
+ }), a = !1, s = !1;
59
81
  else
60
82
  throw new Error(`Unknown hook call type: ${e.hookCall?.type}`);
61
83
  }), it("should have formatter, customFilter and customSort functions", () => {
62
- t(l.formatter).toBeDefined(), r && t(l.customFilter).toBeDefined(), i && t(l.customSort).toBeDefined();
84
+ l(o.formatter).toBeDefined(), a && l(o.customFilter).toBeDefined(), s && l(o.customSort).toBeDefined();
63
85
  });
64
86
  } else
65
87
  it("should not have formatter functions", () => {
66
- t(l.formatter).toBeUndefined(), t(l.customFilter).toBeUndefined(), t(l.customSort).toBeUndefined();
88
+ l(o.formatter).toBeUndefined(), l(o.customFilter).toBeUndefined(), l(o.customSort).toBeUndefined();
67
89
  });
68
90
  });
69
91
  });
70
92
  };
71
93
  export {
72
- V as t
94
+ B as t
73
95
  };
@@ -1,7 +1,7 @@
1
- import { ColumnNestedValueFormatterProps, ColumnDateFormatterProps, ColumnBooleanFormatterProps, ColumnPriceFormatterProps, ColumnPointsFormatterProps, ColumnSetCheckFormatterProps, ColumnUncertaintyFormatterProps, ColumnConcatenatedValuesFormatterProps, Column, ColumnInteractiveCheckFormatterProps, ColumnChipStatusFormatterProps } from '@m4l/components';
1
+ import { ColumnNestedValueFormatterProps, ColumnDateFormatterProps, ColumnBooleanFormatterProps, ColumnPriceFormatterProps, ColumnPointsFormatterProps, ColumnSetCheckFormatterProps, ColumnUncertaintyFormatterProps, ColumnConcatenatedValuesFormatterProps, Column, ColumnInteractiveCheckFormatterProps, ColumnChipStatusFormatterProps, ColumnTagsFormatterProps, ColumnIconFormatterProps, ColumnColorFormatterProps, ColumnImageFormatterProps } from '@m4l/components';
2
2
  type BaseColumnConfig<T> = Column<T, unknown>;
3
3
  type BaseHookCall = {
4
- type: 'nested' | 'date' | 'boolean' | 'price' | 'points' | 'interactiveCheck' | 'setCheck' | 'uncertainty' | 'concatenated' | 'chipStatus';
4
+ type: 'nested' | 'date' | 'boolean' | 'price' | 'points' | 'interactiveCheck' | 'setCheck' | 'uncertainty' | 'concatenated' | 'chipStatus' | 'tags' | 'icon' | 'color' | 'image';
5
5
  };
6
6
  export type TestingNestedValueHookCall<T> = BaseHookCall & ColumnNestedValueFormatterProps<T> & {
7
7
  type: 'nested';
@@ -33,8 +33,20 @@ export type TestingConcatenatedHookCall<T> = BaseHookCall & ColumnConcatenatedVa
33
33
  export type TestingChipStatusHookCall<T> = BaseHookCall & ColumnChipStatusFormatterProps<T> & {
34
34
  type: 'chipStatus';
35
35
  };
36
+ export type TestingTagsHookCall<T> = BaseHookCall & ColumnTagsFormatterProps<T> & {
37
+ type: 'tags';
38
+ };
39
+ export type TestingIconHookCall<T> = BaseHookCall & ColumnIconFormatterProps<T> & {
40
+ type: 'icon';
41
+ };
42
+ export type TestingColorHookCall<T> = BaseHookCall & ColumnColorFormatterProps<T> & {
43
+ type: 'color';
44
+ };
45
+ export type TestingImageHookCall<T> = BaseHookCall & ColumnImageFormatterProps<T> & {
46
+ type: 'image';
47
+ };
36
48
  export type TestingColumnConfig<T> = BaseColumnConfig<T> & {
37
- hookCall?: TestingNestedValueHookCall<T> | TestingDateHookCall<T> | TestingBooleanHookCall<T> | TestingPriceHookCall<T> | TestingPointsHookCall<T> | TestingInteractiveCheckHookCall<T> | TestingSetCheckHookCall<T> | TestingUncertaintyHookCall<T> | TestingConcatenatedHookCall<T> | TestingChipStatusHookCall<T>;
49
+ hookCall?: TestingNestedValueHookCall<T> | TestingDateHookCall<T> | TestingBooleanHookCall<T> | TestingPriceHookCall<T> | TestingPointsHookCall<T> | TestingInteractiveCheckHookCall<T> | TestingSetCheckHookCall<T> | TestingUncertaintyHookCall<T> | TestingConcatenatedHookCall<T> | TestingChipStatusHookCall<T> | TestingTagsHookCall<T> | TestingIconHookCall<T> | TestingColorHookCall<T> | TestingImageHookCall<T>;
38
50
  };
39
51
  export type TestingColumn = Column<unknown, unknown> & {
40
52
  testProps?: Record<string, unknown>;
@@ -1,7 +0,0 @@
1
- export type M4LDataGridCypressColumn = {
2
- key: string;
3
- value: any;
4
- headerText: string;
5
- visible: boolean;
6
- };
7
- export type M4LGetCypressDataGridColumnsConfig<T> = (data: T) => M4LDataGridCypressColumn[];