Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(dropdown): Add UI test cases for dropdown components #55

Open
wants to merge 1 commit into
base: dev
Choose a base branch
from
Open
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
61 changes: 61 additions & 0 deletions tests/dropdown/basic.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { expect, test } from '@playwright/test'

test.describe('dropdown 组件对齐xdesign规范', () => {
test('dropdown 默认显示-- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#basic-usage')
const demo = page.locator('#basic-usage .pc-demo')

await expect(demo).toBeInViewport()
await expect(demo).toHaveScreenshot('default.png')
})

test('dropdown 悬浮下拉-- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#basic-usage')
const wrap = page.locator('.docs-tabs-wrap')
const demo = page.locator('#basic-usage .pc-demo')
const trigger = demo.locator('.tiny-dropdown__trigger .tiny-dropdown__suffix-inner')

await trigger.hover()
await page.waitForTimeout(200)
await expect(wrap).toBeInViewport()
await expect(wrap).toHaveScreenshot('dropdown.png')
})

test('dropdown 悬浮菜单项-- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#basic-usage')
const wrap = page.locator('.docs-tabs-wrap')
const demo = page.locator('#basic-usage .pc-demo')
const trigger = demo.locator('.tiny-dropdown__trigger .tiny-dropdown__suffix-inner')
const item = page.locator('.tiny-dropdown-menu .tiny-dropdown-item')

await trigger.hover()
await page.waitForTimeout(200)
await item.nth(0).hover()

await expect(wrap).toBeInViewport()
await expect(wrap).toHaveScreenshot('item-hover.png')
})

test('dropdown 悬浮禁用菜单项-- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#basic-usage')
const wrap = page.locator('.docs-tabs-wrap')
const demo = page.locator('#basic-usage .pc-demo')
const trigger = demo.locator('.tiny-dropdown__trigger .tiny-dropdown__suffix-inner')
const item = page.locator('.tiny-dropdown-menu .tiny-dropdown-item')

await trigger.hover()
await page.waitForTimeout(200)
await item.nth(4).hover()

await expect(wrap).toBeInViewport()
await expect(wrap).toHaveScreenshot('item-disabled-hover.png')
})
})
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions tests/dropdown/border.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { expect, test } from '@playwright/test'

test.describe('dropdown 组件对齐xdesign规范', () => {
test('dropdown 显示边框圆角-- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider moving the error handler to a global setup.

The page error handler is a good practice, but it might be more efficient to set it up once for all tests in a global setup file.

You could create a global setup file (e.g., global-setup.ts) with:

import { expect, test as base } from '@playwright/test';

const test = base.extend({
  page: async ({ page }, use) => {
    page.on('pageerror', (exception) => expect(exception).toBeNull());
    await use(page);
  },
});

export { test, expect };

Then, import test and expect from this file instead of directly from '@playwright/test'.


await page.goto('dropdown#border')
const demo = page.locator('#border .pc-demo')
Comment on lines +7 to +8
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider using constants for URLs and selectors.

Hardcoding URLs and selectors can make tests fragile. Consider using constants or configuration files for these values.

You could create a constants.ts file with:

export const DROPDOWN_BORDER_URL = 'dropdown#border';
export const DROPDOWN_BORDER_SELECTOR = '#border .pc-demo';

Then use these constants in your test:

import { DROPDOWN_BORDER_URL, DROPDOWN_BORDER_SELECTOR } from './constants';

// ...

await page.goto(DROPDOWN_BORDER_URL);
const demo = page.locator(DROPDOWN_BORDER_SELECTOR);


await expect(demo).toBeInViewport()
await expect(demo).toHaveScreenshot('border-default.png')
Comment on lines +10 to +11
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider additional checks for comprehensive visual testing.

While screenshot comparison is good, consider adding checks for different viewport sizes or themes to ensure the component looks correct in various scenarios.

You could extend the test to check multiple viewports:

const viewports = [
  { width: 1920, height: 1080 },
  { width: 1366, height: 768 },
  { width: 375, height: 667 },
];

for (const viewport of viewports) {
  await page.setViewportSize(viewport);
  await expect(demo).toBeInViewport();
  await expect(demo).toHaveScreenshot(`border-default-${viewport.width}x${viewport.height}.png`);
}

Also, if your application supports different themes, consider testing each theme:

const themes = ['light', 'dark'];

for (const theme of themes) {
  await page.evaluate((t) => document.body.setAttribute('data-theme', t), theme);
  await expect(demo).toHaveScreenshot(`border-default-${theme}.png`);
}

})
})
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
23 changes: 23 additions & 0 deletions tests/dropdown/check-status.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { expect, test } from '@playwright/test'

