mirror of
https://github.com/bitsocialnet/5chan.git
synced 2026-08-03 07:41:04 +02:00
test(settings): expand settings and route coverage
Added focused tests for settings flows, subscription behavior, and route helpers, and fixed the account import success path those tests exposed in account-settings.tsx.
This commit is contained in:
+153
@@ -0,0 +1,153 @@
|
||||
import * as React from 'react';
|
||||
import { createElement } from 'react';
|
||||
import { createRoot, Root } from 'react-dom/client';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import SubscriptionsSetting from '../subscriptions-setting';
|
||||
|
||||
(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true;
|
||||
const act = (React as { act?: (cb: () => void | Promise<void>) => void | Promise<void> }).act as (cb: () => void | Promise<void>) => void | Promise<void>;
|
||||
|
||||
const accountState = vi.hoisted(() => ({
|
||||
value: {
|
||||
name: 'Account 1',
|
||||
subscriptions: ['music-posting.bso'],
|
||||
} as { name: string; subscriptions: string[] },
|
||||
}));
|
||||
|
||||
const subscriptionMocks = vi.hoisted(() => ({
|
||||
byAddress: new Map<string, { subscribed: boolean; subscribe: ReturnType<typeof vi.fn>; unsubscribe: ReturnType<typeof vi.fn> }>(),
|
||||
setAccount: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('react-i18next', () => ({
|
||||
useTranslation: () => ({
|
||||
t: (key: string) => key,
|
||||
}),
|
||||
}));
|
||||
|
||||
vi.mock('@bitsocialhq/bitsocial-react-hooks', () => ({
|
||||
useAccount: () => accountState.value,
|
||||
useSubscribe: ({ subplebbitAddress }: { subplebbitAddress: string }) =>
|
||||
subscriptionMocks.byAddress.get(subplebbitAddress) ?? {
|
||||
subscribed: false,
|
||||
subscribe: vi.fn(),
|
||||
unsubscribe: vi.fn(),
|
||||
},
|
||||
setAccount: subscriptionMocks.setAccount,
|
||||
}));
|
||||
|
||||
let root: Root;
|
||||
let container: HTMLDivElement;
|
||||
let confirmSpy: ReturnType<typeof vi.spyOn>;
|
||||
|
||||
const render = () => {
|
||||
act(() => {
|
||||
root.render(createElement(SubscriptionsSetting));
|
||||
});
|
||||
};
|
||||
|
||||
const getButtonByText = (text: string) => {
|
||||
const button = Array.from(container.querySelectorAll('[role="button"]')).find((candidate) => (candidate.textContent ?? '').includes(text));
|
||||
if (!button) {
|
||||
throw new Error(`Button containing "${text}" not found`);
|
||||
}
|
||||
return button;
|
||||
};
|
||||
|
||||
describe('SubscriptionsSetting', () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
accountState.value = {
|
||||
name: 'Account 1',
|
||||
subscriptions: ['music-posting.bso'],
|
||||
};
|
||||
subscriptionMocks.byAddress = new Map();
|
||||
subscriptionMocks.setAccount.mockReset();
|
||||
confirmSpy = vi.spyOn(window, 'confirm').mockImplementation(() => true);
|
||||
|
||||
container = document.createElement('div');
|
||||
document.body.appendChild(container);
|
||||
root = createRoot(container);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
act(() => root.unmount());
|
||||
container.remove();
|
||||
confirmSpy.mockRestore();
|
||||
});
|
||||
|
||||
it('shows the empty-state message when there are no subscriptions', () => {
|
||||
accountState.value = {
|
||||
name: 'Account 1',
|
||||
subscriptions: [],
|
||||
};
|
||||
|
||||
render();
|
||||
|
||||
expect(container.textContent).toContain('not_subscribed_to_any_board');
|
||||
});
|
||||
|
||||
it('unsubscribes from all boards after confirmation', async () => {
|
||||
accountState.value = {
|
||||
name: 'Account 1',
|
||||
subscriptions: ['music-posting.bso', 'business.eth'],
|
||||
};
|
||||
|
||||
render();
|
||||
|
||||
await act(async () => {
|
||||
getButtonByText('unsubscribe_all').dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
||||
});
|
||||
|
||||
expect(confirmSpy).toHaveBeenCalledWith('unsubscribe_all_confirm');
|
||||
expect(subscriptionMocks.setAccount).toHaveBeenCalledWith({
|
||||
name: 'Account 1',
|
||||
subscriptions: [],
|
||||
});
|
||||
});
|
||||
|
||||
it('does not unsubscribe from all boards when confirmation is cancelled', async () => {
|
||||
confirmSpy.mockReturnValueOnce(false);
|
||||
accountState.value = {
|
||||
name: 'Account 1',
|
||||
subscriptions: ['music-posting.bso', 'business.eth'],
|
||||
};
|
||||
|
||||
render();
|
||||
|
||||
await act(async () => {
|
||||
getButtonByText('unsubscribe_all').dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
||||
});
|
||||
|
||||
expect(subscriptionMocks.setAccount).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('toggles a board subscription with click and keyboard interaction', async () => {
|
||||
const subscribe = vi.fn();
|
||||
const unsubscribe = vi.fn();
|
||||
subscriptionMocks.byAddress.set('music-posting.bso', {
|
||||
subscribed: true,
|
||||
subscribe,
|
||||
unsubscribe,
|
||||
});
|
||||
|
||||
render();
|
||||
|
||||
const subscriptionButton = getButtonByText('unsubscribe');
|
||||
expect(subscriptionButton.textContent).toContain('unsubscribe');
|
||||
|
||||
await act(async () => {
|
||||
subscriptionButton.dispatchEvent(new MouseEvent('click', { bubbles: true }));
|
||||
});
|
||||
|
||||
expect(unsubscribe).toHaveBeenCalledOnce();
|
||||
expect(subscriptionButton.textContent).toContain('subscribe');
|
||||
|
||||
await act(async () => {
|
||||
subscriptionButton.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
|
||||
});
|
||||
|
||||
expect(subscribe).toHaveBeenCalledOnce();
|
||||
expect(subscriptionButton.textContent).toContain('unsubscribe');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user