mirror of
https://github.com/tinyhumansai/openhuman.git
synced 2026-07-27 21:08:00 +00:00
Refactor OAuth provider tests for consistency and readability
- Updated test files for Discord, GitHub, Google, and Twitter to improve code consistency by standardizing async function formatting and import statements. - Enhanced readability by restructuring promise resolutions and waitFor assertions. - Ensured uniformity in the handling of button click events across all OAuth provider tests.
This commit is contained in:
@@ -9,13 +9,13 @@
|
||||
* - Error handling when backend URL lookup fails
|
||||
* - dev-mode URL construction (?responseType=json)
|
||||
*/
|
||||
import type { ComponentProps } from 'react';
|
||||
import { act, fireEvent, screen, waitFor } from '@testing-library/react';
|
||||
import type { ComponentProps } from 'react';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { renderWithProviders } from '../src/test/test-utils';
|
||||
import OAuthProviderButton from '../src/components/oauth/OAuthProviderButton';
|
||||
import { oauthProviderConfigs } from '../src/components/oauth/providerConfigs';
|
||||
import { renderWithProviders } from '../src/test/test-utils';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Module mocks
|
||||
@@ -29,7 +29,7 @@ const { mockGetBackendUrl, mockOpenUrl, mockIsTauri } = vi.hoisted(() => ({
|
||||
|
||||
vi.mock('../src/services/backendUrl', () => ({ getBackendUrl: mockGetBackendUrl }));
|
||||
vi.mock('../src/utils/openUrl', () => ({ openUrl: mockOpenUrl }));
|
||||
vi.mock('../src/utils/tauriCommands', async (importOriginal) => {
|
||||
vi.mock('../src/utils/tauriCommands', async importOriginal => {
|
||||
const actual = await importOriginal<Record<string, unknown>>();
|
||||
return { ...actual, isTauri: mockIsTauri };
|
||||
});
|
||||
@@ -43,7 +43,10 @@ const discordConfig = oauthProviderConfigs.find(p => p.id === 'discord')!;
|
||||
const renderDiscordButton = (props: Partial<ComponentProps<typeof OAuthProviderButton>> = {}) =>
|
||||
renderWithProviders(<OAuthProviderButton provider={discordConfig} {...props} />);
|
||||
|
||||
const clickButton = (btn: HTMLElement) => act(async () => { fireEvent.click(btn); });
|
||||
const clickButton = (btn: HTMLElement) =>
|
||||
act(async () => {
|
||||
fireEvent.click(btn);
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Rendering
|
||||
@@ -115,9 +118,7 @@ describe('OAuthProviderButton (Discord) — web OAuth flow', () => {
|
||||
renderDiscordButton();
|
||||
await clickButton(screen.getByRole('button', { name: /discord/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect((window.location as unknown as { href: string }).href).not.toBe('')
|
||||
);
|
||||
await waitFor(() => expect((window.location as unknown as { href: string }).href).not.toBe(''));
|
||||
expect(mockOpenUrl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -125,9 +126,7 @@ describe('OAuthProviderButton (Discord) — web OAuth flow', () => {
|
||||
renderDiscordButton();
|
||||
await clickButton(screen.getByRole('button', { name: /discord/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect((window.location as unknown as { href: string }).href).not.toBe('')
|
||||
);
|
||||
await waitFor(() => expect((window.location as unknown as { href: string }).href).not.toBe(''));
|
||||
expect(mockGetBackendUrl).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@@ -180,7 +179,11 @@ describe('OAuthProviderButton (Discord) — Tauri OAuth flow', () => {
|
||||
describe('OAuthProviderButton (Discord) — loading state', () => {
|
||||
it('shows spinner and "Connecting..." while getBackendUrl is pending', async () => {
|
||||
let resolve!: (_v: string) => void;
|
||||
mockGetBackendUrl.mockReturnValue(new Promise<string>(res => { resolve = res; }));
|
||||
mockGetBackendUrl.mockReturnValue(
|
||||
new Promise<string>(res => {
|
||||
resolve = res;
|
||||
})
|
||||
);
|
||||
mockIsTauri.mockReturnValue(false);
|
||||
|
||||
renderDiscordButton();
|
||||
@@ -191,12 +194,18 @@ describe('OAuthProviderButton (Discord) — loading state', () => {
|
||||
expect(document.querySelector('.animate-spin')).toBeInTheDocument();
|
||||
expect(button).toBeDisabled();
|
||||
|
||||
await act(async () => { resolve('http://localhost:5005'); });
|
||||
await act(async () => {
|
||||
resolve('http://localhost:5005');
|
||||
});
|
||||
});
|
||||
|
||||
it('ignores a second click while already loading', async () => {
|
||||
let resolve!: (_v: string) => void;
|
||||
mockGetBackendUrl.mockReturnValue(new Promise<string>(res => { resolve = res; }));
|
||||
mockGetBackendUrl.mockReturnValue(
|
||||
new Promise<string>(res => {
|
||||
resolve = res;
|
||||
})
|
||||
);
|
||||
mockIsTauri.mockReturnValue(false);
|
||||
|
||||
renderDiscordButton();
|
||||
@@ -208,7 +217,9 @@ describe('OAuthProviderButton (Discord) — loading state', () => {
|
||||
fireEvent.click(button);
|
||||
expect(mockGetBackendUrl).toHaveBeenCalledTimes(1);
|
||||
|
||||
await act(async () => { resolve('http://localhost:5005'); });
|
||||
await act(async () => {
|
||||
resolve('http://localhost:5005');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -242,9 +253,7 @@ describe('OAuthProviderButton (Discord) — error handling', () => {
|
||||
renderDiscordButton();
|
||||
await clickButton(screen.getByRole('button', { name: /discord/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.getByRole('button', { name: /discord/i })).toBeEnabled()
|
||||
);
|
||||
await waitFor(() => expect(screen.getByRole('button', { name: /discord/i })).toBeEnabled());
|
||||
expect((window.location as unknown as { href: string }).href).toBe('');
|
||||
|
||||
(window as unknown as Record<string, unknown>).location = originalLocation;
|
||||
@@ -257,9 +266,7 @@ describe('OAuthProviderButton (Discord) — error handling', () => {
|
||||
renderDiscordButton();
|
||||
await clickButton(screen.getByRole('button', { name: /discord/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.getByRole('button', { name: /discord/i })).toBeEnabled()
|
||||
);
|
||||
await waitFor(() => expect(screen.getByRole('button', { name: /discord/i })).toBeEnabled());
|
||||
expect(mockOpenUrl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
* - Error handling when backend URL lookup fails
|
||||
* - dev-mode URL construction (?responseType=json)
|
||||
*/
|
||||
import type { ComponentProps } from 'react';
|
||||
import { act, fireEvent, screen, waitFor } from '@testing-library/react';
|
||||
import type { ComponentProps } from 'react';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { renderWithProviders } from '../src/test/test-utils';
|
||||
import OAuthProviderButton from '../src/components/oauth/OAuthProviderButton';
|
||||
import { oauthProviderConfigs } from '../src/components/oauth/providerConfigs';
|
||||
import { renderWithProviders } from '../src/test/test-utils';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Module mocks
|
||||
@@ -29,7 +29,7 @@ const { mockGetBackendUrl, mockOpenUrl, mockIsTauri } = vi.hoisted(() => ({
|
||||
|
||||
vi.mock('../src/services/backendUrl', () => ({ getBackendUrl: mockGetBackendUrl }));
|
||||
vi.mock('../src/utils/openUrl', () => ({ openUrl: mockOpenUrl }));
|
||||
vi.mock('../src/utils/tauriCommands', async (importOriginal) => {
|
||||
vi.mock('../src/utils/tauriCommands', async importOriginal => {
|
||||
const actual = await importOriginal<Record<string, unknown>>();
|
||||
return { ...actual, isTauri: mockIsTauri };
|
||||
});
|
||||
@@ -43,7 +43,10 @@ const githubConfig = oauthProviderConfigs.find(p => p.id === 'github')!;
|
||||
const renderGitHubButton = (props: Partial<ComponentProps<typeof OAuthProviderButton>> = {}) =>
|
||||
renderWithProviders(<OAuthProviderButton provider={githubConfig} {...props} />);
|
||||
|
||||
const clickButton = (btn: HTMLElement) => act(async () => { fireEvent.click(btn); });
|
||||
const clickButton = (btn: HTMLElement) =>
|
||||
act(async () => {
|
||||
fireEvent.click(btn);
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Rendering
|
||||
@@ -115,9 +118,7 @@ describe('OAuthProviderButton (GitHub) — web OAuth flow', () => {
|
||||
renderGitHubButton();
|
||||
await clickButton(screen.getByRole('button', { name: /github/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect((window.location as unknown as { href: string }).href).not.toBe('')
|
||||
);
|
||||
await waitFor(() => expect((window.location as unknown as { href: string }).href).not.toBe(''));
|
||||
expect(mockOpenUrl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -125,9 +126,7 @@ describe('OAuthProviderButton (GitHub) — web OAuth flow', () => {
|
||||
renderGitHubButton();
|
||||
await clickButton(screen.getByRole('button', { name: /github/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect((window.location as unknown as { href: string }).href).not.toBe('')
|
||||
);
|
||||
await waitFor(() => expect((window.location as unknown as { href: string }).href).not.toBe(''));
|
||||
expect(mockGetBackendUrl).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@@ -180,7 +179,11 @@ describe('OAuthProviderButton (GitHub) — Tauri OAuth flow', () => {
|
||||
describe('OAuthProviderButton (GitHub) — loading state', () => {
|
||||
it('shows spinner and "Connecting..." while getBackendUrl is pending', async () => {
|
||||
let resolve!: (_v: string) => void;
|
||||
mockGetBackendUrl.mockReturnValue(new Promise<string>(res => { resolve = res; }));
|
||||
mockGetBackendUrl.mockReturnValue(
|
||||
new Promise<string>(res => {
|
||||
resolve = res;
|
||||
})
|
||||
);
|
||||
mockIsTauri.mockReturnValue(false);
|
||||
|
||||
renderGitHubButton();
|
||||
@@ -191,12 +194,18 @@ describe('OAuthProviderButton (GitHub) — loading state', () => {
|
||||
expect(document.querySelector('.animate-spin')).toBeInTheDocument();
|
||||
expect(button).toBeDisabled();
|
||||
|
||||
await act(async () => { resolve('http://localhost:5005'); });
|
||||
await act(async () => {
|
||||
resolve('http://localhost:5005');
|
||||
});
|
||||
});
|
||||
|
||||
it('ignores a second click while already loading', async () => {
|
||||
let resolve!: (_v: string) => void;
|
||||
mockGetBackendUrl.mockReturnValue(new Promise<string>(res => { resolve = res; }));
|
||||
mockGetBackendUrl.mockReturnValue(
|
||||
new Promise<string>(res => {
|
||||
resolve = res;
|
||||
})
|
||||
);
|
||||
mockIsTauri.mockReturnValue(false);
|
||||
|
||||
renderGitHubButton();
|
||||
@@ -208,7 +217,9 @@ describe('OAuthProviderButton (GitHub) — loading state', () => {
|
||||
fireEvent.click(button);
|
||||
expect(mockGetBackendUrl).toHaveBeenCalledTimes(1);
|
||||
|
||||
await act(async () => { resolve('http://localhost:5005'); });
|
||||
await act(async () => {
|
||||
resolve('http://localhost:5005');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -242,9 +253,7 @@ describe('OAuthProviderButton (GitHub) — error handling', () => {
|
||||
renderGitHubButton();
|
||||
await clickButton(screen.getByRole('button', { name: /github/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.getByRole('button', { name: /github/i })).toBeEnabled()
|
||||
);
|
||||
await waitFor(() => expect(screen.getByRole('button', { name: /github/i })).toBeEnabled());
|
||||
expect((window.location as unknown as { href: string }).href).toBe('');
|
||||
|
||||
(window as unknown as Record<string, unknown>).location = originalLocation;
|
||||
@@ -257,9 +266,7 @@ describe('OAuthProviderButton (GitHub) — error handling', () => {
|
||||
renderGitHubButton();
|
||||
await clickButton(screen.getByRole('button', { name: /github/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.getByRole('button', { name: /github/i })).toBeEnabled()
|
||||
);
|
||||
await waitFor(() => expect(screen.getByRole('button', { name: /github/i })).toBeEnabled());
|
||||
expect(mockOpenUrl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
* - Error handling when the backend URL lookup fails
|
||||
* - dev-mode URL construction (responseType=json query param)
|
||||
*/
|
||||
import type { ComponentProps } from 'react';
|
||||
import { act, fireEvent, screen, waitFor } from '@testing-library/react';
|
||||
import type { ComponentProps } from 'react';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { renderWithProviders } from '../src/test/test-utils';
|
||||
import OAuthLoginSection from '../src/components/oauth/OAuthLoginSection';
|
||||
import OAuthProviderButton from '../src/components/oauth/OAuthProviderButton';
|
||||
import { oauthProviderConfigs } from '../src/components/oauth/providerConfigs';
|
||||
import { renderWithProviders } from '../src/test/test-utils';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Module mocks
|
||||
@@ -30,15 +30,11 @@ const { mockGetBackendUrl, mockOpenUrl, mockIsTauri } = vi.hoisted(() => ({
|
||||
mockIsTauri: vi.fn(),
|
||||
}));
|
||||
|
||||
vi.mock('../src/services/backendUrl', () => ({
|
||||
getBackendUrl: mockGetBackendUrl,
|
||||
}));
|
||||
vi.mock('../src/services/backendUrl', () => ({ getBackendUrl: mockGetBackendUrl }));
|
||||
|
||||
vi.mock('../src/utils/openUrl', () => ({
|
||||
openUrl: mockOpenUrl,
|
||||
}));
|
||||
vi.mock('../src/utils/openUrl', () => ({ openUrl: mockOpenUrl }));
|
||||
|
||||
vi.mock('../src/utils/tauriCommands', async (importOriginal) => {
|
||||
vi.mock('../src/utils/tauriCommands', async importOriginal => {
|
||||
const actual = await importOriginal<Record<string, unknown>>();
|
||||
return { ...actual, isTauri: mockIsTauri };
|
||||
});
|
||||
@@ -58,7 +54,10 @@ const renderGoogleButton = (props: Partial<ComponentProps<typeof OAuthProviderBu
|
||||
renderWithProviders(<OAuthProviderButton provider={googleConfig} {...props} />);
|
||||
|
||||
// act() with an async callback returns Promise<void>, making await valid.
|
||||
const clickButton = (btn: HTMLElement) => act(async () => { fireEvent.click(btn); });
|
||||
const clickButton = (btn: HTMLElement) =>
|
||||
act(async () => {
|
||||
fireEvent.click(btn);
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// OAuthLoginSection — rendering
|
||||
@@ -170,9 +169,7 @@ describe('OAuthProviderButton (Google) — web OAuth flow', () => {
|
||||
renderGoogleButton();
|
||||
await clickButton(screen.getByRole('button', { name: /google/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect((window.location as unknown as { href: string }).href).not.toBe('')
|
||||
);
|
||||
await waitFor(() => expect((window.location as unknown as { href: string }).href).not.toBe(''));
|
||||
expect(mockOpenUrl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -180,9 +177,7 @@ describe('OAuthProviderButton (Google) — web OAuth flow', () => {
|
||||
renderGoogleButton();
|
||||
await clickButton(screen.getByRole('button', { name: /google/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect((window.location as unknown as { href: string }).href).not.toBe('')
|
||||
);
|
||||
await waitFor(() => expect((window.location as unknown as { href: string }).href).not.toBe(''));
|
||||
expect(mockGetBackendUrl).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@@ -227,7 +222,9 @@ describe('OAuthProviderButton (Google) — loading state', () => {
|
||||
it('shows spinner and "Connecting..." text while login is in progress', async () => {
|
||||
let resolveBackendUrl!: (_v: string) => void;
|
||||
mockGetBackendUrl.mockReturnValue(
|
||||
new Promise<string>(res => { resolveBackendUrl = res; })
|
||||
new Promise<string>(res => {
|
||||
resolveBackendUrl = res;
|
||||
})
|
||||
);
|
||||
mockIsTauri.mockReturnValue(false);
|
||||
|
||||
@@ -241,13 +238,17 @@ describe('OAuthProviderButton (Google) — loading state', () => {
|
||||
expect(button).toBeDisabled();
|
||||
|
||||
// Settle the promise so React doesn't warn about state updates after unmount
|
||||
await act(async () => { resolveBackendUrl('http://localhost:5005'); });
|
||||
await act(async () => {
|
||||
resolveBackendUrl('http://localhost:5005');
|
||||
});
|
||||
});
|
||||
|
||||
it('does not respond to a second click while already loading', async () => {
|
||||
let resolveBackendUrl!: (_v: string) => void;
|
||||
mockGetBackendUrl.mockReturnValue(
|
||||
new Promise<string>(res => { resolveBackendUrl = res; })
|
||||
new Promise<string>(res => {
|
||||
resolveBackendUrl = res;
|
||||
})
|
||||
);
|
||||
mockIsTauri.mockReturnValue(false);
|
||||
|
||||
@@ -261,7 +262,9 @@ describe('OAuthProviderButton (Google) — loading state', () => {
|
||||
fireEvent.click(button);
|
||||
expect(mockGetBackendUrl).toHaveBeenCalledTimes(1);
|
||||
|
||||
await act(async () => { resolveBackendUrl('http://localhost:5005'); });
|
||||
await act(async () => {
|
||||
resolveBackendUrl('http://localhost:5005');
|
||||
});
|
||||
});
|
||||
|
||||
it('remains in loading state after successful Tauri openUrl (awaits deep-link callback)', async () => {
|
||||
@@ -311,9 +314,7 @@ describe('OAuthProviderButton (Google) — error handling', () => {
|
||||
renderGoogleButton();
|
||||
await clickButton(screen.getByRole('button', { name: /google/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.getByRole('button', { name: /google/i })).toBeEnabled()
|
||||
);
|
||||
await waitFor(() => expect(screen.getByRole('button', { name: /google/i })).toBeEnabled());
|
||||
expect((window.location as unknown as { href: string }).href).toBe('');
|
||||
|
||||
(window as unknown as Record<string, unknown>).location = originalLocation;
|
||||
@@ -326,9 +327,7 @@ describe('OAuthProviderButton (Google) — error handling', () => {
|
||||
renderGoogleButton();
|
||||
await clickButton(screen.getByRole('button', { name: /google/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.getByRole('button', { name: /google/i })).toBeEnabled()
|
||||
);
|
||||
await waitFor(() => expect(screen.getByRole('button', { name: /google/i })).toBeEnabled());
|
||||
expect(mockOpenUrl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -371,9 +370,7 @@ describe('OAuthProviderButton (Google) — dev mode URL params', () => {
|
||||
renderGoogleButton();
|
||||
await clickButton(screen.getByRole('button', { name: /google/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect((window.location as unknown as { href: string }).href).not.toBe('')
|
||||
);
|
||||
await waitFor(() => expect((window.location as unknown as { href: string }).href).not.toBe(''));
|
||||
expect((window.location as unknown as { href: string }).href).toBe(
|
||||
'https://api.example.com/auth/google/login?responseType=json'
|
||||
);
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
* - Error handling when backend URL lookup fails
|
||||
* - dev-mode URL construction (?responseType=json)
|
||||
*/
|
||||
import type { ComponentProps } from 'react';
|
||||
import { act, fireEvent, screen, waitFor } from '@testing-library/react';
|
||||
import type { ComponentProps } from 'react';
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { renderWithProviders } from '../src/test/test-utils';
|
||||
import OAuthProviderButton from '../src/components/oauth/OAuthProviderButton';
|
||||
import { oauthProviderConfigs } from '../src/components/oauth/providerConfigs';
|
||||
import { renderWithProviders } from '../src/test/test-utils';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Module mocks
|
||||
@@ -29,7 +29,7 @@ const { mockGetBackendUrl, mockOpenUrl, mockIsTauri } = vi.hoisted(() => ({
|
||||
|
||||
vi.mock('../src/services/backendUrl', () => ({ getBackendUrl: mockGetBackendUrl }));
|
||||
vi.mock('../src/utils/openUrl', () => ({ openUrl: mockOpenUrl }));
|
||||
vi.mock('../src/utils/tauriCommands', async (importOriginal) => {
|
||||
vi.mock('../src/utils/tauriCommands', async importOriginal => {
|
||||
const actual = await importOriginal<Record<string, unknown>>();
|
||||
return { ...actual, isTauri: mockIsTauri };
|
||||
});
|
||||
@@ -43,7 +43,10 @@ const twitterConfig = oauthProviderConfigs.find(p => p.id === 'twitter')!;
|
||||
const renderTwitterButton = (props: Partial<ComponentProps<typeof OAuthProviderButton>> = {}) =>
|
||||
renderWithProviders(<OAuthProviderButton provider={twitterConfig} {...props} />);
|
||||
|
||||
const clickButton = (btn: HTMLElement) => act(async () => { fireEvent.click(btn); });
|
||||
const clickButton = (btn: HTMLElement) =>
|
||||
act(async () => {
|
||||
fireEvent.click(btn);
|
||||
});
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Rendering
|
||||
@@ -115,9 +118,7 @@ describe('OAuthProviderButton (Twitter) — web OAuth flow', () => {
|
||||
renderTwitterButton();
|
||||
await clickButton(screen.getByRole('button', { name: /twitter/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect((window.location as unknown as { href: string }).href).not.toBe('')
|
||||
);
|
||||
await waitFor(() => expect((window.location as unknown as { href: string }).href).not.toBe(''));
|
||||
expect(mockOpenUrl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
@@ -125,9 +126,7 @@ describe('OAuthProviderButton (Twitter) — web OAuth flow', () => {
|
||||
renderTwitterButton();
|
||||
await clickButton(screen.getByRole('button', { name: /twitter/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect((window.location as unknown as { href: string }).href).not.toBe('')
|
||||
);
|
||||
await waitFor(() => expect((window.location as unknown as { href: string }).href).not.toBe(''));
|
||||
expect(mockGetBackendUrl).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
@@ -180,7 +179,11 @@ describe('OAuthProviderButton (Twitter) — Tauri OAuth flow', () => {
|
||||
describe('OAuthProviderButton (Twitter) — loading state', () => {
|
||||
it('shows spinner and "Connecting..." while getBackendUrl is pending', async () => {
|
||||
let resolve!: (_v: string) => void;
|
||||
mockGetBackendUrl.mockReturnValue(new Promise<string>(res => { resolve = res; }));
|
||||
mockGetBackendUrl.mockReturnValue(
|
||||
new Promise<string>(res => {
|
||||
resolve = res;
|
||||
})
|
||||
);
|
||||
mockIsTauri.mockReturnValue(false);
|
||||
|
||||
renderTwitterButton();
|
||||
@@ -191,12 +194,18 @@ describe('OAuthProviderButton (Twitter) — loading state', () => {
|
||||
expect(document.querySelector('.animate-spin')).toBeInTheDocument();
|
||||
expect(button).toBeDisabled();
|
||||
|
||||
await act(async () => { resolve('http://localhost:5005'); });
|
||||
await act(async () => {
|
||||
resolve('http://localhost:5005');
|
||||
});
|
||||
});
|
||||
|
||||
it('ignores a second click while already loading', async () => {
|
||||
let resolve!: (_v: string) => void;
|
||||
mockGetBackendUrl.mockReturnValue(new Promise<string>(res => { resolve = res; }));
|
||||
mockGetBackendUrl.mockReturnValue(
|
||||
new Promise<string>(res => {
|
||||
resolve = res;
|
||||
})
|
||||
);
|
||||
mockIsTauri.mockReturnValue(false);
|
||||
|
||||
renderTwitterButton();
|
||||
@@ -208,7 +217,9 @@ describe('OAuthProviderButton (Twitter) — loading state', () => {
|
||||
fireEvent.click(button);
|
||||
expect(mockGetBackendUrl).toHaveBeenCalledTimes(1);
|
||||
|
||||
await act(async () => { resolve('http://localhost:5005'); });
|
||||
await act(async () => {
|
||||
resolve('http://localhost:5005');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -242,9 +253,7 @@ describe('OAuthProviderButton (Twitter) — error handling', () => {
|
||||
renderTwitterButton();
|
||||
await clickButton(screen.getByRole('button', { name: /twitter/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.getByRole('button', { name: /twitter/i })).toBeEnabled()
|
||||
);
|
||||
await waitFor(() => expect(screen.getByRole('button', { name: /twitter/i })).toBeEnabled());
|
||||
expect((window.location as unknown as { href: string }).href).toBe('');
|
||||
|
||||
(window as unknown as Record<string, unknown>).location = originalLocation;
|
||||
@@ -257,9 +266,7 @@ describe('OAuthProviderButton (Twitter) — error handling', () => {
|
||||
renderTwitterButton();
|
||||
await clickButton(screen.getByRole('button', { name: /twitter/i }));
|
||||
|
||||
await waitFor(() =>
|
||||
expect(screen.getByRole('button', { name: /twitter/i })).toBeEnabled()
|
||||
);
|
||||
await waitFor(() => expect(screen.getByRole('button', { name: /twitter/i })).toBeEnabled());
|
||||
expect(mockOpenUrl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["vitest/globals", "@testing-library/jest-dom", "node"]
|
||||
},
|
||||
"compilerOptions": { "types": ["vitest/globals", "@testing-library/jest-dom", "node"] },
|
||||
"include": ["../src", "./*.test.ts", "./*.test.tsx"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user