diff --git a/packages/inscription-view/src/components/editors/part/Part.tsx b/packages/inscription-view/src/components/editors/part/Part.tsx index c1f85108..f18a7740 100644 --- a/packages/inscription-view/src/components/editors/part/Part.tsx +++ b/packages/inscription-view/src/components/editors/part/Part.tsx @@ -1,5 +1,4 @@ import './Part.css'; -import { useState } from 'react'; import { IvyIcons } from '@axonivy/ui-icons'; import { Accordion, @@ -12,7 +11,7 @@ import { Flex } from '@axonivy/ui-components'; import { ErrorBoundary } from 'react-error-boundary'; -import type { PartProps } from './usePart'; +import { useAccordionState, type PartProps } from './usePart'; import type { Severity } from '@axonivy/process-editor-inscription-protocol'; import { useSticky } from './useSticky'; import ErrorFallback from '../../widgets/error/ErrorFallback'; @@ -29,23 +28,20 @@ const Control = ({ name, reset, control, ...props }: Pick) => { - return ( - ({ - message, - variant: severity.toLocaleLowerCase() as Lowercase - }))} - state={state.state} - /> - ); -}; +const State = ({ state }: Pick) => ( + ({ + message, + variant: severity.toLocaleLowerCase() as Lowercase + }))} + state={state.state} + /> +); const Part = ({ parts }: { parts: PartProps[] }) => { - const [value, setValue] = useState(''); - + const { value, updateValue } = useAccordionState(parts); return ( - + {parts.map(part => ( ))} diff --git a/packages/inscription-view/src/components/editors/part/usePart.test.ts b/packages/inscription-view/src/components/editors/part/usePart.test.ts index 9f9fd191..f1eae1e8 100644 --- a/packages/inscription-view/src/components/editors/part/usePart.test.ts +++ b/packages/inscription-view/src/components/editors/part/usePart.test.ts @@ -1,10 +1,10 @@ import { renderHook } from 'test-utils'; -import type { PartStateFlag } from './usePart'; -import { usePartState } from './usePart'; +import type { PartProps, PartStateFlag } from './usePart'; +import { useAccordionState, usePartState } from './usePart'; import type { ValidationResult } from '@axonivy/process-editor-inscription-protocol'; import { describe, test, expect } from 'vitest'; -describe('PartState', () => { +describe('usePartState', () => { function assertState(expectedState: PartStateFlag, data?: unknown, message?: ValidationResult[]) { const { result } = renderHook(() => usePartState({}, data ?? {}, message ?? [])); expect(result.current.state).toEqual(expectedState); @@ -25,3 +25,33 @@ describe('PartState', () => { ]); }); }); + +describe('useAccordionState', () => { + const ACCORDION_STORAGE_KEY = 'process-inscription-accordion'; + const parts = [{ name: 'General' }, { name: 'Dialog' }] as Array; + + test('empty storage', () => { + const { result } = renderHook(() => useAccordionState(parts)); + expect(result.current.value).toEqual(''); + }); + + test('wrong storage', () => { + sessionStorage.setItem(ACCORDION_STORAGE_KEY, 'wrong'); + const { result } = renderHook(() => useAccordionState(parts)); + expect(result.current.value).toEqual(''); + }); + + test('other storage', () => { + sessionStorage.setItem(ACCORDION_STORAGE_KEY, `["Result"]`); + const { result } = renderHook(() => useAccordionState(parts)); + expect(result.current.value).toEqual(''); + }); + + test('matching storage', () => { + sessionStorage.setItem(ACCORDION_STORAGE_KEY, `["Result", "Dialog"]`); + const { result } = renderHook(() => useAccordionState(parts)); + expect(result.current.value).toEqual('Dialog'); + result.current.updateValue(''); + expect(sessionStorage.getItem(ACCORDION_STORAGE_KEY)).toEqual(`["Result"]`); + }); +}); diff --git a/packages/inscription-view/src/components/editors/part/usePart.ts b/packages/inscription-view/src/components/editors/part/usePart.ts index 5958d289..937ddf45 100644 --- a/packages/inscription-view/src/components/editors/part/usePart.ts +++ b/packages/inscription-view/src/components/editors/part/usePart.ts @@ -1,6 +1,6 @@ import type { ValidationResult } from '@axonivy/process-editor-inscription-protocol'; import type { ReactNode } from 'react'; -import { useMemo } from 'react'; +import { useMemo, useState } from 'react'; import { deepEqual } from '../../../utils/equals'; export type PartStateFlag = 'configured' | 'warning' | 'error' | undefined; @@ -36,3 +36,37 @@ export function usePartDirty(initData: unknown, data: unknown): boolean { return !deepEqual(data, initData); }, [data, initData]); } + +const ACCORDION_STORAGE_KEY = 'process-inscription-accordion'; + +export const useAccordionState = (parts: Array) => { + const [value, setValue] = useState(() => { + try { + const storage = sessionStorage.getItem(ACCORDION_STORAGE_KEY) ?? '[]'; + const states = JSON.parse(storage) as Array; + return parts.find(part => states.includes(part.name))?.name ?? ''; + } catch { + console.error('Error reading from sessionStorage'); + return ''; + } + }); + const updateValue = (value: string) => { + setValue(old => { + try { + const storage = sessionStorage.getItem(ACCORDION_STORAGE_KEY) ?? '[]'; + let states = JSON.parse(storage) as Array; + if (states.includes(old)) { + states.splice(states.indexOf(old), 1); + } + if (value) { + states = [value, ...states]; + } + sessionStorage.setItem(ACCORDION_STORAGE_KEY, JSON.stringify(states)); + } catch { + console.error('Error store to sessionStorage'); + } + return value; + }); + }; + return { value, updateValue }; +}; diff --git a/packages/inscription-view/src/components/parts/common/customfield/CustomFieldTable.test.tsx b/packages/inscription-view/src/components/parts/common/customfield/CustomFieldTable.test.tsx index b801e99a..3aaefc92 100644 --- a/packages/inscription-view/src/components/parts/common/customfield/CustomFieldTable.test.tsx +++ b/packages/inscription-view/src/components/parts/common/customfield/CustomFieldTable.test.tsx @@ -49,10 +49,10 @@ describe('CustomFieldTable', () => { test('table can add rows by keyboard', async () => { const view = renderTable(); await TableUtil.assertAddRowWithKeyboard(view, 'number', '1'); + // data does not contain empty object expect(view.data()).toEqual([ { name: 'field1', type: 'STRING', value: 'this is a string' }, - { name: 'number1', type: 'NUMBER', value: '1' }, - { name: '', type: 'STRING', value: '' } + { name: 'number1', type: 'NUMBER', value: '1' } ]); }); diff --git a/packages/inscription-view/src/components/parts/common/customfield/CustomFieldTable.tsx b/packages/inscription-view/src/components/parts/common/customfield/CustomFieldTable.tsx index 188b24dd..6f4f5297 100644 --- a/packages/inscription-view/src/components/parts/common/customfield/CustomFieldTable.tsx +++ b/packages/inscription-view/src/components/parts/common/customfield/CustomFieldTable.tsx @@ -7,7 +7,6 @@ import { memo, useMemo } from 'react'; import { ValidationRow } from '../path/validation/ValidationRow'; import { PathCollapsible } from '../path/PathCollapsible'; import { useResizableEditableTable } from '../table/useResizableEditableTable'; -import { deepEqual } from '../../../../utils/equals'; import { ComboCell, SelectCell, SortableHeader, Table, TableBody, TableCell, TableResizableHeader } from '@axonivy/ui-components'; import type { SelectItem } from '../../../widgets/select/Select'; import { useEditorContext } from '../../../../context/useEditorContext'; @@ -56,35 +55,20 @@ const CustomFieldTable = ({ data, onChange, type }: CustomFieldTableProps) => { [data, items, predefinedCustomField] ); - const updateCustomFields = (rowId: string, columnId: string, value: string) => { - const rowIndex = parseInt(rowId); - const updatedData = data.map((row, index) => { + const updateCustomFields = (data: Array, rowIndex: number, columnId: string) => { + if (columnId !== 'name') { + return data; + } + return data.map((customField, index) => { if (index === rowIndex) { - return { - ...data[rowIndex]!, - [columnId]: value - }; + const predefinedField = predefinedCustomField.find(pcf => pcf.name === customField.name); + if (predefinedField && predefinedField.type !== customField.type) { + return { ...customField, type: predefinedField.type }; + } + return customField; } - return row; + return customField; }); - const autoChangedData = - columnId === 'name' - ? updatedData.map((customField, index) => { - if (index === rowIndex) { - const predefinedField = predefinedCustomField.find(pcf => pcf.name === customField.name); - if (predefinedField && predefinedField.type !== customField.type) { - return { ...customField, type: predefinedField.type }; - } - return customField; - } - return customField; - }) - : updatedData; - if (!deepEqual(autoChangedData[updatedData.length - 1], EMPTY_WFCUSTOMFIELD) && rowIndex === data.length - 1) { - onChange([...autoChangedData, EMPTY_WFCUSTOMFIELD]); - } else { - onChange(autoChangedData); - } }; const { table, rowSelection, setRowSelection, removeRowAction, showAddButton } = useResizableEditableTable({ diff --git a/packages/inscription-view/src/components/parts/common/customfield/StartCustomFieldTable.test.tsx b/packages/inscription-view/src/components/parts/common/customfield/StartCustomFieldTable.test.tsx index d06d5bce..53fa3b67 100644 --- a/packages/inscription-view/src/components/parts/common/customfield/StartCustomFieldTable.test.tsx +++ b/packages/inscription-view/src/components/parts/common/customfield/StartCustomFieldTable.test.tsx @@ -50,10 +50,10 @@ describe('StartCustomFieldTable', () => { const view = renderTable(); await userEvent.click(screen.getAllByRole('row')[2]); await TableUtil.assertAddRowWithKeyboard(view, 'number', '1'); + // data does not contain empty object expect(view.data()).toEqual([ { name: 'field1', value: 'this is a string' }, - { name: 'number1', value: '1' }, - { name: '', value: '' } + { name: 'number1', value: '1' } ]); }); diff --git a/packages/inscription-view/src/components/parts/common/parameter/ParameterTable.test.tsx b/packages/inscription-view/src/components/parts/common/parameter/ParameterTable.test.tsx index 07e7b705..d513d7fd 100644 --- a/packages/inscription-view/src/components/parts/common/parameter/ParameterTable.test.tsx +++ b/packages/inscription-view/src/components/parts/common/parameter/ParameterTable.test.tsx @@ -57,10 +57,10 @@ describe('ParameterTable', () => { const view = renderTable(); await CollapsableUtil.toggle('Input parameters'); await TableUtil.assertAddRowWithKeyboard(view, 'number'); + // data does not contain empty object expect(view.data()).toEqual([ { name: 'field1', type: 'String', desc: 'this is a string' }, - { name: 'number', type: 'Number', desc: '1' }, - { name: '', type: 'String', desc: '' } + { name: 'number', type: 'Number', desc: '1' } ]); }); diff --git a/packages/inscription-view/src/components/parts/common/table/useResizableEditableTable.tsx b/packages/inscription-view/src/components/parts/common/table/useResizableEditableTable.tsx index e61d2ba1..00a778d8 100644 --- a/packages/inscription-view/src/components/parts/common/table/useResizableEditableTable.tsx +++ b/packages/inscription-view/src/components/parts/common/table/useResizableEditableTable.tsx @@ -1,6 +1,6 @@ import type { ColumnDef, RowSelectionState, SortingState } from '@tanstack/react-table'; import { getCoreRowModel, getSortedRowModel, useReactTable } from '@tanstack/react-table'; -import { useState, useEffect } from 'react'; +import { useState } from 'react'; import { deepEqual } from '../../../../utils/equals'; import { IvyIcons } from '@axonivy/ui-icons'; import { TableAddRow } from '@axonivy/ui-components'; @@ -11,7 +11,7 @@ interface UseResizableEditableTableProps { columns: ColumnDef[]; onChange: (change: TData[]) => void; emptyDataObject: TData; - specialUpdateData?: (rowId: string, columnId: string, value: string) => void; + specialUpdateData?: (data: Array, rowIndex: number, columnId: string) => void; } const useResizableEditableTable = ({ @@ -21,29 +21,36 @@ const useResizableEditableTable = ({ emptyDataObject, specialUpdateData }: UseResizableEditableTableProps) => { + const [tableData, setTableData] = useState(data); const [sorting, setSorting] = useState([]); const [rowSelection, setRowSelection] = useState({}); + const updateTableData = (tableData: Array) => { + setTableData(tableData); + onChange(tableData.filter(obj => !deepEqual(obj, emptyDataObject))); + }; + const updateData = (rowId: string, columnId: string, value: string) => { const rowIndex = parseInt(rowId); - const updatedData = data.map((row, index) => { + const updatedData = tableData.map((row, index) => { if (index === rowIndex) { return { - ...data[rowIndex]!, + ...tableData[rowIndex], [columnId]: value }; } return row; }); - if (!deepEqual(updatedData[updatedData.length - 1], emptyDataObject) && rowIndex === data.length - 1) { - onChange([...updatedData, emptyDataObject]); + specialUpdateData?.(updatedData, rowIndex, columnId); + if (!deepEqual(updatedData.at(-1), emptyDataObject) && rowIndex === tableData.length - 1) { + updateTableData([...updatedData, emptyDataObject]); } else { - onChange(updatedData); + updateTableData(updatedData); } }; const table = useReactTable({ - data, + data: tableData, columns, state: { sorting, rowSelection }, columnResizeMode: 'onChange', @@ -55,42 +62,36 @@ const useResizableEditableTable = ({ onSortingChange: setSorting, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), - meta: { updateData: specialUpdateData ? specialUpdateData : updateData } + meta: { updateData } }); - useEffect(() => { - if (Object.keys(rowSelection).length !== 1) { - const filteredData = data.filter(obj => !deepEqual(obj, emptyDataObject)); - if (filteredData.length !== data.length) { - setRowSelection({}); - onChange(filteredData); - } - } - }, [data, emptyDataObject, onChange, rowSelection, table]); - const addRow = () => { - const newData = [...data]; + const newData = [...tableData]; newData.push(emptyDataObject); - onChange(newData); + updateTableData(newData); setRowSelection({ [`${newData.length - 1}`]: true }); }; const showAddButton = () => { - if (data.filter(obj => deepEqual(obj, emptyDataObject)).length === 0) { + if (tableData.filter(obj => deepEqual(obj, emptyDataObject)).length === 0) { return ; } return null; }; const removeRow = (index: number) => { - const newData = [...data]; + const newData = [...tableData]; newData.splice(index, 1); if (newData.length === 0) { setRowSelection({}); - } else if (index === data.length - 1) { + } else if (index === tableData.length - 1) { setRowSelection({ [`${newData.length - 1}`]: true }); } - onChange(newData); + if (newData.length === 1 && deepEqual(newData[0], emptyDataObject)) { + updateTableData([]); + } else { + updateTableData(newData); + } }; const removeRowAction: FieldsetControl = { diff --git a/packages/inscription-view/src/components/parts/name/document/DocumentTable.test.tsx b/packages/inscription-view/src/components/parts/name/document/DocumentTable.test.tsx index 41a0a434..9ae88a93 100644 --- a/packages/inscription-view/src/components/parts/name/document/DocumentTable.test.tsx +++ b/packages/inscription-view/src/components/parts/name/document/DocumentTable.test.tsx @@ -51,10 +51,10 @@ describe('DocumentTable', () => { test('table can add rows by keyboard', async () => { const view = renderTable(); await TableUtil.assertAddRowWithKeyboard(view, 'ivyTeam ❤️'); + // data does not contain empty object expect(view.data()).toEqual([ { name: 'Doc 1', url: 'axonivy.com' }, - { name: 'ivyTeam ❤️', url: 'ivyteam.ch' }, - { name: '', url: '' } + { name: 'ivyTeam ❤️', url: 'ivyteam.ch' } ]); }); diff --git a/packages/inscription-view/src/test-utils/table-utils.tsx b/packages/inscription-view/src/test-utils/table-utils.tsx index eebc9158..f12a4dc3 100644 --- a/packages/inscription-view/src/test-utils/table-utils.tsx +++ b/packages/inscription-view/src/test-utils/table-utils.tsx @@ -31,7 +31,8 @@ export namespace TableUtil { await assertRowCount(expectedRows); const addButton = screen.getByRole('button', { name: 'Add row' }); await userEvent.click(addButton); - expect(view.data()).toHaveLength(expectedRows); + // data does not contain empty object + expect(view.data()).toHaveLength(expectedRows - 1); view.rerender(); await assertRowCount(expectedRows + 1); @@ -51,7 +52,7 @@ export namespace TableUtil { } await userEvent.tab(); view.rerender(); - await waitFor(() => expect(screen.getAllByRole('row')).toHaveLength(rowCount + 1)); + await assertRowCount(rowCount + 1); } export async function assertRemoveRow(view: { data: () => unknown[]; rerender: () => void }, expectedRows: number): Promise { diff --git a/packages/inscription/src/inscription/inscription-ui.tsx b/packages/inscription/src/inscription/inscription-ui.tsx index fe496ad9..1e86a665 100644 --- a/packages/inscription/src/inscription/inscription-ui.tsx +++ b/packages/inscription/src/inscription/inscription-ui.tsx @@ -1,5 +1,5 @@ import { InscriptionClientJsonRpc, IvyScriptLanguage } from '@axonivy/process-editor-inscription-core'; -import { ClientContextProvider, MonacoEditorUtil, initQueryClient } from '@axonivy/process-editor-inscription-view'; +import { ClientContextProvider, MonacoEditorUtil, QueryProvider, initQueryClient } from '@axonivy/process-editor-inscription-view'; import { InscriptionContext } from '@axonivy/process-editor-inscription-protocol'; import { JumpAction, MoveIntoViewportAction, SwitchThemeAction } from '@axonivy/process-editor-protocol'; import { @@ -19,7 +19,7 @@ import { } from '@eclipse-glsp/client'; import { webSocketConnection, type Connection } from '@axonivy/jsonrpc'; import type { MonacoLanguageClient } from 'monaco-languageclient'; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; +import { QueryClient } from '@tanstack/react-query'; import { inject, injectable, postConstruct } from 'inversify'; import { Root, createRoot } from 'react-dom/client'; @@ -72,7 +72,7 @@ export class InscriptionUi extends GLSPAbstractUIExtension implements IActionHan this.root.render( - + this.selectFromOutline(id) }} /> - + ); diff --git a/playwright/tests/inscription/events/end/end-page.spec.ts b/playwright/tests/inscription/events/end/end-page.spec.ts index e224deeb..91762b51 100644 --- a/playwright/tests/inscription/events/end/end-page.spec.ts +++ b/playwright/tests/inscription/events/end/end-page.spec.ts @@ -2,7 +2,7 @@ import { test } from '@playwright/test'; import { InscriptionView, type Inscription } from '../../../page-objects/inscription/inscription-view'; import type { CreateProcessResult } from '../../../glsp-protocol'; import { createProcess } from '../../../glsp-protocol'; -import { EndPageTestEmptyWarning } from '../../parts/end-page'; +import { EndPageTest } from '../../parts/end-page'; import { GeneralTest } from '../../parts/name'; import { runTest } from '../../parts/part-tester'; @@ -27,6 +27,6 @@ test.describe('End Page', () => { }); test('EndPage', async () => { - await runTest(view, EndPageTestEmptyWarning); + await runTest(view, EndPageTest); }); }); diff --git a/playwright/tests/inscription/events/intermediate/wait.spec.ts b/playwright/tests/inscription/events/intermediate/wait.spec.ts index fea04acd..9f900e1f 100644 --- a/playwright/tests/inscription/events/intermediate/wait.spec.ts +++ b/playwright/tests/inscription/events/intermediate/wait.spec.ts @@ -35,7 +35,7 @@ test.describe('Wait', () => { test('Configuration FileIntermediateBean', async () => { const start = view.accordion('Event'); - await start.toggle(); + await start.open(); await start.section('Java Class').open(); await start.combobox().choose('ch.ivyteam.ivy.process.intermediateevent.beans.FileIntermediateEventBean'); diff --git a/playwright/tests/inscription/events/start/program.spec.ts b/playwright/tests/inscription/events/start/program.spec.ts index 6a7b8d47..c3815525 100644 --- a/playwright/tests/inscription/events/start/program.spec.ts +++ b/playwright/tests/inscription/events/start/program.spec.ts @@ -33,7 +33,7 @@ test.describe('Program Start', () => { test('Configuration FilePickupBean', async () => { const start = view.accordion('Java Bean'); - await start.toggle(); + await start.open(); await start.section('Java Class').open(); await start.combobox().choose('ch.ivyteam.ivy.process.eventstart.beans.FilePickupStartEventBean'); @@ -42,7 +42,7 @@ test.describe('Program Start', () => { test('Configuration TimerBean', async () => { const start = view.accordion('Java Bean'); - await start.toggle(); + await start.open(); await start.section('Java Class').open(); await start.combobox().choose('ch.ivyteam.ivy.process.eventstart.beans.TimerBean'); await runTest(view, ConfigTimerBeanTest); diff --git a/playwright/tests/inscription/events/start/start.spec.ts b/playwright/tests/inscription/events/start/start.spec.ts index ce3a76f8..f18b25d3 100644 --- a/playwright/tests/inscription/events/start/start.spec.ts +++ b/playwright/tests/inscription/events/start/start.spec.ts @@ -44,7 +44,7 @@ test.describe('StartRequest', () => { test('Task', async () => { const request = view.accordion('Request'); - await request.toggle(); + await request.open(); const permissions = request.section('Permission'); await permissions.toggle(); await permissions.checkbox('Anonymous').click(); diff --git a/playwright/tests/inscription/mock/browser/attribute.spec.ts b/playwright/tests/inscription/mock/browser/attribute.spec.ts index 9dda47f7..3f052a47 100644 --- a/playwright/tests/inscription/mock/browser/attribute.spec.ts +++ b/playwright/tests/inscription/mock/browser/attribute.spec.ts @@ -5,7 +5,7 @@ import { applyBrowser, assertCodeHidden, assertCodeVisible, code } from './brows test('browser add to input', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const task = inscriptionView.accordion('Task'); - await task.toggle(); + await task.open(); const description = task.macroArea('Description'); await assertCodeHidden(page); @@ -19,7 +19,7 @@ test('browser add to input', async ({ page }) => { test('browser replace selection', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const task = inscriptionView.accordion('Task'); - await task.toggle(); + await task.open(); const category = task.macroInput('Category'); await assertCodeHidden(page); @@ -36,7 +36,7 @@ test('browser replace selection', async ({ page }) => { test('browser add attribute doubleclick', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const task = inscriptionView.accordion('Task'); - await task.toggle(); + await task.open(); const description = task.macroArea('Description'); await assertCodeHidden(page); diff --git a/playwright/tests/inscription/mock/browser/cms.spec.ts b/playwright/tests/inscription/mock/browser/cms.spec.ts index 86d0f939..33b394d8 100644 --- a/playwright/tests/inscription/mock/browser/cms.spec.ts +++ b/playwright/tests/inscription/mock/browser/cms.spec.ts @@ -5,7 +5,7 @@ import { applyBrowser, assertCodeHidden, assertCodeVisible, code } from './brows test('browser add cms string', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const task = inscriptionView.accordion('Task'); - await task.toggle(); + await task.open(); const description = task.macroArea('Description'); await assertCodeHidden(page); @@ -19,7 +19,7 @@ test('browser add cms string', async ({ page }) => { test('browser add cms file', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const task = inscriptionView.accordion('Task'); - await task.toggle(); + await task.open(); const description = task.macroArea('Description'); await assertCodeHidden(page); @@ -33,7 +33,7 @@ test('browser add cms file', async ({ page }) => { test('browser add cms doubleclick', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const task = inscriptionView.accordion('Task'); - await task.toggle(); + await task.open(); const description = task.macroArea('Description'); await assertCodeHidden(page); diff --git a/playwright/tests/inscription/mock/browser/conditionBuilder.spec.ts b/playwright/tests/inscription/mock/browser/conditionBuilder.spec.ts index 878a356c..5bdba0a3 100644 --- a/playwright/tests/inscription/mock/browser/conditionBuilder.spec.ts +++ b/playwright/tests/inscription/mock/browser/conditionBuilder.spec.ts @@ -6,7 +6,7 @@ import { browserBtn } from './browser-mock-utils'; test('Add Condition', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page, { type: 'Alternative' }); const condition = inscriptionView.accordion('Condition'); - await condition.toggle(); + await condition.open(); const conditionSection = condition.section('Condition'); await conditionSection.expectIsOpen(); const conditionTable = condition.table(['label', 'expression']); diff --git a/playwright/tests/inscription/mock/browser/maximizedCodeEditor.spec.ts b/playwright/tests/inscription/mock/browser/maximizedCodeEditor.spec.ts index 3e1d3b5e..ecbae297 100644 --- a/playwright/tests/inscription/mock/browser/maximizedCodeEditor.spec.ts +++ b/playwright/tests/inscription/mock/browser/maximizedCodeEditor.spec.ts @@ -5,7 +5,7 @@ import { assertCodeVisible, code } from './browser-mock-utils'; test('maximized code editor', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const task = inscriptionView.accordion('Task'); - await task.toggle(); + await task.open(); await page.getByText('Code').click(); const codeField = task.scriptArea(); diff --git a/playwright/tests/inscription/mock/browser/role.spec.ts b/playwright/tests/inscription/mock/browser/role.spec.ts index 5910b22c..626360ed 100644 --- a/playwright/tests/inscription/mock/browser/role.spec.ts +++ b/playwright/tests/inscription/mock/browser/role.spec.ts @@ -6,7 +6,7 @@ import { assertCodeHidden, browserBtn } from './browser-mock-utils'; test('browser add role', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const task = inscriptionView.accordion('Task'); - await task.toggle(); + await task.open(); await assertCodeHidden(page); await task.section('Responsible').open(); await applyRoleBrowser(page, 'Employee', 1); @@ -16,7 +16,7 @@ test('browser add role', async ({ page }) => { test('browser role open add role popover', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const task = inscriptionView.accordion('Task'); - await task.toggle(); + await task.open(); await assertCodeHidden(page); await task.section('Responsible').open(); await applyRoleBrowser(page, 'Employee', 1, undefined, true); @@ -26,7 +26,7 @@ test('browser role open add role popover', async ({ page }) => { test('browser add role doubleclick', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const task = inscriptionView.accordion('Task'); - await task.toggle(); + await task.open(); await assertCodeHidden(page); await task.section('Responsible').open(); await applyRoleBrowser(page, undefined, 1, true); diff --git a/playwright/tests/inscription/mock/browser/tableCol.spec.ts b/playwright/tests/inscription/mock/browser/tableCol.spec.ts index b46c4a8c..145078c0 100644 --- a/playwright/tests/inscription/mock/browser/tableCol.spec.ts +++ b/playwright/tests/inscription/mock/browser/tableCol.spec.ts @@ -6,7 +6,7 @@ import { browserBtn, code } from './browser-mock-utils'; test('browser add table column with all fields', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page, { type: 'Database' }); const query = inscriptionView.accordion('Query'); - await query.toggle(); + await query.open(); const allFieldsCheckbox = query.checkbox('Select all fields'); await allFieldsCheckbox.expectUnchecked(); await allFieldsCheckbox.click(); @@ -23,7 +23,7 @@ test('browser add table column with all fields', async ({ page }) => { test('browser add table column with one field', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page, { type: 'Database' }); const query = inscriptionView.accordion('Query'); - await query.toggle(); + await query.open(); const allFieldsCheckbox = query.checkbox('Select all fields'); await allFieldsCheckbox.expectUnchecked(); await page.getByRole('row').nth(1).click(); @@ -40,7 +40,7 @@ test('browser add table column with one field', async ({ page }) => { test('browser add table column doubleclick', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page, { type: 'Database' }); const query = inscriptionView.accordion('Query'); - await query.toggle(); + await query.open(); const allFieldsCheckbox = query.checkbox('Select all fields'); await allFieldsCheckbox.expectUnchecked(); await allFieldsCheckbox.click(); diff --git a/playwright/tests/inscription/mock/browser/type.spec.ts b/playwright/tests/inscription/mock/browser/type.spec.ts index a05efe44..2461f03a 100644 --- a/playwright/tests/inscription/mock/browser/type.spec.ts +++ b/playwright/tests/inscription/mock/browser/type.spec.ts @@ -6,7 +6,7 @@ import { assertCodeHidden, assertCodeVisible, browserBtn, code } from './browser test('browser init searchfilter', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const task = inscriptionView.accordion('Dialog'); - await task.toggle(); + await task.open(); const codeSection = task.section('Code'); await codeSection.open(); @@ -25,7 +25,7 @@ test('browser init searchfilter', async ({ page }) => { test('browser add type', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const task = inscriptionView.accordion('Task'); - await task.toggle(); + await task.open(); await task.section('Expiry').open(); const timeout = task.macroArea('Timeout'); @@ -40,7 +40,7 @@ test('browser add type', async ({ page }) => { test('browser add type as list', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const task = inscriptionView.accordion('Task'); - await task.toggle(); + await task.open(); await task.section('Expiry').open(); const timeout = task.macroArea('Timeout'); @@ -55,7 +55,7 @@ test('browser add type as list', async ({ page }) => { test('browser add type doubleclick', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const task = inscriptionView.accordion('Task'); - await task.toggle(); + await task.open(); await task.section('Expiry').open(); const timeout = task.macroArea('Timeout'); diff --git a/playwright/tests/inscription/mock/code-editor-input.spec.ts b/playwright/tests/inscription/mock/code-editor-input.spec.ts index ff180ddd..4f0ffd3e 100644 --- a/playwright/tests/inscription/mock/code-editor-input.spec.ts +++ b/playwright/tests/inscription/mock/code-editor-input.spec.ts @@ -7,14 +7,14 @@ test.describe('Code Editor Input', () => { test('MacroInput - no new line', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const taskPart = inscriptionView.accordion('Case'); - await taskPart.toggle(); + await taskPart.open(); await assertNoNewLine(page, taskPart.macroInput('Name')); }); test('ScriptInput - no new line', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const taskPart = inscriptionView.accordion('Task'); - await taskPart.toggle(); + await taskPart.open(); const expirySection = taskPart.section('Expiry'); await expirySection.toggle(); await assertNoNewLine(page, expirySection.scriptInput('Timeout')); @@ -44,14 +44,14 @@ test.describe('Code Editor Input', () => { async function assertAcceptScriptCellValue(page: Page, key?: string) { const inscriptionView = await InscriptionView.mock(page); const taskPart = inscriptionView.accordion('Output'); - await taskPart.toggle(); + await taskPart.open(); await taskPart.table(['label', 'expression']).row(1).column(1).fill('test'); if (key) { await page.keyboard.press(key); } - await taskPart.toggle(); - await taskPart.toggle(); + await taskPart.open(); + await taskPart.open(); await taskPart.table(['label', 'expression']).row(1).column(1).expectValue('test'); } }); diff --git a/playwright/tests/inscription/mock/dnd.spec.ts b/playwright/tests/inscription/mock/dnd.spec.ts index 3eb0783e..bbe92c33 100644 --- a/playwright/tests/inscription/mock/dnd.spec.ts +++ b/playwright/tests/inscription/mock/dnd.spec.ts @@ -5,7 +5,7 @@ test.describe('Drag and drop features', () => { test('Alternative condition reorder', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page, { type: 'Alternative' }); const conditions = inscriptionView.accordion('Condition'); - await conditions.toggle(); + await conditions.open(); const rows = page.locator('.ui-dnd-row'); await expect(rows).toHaveCount(2); diff --git a/playwright/tests/inscription/mock/mapping.spec.ts b/playwright/tests/inscription/mock/mapping.spec.ts index 720c6841..19bd4504 100644 --- a/playwright/tests/inscription/mock/mapping.spec.ts +++ b/playwright/tests/inscription/mock/mapping.spec.ts @@ -5,7 +5,7 @@ test.describe('Mappings', () => { test('DialogCall change will update mapping tree', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const callPart = inscriptionView.accordion('Dialog'); - await callPart.toggle(); + await callPart.open(); const dialogSection = callPart.section('Dialog'); await dialogSection.open(); @@ -21,22 +21,24 @@ test.describe('Mappings', () => { test('SubStart result param change will update mapping tree', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page, { type: 'CallSubStart' }); const resultPart = inscriptionView.accordion('Result'); - await resultPart.toggle(); + await resultPart.open(); - await resultPart.section('Mapping').open(); - const resultTable = resultPart.table(['text', 'label', 'expression']); + const mapping = resultPart.section('Mapping'); + await mapping.open(); + const resultTable = mapping.table(['label', 'expression']); await resultTable.expectRowCount(1); const params = resultPart.section('Result parameters'); - await params.toggle(); - const paramTable = params.table(['text', 'label', 'expression']); + await params.open(); + const paramTable = params.table(['text', 'text', 'text']); await paramTable.expectRowCount(0); await paramTable.addRow(); - await params.toggle(); + await resultTable.expectRowCount(1); + + await paramTable.row(0).fill(['test', 'String', 'test']); await resultTable.expectRowCount(2); - await params.toggle(); await paramTable.clear(); await resultTable.expectRowCount(1); }); diff --git a/playwright/tests/inscription/mock/part-state.spec.ts b/playwright/tests/inscription/mock/part-state.spec.ts index 90cd9eb6..ca918e7d 100644 --- a/playwright/tests/inscription/mock/part-state.spec.ts +++ b/playwright/tests/inscription/mock/part-state.spec.ts @@ -10,16 +10,16 @@ test.describe('Part states', () => { await casePart.expectState('configured'); await dialogPart.expectState('warning'); - await casePart.toggle(); + await casePart.open(); await casePart.macroInput('Name').clear(); - await casePart.toggle(); + await casePart.close(); await casePart.expectState('error'); await dialogPart.expectState('warning'); - await dialogPart.toggle(); + await dialogPart.open(); await dialogPart.section('Dialog').open(); await dialogPart.combobox().choose('AcceptRequest'); - await dialogPart.toggle(); + await dialogPart.close(); await casePart.expectState('error'); await dialogPart.expectState('configured'); }); diff --git a/playwright/tests/inscription/mock/readonly.spec.ts b/playwright/tests/inscription/mock/readonly.spec.ts index eecb80b3..51f97a47 100644 --- a/playwright/tests/inscription/mock/readonly.spec.ts +++ b/playwright/tests/inscription/mock/readonly.spec.ts @@ -5,14 +5,14 @@ test.describe('Readonly', () => { test('edit mode', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const name = inscriptionView.accordion('General'); - await name.toggle(); + await name.open(); await name.textArea({ label: 'Display name' }).expectEnabled(); }); test('readonly mode', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page, { readonly: true }); const name = inscriptionView.accordion('General'); - await name.toggle(); + await name.open(); await name.textArea({ label: 'Display name' }).expectDisabled(); }); }); diff --git a/playwright/tests/inscription/mock/reset.spec.ts b/playwright/tests/inscription/mock/reset.spec.ts index e52514f4..41b28a51 100644 --- a/playwright/tests/inscription/mock/reset.spec.ts +++ b/playwright/tests/inscription/mock/reset.spec.ts @@ -5,7 +5,7 @@ test.describe('Reset part', () => { test('reset button', async ({ page }) => { const inscriptionView = await InscriptionView.mock(page); const part = inscriptionView.accordion('General'); - await part.toggle(); + await part.open(); const resetBtn = part.reset(); await expect(resetBtn).not.toBeVisible(); diff --git a/playwright/tests/inscription/mock/validation.spec.ts b/playwright/tests/inscription/mock/validation.spec.ts index 8eefbbb7..5ada522c 100644 --- a/playwright/tests/inscription/mock/validation.spec.ts +++ b/playwright/tests/inscription/mock/validation.spec.ts @@ -13,7 +13,7 @@ test.describe('Validations', () => { const name = section.macroInput('Name'); const desc = section.macroArea('Description'); - await part.toggle(); + await part.open(); await section.open(); await expect(name.locator).toHaveCSS('border-color', normalColor); await expect(desc.locator).toHaveCSS('border-color', normalColor); @@ -32,7 +32,7 @@ test.describe('Validations', () => { const dialog = dialogSection.combobox(); const mapping = mappingSection.table(['text', 'expression']); - await part.toggle(); + await part.open(); await dialogSection.open(); await mappingSection.open(); await expect(dialog.locator).toHaveCSS('border-color', warningColor); diff --git a/playwright/tests/inscription/parts/end-page.ts b/playwright/tests/inscription/parts/end-page.ts index 99a2b66c..df68aea3 100644 --- a/playwright/tests/inscription/parts/end-page.ts +++ b/playwright/tests/inscription/parts/end-page.ts @@ -7,7 +7,7 @@ class EndPage extends PartObject { section: Section; endPage: TextArea; - constructor(part: Part, readonly warningIfEmpty = false) { + constructor(part: Part) { super(part); this.section = part.section('End Page'); this.endPage = this.section.textArea({}); @@ -27,14 +27,9 @@ class EndPage extends PartObject { } async assertClear() { - if (this.warningIfEmpty) { - await this.section.expectIsOpen(); - await this.endPage.expectEmpty(); - } else { - await this.section.expectIsClosed(); - } + await this.section.open(); + await this.endPage.expectEmpty(); } } export const EndPageTest = new NewPartTest('End Page', (part: Part) => new EndPage(part)); -export const EndPageTestEmptyWarning = new NewPartTest('End Page', (part: Part) => new EndPage(part, true)); diff --git a/playwright/tests/inscription/parts/error-throw.ts b/playwright/tests/inscription/parts/error-throw.ts index be8f9daa..36090f9b 100644 --- a/playwright/tests/inscription/parts/error-throw.ts +++ b/playwright/tests/inscription/parts/error-throw.ts @@ -40,7 +40,7 @@ class ErrorThrow extends PartObject { } async assertClear() { - await this.errorSection.expectIsOpen(); //warning in input + await this.errorSection.open(); await this.error.expectValue('undefined'); await this.cause.expectEmpty(); await this.codeSection.expectIsOpen(); diff --git a/playwright/tests/inscription/parts/event.ts b/playwright/tests/inscription/parts/event.ts index 8981006b..ea56ee42 100644 --- a/playwright/tests/inscription/parts/event.ts +++ b/playwright/tests/inscription/parts/event.ts @@ -64,7 +64,7 @@ class Event extends PartObject { async assertClear() { await this.javaClass.expectValue('ch.ivyteam.ivy.process.intermediateevent.AbstractProcessIntermediateEventBean'); - await this.eventSection.expectIsOpen(); //error on event input + await this.eventSection.open(); await this.eventId.expectEmpty(); await this.expirySection.expectIsClosed(); } diff --git a/playwright/tests/inscription/parts/part-tester.ts b/playwright/tests/inscription/parts/part-tester.ts index 83cad846..b42827dd 100644 --- a/playwright/tests/inscription/parts/part-tester.ts +++ b/playwright/tests/inscription/parts/part-tester.ts @@ -45,20 +45,20 @@ export class NewPartTest implements PartTest { export async function runTest(view: Inscription, test: PartTest) { const accordion = view.accordion(test.partName()); - await accordion.toggle(); + await accordion.open(); await test.fill(accordion); await view.expectMutationStateSuccess(); await view.page.reload(); - await accordion.toggle(); + await accordion.open(); await test.assertFill(accordion); await view.page.reload(); - await accordion.toggle(); + await accordion.open(); await test.clear(accordion); await view.expectMutationStateSuccess(); await view.page.reload(); - await accordion.toggle(); + await accordion.open(); await test.assertClear(accordion); } diff --git a/playwright/tests/inscription/parts/program-interface-start.ts b/playwright/tests/inscription/parts/program-interface-start.ts index 05c4cbe3..31df3ef6 100644 --- a/playwright/tests/inscription/parts/program-interface-start.ts +++ b/playwright/tests/inscription/parts/program-interface-start.ts @@ -27,6 +27,7 @@ class ProgramInterfaceStart extends PartObject { } async assertClear() { + await this.javaSection.open(); await this.javaClass.expectValue(''); } } diff --git a/playwright/tests/inscription/parts/web-service-process.ts b/playwright/tests/inscription/parts/web-service-process.ts index 45df0d96..2d50eaea 100644 --- a/playwright/tests/inscription/parts/web-service-process.ts +++ b/playwright/tests/inscription/parts/web-service-process.ts @@ -33,7 +33,7 @@ class WsProcessPart extends PartObject { } async assertClear() { - await this.section.expectIsOpen(); //error on input + await this.section.open(); await this.qualifiedName.expectEmpty(); await this.authentication.expectSelected('None/Container'); } diff --git a/playwright/tests/inscription/widgets/code-editor.spec.ts b/playwright/tests/inscription/widgets/code-editor.spec.ts index 1857a727..242926c8 100644 --- a/playwright/tests/inscription/widgets/code-editor.spec.ts +++ b/playwright/tests/inscription/widgets/code-editor.spec.ts @@ -17,7 +17,7 @@ test.describe('Code Editor', () => { test('MacroInput', async () => { const taskPart = view.accordion('Task'); - await taskPart.toggle(); + await taskPart.open(); const details = taskPart.section('Details'); await details.open(); const name = details.macroInput('Name'); @@ -27,7 +27,7 @@ test.describe('Code Editor', () => { test('MacroArea', async () => { const taskPart = view.accordion('Task'); - await taskPart.toggle(); + await taskPart.open(); const details = taskPart.section('Details'); await details.open(); const description = details.macroArea('Description'); @@ -37,7 +37,7 @@ test.describe('Code Editor', () => { test('ScriptArea', async () => { const taskPart = view.accordion('Task'); - await taskPart.toggle(); + await taskPart.open(); const codeSection = taskPart.section('Code'); await codeSection.toggle(); const code = codeSection.scriptArea(); @@ -47,7 +47,7 @@ test.describe('Code Editor', () => { test('ScriptInput', async () => { const taskPart = view.accordion('Task'); - await taskPart.toggle(); + await taskPart.open(); const expirySection = taskPart.section('Expiry'); await expirySection.toggle(); const timeout = expirySection.scriptInput('Timeout'); diff --git a/playwright/tests/inscription/widgets/web-service-auth.spec.ts b/playwright/tests/inscription/widgets/web-service-auth.spec.ts index c8000391..3952b76a 100644 --- a/playwright/tests/inscription/widgets/web-service-auth.spec.ts +++ b/playwright/tests/inscription/widgets/web-service-auth.spec.ts @@ -17,7 +17,7 @@ test.describe('Web Service Auth Link', () => { test('jump to process', async () => { const wsPart = view.accordion('Web Service'); - await wsPart.toggle(); + await wsPart.open(); await expect(wsPart.currentLocator().getByText('Web service authentication on the')).toBeVisible(); const link = wsPart.currentLocator().locator('a', { hasText: 'process' }); await expect(link).toBeVisible(); diff --git a/playwright/tests/page-objects/inscription/accordion.ts b/playwright/tests/page-objects/inscription/accordion.ts index 09ab0a31..e6429e19 100644 --- a/playwright/tests/page-objects/inscription/accordion.ts +++ b/playwright/tests/page-objects/inscription/accordion.ts @@ -12,8 +12,20 @@ export class Accordion extends Part { this.toggleButtonLocator = Accordion.toggleButtonLocator(page, label); } - async toggle() { - await this.toggleButtonLocator.click(); + async open() { + await expect(this.toggleButtonLocator).toBeVisible(); + if ((await this.toggleButtonLocator.getAttribute('data-state')) === 'closed') { + await this.toggleButtonLocator.click(); + } + await this.expectOpen(); + } + + async close() { + await expect(this.toggleButtonLocator).toBeVisible(); + if ((await this.toggleButtonLocator.getAttribute('data-state')) === 'open') { + await this.toggleButtonLocator.click(); + } + await this.expectClosed(); } private static locator(page: Page, label: string) { @@ -40,4 +52,12 @@ export class Accordion extends Part { await expect(stateLocator).toBeHidden(); } } + + async expectOpen() { + await expect(this.toggleButtonLocator).toHaveAttribute('data-state', 'open'); + } + + async expectClosed() { + await expect(this.toggleButtonLocator).toHaveAttribute('data-state', 'closed'); + } } diff --git a/playwright/tests/page-objects/inscription/table.ts b/playwright/tests/page-objects/inscription/table.ts index 8d246b2f..a217fb31 100644 --- a/playwright/tests/page-objects/inscription/table.ts +++ b/playwright/tests/page-objects/inscription/table.ts @@ -36,7 +36,7 @@ export class Table { async clear() { let totalRows = await this.rows.count(); while (totalRows > 0) { - await this.row(0).remove(); + await this.row(totalRows - 1).remove(); await expect(this.rows).toHaveCount(totalRows - 1); totalRows = await this.rows.count(); } diff --git a/playwright/tests/screenshots/editor/editor.spec.ts b/playwright/tests/screenshots/editor/editor.spec.ts index dbaf4a80..1b41a2d8 100644 --- a/playwright/tests/screenshots/editor/editor.spec.ts +++ b/playwright/tests/screenshots/editor/editor.spec.ts @@ -46,7 +46,7 @@ test('connector-process', async ({ page }) => { const inscription = await subStart.inscribe(); await expect(subStart.locator().getByRole('img').first()).toHaveAttribute('src', /.+user.png/); const start = inscription.accordion('Start'); - await start.toggle(); + await start.open(); await start.section('Mapping').close(); await start.section('Input parameters').open(); await screenshot(page, 'connector-process.png', { height: 400 }); @@ -59,7 +59,7 @@ test('connector-user', async ({ page }) => { await expect(subCall.locator().getByRole('img').first()).toHaveAttribute('src', /.+user.png/); await page.waitForTimeout(1000); // wait for user.png being rendered const process = inscription.accordion('Process'); - await process.toggle(); + await process.open(); await screenshot(page, 'connector-user.png', { height: 400 }); }); diff --git a/playwright/tests/screenshots/inscription/browsers.spec.ts b/playwright/tests/screenshots/inscription/browsers.spec.ts index 42c2ae3f..2433ba87 100644 --- a/playwright/tests/screenshots/inscription/browsers.spec.ts +++ b/playwright/tests/screenshots/inscription/browsers.spec.ts @@ -71,7 +71,7 @@ async function openSection(page: Page, pid: string, accordionName: string, secti const view = await InscriptionView.selectElement(page, pid, 'inscription-test-project'); await page.addStyleTag({ content: 'body { overflow: hidden; }' }); const accordion = view.accordion(accordionName); - await accordion.toggle(); + await accordion.open(); const section = accordion.section(sectionName); await section.open(); await page.setViewportSize({ width: 500, height: 500 }); diff --git a/playwright/tests/screenshots/inscription/screenshot-util.ts b/playwright/tests/screenshots/inscription/screenshot-util.ts index e2c168a1..8d4df3e2 100644 --- a/playwright/tests/screenshots/inscription/screenshot-util.ts +++ b/playwright/tests/screenshots/inscription/screenshot-util.ts @@ -6,7 +6,7 @@ export async function screenshotAccordion(page: Page, pid: string, accordionName const view = await InscriptionView.selectElement(page, pid, 'inscription-test-project'); await page.addStyleTag({ content: 'body { overflow: hidden; }' }); const accordion = view.accordion(accordionName); - await accordion.toggle(); + await accordion.open(); if (fullView) { const editor = view.page.locator('.editor'); await editor.evaluate(element => (element.style.height = 'unset')); @@ -15,18 +15,18 @@ export async function screenshotAccordion(page: Page, pid: string, accordionName } else { await screenshot(accordion.currentLocator(), screenshotName); } - await accordion.toggle(); + await accordion.open(); } export async function screenshotSection(page: Page, pid: string, accordionName: string, sectionName: string, screenshotName: string) { const view = await InscriptionView.selectElement(page, pid, 'inscription-test-project'); await page.addStyleTag({ content: 'body { overflow: hidden; }' }); const accordion = view.accordion(accordionName); - await accordion.toggle(); + await accordion.open(); const section = accordion.section(sectionName); await section.open(); await screenshot(section.currentLocator(), screenshotName); - await accordion.toggle(); + await accordion.open(); } export async function screenshot(page: Locator, name: string) { diff --git a/playwright/tests/screenshots/inscription/scripting.spec.ts b/playwright/tests/screenshots/inscription/scripting.spec.ts index 3ead3f69..49651ce3 100644 --- a/playwright/tests/screenshots/inscription/scripting.spec.ts +++ b/playwright/tests/screenshots/inscription/scripting.spec.ts @@ -53,7 +53,7 @@ async function openAccordion(page: Page, pid: string, accordionName): Promise { await input.expectValue(''); await start.select(); - await part.toggle(); + await part.open(); await part.reset().click(); await input.expectValue('start'); }); @@ -37,7 +37,7 @@ test('ivyscript lsp', async ({ page }) => { const processEditor = await ProcessEditor.openProcess(page); const view = await processEditor.startElement.inscribe(); const part = view.accordion('Start'); - await part.toggle(); + await part.open(); const section = part.section('Code'); await section.open(); const code = section.scriptArea(); @@ -55,9 +55,33 @@ test('process', async ({ page }) => { await view.expectClosed(); }); +test('hold accordion state', async ({ page }) => { + const processEditor = await ProcessEditor.openProcess(page); + const view = await processEditor.endElement.inscribe(); + const general = view.accordion('General'); + const task = view.accordion('Task'); + await general.expectClosed(); + await general.open(); + await general.expectOpen(); + + await processEditor.startElement.select(); + await general.expectOpen(); + await task.expectClosed(); + await task.open(); + await general.expectClosed(); + await task.expectOpen(); + + await processEditor.endElement.select(); + await general.expectClosed(); + + await processEditor.startElement.select(); + await general.expectClosed(); + await task.expectOpen(); +}); + async function changeName(view: Inscription, oldValue: string, value: string) { const part = view.accordion('General'); - await part.toggle(); + await part.open(); const section = part.section('Name / Description'); await section.open(); const input = section.textArea({ label: 'Display name' });