diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml index a0e0b0f2..00e30704 100644 --- a/.github/workflows/dev.yml +++ b/.github/workflows/dev.yml @@ -40,6 +40,17 @@ jobs: node-version: 20 - run: npm ci - run: npm run lint + test-typescript: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + with: + submodules: true + - uses: actions/setup-node@v1 + with: + node-version: 20 + - run: npm ci + - run: npm run test:typescript test: runs-on: ubuntu-latest steps: diff --git a/package.json b/package.json index 57b71508..2b0ee58a 100644 --- a/package.json +++ b/package.json @@ -22,6 +22,7 @@ "test:watch": "vitest watch", "build": "vite build", "prepare": "npm run build", + "test:typescript": "tsc --project tsconfig.test.json", "demo:reload": "npm run build && cd demo && npm i file:../", "docs": "typedoc", "modulereport": "tsc --noEmit --esModuleInterop scripts/moduleReport.ts && esr scripts/moduleReport.ts" diff --git a/test/Messages.test.ts b/test/Messages.test.ts index 1df1b4a6..9e71c171 100644 --- a/test/Messages.test.ts +++ b/test/Messages.test.ts @@ -2,6 +2,7 @@ import * as Ably from 'ably'; import { beforeEach, describe, expect, it, vi } from 'vitest'; import { ChatApi } from '../src/ChatApi.js'; +import { normaliseClientOptions } from '../src/config.js'; import { MessageEvents } from '../src/events.js'; import { DefaultRoom } from '../src/Room.js'; import { randomRoomId } from './helper/identifier.js'; @@ -71,7 +72,13 @@ describe('Messages', () => { createdAt: timestamp, }); - const room = new DefaultRoom('coffee-room-chat', realtime, chatApi, { typingTimeoutMs: 300 }, makeTestLogger()); + const room = new DefaultRoom( + 'coffee-room-chat', + realtime, + chatApi, + normaliseClientOptions({ typingTimeoutMs: 300 }), + makeTestLogger(), + ); const messagePromise = room.messages.send('hello there'); const message = await messagePromise; diff --git a/test/Presence.integration.test.ts b/test/Presence.integration.test.ts index b9733e82..7747b8c7 100644 --- a/test/Presence.integration.test.ts +++ b/test/Presence.integration.test.ts @@ -59,7 +59,7 @@ describe('UserPresence', { timeout: 10000 }, () => { realtimeClient: Realtime, event: PresenceAction | PresenceAction[], realtimeChannelName: string, - expectationFn: (member: object) => void, + expectationFn: (member: Ably.PresenceMessage) => void, ) { return new Promise((resolve) => { const presence = realtimeClient.channels.get(realtimeChannelName).presence; diff --git a/test/SubscriptionManager.test.ts b/test/SubscriptionManager.test.ts index 2c6e4bf0..1a28bbf2 100644 --- a/test/SubscriptionManager.test.ts +++ b/test/SubscriptionManager.test.ts @@ -50,7 +50,7 @@ const waitForPresenceEvent = ( }; // Wait for the channel to change state to the expected state -const waitForChannelStateChange = (channel, expectedState) => { +const waitForChannelStateChange = (channel: Ably.RealtimeChannel, expectedState: Ably.ChannelState) => { return new Promise((resolve, reject) => { const interval = setInterval(() => { if (channel.state === expectedState) { @@ -67,7 +67,7 @@ const waitForChannelStateChange = (channel, expectedState) => { // Assert that a channel does not enter the expected state // during the interval -const assertNoChannelStateChange = (channel, expectedState) => { +const assertNoChannelStateChange = (channel: Ably.RealtimeChannel, expectedState: Ably.ChannelState) => { return new Promise((resolve, reject) => { const interval = setInterval(() => { if (channel.state === expectedState) { @@ -96,7 +96,7 @@ describe('subscription manager', { timeout: 15000 }, () => { const { channel, publishChannel, subscriptionManager } = context; const receivedMessages: Ably.Message[] = []; - const listener = (message) => { + const listener = (message: Ably.Message) => { receivedMessages.push(message); }; await subscriptionManager.subscribe(['test-event'], listener); @@ -116,7 +116,7 @@ describe('subscription manager', { timeout: 15000 }, () => { const { channel, publishChannel, subscriptionManager } = context; const receivedMessages: Ably.Message[] = []; - const listener = (message) => { + const listener = (message: Ably.Message) => { receivedMessages.push(message); }; await subscriptionManager.subscribe(listener); @@ -138,7 +138,7 @@ describe('subscription manager', { timeout: 15000 }, () => { const { channel, publishChannel, subscriptionManager } = context; const receivedMessages: Ably.PresenceMessage[] = []; - const listener = (message) => { + const listener = (message: Ably.PresenceMessage) => { receivedMessages.push(message); }; await subscriptionManager.presenceSubscribe(listener); @@ -156,7 +156,7 @@ describe('subscription manager', { timeout: 15000 }, () => { const { channel, publishChannel, subscriptionManager } = context; const receivedMessages: Ably.PresenceMessage[] = []; - const listener = (message) => { + const listener = (message: Ably.PresenceMessage) => { receivedMessages.push(message); }; await subscriptionManager.presenceSubscribe('update', listener); @@ -276,7 +276,7 @@ describe('subscription manager', { timeout: 15000 }, () => { }); it('should emit an enter event with supplied data when entering presence', async (context) => { const receivedMessages: Ably.PresenceMessage[] = []; - const listener = (message) => { + const listener = (message: Ably.PresenceMessage) => { receivedMessages.push(message); }; // subscribe to presence events @@ -297,7 +297,7 @@ describe('subscription manager', { timeout: 15000 }, () => { it('should emit an event enter when joining for the first time', async (context) => { const receivedMessages: Ably.PresenceMessage[] = []; - const listener = (message) => { + const listener = (message: Ably.PresenceMessage) => { receivedMessages.push(message); }; // subscribe to presence events @@ -311,7 +311,7 @@ describe('subscription manager', { timeout: 15000 }, () => { it('should emit an update event if already entered presence', async (context) => { const receivedMessages: Ably.PresenceMessage[] = []; - const listener = (message) => { + const listener = (message: Ably.PresenceMessage) => { receivedMessages.push(message); }; // Join presence first @@ -347,7 +347,7 @@ describe('subscription manager', { timeout: 15000 }, () => { it('should emit a leave event with supplied data when leaving presence', async (context) => { const receivedMessages: Ably.PresenceMessage[] = []; - const listener = (message) => { + const listener = (message: Ably.PresenceMessage) => { receivedMessages.push(message); }; // subscribe to presence events diff --git a/test/Typing.integration.test.ts b/test/Typing.integration.test.ts index 8b79481e..791b48e5 100644 --- a/test/Typing.integration.test.ts +++ b/test/Typing.integration.test.ts @@ -2,6 +2,7 @@ import * as Ably from 'ably'; import { beforeEach, describe, expect, it } from 'vitest'; +import { normaliseClientOptions } from '../src/config.js'; import { Room } from '../src/Room.js'; import { DefaultRooms, Rooms } from '../src/Rooms.js'; import { TypingEvent } from '../src/Typing.js'; @@ -40,7 +41,11 @@ describe('Typing', () => { beforeEach((context) => { context.realtime = ablyRealtimeClient(); context.roomId = randomRoomId(); - context.chat = new DefaultRooms(context.realtime, { typingTimeoutMs: 300 }, makeTestLogger()); + context.chat = new DefaultRooms( + context.realtime, + normaliseClientOptions({ typingTimeoutMs: 300 }), + makeTestLogger(), + ); context.clientId = context.realtime.auth.clientId; context.chatRoom = context.chat.get(context.roomId); }); @@ -104,13 +109,13 @@ describe('Typing', () => { const clientId1 = randomClientId(); const client1 = new DefaultRooms( ablyRealtimeClient({ clientId: clientId1 }), - { typingTimeoutMs: 1000 }, + normaliseClientOptions({ typingTimeoutMs: 1000 }), makeTestLogger(), ); const clientId2 = randomClientId(); const client2 = new DefaultRooms( ablyRealtimeClient({ clientId: clientId2 }), - { typingTimeoutMs: 1000 }, + normaliseClientOptions({ typingTimeoutMs: 1000 }), makeTestLogger(), ); diff --git a/test/logger.test.ts b/test/logger.test.ts index 604d0b33..0bf64e06 100644 --- a/test/logger.test.ts +++ b/test/logger.test.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from 'vitest'; import { normaliseClientOptions } from '../src/config.js'; -import { LogContext, LogLevel, makeLogger } from '../src/logger.js'; +import { LogContext, Logger, LogLevel, makeLogger } from '../src/logger.js'; const defaultLogContext = { contextKey: 'contextValue' }; @@ -38,7 +38,7 @@ describe('logger', () => { }); const logger = makeLogger(options); - logger[logLevel]('test', logContext); + callMethodForLevel(logger, logLevel, logContext); reject('Expected logHandler to be called'); }), ); @@ -71,8 +71,28 @@ describe('logger', () => { }); const logger = makeLogger(options); - logger[logLevel]('test'); + callMethodForLevel(logger, logLevel); done(); }), ); }); + +const callMethodForLevel = (log: Logger, level: Omit, context?: object | undefined) => { + switch (level) { + case LogLevel.trace: + log.trace('test', context); + break; + case LogLevel.debug: + log.debug('test', context); + break; + case LogLevel.info: + log.info('test', context); + break; + case LogLevel.warn: + log.warn('test', context); + break; + case LogLevel.error: + log.error('test', context); + break; + } +}; diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 00000000..3187837c --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,33 @@ +{ + "include": [ + "test/**/*.spec.ts", + "test/**/*.test.ts" + ], + "exclude": [ + "test/utils/**/*.ts" + ], + "compilerOptions": { + "noEmit": true, + "target": "es6", + "sourceMap": true, + "strict": true, + "alwaysStrict": true, + "noImplicitThis": true, + "esModuleInterop": true, + "declaration": true, + "moduleResolution": "node", + "skipLibCheck": true, + "allowJs": true, + "allowSyntheticDefaultImports": true, + "resolveJsonModule": true, + "allowImportingTsExtensions": true, + "lib": [ + "DOM", + "DOM.Iterable", + "ESNext" + ], + "types": [ + "node" + ] + } +}