iT邦幫忙

2024 iThome 鐵人賽

DAY 10
1

開始單元測試前,先讓我們設定一下測試範圍,避免執行到 e2e 測試的部分。

vitest 可以和 vite 共用設定檔,所以我們在 vite 新增設定即可。

vite.config.ts

...

export default defineConfig(({ command, mode }) => {
  ...

  return {
    ...
    test: {
      include: ['src/**/*.{test,spec}.ts'],
      ...
    },
  }
})

現在讓我們新增測試檔案。

src\components\text-characters-transition\text-characters-transition.spec.ts

import { mount } from '@vue/test-utils';
import { test, expect } from 'vitest';

import TextCharactersTransition from './text-characters-transition.vue';

test('測試案例', () => {
  const wrapper = mount(TextCharactersTransition);
  expect(wrapper).toBeDefined();
})

新增測試案例

讓我們依序新增各種測試案例吧。∠( ᐛ 」∠)_

容器與 label

src\components\text-characters-transition\text-characters-transition.spec.ts

...

test('容器可以指定 HTML tag', () => {
  const tag = 'span';

  const wrapper = mount(TextCharactersTransition, {
    props: {
      label: '文字',
      tag,
    },
  });

  const container = wrapper.find('[aria-label]');
  expect(container.element.tagName).toBe('SPAN');
})

describe('容器之 aria-label 必須等於 label', () => {
  test('label 為 string', () => {
    const label = '文字';

    const wrapper = mount(TextCharactersTransition, {
      props: { label },
    });

    const container = wrapper.find('[aria-label]');
    expect(container.element.tagName).toBe('P');
    expect(container.attributes('aria-label')).toBe(label);
  })

  test('label 為 string[]', () => {
    const label = ['文字文字文字', '文字文字文字'];

    const wrapper = mount(TextCharactersTransition, {
      props: { label },
    });

    const container = wrapper.find('[aria-label]');
    expect(container.attributes('aria-label')).toBe(label.join(''));

    const list = wrapper.findAll('span');
    expect(list).toHaveLength(label.length);
  })
})

test('被拆分的 span 數量必須等於 label 字數', () => {
  const label = '文字文字文字文字文字';

  const wrapper = mount(TextCharactersTransition, {
    props: { label },
  });

  const list = wrapper.findAll('span');
  expect(list).toHaveLength(label.length);
})

再來是 splitter。

src\components\text-characters-transition\text-characters-transition.spec.ts

...

describe('splitter 指定拆分方式', () => {
  test('根據「,」拆分', () => {
    const splitter = /(,)/;

    const label = '文字文字,文字文字,文字';

    const wrapper = mount(TextCharactersTransition, {
      props: { label, splitter },
    });

    const list = wrapper.findAll('span');
    expect(list).toHaveLength(
      label.split(splitter).length
    );
  })

  test('自定義拆分 function', async () => {
    const label = '文字文字文字文字文字';

    const splitter = (text: string) => {
      if (text.includes('鱈魚')) {
        return text.split('鱈魚');
      }

      return text.split('');
    };

    const wrapper = mount(TextCharactersTransition, {
      props: { label, splitter },
    });

    const list = wrapper.findAll('span');
    expect(list).toHaveLength(label.length);

    const newLabel = '文字文字鱈魚文字文字';
    await wrapper.setProps({ label: newLabel });

    const newList = wrapper.findAll('span');
    expect(newList).toHaveLength(
      splitter(newLabel).length
    );
  })
})

最後是切換 visible 會觸發對應事件部分。

src\components\text-characters-transition\text-characters-transition.spec.ts

...

test('切換 visible 會觸發對應事件', async () => {
  const wrapper = mount(TextCharactersTransition, {
    props: {
      visible: false,
      label: '文字文字',
    },
  });

  expect(wrapper.emitted()).not.toHaveProperty('before-enter');
  expect(wrapper.emitted()).not.toHaveProperty('after-enter');

  await wrapper.setProps({ visible: true });
  await promiseTimeout(2000);

  expect(wrapper.emitted()).toHaveProperty('before-enter');
  expect(wrapper.emitted()).toHaveProperty('after-enter');
})

這次的測試相當順利!(/≧▽≦)/

 ✓ src/components/text-characters-transition/text-characters-transition.spec.ts (7) 2060ms
   ✓ 容器可以指定 HTML tag
   ✓ 容器之 aria-label 必須等於 label (2)
     ✓ label 為 string
     ✓ label 為 string[]
   ✓ 被拆分的 span 數量必須等於 label 字數
   ✓ splitter 指定拆分方式 (2)
     ✓ 根據「,」拆分
     ✓ 自定義拆分 function
   ✓ 切換 visible 會觸發對應事件 2005ms

 Test Files  1 passed (1)
      Tests  7 passed (7)
   Start at  23:42:25
   Duration  2.38s

總結

  • 完成「逐字過場」單元測試

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

GitLab - D10


上一篇
D09 - 逐字轉場:開發元件
下一篇
D11 - 逐字轉場:更多範例
系列文
要不要 Vue 點酷酷的元件?30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言