私のコンポーネント:
<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
ブランチは機能していないようです。
私が間違っていることはありますか?前もって感謝します。