From f7c8fd5fd699b821d18d6935db87bd8dd6f53d93 Mon Sep 17 00:00:00 2001 From: Nikita Barsukov Date: Mon, 11 Nov 2024 12:17:04 +0300 Subject: [PATCH] fix(kit): `TuiTabsWithMore` should share `TuiActiveZone` for nested dropdowns inside `more`-section (#9714) --- .../tests/kit/tabs/tabs.pw.spec.ts | 123 +++++++++++++----- .../utils/page-objects/index.ts | 1 + .../utils/page-objects/tabs.ts | 16 +++ .../components/tabs/examples/3/index.html | 2 +- .../components/tabs/examples/3/index.ts | 1 - .../tabs/tabs-with-more.template.html | 7 +- 6 files changed, 108 insertions(+), 42 deletions(-) create mode 100644 projects/demo-playwright/utils/page-objects/tabs.ts diff --git a/projects/demo-playwright/tests/kit/tabs/tabs.pw.spec.ts b/projects/demo-playwright/tests/kit/tabs/tabs.pw.spec.ts index 3a8b329d36c4..441be21244a5 100644 --- a/projects/demo-playwright/tests/kit/tabs/tabs.pw.spec.ts +++ b/projects/demo-playwright/tests/kit/tabs/tabs.pw.spec.ts @@ -1,68 +1,119 @@ import {DemoRoute} from '@demo/routes'; -import {TuiDocumentationPagePO, tuiGoto} from '@demo-playwright/utils'; +import {TuiDocumentationPagePO, tuiGoto, TuiTabsPO} from '@demo-playwright/utils'; +import type {Locator} from '@playwright/test'; import {expect, test} from '@playwright/test'; -test.describe('Tabs', () => { - test('no extra margin after the last tab', async ({page}) => { - await page.setViewportSize({width: 1500, height: 500}); - await tuiGoto(page, DemoRoute.Tabs); +const {describe, beforeEach} = test; - const example = new TuiDocumentationPagePO(page).getExample('#complex'); +describe('Tabs', () => { + describe('Examples', () => { + beforeEach(async ({page}) => { + await tuiGoto(page, DemoRoute.Tabs); + }); + + describe('complex', () => { + let example!: Locator; + let tabsPO!: TuiTabsPO; + + beforeEach(async ({page}) => { + example = new TuiDocumentationPagePO(page).getExample('#complex'); + tabsPO = new TuiTabsPO(example.locator('tui-tabs-with-more')); + + await example.scrollIntoViewIfNeeded(); + }); - await example.scrollIntoViewIfNeeded(); + test('no extra margin after the last tab', async ({page}) => { + await page.setViewportSize({width: 1500, height: 500}); - await expect(example).toHaveScreenshot('01-tabs-1.png'); + await expect(example).toHaveScreenshot('01-tabs-1.png'); - await page.locator('button:has-text("Collaborators")').click(); + await page.locator('button:has-text("Collaborators")').click(); - await expect(example).toHaveScreenshot('01-tabs-2.png'); + await expect(example).toHaveScreenshot('01-tabs-2.png'); - await page.locator('button:has-text("Neil Innes")').click(); + await page.locator('button:has-text("Neil Innes")').click(); - await expect(example).toHaveScreenshot('01-tabs-3.png'); + await expect(example).toHaveScreenshot('01-tabs-3.png'); - await page.setViewportSize({width: 560, height: 500}); + await page.setViewportSize({width: 560, height: 500}); - await expect(example).toHaveScreenshot('01-tabs-4.png'); + await expect(example).toHaveScreenshot('01-tabs-4.png'); - await example.locator('tui-tabs-with-more .t-more').click(); + await example.locator('tui-tabs-with-more .t-more').click(); - await expect(example).toHaveScreenshot('01-tabs-5.png'); + await expect(example).toHaveScreenshot('01-tabs-5.png'); - await page.locator('button:has-text("John Cleese")').nth(1).focus(); - await page.keyboard.down('Enter'); + await page.locator('button:has-text("John Cleese")').nth(1).focus(); + await page.keyboard.down('Enter'); - await expect(example).toHaveScreenshot('01-tabs-6.png'); + await expect(example).toHaveScreenshot('01-tabs-6.png'); + + await example.locator('tui-tabs-with-more .t-more').click(); + await page.locator('button:has-text("Collaborators")').nth(1).focus(); + await page.keyboard.down('Enter'); + + await expect(example).toHaveScreenshot('01-tabs-7.png'); + + await page.locator('button:has-text("Neil Innes")').nth(0).focus(); + await page.keyboard.down('Enter'); + + await expect(example).toHaveScreenshot('01-tabs-8.png'); + }); - await example.locator('tui-tabs-with-more .t-more').click(); - await page.locator('button:has-text("Collaborators")').nth(1).focus(); - await page.keyboard.down('Enter'); + test('shows only a single dropdown for the nested item (with [tuiDropdown]) inside more section', async ({ + page, + }) => { + await page.setViewportSize({width: 600, height: 700}); - await expect(example).toHaveScreenshot('01-tabs-7.png'); + await expect(tabsPO.more).toBeVisible(); - await page.locator('button:has-text("Neil Innes")').nth(0).focus(); - await page.keyboard.down('Enter'); + await tabsPO.more.click(); + await tabsPO.getMoreOption('Eric Idle').click(); + await tabsPO.more.click(); + await tabsPO.getMoreOption('Collaborators').click(); - await expect(example).toHaveScreenshot('01-tabs-8.png'); + await expect(page.locator('tui-dropdown')).toHaveCount(2); + await expect(page).toHaveScreenshot( + 'tabs-dropdown-inside-more-dropdown.png', + ); + + await page + .locator('tui-dropdown [tuiOption]', { + hasText: 'Carol Cleveland', + }) + .hover(); + + await expect(page).toHaveScreenshot( + 'tabs-dropdown-inside-more-dropdown-hover-item.png', + ); + }); + }); }); - test.describe('API', () => { + describe('API', () => { + let example!: Locator; + + beforeEach(({page}) => { + example = new TuiDocumentationPagePO(page).apiPageExample; + }); + [-2, -1, 0, 1, 2, 3, 4, 5, 100, 1000].forEach((index) => { test(`clamp active activeItemIndex=${index}`, async ({page}) => { await tuiGoto(page, `/navigation/tabs/API?activeItemIndex=${index}`); - await expect( - new TuiDocumentationPagePO(page).apiPageExample, - ).toHaveScreenshot(`02-tabs-activeItemIndex-${index}.png`); + await expect(example).toHaveScreenshot( + `02-tabs-activeItemIndex-${index}.png`, + ); }); }); - }); - test('Single button', async ({page}) => { - await tuiGoto(page, `${DemoRoute.Tabs}/API?activeItemIndex=2&sandboxWidth=133`); + test('Single button', async ({page}) => { + await tuiGoto( + page, + `${DemoRoute.Tabs}/API?activeItemIndex=2&sandboxWidth=133`, + ); - await expect(new TuiDocumentationPagePO(page).apiPageExample).toHaveScreenshot( - '03-tabs-single-item-01.png', - ); + await expect(example).toHaveScreenshot('03-tabs-single-item-01.png'); + }); }); }); diff --git a/projects/demo-playwright/utils/page-objects/index.ts b/projects/demo-playwright/utils/page-objects/index.ts index e3808d3ce9eb..ef2a28c63cfe 100644 --- a/projects/demo-playwright/utils/page-objects/index.ts +++ b/projects/demo-playwright/utils/page-objects/index.ts @@ -22,4 +22,5 @@ export * from './range.po'; export * from './select.po'; export * from './slider.po'; export * from './table-pagination-page.po'; +export * from './tabs'; export * from './textfield-with-data-list.po'; diff --git a/projects/demo-playwright/utils/page-objects/tabs.ts b/projects/demo-playwright/utils/page-objects/tabs.ts new file mode 100644 index 000000000000..81736f046919 --- /dev/null +++ b/projects/demo-playwright/utils/page-objects/tabs.ts @@ -0,0 +1,16 @@ +import type {Locator} from '@playwright/test'; + +export class TuiTabsPO { + public readonly more = this.host.locator('> button.t-more'); + public readonly moreDropdown = this.host.page().locator('tui-dropdown'); + + constructor(private readonly host: Locator) {} + + public getMoreOption(indexOrText: number | string): Locator { + if (typeof indexOrText === 'number') { + this.moreDropdown.locator('button[tuiTab]').locator(`nth=${indexOrText}`); + } + + return this.moreDropdown.locator(`button[tuiTab]:has-text("${indexOrText}")`); + } +} diff --git a/projects/demo/src/modules/components/tabs/examples/3/index.html b/projects/demo/src/modules/components/tabs/examples/3/index.html index 9033e09b71b2..2521fe306e7e 100644 --- a/projects/demo/src/modules/components/tabs/examples/3/index.html +++ b/projects/demo/src/modules/components/tabs/examples/3/index.html @@ -24,10 +24,10 @@

Monty Python