iT邦幫忙

2024 iThome 鐵人賽

DAY 27
0

第一步老樣子就是來新增測試檔案。◝( •ω• )◟

e2e\components\slider-stubborn.spec.ts

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

test.beforeEach(async ({ page }) => {
  await page.goto('http://localhost:5173/components/slider-stubborn/');
});

test('頁面必須存在(title 不可出現 404)', async ({ page }) => {
  const title = await page.title();
  expect(title).not.toContain('404');
});

元件加上 title,方便定位。

docs\components\slider-stubborn\index.md

...

<basic-usage title="basic-usage" />

...

<custom-prop title="custom-prop"/>

...

測試:基本用法

disabled 為 true 時,數值不會變動。

e2e\components\slider-stubborn.spec.ts

...

test.describe('基本用法', () => {
  test('必須有文字為「基本用法」的 h3', async ({ page }) => {
    const h3Els = page.locator('h3');
    const target = h3Els.getByText('基本用法');
    await expect(target).toBeVisible();
  });

  test('必須存在 checkbox 與 slider', async ({ page }) => {
    const section = page.getByTitle('basic-usage');

    const checkbox = section.getByRole('checkbox');
    await expect(checkbox).toBeVisible();

    const slider = section.getByRole('slider');
    await expect(slider).toBeVisible();
  });

  test('左右拉動時,aria-valuenow 數值必須發生變化', async ({ page }) => {
    const section = page.getByTitle('basic-usage');
    const slider = section.getByRole('slider');

    const sliderBoundingBox = await slider.boundingBox();

    // 拉到最左邊
    await slider.click({
      position: {
        x: 0,
        y: 0
      }
    });
    const value01 = await slider.getAttribute('aria-valuenow');

    // 拉到 2/3 的位置
    await slider.click({
      position: {
        x: (sliderBoundingBox?.width ?? 10) / 3 * 2,
        y: 0
      }
    });
    const value02 = await slider.getAttribute('aria-valuenow');

    expect(Number(value02)).toBeGreaterThan(Number(value01));
  });

  test('disabled 後,數值不會變動', async ({ page }) => {
    const section = page.getByTitle('basic-usage');
    const checkbox = section.getByRole('checkbox');
    const slider = section.getByRole('slider');

    const value = await slider.getAttribute('aria-valuenow');

    await checkbox.check();

    // 拉到最左邊
    await slider.click({
      position: { x: 0, y: 0 },
      /** 
       * 忽略可操作性檢查(actionability checks)
       * 
       * [文件](https://playwright.dev/docs/actionability#forcing-actions)
       * 
       * 以免因為 disabled 導致測試一直 timeout
       */
      force: true,
    });
    const newValue = await slider.getAttribute('aria-valuenow');

    expect(Number(value)).toBe(Number(newValue));
  });
})

相當順利。ヾ(◍'౪`◍)ノ゙

image.png

測試:參數客製

拉動握把會讓握把變長。

e2e\components\slider-stubborn.spec.ts

...

test.describe('參數客製', () => {
  test('必須有文字為「參數客製」的 h3', async ({ page }) => {
    const h3Els = page.locator('h3');
    const target = h3Els.getByText('參數客製');
    await expect(target).toBeVisible();
  });

  test('拉動握把會讓握把變長', async ({ page }) => {
    const section = page.getByTitle('custom-prop');
    await expect(section).toBeVisible();

    // 有兩個 slider
    const sliders = await section.getByRole('slider').all();
    expect(sliders).toHaveLength(2);

    // 拉動所有 slider,判斷 svg 尺寸是否有變化
    for (const slider of sliders) {
      const svg = slider.locator('svg');

      const svgSize = await svg.boundingBox();

      // 定位在 slider 上,按下滑鼠後移動到螢幕左上角(0, 0)
      await slider.hover();
      await page.mouse.down();
      await page.mouse.move(0, 0);

      // 取得移動後的 svg 尺寸
      const newSvgSize = await svg.boundingBox();

      await page.mouse.up();

      expect(newSvgSize!.width).toBeGreaterThan(svgSize!.width);
      expect(newSvgSize!.height).toBeGreaterThan(svgSize!.height);
    }
  });
})

順利通過!(´,,•ω•,,)

image.png

一旁的瀏覽視窗還可以看到握把狂野 Q 彈的樣子,是不是很酷啊!(/≧▽≦)/

image.png

以上我們完成基本 e2e 測試了,大家可以想想還有甚麼更細緻的案例。

歡迎大家自由發揮!( ´ ▽ ` )ノ

恭喜一路看到此的讀者們,我們成功完成所有元件了!✧⁑。٩(ˊᗜˋ*)و✧⁕。

總結

  • 完成「固執的滑動條」介紹頁面 e2e 測試

以上程式碼已同步至 GitLab,大家可以前往下載:

GitLab - D27


上一篇
D26 - 固執的滑動條:更多範例
下一篇
D28 - 來點 Web Component
系列文
要不要 Vue 點酷酷的元件?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言