iT邦幫忙

2024 iThome 鐵人賽

DAY 22
0

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

e2e\components\wrapper-physics.spec.ts

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

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

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

先將元件加上 title,方便定位。

docs\components\wrapper-physics\index.md

...

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

<body-property title="body-property"/>

...

<adjust-gravity title="adjust-gravity"/>

...

執行腳本開始運行 e2e 測試。

npm run test:e2e-ui

測試:基本用法

測試元素是否存在,按下開始元素會移動,重置會回歸原位

e2e\components\text-characters-transition.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('basic-usage');
    await expect(section).toBeVisible();

    const list = ['開始', '重置', '安安安', '安安', '安'];
    for (const text of list) {
      const target = section.getByText(text, { exact: true });
      await expect(target).toBeVisible();
    }
  });

  test('按下開始元素會移動,重置會回歸原位', async ({ page }) => {
    const section = page.getByTitle('basic-usage');
    await expect(section).toBeVisible();

    const startBtn = section.getByText('開始');
    const resetBtn = section.getByText('重置');

    const list = ['開始', '重置', '安安安', '安安', '安'];
    const targets = list.map((text) => section.getByText(text, { exact: true }));

    for (const target of targets) {
      await expect(target).toHaveAttribute(
        'style', 'transform: translate(0px, 0px) rotate(0deg);'
      );
    }

    await startBtn.click();
    // 等待 500ms
    await page.waitForTimeout(500);

    for (const target of targets) {
      await expect(target).not.toHaveAttribute(
        'style', 'transform: translate(0px, 0px) rotate(0deg);'
      );
    }

    await resetBtn.click();

    for (const target of targets) {
      await expect(target).toHaveAttribute(
        'style', 'transform: translate(0px, 0px) rotate(0deg);'
      );
    }
  });
})

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

image.png

測試:物體性質

isStatic 以外的物體會移動。

e2e\components\text-characters-transition.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('body-property');
    await expect(section).toBeVisible();

    const startBtn = section.getByText('開始');
    await startBtn.click();
    await page.waitForTimeout(500);

    const staticList = ['靜', '止'];
    const list = ['追', '趕', '慢', '跑', '跳', '碰'];

    const staticTargets = staticList.map((text) => section.getByText(text, { exact: true }));
    const targets = list.map((text) => section.getByText(text, { exact: true }));

    for (const target of staticTargets) {
      await expect(target).toBeVisible();
      await expect(target).toHaveAttribute(
        'style', 'transform: translate(0px, 0px) rotate(0deg);'
      );
    }

    for (const target of targets) {
      await expect(target).toBeVisible();
      await expect(target).not.toHaveAttribute(
        'style', 'transform: translate(0px, 0px) rotate(0deg);'
      );
    }
  });
})

成功!◝( •ω• )◟

image.png

測試:調整重力

這個案例稍微複雜一點,不過也是很好理解。ヽ(●`∀´●)ノ

e2e\components\text-characters-transition.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('adjust-gravity');
    await expect(section).toBeVisible();

    await page.waitForTimeout(500);

    const targets = section.getByText('🐟', { exact: true });

    // 重力預設往下,物理物件會往下移動
    for (const target of await targets.all()) {
      const attr = await target.getAttribute('style');
      if (!attr) {
        throw new Error('attr is null');
      }

      // 取出 translateY 部分數值
      const translateY = attr.match(/transform: translate\(0px, (.*?)px\)/)?.[1];
      if (!translateY) {
        throw new Error('translateY is null');
      }

      expect(parseFloat(translateY)).toBeGreaterThan(0);
    }

    // 調整重力往上
    const ySlider = section.getByRole('slider').nth(1);
    ySlider.fill('-2');

    await page.waitForTimeout(500);

    // 物體會往上移動
    for (const target of await targets.all()) {
      const attr = await target.getAttribute('style');
      if (!attr) {
        throw new Error('attr is null');
      }

      // 取出 translateY 部分數值
      const translateY = attr.match(/transform: translate\(0px, (.*?)px\)/)?.[1];
      if (!translateY) {
        throw new Error('translateY is null');
      }

      expect(parseFloat(translateY)).toBeLessThan(0);
    }
  });
})

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

image.png

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

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

總結

  • 完成「物理包裝器」介紹頁面 e2e 測試

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

GitLab - D22


上一篇
D21 - 物理包裝器:更多範例
下一篇
D23 - 固執的滑動條:分析需求
系列文
要不要 Vue 點酷酷的元件?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言