test.describe('dropdown 组件对齐xdesign规范', () => {
test('dropdown 选中状态 -- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#check-status')
const wrap = page.locator('.docs-tabs-wrap')
const demo = page.locator('#check-status .pc-demo')
const trigger = demo.locator('.tiny-dropdown__trigger')
const item = page.locator('.tiny-dropdown-menu .tiny-dropdown-item')

await trigger.locator('.tiny-dropdown__suffix-inner').hover()
await page.waitForTimeout(300)
await item.nth(0).locator('.tiny-dropdown-item__content').click()
await page.waitForTimeout(300)
await trigger.locator('.tiny-dropdown__suffix-inner').hover()
await page.waitForTimeout(300)
Comment on lines +13 to +18
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace fixed timeouts with more reliable waiting mechanisms.

Using waitForTimeout can make tests flaky and unnecessarily slow. Instead, consider waiting for specific events or state changes.

Replace waitForTimeout calls with more reliable waiting mechanisms. For example:

await trigger.locator('.tiny-dropdown__suffix-inner').hover();
await page.waitForSelector('.tiny-dropdown-menu', { state: 'visible' });

await item.nth(0).locator('.tiny-dropdown-item__content').click();
await page.waitForSelector('.tiny-dropdown-menu', { state: 'hidden' });

await trigger.locator('.tiny-dropdown__suffix-inner').hover();
await page.waitForSelector('.tiny-dropdown-menu', { state: 'visible' });

This approach waits for the dropdown menu to become visible or hidden, which is more reliable than fixed timeouts.

await expect(wrap).toBeInViewport()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure the element is in view before screenshot.

While checking if the element is in the viewport is good, it's better to ensure it's in view before taking the screenshot.

Consider scrolling the element into view before checking and taking the screenshot:

await wrap.scrollIntoViewIfNeeded();
await expect(wrap).toBeInViewport();

This ensures the element is always in view before the screenshot is taken, leading to more consistent results.


await expect(wrap).toHaveScreenshot('check-status.png')
})
})
Comment on lines +21 to +23
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enhance screenshot comparison reliability.

While screenshot comparison is valuable, it can be sensitive to minor visual differences across environments.

Consider the following improvements:

  1. Add a tolerance parameter to allow for minor pixel differences:
await expect(wrap).toHaveScreenshot('check-status.png', { maxDiffPixels: 100 });
  1. Take screenshots for different viewport sizes to ensure responsiveness:
for (const size of [{ width: 1280, height: 720 }, { width: 1920, height: 1080 }]) {
  await page.setViewportSize(size);
  await expect(wrap).toHaveScreenshot(`check-status-${size.width}x${size.height}.png`, { maxDiffPixels: 100 });
}

These changes will make the test more robust across different environments and screen sizes.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 55 additions & 0 deletions tests/dropdown/disabled.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { expect, test } from '@playwright/test'

test.describe('dropdown 组件对齐xdesign规范', () => {
test('dropdown 禁用显示-- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#disabled')
const demo = page.locator('#disabled .pc-demo')

await expect(demo).toBeInViewport()
await expect(demo).toHaveScreenshot('disabled-default.png')
})

test('dropdown 悬浮禁用下拉菜单-- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#disabled')
const wrap = page.locator('.docs-tabs-wrap')
const demo = page.locator('#disabled .pc-demo')
const trigger = demo.locator('.tiny-dropdown__trigger')

