Jest测试中导入绑定window的Django自动生成自执行函数模块问题
When dealing with Django's auto-generated jsi18n module (or similar self-executing functions that bind to window) in Jest, the key challenge is ensuring the module runs with this pointing to the browser-like window object that Jest's jsdom environment provides. Here's how to get your global translation functions (like gettext()) working smoothly in tests:
Step 1: Configure Jest to Use JSDOM
First, make sure Jest simulates a browser environment. Add or update your jest.config.js file:
module.exports = { // Use jsdom to mimic browser window/document behavior testEnvironment: 'jsdom', // Specify a setup file to run before all tests setupFilesAfterEnv: ['./jest.setup.js'], // Include other Jest config options as needed for your project };
Step 2: Inject the jsi18n Script Into JSDOM
Create a jest.setup.js file in your project root. This file runs before any tests, and we'll use it to load the Django translation script in a way that ensures this refers to the window object:
const fs = require('fs'); const path = require('path'); // Update this path to point to your actual Django-generated jsi18n file const jsi18nPath = path.resolve(__dirname, '../static/js/django-jsi18n.js'); // Read the script content from the file const jsi18nContent = fs.readFileSync(jsi18nPath, 'utf8'); // Create a script element and append it to the jsdom document const script = document.createElement('script'); script.textContent = jsi18nContent; document.head.appendChild(script);
This works because when a script runs via a <script> tag in jsdom, the this keyword in the self-executing function points to the window object—just like it would in a real browser. The script will attach Django's translation utilities to window and expose global functions like gettext().
Step 3: Verify Global Functions Work in Tests
Now, your React component's use of gettext() will work in tests exactly as it does in production. For example:
// Your component (e.g., AlertMessage.jsx) import React from 'react'; export default function AlertMessage() { return <p>{gettext('got it')}</p>; }
// Your test file (e.g., AlertMessage.test.jsx) import React from 'react'; import { render } from '@testing-library/react'; import AlertMessage from './AlertMessage'; test('renders translated alert text', () => { const { getByText } = render(<AlertMessage />); // Replace with the actual translated string from your jsi18n file expect(getByText('Got it!')).toBeInTheDocument(); });
Alternative: Mock Translation Functions (For Isolated Testing)
If you don't need to test actual translated strings and just want to verify component logic, you can mock the global translation functions directly:
// Add this to jest.setup.js or individual test files global.gettext = (str) => str; // Simple mock that returns the input string global.ngettext = (singular, plural, count) => count === 1 ? singular : plural;
This is great for isolating component behavior without relying on external translation files.
内容的提问来源于stack exchange,提问作者Darren

