By lynds
I’m very new to Vue/Jest and I have been struggling to fathom how to write my tests for a menu component and I can’t seem to find the answers. I need to write test cases for the props that are passed in the menu. One test case is when the burger menu is clicked and the menu is shown. The other is to check whether the account and logout menu items is shown or not shown.
In my MobileMenu.vue file:
<transition name="fade">
<div
v-show="active"
class="overlay"
@click.stop="$emit('toggle-menu')"
/>
</transition>
<transition name="slide-left">
<ul
v-show="active"
class="mobile-menu"
@click="handleClick"
>
<li
class="close"
@click.stop="$emit('toggle-menu')"
>
</li>
<template v-if="isLogged">
<MobileMenuItem
to="/account/dashboard"
name="My Account"
data-testid="loggedIn-menu-items"
/>
<MobileMenuItem
to="/logout"
name="Logout"
data-testid="loggedIn-menu-items"
/>
</template>
</ul>
</transition>
<script>
import MobileMenuItem from '@/components/layout/menu/MobileMenuItem'
export default {
name: 'MobileMenu',
components: { MobileMenuItem },
props: {
active: {
type: Boolean,
default: false,
},
isLogged: {
type: Boolean,
default: false,
}
},
methods: {
handleClick($event) {
if ($event.target.tagName === 'A') {
this.$emit('toggle-menu')
}
}
}
}
</script>
In my MobileMenu.spec.js:
import Vue from 'vue'
import Vuetify from 'vuetify'
import '@testing-library/jest-dom/extend-expect'
import { render, screen } from '@testing-library/vue'
import MobileMenu from '@/components/layout/menu/MobileMenu.vue'
function renderComponent(props = {}) {
return render(MobileMenu, {
props,
mocks: {
$vuetify: { breakpoint: {}}
},
});
}
describe('Testing MobileMenu Component props', () => {
it('becomes active when the hamburger button is clicked', () => {
})
it('if a user is not logged in, do not show my account and logout', () => {
expect(screen.queryByTestId('loggedIn-menu-items')).not.toBeInTheDocument();
//expect(screen.queryByTestId('loggedIn-menu-items')).toHaveLength(0)
// const { container } = renderComponent()
// console.log(container)
// renderComponent({
// isLogged: false
// })
// console.log(screen.queryByTestId('loggedIn-menu-items'))
// expect(screen.queryByTestId('loggedIn-menu-items')).not.toBeInTheDocument()
//console.log(screen.queryByTestId('loggedIn-menu-items'))
//expect(screen.queryByTestId('loggedIn-menu-items')).toHaveLength(0)
})
it('if a user is logged in, show my account and logout', () => {
renderComponent({
isLogged: true
})
expect(screen.getByTestId('loggedIn-menu-items')).toBeTruthy();
// const elements = screen.queryByTestId('loggedIn-menu-items');
// console.log(elements)
//expect(screen.getByTestId('loggedIn-menu-items').length).toHaveLength(2);
//expect(screen.queryByTestId('loggedIn-menu-items')).toBeInTheDocument()
//console.log(screen.queryByTestId('loggedIn-menu-items'))
//expect(screen.queryByTestId('loggedIn-menu-items')).toHaveLength(2)
})
})
As you can see I’ve attempted quite a bit to get this right but I am really struggling with it and my tests keep failing.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Hi there,
Writing tests with Vue and Jest can be quite straightforward once you get the hang of it. The @testing-library/vue library is designed to encourage good testing practices and it provides utilities that allow you to work with your Vue components in a way that is closer to how a user would interact with the application.
Testing the “active” prop effect on menu visibility:
You need to test whether toggling the active prop shows or hides the menu. You should trigger a click event and check the visibility of the .overlay and .mobile-menu elements accordingly.
Testing the display of menu items based on the “isLogged” prop:
You want to verify that the menu items related to the logged-in state are only shown when isLogged is true.
Here is how you could write your tests:
import { fireEvent, render } from '@testing-library/vue'
import MobileMenu from '@/components/layout/menu/MobileMenu.vue'
describe('MobileMenu.vue', () => {
// Helper function to render the component with props
function renderMobileMenu(props) {
return render(MobileMenu, {
props: {
...props,
},
// Provide any additional options here
// mocks, slots, etc.
});
}
it('becomes active when the hamburger button is clicked', async () => {
const { getByTestId, queryByTestId } = renderMobileMenu({ active: false });
// Assuming you have a button to toggle the menu that you can click
const toggleButton = getByTestId('hamburger-button');
await fireEvent.click(toggleButton);
// Check if the overlay is shown now
expect(queryByTestId('overlay')).toBeVisible();
expect(queryByTestId('mobile-menu')).toBeVisible();
});
it('if a user is not logged in, do not show my account and logout', () => {
const { queryByTestId } = renderMobileMenu({ isLogged: false });
// The menu items should not be in the document
expect(queryByTestId('loggedIn-menu-items')).not.toBeInTheDocument();
});
it('if a user is logged in, show my account and logout', () => {
const { getAllByTestId } = renderMobileMenu({ isLogged: true });
// The menu items should be visible
// Use getAllByTestId if there are multiple elements with the same test ID
const loggedInMenuItems = getAllByTestId('loggedIn-menu-items');
expect(loggedInMenuItems.length).toBe(2);
loggedInMenuItems.forEach(item => {
expect(item).toBeVisible();
});
});
});
Note the following:
getAllByTestId is used instead of getByTestId when you are expecting multiple elements with the same data-testid. It returns an array of elements.queryByTestId is used when you want to assert that an element is not present. It returns null if the element is not found, which is useful for checks with .not.toBeInTheDocument().'hamburger-button' and 'overlay' with the actual data-testid attributes of the hamburger button and the overlay div if you have them. If not, you might need to add these data-testid attributes or select the elements by their class names or roles.await with fireEvent as needed, and you may need to use waitFor or findBy* queries for elements that take time to appear as a result of state changes.Best,
Bobby
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.
Full documentation for every DigitalOcean product.
The Wave has everything you need to know about building a business, from raising funding to marketing your product.
Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.
New accounts only. By submitting your email you agree to our Privacy Policy
Scale up as you grow — whether you're running one virtual machine or ten thousand.
Sign up and get $200 in credit for your first 60 days with DigitalOcean.*
*This promotional offer applies to new accounts only.