In my vue.js
application with firebase authentication, I encountered an issue while testing the Login.vue
component. To mock firebase auth, I had to simulate the configuration file used for initializing firebase (named firebase.config
). It's worth mentioning that in my config file, firebase.auth()
is exported as auth
, hence why I'm using fb.auth
instead of fb.auth()
in my code.
One of the test scenarios involves checking if a user is authenticated but not emailVerified
, which should trigger displaying an email dialog. The focus of the test is on verifying whether the data property dialogEmail
is being set to true
.
During the sign-in process, I configured the firebase authentication state persistence to 'session'. While this setup poses no problems in the app itself, it caused issues during testing.
Snippet from Login.vue
(abbreviated component code):
<template>
<v-btn @click="signInUser(email, password)">
Sign in
<v/btn>
</template>
<script>
import * as fb from '@/firebase.config';
export default {
data () {
return {
email: '',
password: '',
};
},
methods: {
async signInUser (email, password) {
try {
await fb.auth.setPersistence('session');
const { user } = await fb.auth.signInWithEmailAndPassword(email, password);
if (user.emailVerified) {
this.$router.push('/home');
} else {
this.dialogEmail = true;
}
} catch (err) {
// ...error handling
}
},
},
};
</script>
Snippet from login.spec.js
:
import Vuetify from 'vuetify';
import { mount, createLocalVue } from '@vue/test-utils';
import Login from '@/views/Login';
jest.mock('@/firebase.config', () => ({
auth: {
setPersistence: () => Promise.resolve(),
signInWithEmailAndPassword: () => Promise.resolve({ user: { emailVerified: false } }),
},
}));
const localVue = createLocalVue();
const $router = { push: jest.fn() };
describe('login.vue', () => {
let vuetify;
beforeEach(() => {
vuetify = new Vuetify();
});
const mountFunction = () => mount(Login, {
localVue,
vuetify,
mocks: { $router },
});
it('shows dialog if user email not verified on sign in', async () => {
expect.assertions(1);
const wrapper = mountFunction();
const signInButton = wrapper.find('[data-test="signIn"]');
await wrapper.setData({ email: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="42242d2d022023306c2d3025">[email protected]</a>', password: 'FooBarBaz' });
await signInButton.trigger('click');
expect(wrapper.vm.dialogEmail).toBe(true);
});
});
The main functionality of my app works perfectly fine. However, my test scenario was failing with an unexpected output:
expect(received).toBe(expected) // Object.is equality
Expected: true
Received: false
Surprisingly, adding a short delay before the assertion allowed the test to pass successfully. This raised questions about why the extra timeout was needed and what exactly was happening behind the scenes. Seeking clarification on this matter prompted me to seek insights here.