-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
414 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import { Room } from '@ably/chat'; | ||
import { describe, expect, it, vi } from 'vitest'; | ||
|
||
import { wrapRoomPromise } from '../../../src/react/helper/room-promise.ts'; | ||
import { makeTestLogger } from '../../helper/logger.ts'; | ||
import { makeRandomRoom } from '../../helper/room.ts'; | ||
|
||
describe('room-promise', () => { | ||
it('should mount and unmount with promise resolution', async () => { | ||
let shouldResolve = false; | ||
let hasResolved = false; | ||
const roomPromise = new Promise<Room>((resolve) => { | ||
const interval = setInterval(() => { | ||
if (shouldResolve) { | ||
clearInterval(interval); | ||
resolve(makeRandomRoom({})); | ||
} | ||
}, 150); | ||
}); | ||
|
||
// Wrap the promise | ||
let hasUnmounted = false; | ||
const wrapped = wrapRoomPromise( | ||
roomPromise, | ||
(room) => { | ||
hasResolved = true; | ||
expect(room).toBeDefined(); | ||
|
||
return () => { | ||
hasUnmounted = true; | ||
}; | ||
}, | ||
makeTestLogger(), | ||
'test-room', | ||
); | ||
|
||
// Now say the promise should resolve | ||
shouldResolve = true; | ||
await vi.waitFor(() => { | ||
expect(hasResolved).toBe(true); | ||
}); | ||
|
||
// Now call unmount | ||
wrapped.unmount()(); | ||
|
||
expect(hasUnmounted).toBe(true); | ||
}); | ||
|
||
it('should mount and unmount before promise resolution', async () => { | ||
let shouldResolve = false; | ||
const roomPromise = new Promise<Room>((resolve) => { | ||
const interval = setInterval(() => { | ||
if (shouldResolve) { | ||
clearInterval(interval); | ||
resolve(makeRandomRoom({})); | ||
} | ||
}, 150); | ||
}); | ||
|
||
// Wrap the promise | ||
const wrapped = wrapRoomPromise( | ||
roomPromise, | ||
() => { | ||
// Should never be called | ||
expect(true).toBe(false); | ||
|
||
return () => { | ||
expect(true).toBe(false); | ||
}; | ||
}, | ||
makeTestLogger(), | ||
'test-room', | ||
); | ||
|
||
// Now call unmount | ||
wrapped.unmount()(); | ||
|
||
// Now say the promise should resolve | ||
shouldResolve = true; | ||
|
||
// Wait for 5 intervals of 150ms to confirm the callback was never called | ||
for (let i = 0; i < 5; i++) { | ||
await new Promise((resolve) => setTimeout(resolve, 150)); | ||
} | ||
|
||
// Calling unmount again should be a noop | ||
wrapped.unmount()(); | ||
|
||
// Wait for another set of intervals to confirm the callback was never called | ||
for (let i = 0; i < 5; i++) { | ||
await new Promise((resolve) => setTimeout(resolve, 150)); | ||
} | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
import { Logger, Room, RoomLifecycle, RoomOptionsDefaults, RoomStatusChange } from "@ably/chat"; | ||
Check failure on line 1 in test/react/helper/use-eventual-room.test.tsx GitHub Actions / lint
|
||
import { cleanup, renderHook } from "@testing-library/react"; | ||
import * as Ably from 'ably'; | ||
import { afterEach,beforeEach,describe, expect, it, vi } from "vitest"; | ||
|
||
import { InternalRoomStatus } from "../../../src/core/room-status.ts"; | ||
import { useEventualRoom, useEventualRoomProperty } from "../../../src/react/helper/use-eventual-room.ts"; | ||
import { useRoomStatus } from "../../../src/react/helper/use-room-status.ts"; | ||
import { makeTestLogger } from "../../helper/logger.ts"; | ||
import { makeRandomRoom } from "../../helper/room.ts"; | ||
import { waitForEventualHookValue } from "../../helper/wait-for-eventual-hook.ts"; | ||
|
||
let mockRoom: Room; | ||
let mockRoomContext: { room: Promise<Room> }; | ||
let mockLogger: Logger | ||
|
||
vi.mock('../../../src/react/helper/use-room-context.js', () => ({ | ||
useRoomContext: () => mockRoomContext, | ||
})); | ||
|
||
vi.mock('../../../src/react/hooks/use-logger.js', () => ({ | ||
useLogger: () => mockLogger, | ||
})); | ||
|
||
vi.mock('ably'); | ||
|
||
const updateMockRoom = (newRoom: Room) => { | ||
mockRoom = newRoom; | ||
mockRoomContext = { room: Promise.resolve(newRoom) }; | ||
}; | ||
|
||
describe('eventual rooms', () => { | ||
beforeEach(() => { | ||
mockLogger = makeTestLogger(); | ||
updateMockRoom(makeRandomRoom({ options: RoomOptionsDefaults})); | ||
}); | ||
|
||
afterEach(() => { | ||
cleanup(); | ||
}); | ||
|
||
describe('useEventualRoom', () => { | ||
it('returns the room', async () => { | ||
const {result} = renderHook(() => useEventualRoom()); | ||
|
||
// We should start with the room being undefined | ||
expect(result.current).toBeUndefined(); | ||
|
||
// Eventually, the room should resolve | ||
await vi.waitFor(() => { expect(result.current).toBe(mockRoom); }); | ||
}); | ||
|
||
it('updates the room', async () => { | ||
const {result, rerender} = renderHook(() => useEventualRoom()); | ||
|
||
// We should start with the room being undefined | ||
expect(result.current).toBeUndefined(); | ||
|
||
// Eventually, the room should resolve | ||
await vi.waitFor(() => { expect(result.current).toBe(mockRoom); }); | ||
|
||
// Now update the room and re-render | ||
const newRoom = makeRandomRoom({ options: RoomOptionsDefaults}); | ||
updateMockRoom(newRoom); | ||
|
||
rerender(); | ||
|
||
// Eventually, the room should resolve | ||
await vi.waitFor(() => { expect(result.current).toBe(newRoom); }); | ||
}); | ||
}); | ||
|
||
describe('useEventualRoomProperty', () => { | ||
it('returns the room property', async () => { | ||
const {result} = renderHook(() => useEventualRoomProperty(() => mockRoom.messages)); | ||
|
||
// We should start with the room being undefined | ||
expect(result.current).toBeUndefined(); | ||
|
||
// Eventually, the room should resolve | ||
await vi.waitFor(() => { expect(result.current).toBe(mockRoom.messages); }); | ||
}); | ||
|
||
it('updates the room property', async () => { | ||
const {result, rerender} = renderHook(() => useEventualRoomProperty(() => mockRoom.messages)); | ||
|
||
// We should start with the room being undefined | ||
expect(result.current).toBeUndefined(); | ||
|
||
// Eventually, the room should resolve | ||
await vi.waitFor(() => { expect(result.current).toBe(mockRoom.messages); }); | ||
|
||
// Now update the room and re-render | ||
const newRoom = makeRandomRoom({ options: RoomOptionsDefaults}); | ||
updateMockRoom(newRoom); | ||
|
||
rerender(); | ||
|
||
// Eventually, the room should resolve | ||
await vi.waitFor(() => { expect(result.current).toBe(newRoom.messages); }); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import { ChatClient, RoomOptionsDefaults } from "@ably/chat"; | ||
import { cleanup, render } from "@testing-library/react"; | ||
import { afterEach,describe, expect, it } from "vitest"; | ||
|
||
import { useRoomContext } from "../../../src/react/helper/use-room-context.ts"; | ||
import { ChatRoomProvider } from "../../../src/react/index.ts"; | ||
import { ChatClientProvider } from "../../../src/react/providers/chat-client-provider.tsx"; | ||
import { newChatClient as newChatClientLib } from "../../helper/chat.ts"; | ||
|
||
function newChatClient() { | ||
return newChatClientLib() as unknown as ChatClient; | ||
} | ||
|
||
describe('useRoom', () => { | ||
afterEach(() => { | ||
cleanup(); | ||
}); | ||
|
||
it('should throw an error if used outside of ChatRoomProvider', () => { | ||
const chatClient = newChatClient(); | ||
|
||
const TestThrowError: React.FC = () => { | ||
expect(() => useRoomContext('foo')).toThrowErrorInfo({ | ||
code: 40000, | ||
message: 'foo hook must be used within a <ChatRoomProvider>', | ||
}); | ||
return null; | ||
}; | ||
|
||
const TestProvider = () => ( | ||
<ChatClientProvider client={chatClient}> | ||
<TestThrowError /> | ||
</ChatClientProvider> | ||
); | ||
|
||
render(<TestProvider />); | ||
}); | ||
|
||
it('should return the context if used within ChatRoomProvider', () => { | ||
const chatClient = newChatClient(); | ||
|
||
const TestUseRoom: React.FC = () => { | ||
const context = useRoomContext('foo'); | ||
expect(context).toBeDefined(); | ||
expect(context.roomId).toBe('foo'); | ||
expect(context.options).toBe(RoomOptionsDefaults); | ||
return null; | ||
}; | ||
|
||
const TestProvider = () => ( | ||
<ChatClientProvider client={chatClient}> | ||
<ChatRoomProvider id="foo" options={RoomOptionsDefaults}> | ||
<TestUseRoom /> | ||
</ChatRoomProvider> | ||
</ChatClientProvider> | ||
); | ||
|
||
render(<TestProvider />); | ||
}); | ||
}); |
Oops, something went wrong.