Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,42 @@ on:
required: false

jobs:
playwright:
name: Playwright
runs-on: ubuntu-latest
strategy:
matrix:
react: ['18', '19']
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
with:
node-version-file: '.nvmrc'
cache: 'yarn'

- name: Install
run: yarn install --immutable

- name: Install React 18
if: ${{ matrix.react == '18' }}
run: |
yarn add "@types/react@18" "@types/react-dom@18" --dev
yarn add react@18 react-dom@18

- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with:
name: build-${{ matrix.react }}
path: packages

- name: Install Playwright browsers
run: npx playwright install --with-deps chromium

- name: Run Playwright tests
run: yarn test:pw playwright/test/ packages/main/src/components/SelectDialog/test/ --project chromium

cypress:
name: Cypress
runs-on: ubuntu-latest
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,10 @@ debug-storybook.log
.vscode
.cursor/rules/nx-rules.mdc
.github/instructions/nx.instructions.md

# Playwright
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/playwright/.auth/
2 changes: 1 addition & 1 deletion eslint.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ const config = tseslint.config(
},
},
{
files: ['**/*.cy.ts', '**/*.cy.tsx'],
files: ['**/*.cy.ts', '**/*.cy.tsx', '**/*.spec.ts', '**/*.spec.tsx', 'playwright/**/*'],

plugins: {
'no-only-tests': noOnlyTests,
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
"test:prepare": "rimraf temp && lerna run build",
"test:open": "CYPRESS_COVERAGE=false cypress open --component --browser chrome",
"test": "yarn test:prepare && cypress run --component --browser chrome --spec packages",
"test:pw": "playwright test -c playwright-ct.config.ts",
"test:pw:open": "playwright test -c playwright-ct.config.ts --ui",
"clean": "tsc --build --clean && tsc --build tsconfig.build.json --clean && rimraf temp .out && lerna run clean",
"clean:remove-modules": "yarn clean && rimraf node_modules",
"prettier:all": "prettier --write --config ./prettier.config.js \"**/*\"",
Expand Down Expand Up @@ -60,6 +62,8 @@
"@cypress/code-coverage": "4.0.0",
"@eslint/compat": "2.0.2",
"@eslint/js": "9.39.3",
"@playwright/experimental-ct-react": "1.58.2",
"@playwright/test": "1.58.2",
"@semantic-release/github": "12.0.6",
"@testing-library/cypress": "10.1.0",
"@types/jscodeshift": "17.3.0",
Expand Down
202 changes: 202 additions & 0 deletions packages/main/src/components/SelectDialog/test/SelectDialog.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
import { expect } from '@playwright/experimental-ct-react';
import { test } from '../../../../../../playwright/ui5-fixtures.js';
import {
SelectDialogBasicTestComp,
SelectDialogHeaderTestComp,
SelectDialogSelectionWithToggleTestComp,
SelectDialogSearchTestComp,
SelectDialogConfirmButtonTextTestComp,
SelectDialogNumberOfSelectedItemsTestComp,
SelectDialogCancelWithToggleTestComp,
SelectDialogConfirmButtonPropsTestComp,
} from './SelectDialogTestComponents.js';

test.describe('SelectDialog', () => {
test('Basic', async ({ mount, page }) => {
await mount(<SelectDialogBasicTestComp />);
await expect(page.locator('[ui5-dialog]')).toBeVisible();
await expect(page.locator('[ui5-input][placeholder="Search"]')).toBeVisible();
await page.getByText('Cancel').click();
await expect(page.locator('[ui5-dialog]')).not.toBeVisible();
});

test('with headerText', async ({ mount, page, ui5wc }) => {
await mount(<SelectDialogHeaderTestComp />);
const header = page.getByText('Select Dialog');
await expect(header).toHaveCSS('grid-column-start', 'titleStart');
await expect(header).toHaveCSS('grid-column-end', 'titleCenter');
await expect(header).toHaveAttribute('level', 'H1');

await ui5wc.closePopupWithEsc();
await page.getByTestId('toggle-center').click();
await page.getByTestId('open-btn').click();
await expect(header).toHaveCSS('grid-area', 'titleCenter');
await expect(header).toHaveAttribute('level', 'H1');

await ui5wc.closePopupWithEsc();
await page.getByTestId('set-h2').click();
await page.getByTestId('open-btn').click();
await expect(header).toHaveAttribute('level', 'H2');
});

test('selection', async ({ mount, page, ui5wc }) => {
await mount(<SelectDialogSelectionWithToggleTestComp />);
const list = page.locator('[ui5-list]');

// Single mode - no rememberSelections
await expect(page.locator('[ui5-dialog]')).toBeVisible();
await list.getByText('Product1').click();
await expect(page.locator('[ui5-dialog]')).not.toBeVisible();
await expect(page.getByTestId('selected-items')).toHaveText('Last Selected Item: Product1');
await page.getByTestId('open-btn').click();
const listItems = page.locator('[ui5-li]');
for (let i = 0; i < 5; i++) {
await expect(listItems.nth(i)).not.toHaveAttribute('selected');
}
await ui5wc.closePopupWithEsc();

// Single mode - with rememberSelections
await page.getByTestId('toggle-remember').click();
await page.getByTestId('open-btn').click();
await list.getByText('Product1').click();
await expect(page.locator('[ui5-dialog]')).not.toBeVisible();
await expect(page.getByTestId('selected-items')).toHaveText('Last Selected Item: Product1');
await page.getByTestId('open-btn').click();
await expect(list.locator('[ui5-li][text="Product1"]')).toHaveAttribute('selected');
for (const text of ['Product0', 'Product2', 'Product3', 'Product4']) {
await expect(list.locator(`[ui5-li][text="${text}"]`)).not.toHaveAttribute('selected');
}
await ui5wc.closePopupWithEsc();

await expect(page.getByTestId('close-count')).toHaveText('4');
await expect(page.getByTestId('confirm-count')).toHaveText('2');
await expect(page.getByTestId('change-count')).toHaveText('2');

// Close via Cancel and Escape
await page.getByTestId('reset').click();
await page.getByTestId('open-btn').click();
await page.getByText('Cancel').click();
await expect(page.locator('[ui5-dialog]')).not.toBeVisible();
await expect(page.getByTestId('close-count')).toHaveText('5');

await page.getByTestId('open-btn').click();
await expect(page.locator('[ui5-dialog]')).toBeVisible();
await ui5wc.closePopupWithEsc();

await expect(page.getByTestId('close-count')).toHaveText('6');
await expect(page.getByTestId('confirm-count')).toHaveText('2');
await expect(page.getByTestId('change-count')).toHaveText('2');

// Multiple mode - no rememberSelections
await page.getByTestId('reset').click();
await page.getByTestId('set-multiple').click();
await page.getByTestId('open-btn').click();
await expect(page.locator('[ui5-dialog]')).toBeVisible();
await list.getByText('Product1').click();
await list.getByText('Product3').click();
await page.getByRole('button', { name: 'Select' }).click();
await expect(page.getByTestId('selected-items')).toHaveText('Last Selected Item: Product1Product3');

await page.getByTestId('open-btn').click();
for (let i = 0; i < 5; i++) {
await expect(listItems.nth(i)).not.toHaveAttribute('selected');
}

// Multiple mode - with rememberSelections
await page.getByText('Cancel').click();
await page.getByTestId('toggle-remember').click();
await page.getByTestId('open-btn').click();
await list.getByText('Product1').click();
await list.getByText('Product3').click();
await expect(page.locator('[ui5-dialog]')).toBeVisible();
await page.getByRole('button', { name: 'Select' }).click();
await expect(page.getByTestId('selected-items')).toHaveText('Last Selected Item: Product1Product3');
await page.getByTestId('open-btn').click();
await expect(list.locator('[ui5-li][text="Product1"]')).toHaveAttribute('selected');
await expect(list.locator('[ui5-li][text="Product3"]')).toHaveAttribute('selected');
for (const text of ['Product0', 'Product2', 'Product4']) {
await expect(list.locator(`[ui5-li][text="${text}"]`)).not.toHaveAttribute('selected');
}
await ui5wc.closePopupWithEsc();

await expect(page.getByTestId('close-count')).toHaveText('10');
await expect(page.getByTestId('confirm-count')).toHaveText('4');
await expect(page.getByTestId('change-count')).toHaveText('6');
});

test('Search', async ({ mount, page, ui5wc }) => {
await mount(<SelectDialogSearchTestComp />);
await expect(page.locator('[accessible-name="Reset"][ui5-icon]')).not.toBeVisible();

const input = page.locator('[ui5-input]');
await ui5wc.typeIntoInput(input, 'Test');
await expect(page.getByTestId('input-val')).toHaveText('input: Test');
await expect(page.getByTestId('search-count')).toHaveText('0');
await expect(page.getByTestId('input-count')).toHaveText('1');
await expect(page.getByTestId('reset-count')).toHaveText('0');

await input.locator('input').press('Enter');
await expect(page.getByTestId('search-val')).toHaveText('search: Test');
await expect(page.getByTestId('search-count')).toHaveText('1');
await expect(page.getByTestId('input-count')).toHaveText('1');
await expect(page.getByTestId('reset-count')).toHaveText('0');

await page.locator('[accessible-name="Search"][ui5-icon]').click();
await expect(page.getByTestId('search-count')).toHaveText('2');
await expect(page.getByTestId('input-count')).toHaveText('1');
await expect(page.getByTestId('reset-count')).toHaveText('0');

await page.locator('[part="clear-icon"][ui5-icon]').click();
await expect(page.getByTestId('search-count')).toHaveText('2');
// clearing the input via clear button fires input event as well
await expect(page.getByTestId('input-count')).toHaveText('2');
await expect(page.getByTestId('reset-count')).toHaveText('1');
await expect(page.locator('[accessible-name="Reset"][ui5-icon]')).not.toBeVisible();
});

test('confirmButtonText', async ({ mount, page }) => {
await mount(<SelectDialogConfirmButtonTextTestComp />);
await expect(page.locator('[ui5-dialog]')).toBeVisible();
await page.getByText('Exterminate').click();
await expect(page.getByTestId('confirm-count')).toHaveText('1');
await expect(page.locator('[ui5-dialog]')).not.toBeVisible();
});

test('numberOfSelectedItems', async ({ mount, page }) => {
await mount(<SelectDialogNumberOfSelectedItemsTestComp />);
await expect(page.getByText('Selected: 1337')).toBeVisible();
});

test('onCancel', async ({ mount, page, ui5wc }) => {
await mount(<SelectDialogCancelWithToggleTestComp />);

// Single mode
await page.getByTestId('open-btn').click();
await page.getByText('Cancel').click();
await expect(page.getByTestId('cancel-count')).toHaveText('1');

await page.getByTestId('open-btn').click();
await expect(page.locator('[ui5-dialog]')).toBeVisible();
await ui5wc.closePopupWithEsc();
await expect(page.getByTestId('cancel-count')).toHaveText('2');

// Multiple mode
await page.getByTestId('set-multiple').click();
await page.getByTestId('open-btn').click();
await page.getByText('Cancel').click();
await expect(page.getByTestId('cancel-count')).toHaveText('3');

await page.getByTestId('open-btn').click();
await expect(page.locator('[ui5-dialog]')).toBeVisible();
await ui5wc.closePopupWithEsc();
await expect(page.getByTestId('cancel-count')).toHaveText('4');
});

test('confirmButtonProps', async ({ mount, page }) => {
await mount(<SelectDialogConfirmButtonPropsTestComp />);
const btn = page.getByTestId('confirmBtn');
await expect(btn).toBeVisible();
await expect(btn).toHaveAttribute('disabled');
await expect(btn).toHaveAttribute('design', 'Emphasized');
});
});
Loading
Loading