await trigger.nth(0).locator('.tiny-dropdown__suffix-inner').hover()
await page.waitForTimeout(200)
await expect(wrap).toBeInViewport()
await expect(wrap).toHaveScreenshot('disabled-hover.png')
})

test('dropdown 悬浮禁用按钮类型下拉菜单-- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#disabled')
const wrap = page.locator('.docs-tabs-wrap')
const demo = page.locator('#disabled .pc-demo')
const trigger = demo.locator('.tiny-dropdown__trigger')

await trigger.nth(1).hover()
await page.waitForTimeout(200)
await expect(wrap).toBeInViewport()
await expect(wrap).toHaveScreenshot('button-disabled-hover.png')
})

test('dropdown 悬浮禁用菜单项-- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#disabled')
const wrap = page.locator('.docs-tabs-wrap')
const demo = page.locator('#disabled .pc-demo')
const trigger = demo.locator('.tiny-dropdown__trigger')

await trigger.nth(2).locator('.tiny-dropdown__suffix-inner').hover()
await page.waitForTimeout(200)
await expect(wrap).toBeInViewport()
await expect(wrap).toHaveScreenshot('item-disabled.png')
})
})
Comment on lines +1 to +55
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider refactoring for improved maintainability and consistency.

The test suite effectively covers various aspects of the disabled dropdown component. However, there are some opportunities for improvement:

  1. Refactor common setup code:
    Consider using a beforeEach hook to reduce repetition in navigation and error handling setup.

  2. Internationalization:
    The test descriptions are in Chinese. For better maintainability in international teams, consider using English or implementing a localization system for test descriptions.

  3. Consistent naming:
    Ensure consistent naming for screenshot files. For example, use the pattern [component]-[state]-[action].png.

  4. Helper functions:
    Consider creating helper functions for common operations like hovering and capturing screenshots to reduce code duplication and improve readability.

Here's an example of how you might refactor the common setup:

test.describe('Dropdown component alignment with xdesign specification', () => {
  test.beforeEach(async ({ page }) => {
    page.on('pageerror', (exception) => expect(exception).toBeNull())
    await page.goto('dropdown#disabled')
  })

  // ... existing test cases with reduced setup code
})

This refactoring will make the test suite more maintainable and easier to extend in the future.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 47 additions & 0 deletions tests/dropdown/events.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { expect, test } from '@playwright/test'

test.describe('dropdown 组件对齐xdesign规范', () => {
test('dropdown 按钮类型事件 -- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#events')
const body = page.locator('body')
const wrap = page.locator('.docs-tabs-wrap')
const demo = page.locator('#events .pc-demo')
const dropdown = demo.locator('.tiny-dropdown')
const trigger = dropdown.nth(0).locator('.tiny-dropdown__trigger')
const item = page.locator('body > .tiny-dropdown-menu .tiny-dropdown-item')

await dropdown.nth(0).locator('.tiny-dropdown__title-button').click()
await page.waitForTimeout(100)
await trigger.hover()
await page.waitForTimeout(100)
await item.nth(0).click()
await page.waitForTimeout(100)
await dropdown.nth(0).locator('.tiny-dropdown__title-button').hover()
await page.waitForTimeout(100)

await expect(body).toBeInViewport()
await expect(body).toHaveScreenshot('button-events.png')
})
Comment on lines +4 to +26
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider improving test stability and maintainability.

The test case covers various interactions, which is great for UI testing. However, there are a few areas that could be improved:

  1. Replace page.waitForTimeout() with more stable waiting mechanisms like waitForSelector() or waitForLoadState(). This will make the tests less prone to timing issues.

  2. Consider extracting repeated selectors and actions into reusable functions to improve maintainability.

  3. Be aware that screenshot comparisons might be sensitive to minor UI changes. Consider using more specific element-level comparisons where possible.

Here's an example of how you could refactor part of the test:

async function waitForDropdownInteraction(page) {
  await page.waitForSelector('.tiny-dropdown-menu', { state: 'visible' });
}

