1/* eslint-env jest */ 2import { config } from '@vue/test-utils'; 3 4// Make Math.random deterministic for stable snapshots (e.g., IDs in components) 5jest.spyOn(Math, 'random').mockReturnValue(0.123456789); 6 7// Provide a minimal vue-router API for tests that import it 8jest.mock('vue-router', () => ({ 9 createRouter: () => ({}), 10 createMemoryHistory: () => ({}), 11})); 12 13// Create a shared i18n instance for component tests 14// This provides a working i18n plugin for components that use useI18n() 15import { createI18n } from 'vue-i18n'; 16import enUS from '@/locales/en-US.json'; 17 18// Mock the default export of @/i18n to provide a working i18n instance. 19// In Jest, require.context doesn't work, so the real module would have no messages. 20// Note: The i18n.*.spec.js tests use jest.unmock('@/i18n') to test the real module. 21jest.mock('@/i18n', () => { 22 const { createI18n: create } = require('vue-i18n'); 23 // eslint-disable-next-line global-require 24 const messages = require('@/locales/en-US.json'); 25 const mockI18n = create({ 26 legacy: false, 27 locale: 'en-US', 28 fallbackLocale: 'en-US', 29 globalInjection: true, 30 messages: { 31 'en-US': messages.default || messages, 32 en: messages.default || messages, 33 }, 34 }); 35 36 // Re-export the real named exports for tests that need them 37 // eslint-disable-next-line global-require 38 const actual = jest.requireActual('@/i18n'); 39 return { 40 __esModule: true, 41 default: mockI18n, 42 loadBaseLocaleMessages: actual.loadBaseLocaleMessages, 43 loadEnvLocaleMessages: actual.loadEnvLocaleMessages, 44 createI18nInstance: actual.createI18nInstance, 45 }; 46}); 47 48export const testI18n = createI18n({ 49 legacy: false, 50 locale: 'en-US', 51 fallbackLocale: 'en-US', 52 globalInjection: true, 53 messages: { 54 'en-US': enUS, 55 en: enUS, // Alias for linked message resolution 56 }, 57}); 58 59// Provide default global mocks/stubs 60config.global.mocks = { 61 $t: (k) => k, 62 $route: { meta: { title: '' } }, 63 $eventBus: { 64 on: () => {}, 65 off: () => {}, 66 emit: () => {}, 67 $on: () => {}, 68 $off: () => {}, 69 $emit: () => {}, 70 }, 71}; 72 73// Stubs with single root elements to properly inherit attributes like data-test-id 74config.global.stubs = { 75 'router-link': { template: '<a><slot/></a>' }, 76 'b-navbar': { template: '<nav><slot/></nav>' }, 77 'b-navbar-brand': { template: '<div><slot/></div>' }, 78 'b-navbar-nav': { template: '<div><slot/></div>' }, 79 'b-dropdown': { template: '<div><slot/></div>' }, 80 'b-dropdown-item': { template: '<div><slot/></div>' }, 81 'b-nav': { template: '<ul class="nav mb-4 flex-column"><slot/></ul>' }, 82 'b-nav-item': { template: '<li><slot/></li>' }, 83 'b-collapse': { template: '<ul><slot/></ul>' }, 84 'b-button': { template: '<button><slot/></button>' }, 85 'b-input-group': { template: '<div class="input-group"><slot/></div>' }, 86 'b-input-group-prepend': { 87 template: '<div class="input-group-prepend"><slot/></div>', 88 }, 89 'b-input-group-text': { 90 template: '<span class="input-group-text"><slot/></span>', 91 }, 92 'b-form-group': { template: '<div class="form-group mb-2"><slot/></div>' }, 93 'b-form-input': { template: '<input class="form-control search-input" />' }, 94 'b-form-checkbox': { template: '<div class="form-check"><slot/></div>' }, 95 'b-form-radio': { template: '<div class="form-check"><slot/></div>' }, 96 'b-form-select': { template: '<select><slot/></select>' }, 97 'b-progress': { template: '<div class="progress"><slot/></div>' }, 98 'b-progress-bar': { template: '<div class="progress-bar"></div>' }, 99 'b-modal': { template: '<div class="modal"><slot/></div>' }, 100 'b-tooltip': { template: '<div><slot/></div>' }, 101}; 102 103// Provide plugins - i18n for useI18n() support, and $root helpers 104config.global.plugins = [ 105 testI18n, 106 { 107 install(app) { 108 // eslint-disable-next-line no-param-reassign 109 app.config.globalProperties.$root = 110 app.config.globalProperties.$root || {}; 111 if (!app.config.globalProperties.$root.$on) { 112 app.config.globalProperties.$root.$on = () => {}; 113 } 114 if (!app.config.globalProperties.$root.$emit) { 115 app.config.globalProperties.$root.$emit = () => {}; 116 } 117 app.mixin({ 118 beforeCreate() { 119 const r = this.$root; 120 if (r && !r.$on) r.$on = () => {}; 121 if (r && !r.$emit) r.$emit = () => {}; 122 }, 123 }); 124 }, 125 }, 126]; 127 128// Stub bootstrap-vue directives 129config.global.directives = { 130 'b-tooltip': () => {}, 131 'b-toggle': () => {}, 132}; 133