我的组件:
<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
分支似乎并没有起作用。
有什么我做错了吗?提前致谢。