xref: /openbmc/webui-vue/tests/jest.setup.js (revision 313d15cf9f14e8a264f97a3370c3be4e494e5e0d)
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