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;

Jest 設定<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)

loggedInの値をHTML出力に「印刷」しようとすると、

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

出力loggedInは「はい」または「いいえ」ですが、ifブランチは機能していないようです。

私が間違っていることはありますか?前もって感謝します。

4

1 に答える 1