// In the test
await dropdown.nth(0).locator('.tiny-dropdown__title-button').click();
await waitForDropdownInteraction(page);
await trigger.hover();
await waitForDropdownInteraction(page);

Would you like me to provide a full refactoring of this test case or create a GitHub issue to track these improvements?


test('dropdown 默认类型事件 -- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#events')
const body = page.locator('body')
const wrap = page.locator('.docs-tabs-wrap')
const demo = page.locator('#events .pc-demo')
const dropdown = demo.locator('.tiny-dropdown')
const trigger = dropdown.nth(1).locator('.tiny-dropdown__trigger')
const item = page.locator('body > .tiny-dropdown-menu .tiny-dropdown-item')

await trigger.locator('.tiny-dropdown__suffix-inner').hover()
await page.waitForTimeout(100)
await item.nth(0).click()
await page.waitForTimeout(100)

await expect(body).toBeInViewport()
await expect(body).toHaveScreenshot('default-events.png')
})
Comment on lines +28 to +46
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tip

Codebase Verification

Code duplication confirmed; refactoring recommended.

  • Multiple dropdown test files exhibit similar patterns, indicating code duplication.
  • Refactoring using shared setup functions or fixtures will enhance maintainability and reduce redundancy.
Analysis chain

Refactor to reduce duplication and improve test stability.

This test case is well-structured but has similar improvement opportunities as the first test:

  1. Replace page.waitForTimeout() with more stable waiting mechanisms.
  2. Consider extracting common setup code and selectors into shared functions or fixtures.

Additionally, there's significant duplication between this test and the previous one. Consider refactoring to reduce this duplication.

Here's an example of how you could reduce duplication:

async function setupDropdownTest(page) {
  await page.goto('dropdown#events');
  const body = page.locator('body');
  const demo = page.locator('#events .pc-demo');
  const dropdown = demo.locator('.tiny-dropdown');
  return { body, dropdown };
}

// In each test
const { body, dropdown } = await setupDropdownTest(page);
// ... rest of the test-specific code

This refactoring will make the tests more maintainable and easier to update in the future.

To ensure we're not missing any other dropdown tests that could benefit from this refactoring, let's check for similar patterns:

This will help us identify if there are other files where we could apply similar improvements.

Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other dropdown test files
fd -e ts -e js 'dropdown.*spec' tests

# Search for similar patterns in other test files
rg -t ts -t js 'test\(.*dropdown.*,.*async.*\{.*page.*\}.*\).*\{' tests

Length of output: 3815

})
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 21 additions & 0 deletions tests/dropdown/hide-on-click.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { expect, test } from '@playwright/test'

test.describe('dropdown 组件对齐xdesign规范', () => {
test('dropdown 显示箭头 -- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#hide-on-click')
const wrap = page.locator('.docs-tabs-wrap')
const demo = page.locator('#hide-on-click .pc-demo')
const trigger = demo.locator('.tiny-dropdown__trigger')
const item = page.locator('.tiny-dropdown-menu .tiny-dropdown-item')

// 选中不收起弹框
await trigger.locator('.tiny-dropdown__suffix-inner').hover()
await page.waitForTimeout(300)
await item.nth(0).locator('.tiny-dropdown-item__content').click()
await page.waitForTimeout(300)
await expect(wrap).toBeInViewport()
await expect(wrap).toHaveScreenshot('click-visible.png')
})
Comment on lines +4 to +20
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve test stability and coverage

  1. Replace page.waitForTimeout() with more stable waiting mechanisms:
    Instead of using fixed timeouts, consider using Playwright's built-in waiting mechanisms like waitForSelector() or waitForLoadState(). This will make your tests more reliable and less prone to timing issues.

  2. Add assertions for the "hide on click" behavior:
    The test file is named "hide-on-click", but the current test doesn't verify this behavior. Consider adding assertions to check if the dropdown hides when clicked outside or on a menu item.

  3. Use more specific assertions:
    While screenshot comparisons can be useful, they can also be brittle and lead to false negatives due to minor pixel differences. Consider adding more specific assertions to check the visibility and state of dropdown elements.

