Vitest "SyntaxError: Invalid or unexpected token" - Mocking Font Files
If you're using Vitest for testing your Vue.js or React application and you're encountering a "SyntaxError: Invalid or unexpected token" error related to font files, you're not alone. This issue often arises when Vitest tries to parse and load fonts during your tests, leading to unexpected behavior.
Let's explore this common problem, understand its root cause, and discover how to fix it.
The Problem:
Imagine this scenario: you're writing a test for a component that uses a custom font. Your test code looks something like this:
import { mount } from '@vue/test-utils';
import MyComponent from './MyComponent.vue';
describe('MyComponent', () => {
it('should render with the correct font', () => {
const wrapper = mount(MyComponent);
expect(wrapper.element.style.fontFamily).toContain('MyCustomFont');
});
});
When running your test, you might encounter the dreaded "SyntaxError: Invalid or unexpected token" error. This often occurs because Vitest tries to load the font file, leading to parsing issues.
Understanding the Error:
The problem stems from Vitest's attempt to interpret the font file as JavaScript code. Font files, such as .ttf
, .woff
, or .otf
, are binary data and not meant to be parsed as JavaScript. This mismatch creates the "Invalid or unexpected token" error.
The Solution: Mocking Font Files
To avoid this error, we need to "mock" the font file loading behavior during our tests. This means preventing Vitest from trying to parse the font data. We can achieve this using a combination of the following:
-
Setting up a mock module: Create a simple mock module for font files. This module will serve as a placeholder, preventing Vitest from attempting to load the actual font file.
// src/mocks/font.js export default () => {};
-
Configure Vitest's mock resolution: Configure Vitest to resolve all font file imports to your mock module. This ensures that the actual font file is never loaded during testing.
// vite.config.js import { defineConfig } from 'vite'; import { resolve } from 'path'; export default defineConfig({ resolve: { alias: { // Configure all fonts to resolve to the mock module '@fonts/*': resolve(__dirname, 'src/mocks/font.js'), }, }, test: { // ... your other test configurations }, });
Explanation:
-
Mock Module: The
font.js
module acts as a dummy placeholder. When Vitest encounters a font import, it finds this mock module instead of the actual font file, effectively preventing parsing errors. -
Vite Configuration: The
alias
configuration invite.config.js
tells Vitest that any import starting with@fonts/*
should be replaced with your mock module. This allows you to easily manage font mocking across your test suite.
Example:
Let's apply this solution to our earlier example:
// src/mocks/font.js
export default () => {};
// src/MyComponent.vue
// (Component code using the custom font)
// tests/MyComponent.spec.js
import { mount } from '@vue/test-utils';
import MyComponent from './MyComponent.vue';
describe('MyComponent', () => {
it('should render with the correct font', () => {
const wrapper = mount(MyComponent);
// Expect the font family to be set correctly, even though the actual font is not loaded
expect(wrapper.element.style.fontFamily).toContain('MyCustomFont');
});
});
Additional Notes:
- Remember to adapt the
@fonts/*
wildcard pattern in your Vite configuration to match the specific folder where your font files are located. - If you're using a different test runner like Jest, you might need to modify the mocking approach based on its configuration options.
Conclusion:
Mocking font files is a crucial step in ensuring smooth testing with Vitest. By preventing Vitest from attempting to parse font data, you can eliminate the "Invalid or unexpected token" error and focus on testing your application's core functionality. By implementing this solution, you can write robust tests that accurately reflect your component's behavior, even when dealing with external resources like fonts.