Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 33 additions & 20 deletions packages/react/src/components/auth/AuthBoundary.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import {ResourceProvider} from '../../context/ResourceProvider'
import {useAuthState} from '../../hooks/auth/useAuthState'
import {useLoginUrl} from '../../hooks/auth/useLoginUrl'
import {useVerifyOrgProjects} from '../../hooks/auth/useVerifyOrgProjects'
import {useSanityInstance} from '../../hooks/context/useSanityInstance'
import {AuthBoundary} from './AuthBoundary'

// Mock hooks
Expand All @@ -23,9 +22,6 @@ vi.mock('../../hooks/auth/useHandleAuthCallback', () => ({
vi.mock('../../hooks/auth/useLogOut', () => ({
useLogOut: vi.fn(() => async () => {}),
}))
vi.mock('../../hooks/context/useSanityInstance', () => ({
useSanityInstance: vi.fn(),
}))

// Mock AuthError throwing scenario
vi.mock('./AuthError', async (importOriginal) => {
Expand Down Expand Up @@ -109,7 +105,6 @@ describe('AuthBoundary', () => {
const mockUseAuthState = vi.mocked(useAuthState)
const mockUseLoginUrl = vi.mocked(useLoginUrl)
const mockUseVerifyOrgProjects = vi.mocked(useVerifyOrgProjects)
const mockUseSanityInstance = vi.mocked(useSanityInstance)
const testProjectIds = ['proj-test'] // Example project ID for tests

// Mock Sanity instance
Expand Down Expand Up @@ -139,8 +134,6 @@ describe('AuthBoundary', () => {
mockUseLoginUrl.mockReturnValue('http://example.com/login')
// Default mock for useVerifyOrgProjects - returns null (no error)
mockUseVerifyOrgProjects.mockImplementation(() => null)
// Mock useSanityInstance to return our mock instance
mockUseSanityInstance.mockReturnValue(mockSanityInstance)
})

afterEach(() => {
Expand Down Expand Up @@ -170,7 +163,9 @@ describe('AuthBoundary', () => {
isExchangingToken: false,
})
const {container} = render(
<AuthBoundary projectIds={testProjectIds}>Protected Content</AuthBoundary>,
<ResourceProvider projectId="p" dataset="d" fallback={null}>
<AuthBoundary projectIds={testProjectIds}>Protected Content</AuthBoundary>
</ResourceProvider>,
)

// The callback screen renders null check that it renders nothing
Expand All @@ -184,7 +179,11 @@ describe('AuthBoundary', () => {
currentUser: null,
token: 'exampleToken',
})
render(<AuthBoundary projectIds={testProjectIds}>Protected Content</AuthBoundary>)
render(
<ResourceProvider projectId="p" dataset="d" fallback={null}>
<AuthBoundary projectIds={testProjectIds}>Protected Content</AuthBoundary>
</ResourceProvider>,
)

expect(screen.getByText('Protected Content')).toBeInTheDocument()
})
Expand All @@ -194,7 +193,11 @@ describe('AuthBoundary', () => {
type: AuthStateType.ERROR,
error: new Error('test error'),
})
render(<AuthBoundary projectIds={testProjectIds}>Protected Content</AuthBoundary>)
render(
<ResourceProvider projectId="p" dataset="d" fallback={null}>
<AuthBoundary projectIds={testProjectIds}>Protected Content</AuthBoundary>
</ResourceProvider>,
)

// The AuthBoundary should throw an AuthError internally
// and then display the LoginError component as the fallback.
Expand All @@ -207,7 +210,11 @@ describe('AuthBoundary', () => {
})

it('renders children when logged in and org verification passes', () => {
render(<AuthBoundary projectIds={testProjectIds}>Protected Content</AuthBoundary>)
render(
<ResourceProvider projectId="p" dataset="d" fallback={null}>
<AuthBoundary projectIds={testProjectIds}>Protected Content</AuthBoundary>
</ResourceProvider>,
)
expect(screen.getByText('Protected Content')).toBeInTheDocument()
})

Expand All @@ -226,9 +233,11 @@ describe('AuthBoundary', () => {

// Need to catch the error thrown during render. ErrorBoundary mock handles this.
render(
<AuthBoundary verifyOrganization={true} projectIds={testProjectIds}>
<div>Protected Content</div>
</AuthBoundary>,
<ResourceProvider projectId="p" dataset="d" fallback={null}>
<AuthBoundary verifyOrganization={true} projectIds={testProjectIds}>
<div>Protected Content</div>
</AuthBoundary>
</ResourceProvider>,
)

// The ErrorBoundary's FallbackComponent should be rendered
Expand Down Expand Up @@ -256,9 +265,11 @@ describe('AuthBoundary', () => {
})

render(
<AuthBoundary verifyOrganization={false} projectIds={testProjectIds}>
<div>Protected Content</div>
</AuthBoundary>,
<ResourceProvider projectId="p" dataset="d" fallback={null}>
<AuthBoundary verifyOrganization={false} projectIds={testProjectIds}>
<div>Protected Content</div>
</AuthBoundary>
</ResourceProvider>,
)

// Should render children because verification is disabled
Expand All @@ -279,9 +290,11 @@ describe('AuthBoundary', () => {
mockUseVerifyOrgProjects.mockImplementation(() => null)

render(
<AuthBoundary projectIds={testProjectIds}>
<div>Protected Content</div>
</AuthBoundary>,
<ResourceProvider projectId="p" dataset="d" fallback={null}>
<AuthBoundary projectIds={testProjectIds}>
<div>Protected Content</div>
</AuthBoundary>
</ResourceProvider>,
)

await waitFor(() => {
Expand Down
93 changes: 53 additions & 40 deletions packages/react/src/context/ComlinkTokenRefresh.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import {afterEach, beforeEach, describe, expect, it, type Mock, vi} from 'vitest

import {useAuthState} from '../hooks/auth/useAuthState'
import {useWindowConnection} from '../hooks/comlink/useWindowConnection'
import {useSanityInstance} from '../hooks/context/useSanityInstance'
import {ComlinkTokenRefreshProvider} from './ComlinkTokenRefresh'
import {ResourceProvider} from './ResourceProvider'

// Mocks
vi.mock('@sanity/sdk', async () => {
Expand All @@ -26,28 +26,20 @@ vi.mock('../hooks/comlink/useWindowConnection', () => ({
useWindowConnection: vi.fn(),
}))

vi.mock('../hooks/context/useSanityInstance', () => ({
useSanityInstance: vi.fn(),
}))

// Use simpler mock typings
const mockGetIsInDashboardState = getIsInDashboardState as Mock
const mockSetAuthToken = setAuthToken as Mock
const mockUseAuthState = useAuthState as Mock
const mockUseWindowConnection = useWindowConnection as Mock
const mockUseSanityInstance = useSanityInstance as Mock

const mockFetch = vi.fn()
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const mockSanityInstance: any = {projectId: 'test', dataset: 'test'}

describe('ComlinkTokenRefresh', () => {
beforeEach(() => {
vi.useFakeTimers()
mockGetIsInDashboardState.mockReturnValue({getCurrent: vi.fn(() => false)})
mockUseAuthState.mockReturnValue({type: AuthStateType.LOGGED_IN})
mockUseWindowConnection.mockReturnValue({fetch: mockFetch})
mockUseSanityInstance.mockReturnValue(mockSanityInstance)
})

afterEach(() => {
Expand All @@ -64,9 +56,11 @@ describe('ComlinkTokenRefresh', () => {
it('should not request new token on 401 if not in dashboard', async () => {
mockUseAuthState.mockReturnValue({type: AuthStateType.LOGGED_IN})
const {rerender} = render(
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>,
<ResourceProvider projectId="test-project" dataset="test-dataset" fallback={null}>
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>
</ResourceProvider>,
)

mockUseAuthState.mockReturnValue({
Expand All @@ -75,9 +69,11 @@ describe('ComlinkTokenRefresh', () => {
})
act(() => {
rerender(
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>,
<ResourceProvider projectId="test-project" dataset="test-dataset" fallback={null}>
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>
</ResourceProvider>,
)
})

Expand All @@ -95,9 +91,11 @@ describe('ComlinkTokenRefresh', () => {

it('should initialize useWindowConnection with correct parameters', () => {
render(
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>,
<ResourceProvider projectId="test-project" dataset="test-dataset" fallback={null}>
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>
</ResourceProvider>,
)

expect(mockUseWindowConnection).toHaveBeenCalledWith(
Expand All @@ -116,16 +114,18 @@ describe('ComlinkTokenRefresh', () => {
mockFetch.mockResolvedValueOnce({token: 'new-token'})

render(
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>,
<ResourceProvider projectId="test-project" dataset="test-dataset" fallback={null}>
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>
</ResourceProvider>,
)

await act(async () => {
await vi.advanceTimersByTimeAsync(100)
})

expect(mockSetAuthToken).toHaveBeenCalledWith(mockSanityInstance, 'new-token')
expect(mockSetAuthToken).toHaveBeenCalledWith(expect.any(Object), 'new-token')
expect(mockFetch).toHaveBeenCalledTimes(1)
})

Expand All @@ -137,9 +137,11 @@ describe('ComlinkTokenRefresh', () => {
mockFetch.mockResolvedValueOnce({token: null})

render(
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>,
<ResourceProvider projectId="test-project" dataset="test-dataset" fallback={null}>
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>
</ResourceProvider>,
)

await act(async () => {
Expand All @@ -157,9 +159,11 @@ describe('ComlinkTokenRefresh', () => {
mockFetch.mockRejectedValueOnce(new Error('Fetch failed'))

render(
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>,
<ResourceProvider projectId="test-project" dataset="test-dataset" fallback={null}>
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>
</ResourceProvider>,
)

await act(async () => {
Expand All @@ -173,9 +177,12 @@ describe('ComlinkTokenRefresh', () => {
it('should not request new token for non-401 errors', async () => {
mockUseAuthState.mockReturnValue({type: AuthStateType.LOGGED_IN})
const {rerender} = render(
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>,
<ResourceProvider fallback={null}>
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>
,
</ResourceProvider>,
)

mockUseAuthState.mockReturnValue({
Expand All @@ -184,9 +191,11 @@ describe('ComlinkTokenRefresh', () => {
})
act(() => {
rerender(
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>,
<ResourceProvider fallback={null}>
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>
</ResourceProvider>,
)
})

Expand All @@ -199,17 +208,21 @@ describe('ComlinkTokenRefresh', () => {
it('should request new token on LOGGED_OUT state', async () => {
mockUseAuthState.mockReturnValue({type: AuthStateType.LOGGED_IN})
const {rerender} = render(
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>,
<ResourceProvider fallback={null}>
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>
</ResourceProvider>,
)

mockUseAuthState.mockReturnValue({type: AuthStateType.LOGGED_OUT})
act(() => {
rerender(
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>,
<ResourceProvider fallback={null}>
<ComlinkTokenRefreshProvider>
<div>Test</div>
</ComlinkTokenRefreshProvider>
</ResourceProvider>,
)
})

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
import {createSanityInstance, getDashboardOrganizationId} from '@sanity/sdk'
import {getDashboardOrganizationId} from '@sanity/sdk'
import {renderHook} from '@testing-library/react'
import {throwError} from 'rxjs'
import {describe, expect, it, vi} from 'vitest'

import {ResourceProvider} from '../../context/ResourceProvider'
import {useDashboardOrganizationId} from './useDashboardOrganizationId'

vi.mock('../context/useSanityInstance', () => ({
useSanityInstance: vi.fn().mockReturnValue(createSanityInstance({projectId: 'p', dataset: 'd'})),
}))

vi.mock('@sanity/sdk', async (importOriginal) => {
const actual = await importOriginal()
return {...(actual || {}), getDashboardOrganizationId: vi.fn()}
Expand All @@ -23,7 +20,13 @@ describe('useDashboardOrganizationId', () => {
observable: throwError(() => new Error('Unexpected usage of observable')),
})

const {result} = renderHook(() => useDashboardOrganizationId())
const {result} = renderHook(() => useDashboardOrganizationId(), {
wrapper: ({children}) => (
<ResourceProvider projectId="test-project" dataset="test-dataset" fallback={null}>
{children}
</ResourceProvider>
),
})
expect(result.current).toBeUndefined()
})

Expand All @@ -36,7 +39,13 @@ describe('useDashboardOrganizationId', () => {
observable: throwError(() => new Error('Unexpected usage of observable')),
})

const {result} = renderHook(() => useDashboardOrganizationId())
const {result} = renderHook(() => useDashboardOrganizationId(), {
wrapper: ({children}) => (
<ResourceProvider projectId="test-project" dataset="test-dataset" fallback={null}>
{children}
</ResourceProvider>
),
})
expect(result.current).toBe(mockOrgId)
})
})
Loading
Loading