4

我的组件:

<script lang="ts">
  import { Button } from 'carbon-components-svelte';
  import firebase from 'firebase/app';
  import { auth } from '../../firebase-shortcut';
  import AuthButton from '../auth/AuthButton.svelte';

  let loggedIn: 'loading' | 'yes' | 'no' = 'loading';
  let userName: string;
  auth.onAuthStateChanged((x) => {
    loggedIn = Boolean(x) ? 'yes' : 'no';
    if (x) {
      userName = x.displayName;
    };
  })

  const googleProvider = {
    instance: new firebase.auth.GoogleAuthProvider(),
    name: 'Google'
  };
</script>

<section>
  <div>
    {#if loggedIn === 'yes'}
      <Button as let:props kind="secondary">
        <span {...props}>{userName}</span>
      </Button>
    {:else if loggedIn === 'no'}
      <AuthButton provider={googleProvider} />
    {:else}<!-- loggedIn === 'loading' -->
      <Button skeleton aria-busy="true" />
    {/if}
  </div>
</section>

测试代码:

import Toolbar from './Toolbar.svelte';
import { render, act } from '@testing-library/svelte';

jest.mock('../../firebase-shortcut');
const { __setAuthState } = require('../../firebase-shortcut');

describe('Toolbar', () => {
  it('should render loader', () => {
    const { queryByText } = render(Toolbar);

    const result = queryByText('로딩...');
    expect(result).toBeTruthy();
  });

  it('should render user when signed in', async () => {
    const displayName = '우섭';
    const { queryByText } = render(Toolbar);

    __setAuthState({ displayName });
    await act();

    const result = queryByText(displayName);
    expect(result).toBeTruthy();
  });

  it('should render button when not signed in', async () => {
    const { queryByRole } = render(Toolbar);

    __setAuthState(null);
    await act();

    const result = queryByRole('button');
    expect(result).toBeTruthy();
  });
});

模拟文件(__mocks__/firebase-shortcut.ts):

import type firebase from 'firebase/app';

const mocked = jest.createMockFromModule('./firebase-shortcut') as any;

let onAuthStateChanged: (x: Partial<firebase.User>) => void;
mocked.auth = {
  onAuthStateChanged: (f: (x: firebase.User) => void) => {
    onAuthStateChanged = f;
  },
};
mocked.__setAuthState = (x: Partial<firebase.User>) => {
  onAuthStateChanged && onAuthStateChanged(x);
};

module.exports = mocked;

开玩笑的配置<project root>/jest.config.js

module.exports = {
  preset: 'ts-jest',
  transform: {
    '^.+\\.svelte$': ['svelte-jester', { preprocess: true }],
    '^.+\\.ts$': 'ts-jest',
  },
  setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
  moduleFileExtensions: ['js', 'ts', 'svelte']
};

如果我通过 打印组件状态console.log(render(...).component),它会打印出该loggedIn状态被正确设置为'yes''no'在每种情况下。但实际得到的渲染结果render(...).container.innerHTML,并没有更新。

加上 Jest 输出打印出一个奇怪的错误:

    TypeError: Cannot read property 'd' of undefined



      at Object.destroy [as d] (src/components/toolbar/Toolbar.svelte:296:40)
      at destroy_component (node_modules/svelte/internal/index.js:1434:36)
      at Toolbar.$destroy (node_modules/svelte/internal/index.js:1552:9)
      at Toolbar.$destroy (node_modules/svelte/internal/index.js:1665:15)
      at cleanupAtContainer (node_modules/@testing-library/svelte/dist/pure.js:116:48)
          at Array.forEach (<anonymous>)
      at cleanup (node_modules/@testing-library/svelte/dist/pure.js:126:37)
      at Object.<anonymous>.afterEach (node_modules/@testing-library/svelte/dist/index.js:27:23)

如果我尝试将 "printing"loggedIn的值转换为 HTML 输出,例如

<section>
...
    {loggedIn}
    {#if loggedIn === 'yes'}
...

输出结果loggedIn是“是”或“否”,但if分支似乎并没有起作用。

有什么我做错了吗?提前致谢。

4

1 回答 1

0

使用组件 fromcarbon-components-svelte似乎是原因。我让它们通过slots 注入,因此在测试期间实际上没有渲染甚至导入任何 Carbon 组件。现在测试运行正常。

于 2020-12-23T19:59:30.010 回答