import { merge } from 'lodash-es'; import userEvent from '@testing-library/user-event'; import { SETTINGS_STORE_DEFAULT_STATE } from '@/__tests__/utils'; import { ROLE, STORES } from '@/constants'; import { createTestingPinia } from '@pinia/testing'; import BannerStack from '@/components/banners/BannerStack.vue'; import type { RenderOptions } from '@/__tests__/render'; import { createComponentRenderer } from '@/__tests__/render'; import { waitFor } from '@testing-library/vue'; import { useUIStore } from '@/stores/ui.store'; import { useUsersStore } from '@/stores/users.store'; let uiStore: ReturnType; const initialState = { [STORES.SETTINGS]: { settings: merge({}, SETTINGS_STORE_DEFAULT_STATE.settings), }, [STORES.UI]: { bannerStack: ['TRIAL_OVER', 'V1', 'NON_PRODUCTION_LICENSE', 'EMAIL_CONFIRMATION'], }, [STORES.USERS]: { currentUserId: 'aaa-bbb', usersById: { 'aaa-bbb': { id: 'aaa-bbb', role: ROLE.Owner, }, 'bbb-bbb': { id: 'bbb-bbb', role: ROLE.Member, }, }, }, }; const defaultRenderOptions: RenderOptions = { pinia: createTestingPinia({ initialState }), }; const renderComponent = createComponentRenderer(BannerStack, defaultRenderOptions); describe('BannerStack', () => { beforeEach(() => { uiStore = useUIStore(); }); afterEach(() => { vi.clearAllMocks(); }); it('should render banner with the highest priority', async () => { const { getByTestId, queryByTestId } = renderComponent(); const bannerStack = getByTestId('banner-stack'); expect(bannerStack).toBeInTheDocument(); // Only V1 banner should be visible expect(getByTestId('banners-V1')).toBeInTheDocument(); expect(queryByTestId('banners-TRIAL_OVER')).not.toBeInTheDocument(); }); it('should dismiss banner on click', async () => { const { getByTestId } = renderComponent(); const dismissBannerSpy = vi.spyOn(uiStore, 'dismissBanner').mockImplementation(async () => {}); expect(getByTestId('banners-V1')).toBeInTheDocument(); const closeTrialBannerButton = getByTestId('banner-V1-close'); expect(closeTrialBannerButton).toBeInTheDocument(); await userEvent.click(closeTrialBannerButton); expect(dismissBannerSpy).toHaveBeenCalledWith('V1'); }); it('should permanently dismiss banner on click', async () => { const { getByTestId } = renderComponent(); const dismissBannerSpy = vi.spyOn(uiStore, 'dismissBanner').mockImplementation(async () => {}); const permanentlyDismissBannerLink = getByTestId('banner-confirm-v1'); expect(permanentlyDismissBannerLink).toBeInTheDocument(); await userEvent.click(permanentlyDismissBannerLink); expect(dismissBannerSpy).toHaveBeenCalledWith('V1', 'permanent'); }); it('should not render permanent dismiss link if user is not owner', async () => { const { queryByTestId } = renderComponent({ pinia: createTestingPinia({ initialState: merge(initialState, { [STORES.USERS]: { currentUserId: 'bbb-bbb', }, }), }), }); expect(queryByTestId('banner-confirm-v1')).not.toBeInTheDocument(); }); it('should send email confirmation request from the banner', async () => { const { getByTestId, getByText } = renderComponent({ pinia: createTestingPinia({ initialState: { ...initialState, [STORES.UI]: { bannerStack: ['EMAIL_CONFIRMATION'], }, }, }), }); const confirmEmailSpy = vi.spyOn(useUsersStore(), 'sendConfirmationEmail'); getByTestId('confirm-email-button').click(); await waitFor(() => expect(confirmEmailSpy).toHaveBeenCalled()); await waitFor(() => { expect(getByText('Confirmation email sent')).toBeInTheDocument(); }); }); it('should show error message if email confirmation fails', async () => { const ERROR_MESSAGE = 'Something went wrong'; const { getByTestId, getByText } = renderComponent({ pinia: createTestingPinia({ initialState: { ...initialState, [STORES.UI]: { bannerStack: ['EMAIL_CONFIRMATION'], }, }, }), }); const confirmEmailSpy = vi .spyOn(useUsersStore(), 'sendConfirmationEmail') .mockImplementation(() => { throw new Error(ERROR_MESSAGE); }); getByTestId('confirm-email-button').click(); await waitFor(() => expect(confirmEmailSpy).toHaveBeenCalled()); await waitFor(() => { expect(getByText(ERROR_MESSAGE)).toBeInTheDocument(); }); }); it('should render empty banner stack when there are no banners to display', async () => { const { queryByTestId } = renderComponent({ pinia: createTestingPinia({ initialState: { ...initialState, [STORES.UI]: { bannerStack: [], }, }, }), }); expect(queryByTestId('banner-stack')).toBeEmptyDOMElement(); }); });