mirror of
https://github.com/unraid/api.git
synced 2026-01-02 22:50:02 -06:00
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - App-wide internationalization: dynamic locale detection/loading, many new locale bundles, and CLI helpers to extract/sort translation keys. - **Accessibility** - Brand button supports keyboard activation (Enter/Space). - **Documentation** - Internationalization guidance added to API and Web READMEs. - **Refactor** - UI updated to use centralized i18n keys and a unified locale loading approach. - **Tests** - Test utilities updated to support i18n and localized assertions. - **Chores** - Crowdin config and i18n scripts added; runtime locale exposed for selection. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
233 lines
7.4 KiB
TypeScript
233 lines
7.4 KiB
TypeScript
import { nextTick } from 'vue';
|
|
import { createPinia, setActivePinia } from 'pinia';
|
|
import { mount } from '@vue/test-utils';
|
|
|
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
|
import type { VueWrapper } from '@vue/test-utils';
|
|
import type { Pinia } from 'pinia';
|
|
|
|
import Modals from '~/components/Modals.standalone.vue';
|
|
import { useCallbackActionsStore } from '~/store/callbackActions';
|
|
import { useTrialStore } from '~/store/trial';
|
|
import { useUpdateOsStore } from '~/store/updateOs';
|
|
|
|
// Mock child components
|
|
vi.mock('~/components/Activation/ActivationModal.vue', () => ({
|
|
default: {
|
|
name: 'ActivationModal',
|
|
props: [],
|
|
template: '<div>ActivationModal</div>',
|
|
},
|
|
}));
|
|
|
|
vi.mock('~/components/UpdateOs/ChangelogModal.vue', () => ({
|
|
default: {
|
|
name: 'UpdateOsChangelogModal',
|
|
props: ['open'],
|
|
template: '<div v-if="open">ChangelogModal</div>',
|
|
},
|
|
}));
|
|
|
|
vi.mock('~/components/UpdateOs/CheckUpdateResponseModal.vue', () => ({
|
|
default: {
|
|
name: 'UpdateOsCheckUpdateResponseModal',
|
|
props: ['open'],
|
|
template: '<div v-if="open">CheckUpdateResponseModal</div>',
|
|
},
|
|
}));
|
|
|
|
vi.mock('~/components/UserProfile/CallbackFeedback.vue', () => ({
|
|
default: {
|
|
name: 'UpcCallbackFeedback',
|
|
props: ['open'],
|
|
template: '<div v-if="open">CallbackFeedback</div>',
|
|
},
|
|
}));
|
|
|
|
vi.mock('~/components/UserProfile/Trial.vue', () => ({
|
|
default: {
|
|
name: 'UpcTrial',
|
|
props: ['open'],
|
|
template: '<div v-if="open">Trial</div>',
|
|
},
|
|
}));
|
|
|
|
vi.mock('vue-i18n', () => ({
|
|
useI18n: () => ({
|
|
t: (key: string) => key,
|
|
}),
|
|
}));
|
|
|
|
describe('Modals.standalone.vue', () => {
|
|
let wrapper: VueWrapper;
|
|
let pinia: Pinia;
|
|
|
|
beforeEach(() => {
|
|
pinia = createPinia();
|
|
setActivePinia(pinia);
|
|
|
|
wrapper = mount(Modals, {
|
|
global: {
|
|
plugins: [pinia],
|
|
},
|
|
});
|
|
});
|
|
|
|
afterEach(() => {
|
|
wrapper?.unmount();
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
it('should render modals container with correct id and ref', () => {
|
|
const modalsDiv = wrapper.find('#modals');
|
|
expect(modalsDiv.exists()).toBe(true);
|
|
expect(modalsDiv.attributes('class')).toContain('relative');
|
|
expect(modalsDiv.attributes('class')).toContain('z-[999999]');
|
|
});
|
|
|
|
it('should render all modal components', () => {
|
|
expect(wrapper.findComponent({ name: 'UpcCallbackFeedback' }).exists()).toBe(true);
|
|
expect(wrapper.findComponent({ name: 'UpcTrial' }).exists()).toBe(true);
|
|
expect(wrapper.findComponent({ name: 'UpdateOsCheckUpdateResponseModal' }).exists()).toBe(true);
|
|
expect(wrapper.findComponent({ name: 'UpdateOsChangelogModal' }).exists()).toBe(true);
|
|
expect(wrapper.findComponent({ name: 'ActivationModal' }).exists()).toBe(true);
|
|
});
|
|
|
|
it('should pass correct props to CallbackFeedback based on store state', async () => {
|
|
const callbackStore = useCallbackActionsStore();
|
|
callbackStore.callbackStatus = 'loading';
|
|
|
|
await nextTick();
|
|
|
|
const callbackFeedback = wrapper.findComponent({ name: 'UpcCallbackFeedback' });
|
|
expect(callbackFeedback.props('open')).toBe(true);
|
|
|
|
callbackStore.callbackStatus = 'ready';
|
|
await nextTick();
|
|
expect(callbackFeedback.props('open')).toBe(false);
|
|
});
|
|
|
|
it('should pass correct props to Trial modal based on store state', async () => {
|
|
const trialStore = useTrialStore();
|
|
// trialModalVisible is computed based on trialStatus
|
|
trialStore.trialStatus = 'trialStart';
|
|
|
|
await nextTick();
|
|
|
|
const trialModal = wrapper.findComponent({ name: 'UpcTrial' });
|
|
expect(trialModal.props('open')).toBe(true);
|
|
|
|
trialStore.trialStatus = 'ready';
|
|
await nextTick();
|
|
expect(trialModal.props('open')).toBe(false);
|
|
});
|
|
|
|
it('should pass correct props to UpdateOs modal based on store state', async () => {
|
|
const updateOsStore = useUpdateOsStore();
|
|
updateOsStore.setModalOpen(true);
|
|
|
|
await nextTick();
|
|
|
|
const updateOsModal = wrapper.findComponent({ name: 'UpdateOsCheckUpdateResponseModal' });
|
|
expect(updateOsModal.props('open')).toBe(true);
|
|
|
|
updateOsStore.setModalOpen(false);
|
|
await nextTick();
|
|
expect(updateOsModal.props('open')).toBe(false);
|
|
});
|
|
|
|
it('should pass correct props to Changelog modal based on store state', async () => {
|
|
const updateOsStore = useUpdateOsStore();
|
|
// changelogModalVisible is computed based on releaseForUpdate
|
|
updateOsStore.setReleaseForUpdate({
|
|
version: '6.13.0',
|
|
name: 'Unraid 6.13.0',
|
|
date: '2024-01-01',
|
|
isNewer: true,
|
|
isEligible: true,
|
|
changelog: null,
|
|
sha256: null,
|
|
});
|
|
|
|
await nextTick();
|
|
|
|
const changelogModal = wrapper.findComponent({ name: 'UpdateOsChangelogModal' });
|
|
expect(changelogModal.props('open')).toBe(true);
|
|
|
|
updateOsStore.setReleaseForUpdate(null);
|
|
await nextTick();
|
|
expect(changelogModal.props('open')).toBe(false);
|
|
});
|
|
|
|
it('should render all modal components without t props (using useI18n)', () => {
|
|
const components = [
|
|
'UpcCallbackFeedback',
|
|
'UpcTrial',
|
|
'UpdateOsCheckUpdateResponseModal',
|
|
'UpdateOsChangelogModal',
|
|
];
|
|
|
|
components.forEach((componentName) => {
|
|
const component = wrapper.findComponent({ name: componentName });
|
|
expect(component.exists()).toBe(true);
|
|
// Components now use useI18n internally, so no t prop should be passed
|
|
expect(component.props('t')).toBeUndefined();
|
|
});
|
|
});
|
|
|
|
it('should use computed properties for reactive store access', async () => {
|
|
// Test that computed properties react to store changes
|
|
const callbackStore = useCallbackActionsStore();
|
|
const trialStore = useTrialStore();
|
|
const updateOsStore = useUpdateOsStore();
|
|
|
|
// Initially all should be closed/default
|
|
expect(wrapper.findComponent({ name: 'UpcCallbackFeedback' }).props('open')).toBe(false);
|
|
expect(wrapper.findComponent({ name: 'UpcTrial' }).props('open')).toBe(false);
|
|
expect(wrapper.findComponent({ name: 'UpdateOsCheckUpdateResponseModal' }).props('open')).toBe(
|
|
false
|
|
);
|
|
expect(wrapper.findComponent({ name: 'UpdateOsChangelogModal' }).props('open')).toBe(false);
|
|
|
|
// Update all stores using proper methods
|
|
callbackStore.callbackStatus = 'loading';
|
|
trialStore.trialStatus = 'trialStart';
|
|
updateOsStore.setModalOpen(true);
|
|
updateOsStore.setReleaseForUpdate({
|
|
version: '6.13.0',
|
|
name: 'Unraid 6.13.0',
|
|
date: '2024-01-01',
|
|
isNewer: true,
|
|
isEligible: true,
|
|
changelog: null,
|
|
sha256: null,
|
|
});
|
|
|
|
await nextTick();
|
|
|
|
// All should be open now
|
|
expect(wrapper.findComponent({ name: 'UpcCallbackFeedback' }).props('open')).toBe(true);
|
|
expect(wrapper.findComponent({ name: 'UpcTrial' }).props('open')).toBe(true);
|
|
expect(wrapper.findComponent({ name: 'UpdateOsCheckUpdateResponseModal' }).props('open')).toBe(true);
|
|
expect(wrapper.findComponent({ name: 'UpdateOsChangelogModal' }).props('open')).toBe(true);
|
|
});
|
|
|
|
it('should render modals container even when all modals are closed', () => {
|
|
const callbackStore = useCallbackActionsStore();
|
|
const trialStore = useTrialStore();
|
|
const updateOsStore = useUpdateOsStore();
|
|
|
|
// Set all modals to closed state
|
|
callbackStore.callbackStatus = 'ready';
|
|
trialStore.trialStatus = 'ready';
|
|
updateOsStore.setModalOpen(false);
|
|
updateOsStore.setReleaseForUpdate(null);
|
|
|
|
const modalsDiv = wrapper.find('#modals');
|
|
expect(modalsDiv.exists()).toBe(true);
|
|
// Container should still exist
|
|
expect(wrapper.findComponent({ name: 'ActivationModal' }).exists()).toBe(true);
|
|
});
|
|
});
|