Here's an example of how you could improve the test:

test('dropdown hides on click and shows arrow -- UI and behavior', async ({ page }) => {
  page.on('pageerror', (exception) => expect(exception).toBeNull())

  await page.goto('dropdown#hide-on-click')
  const demo = page.locator('#hide-on-click .pc-demo')
  const trigger = demo.locator('.tiny-dropdown__trigger')
  const dropdownMenu = page.locator('.tiny-dropdown-menu')
  const item = dropdownMenu.locator('.tiny-dropdown-item').first()

  // Open dropdown
  await trigger.click()
  await expect(dropdownMenu).toBeVisible()

  // Verify arrow visibility
  const arrow = trigger.locator('.tiny-dropdown__suffix-inner')
  await expect(arrow).toBeVisible()

  // Click item and verify dropdown hides
  await item.click()
  await expect(dropdownMenu).not.toBeVisible()

  // Reopen dropdown
  await trigger.click()
  await expect(dropdownMenu).toBeVisible()

  // Click outside and verify dropdown hides
  await page.mouse.click(0, 0)
  await expect(dropdownMenu).not.toBeVisible()

  // Take screenshot for additional visual verification
  await expect(page).toHaveScreenshot('dropdown-closed.png')
}

This improved version:

  • Uses waitFor... methods implicitly through the expect assertions.
  • Verifies the "hide on click" behavior for both clicking an item and clicking outside.
  • Includes specific assertions for element visibility.
  • Still includes a screenshot comparison for additional visual verification.

})
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
31 changes: 31 additions & 0 deletions tests/dropdown/inherit-width.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { expect, test } from '@playwright/test'

