My component:
<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>
test code:
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();
});
});
mock file (__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 config at <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']
};
If I print the component state by console.log(render(...).component)
, it prints that loggedIn
state is correctly set as 'yes'
and 'no'
in each case. But the actual render result obtained by render(...).container.innerHTML
, nothing's updated.
Plus the Jest output prints a weird error:
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)
If I try "printing" loggedIn
's value to HTML output, like
<section>
...
{loggedIn}
{#if loggedIn === 'yes'}
...
The output says loggedIn
is 'yes' or 'no', but the if
branches don't just seem to work.
Is there anything I'm doing wrong? Thanks in advance.
Using components from
carbon-components-svelte
seems to be the reason. I made them get injected viaslot
s, so that during the test no Carbon components were actually rendered or even imported. Now tests are running okay.