test.describe('dropdown 组件对齐xdesign规范', () => {
test('dropdown 默认由内容撑开', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#inherit-width')
const wrap = page.locator('.docs-tabs-wrap')
const demo = page.locator('#inherit-width .pc-demo')
const trigger = demo.locator('.tiny-dropdown__trigger')

await trigger.nth(0).hover()
await page.waitForTimeout(300)
await expect(wrap).toBeInViewport()
await expect(wrap).toHaveScreenshot('default.png')
})
Comment on lines +4 to +16
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improve test reliability and internationalization.

  1. Consider translating the test description to English for better collaboration:

    test('Dropdown expands to fit content by default', async ({ page }) => {
  2. Replace page.waitForTimeout(300) with a more reliable wait condition:

    await page.waitForSelector('.tiny-dropdown__content', { state: 'visible' })

    This change will make the test more robust and less prone to timing issues.

  3. The overall structure and error handling are good practices. Keep them as they are.


test('dropdown 继承宽度 -- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#inherit-width')
const wrap = page.locator('.docs-tabs-wrap')
const demo = page.locator('#inherit-width .pc-demo')
const trigger = demo.locator('.tiny-dropdown__trigger')

await trigger.nth(1).hover()
await page.waitForTimeout(300)
await expect(wrap).toBeInViewport()
await expect(wrap).toHaveScreenshot('inherit-width.png')
})
Comment on lines +18 to +30
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refactor for DRY principle and improve test reliability.

  1. Translate the test description to English:

    test('Dropdown inherits width -- UI screenshot', async ({ page }) => {
  2. Replace page.waitForTimeout(300) with a more reliable wait condition, as suggested in the previous comment.

  3. To reduce code duplication, consider refactoring common setup code into a separate function:

async function setupDropdownTest(page, index) {
  page.on('pageerror', (exception) => expect(exception).toBeNull())
  await page.goto('dropdown#inherit-width')
  const wrap = page.locator('.docs-tabs-wrap')
  const demo = page.locator('#inherit-width .pc-demo')
  const trigger = demo.locator('.tiny-dropdown__trigger')
  await trigger.nth(index).hover()
  await page.waitForSelector('.tiny-dropdown__content', { state: 'visible' })
  return { wrap, demo, trigger }
}

test('Dropdown expands to fit content by default', async ({ page }) => {
  const { wrap } = await setupDropdownTest(page, 0)
  await expect(wrap).toBeInViewport()
  await expect(wrap).toHaveScreenshot('default.png')
})

test('Dropdown inherits width -- UI screenshot', async ({ page }) => {
  const { wrap } = await setupDropdownTest(page, 1)
  await expect(wrap).toBeInViewport()
  await expect(wrap).toHaveScreenshot('inherit-width.png')
})

This refactoring will make the tests more maintainable and reduce duplication.

})
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 35 additions & 0 deletions tests/dropdown/lazy-show-popper.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { expect, test } from '@playwright/test'

test.describe('dropdown 组件对齐xdesign规范', () => {
test('dropdown 默认不懒加载 -- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#lazy-show-popper')
const wrap = page.locator('.docs-tabs-wrap')
const demo = page.locator('#lazy-show-popper .pc-demo')
const dropdown = demo.locator('.tiny-dropdown')
const trigger = dropdown.nth(0).locator('.tiny-dropdown__trigger')

await dropdown.nth(0).locator('.tiny-dropdown__suffix-inner').hover()
await page.waitForTimeout(100)

await expect(wrap).toBeInViewport()
await expect(wrap).toHaveScreenshot('default.png')
})

test('dropdown 懒加载 -- UI截图', async ({ page }) => {
page.on('pageerror', (exception) => expect(exception).toBeNull())

await page.goto('dropdown#lazy-show-popper')
const wrap = page.locator('.docs-tabs-wrap')
const demo = page.locator('#lazy-show-popper .pc-demo')
const dropdown = demo.locator('.tiny-dropdown')
const trigger = dropdown.nth(1).locator('.tiny-dropdown__trigger')

await trigger.locator('.tiny-dropdown__suffix-inner').hover()
await page.waitForTimeout(100)

await expect(wrap).toBeInViewport()
await expect(wrap).toHaveScreenshot('lazy.png')
})
Comment on lines +20 to +34
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enhance lazy loading test and improve screenshot naming.

The test structure for the lazy loading case is consistent with the first test, which is good. However, there are a couple of areas for improvement:

  1. The test doesn't explicitly verify the lazy loading behavior. Consider adding assertions to check if the dropdown content is initially not in the DOM and only appears after hovering.

  2. The screenshot naming could be more descriptive.

Here's a suggested improvement:

test('dropdown lazy loading -- UI screenshot', async ({ page }) => {
  // ... (existing setup code)

  // Check that dropdown content is not initially in the DOM
  await expect(dropdown.nth(1).locator('.tiny-dropdown__content')).not.toBeVisible();

  await trigger.locator('.tiny-dropdown__suffix-inner').hover();
  await page.waitForTimeout(100);

  // Check that dropdown content is now visible
  await expect(dropdown.nth(1).locator('.tiny-dropdown__content')).toBeVisible();

  await expect(wrap).toBeInViewport();
  await expect(wrap).toHaveScreenshot('dropdown_lazy_loaded.png');
});

This change adds explicit checks for the lazy loading behavior and uses a more descriptive screenshot name.

})
Comment on lines +1 to +35
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enhance test coverage and error handling.

While the current tests cover the basic scenarios for default and lazy loading, there are opportunities to improve the overall test coverage and error handling:

  1. Add test cases for interacting with dropdown items, such as selecting an item and verifying the result.
  2. Include tests for different states of the dropdown (disabled, loading, etc.).
  3. Improve error handling by checking for specific errors rather than expecting all errors to be null.

Here's an example of how you might add a test for item selection:

test('dropdown item selection', async ({ page }) => {
  // ... (setup code)

  await trigger.click();
  await dropdown.locator('.tiny-dropdown__item').nth(1).click();

  // Assert that the selected item is reflected in the trigger
  await expect(trigger).toHaveText('Selected Item');
});

For error handling, consider using a more specific approach:

page.on('pageerror', (error) => {
  if (error.message.includes('Expected error message')) {
    console.warn('Expected error occurred:', error.message);
  } else {
    throw error;
  }
});

This allows you to handle expected errors while still catching unexpected ones.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading