From 953c5c4fbe0086a0555edb423697fe075aedafd9 Mon Sep 17 00:00:00 2001 From: na2na-p Date: Wed, 22 Nov 2023 14:48:58 +0900 Subject: [PATCH] =?UTF-8?q?=E3=82=AB=E3=83=90=E3=83=AC=E3=83=83=E3=82=B8?= =?UTF-8?q?=E5=90=91=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/core/index.ts | 2 +- src/features/core/internal/Voice/index.ts | 9 ++- .../Voice/internal/Voice.class.spec.ts | 55 ++++++++++++++++++- .../internal/Voice/internal/Voice.class.ts | 15 ++--- .../internal/getJoinableStateStatus.spec.ts | 2 +- src/features/others/assertNever.ts | 3 - src/features/others/assertNever/index.ts | 1 + .../assertNever/internal/assertNever.func.ts | 4 ++ .../assertNever/internal/assertNever.spec.ts | 15 +++++ 9 files changed, 90 insertions(+), 16 deletions(-) delete mode 100644 src/features/others/assertNever.ts create mode 100644 src/features/others/assertNever/index.ts create mode 100644 src/features/others/assertNever/internal/assertNever.func.ts create mode 100644 src/features/others/assertNever/internal/assertNever.spec.ts diff --git a/src/features/core/index.ts b/src/features/core/index.ts index adf08c14..d69b76c4 100644 --- a/src/features/core/index.ts +++ b/src/features/core/index.ts @@ -1,9 +1,9 @@ export { Client } from './internal/Client/index.js'; export { - Voice, getJoinableStateStatus, JOINABLE_STATE_STATUS, getActorConnectionState, type ConnectionState, getVoiceInstance, } from './internal/Voice/index.js'; +export type { Voice } from './internal/Voice/index.js'; diff --git a/src/features/core/internal/Voice/index.ts b/src/features/core/internal/Voice/index.ts index a8cd5dcf..ad4d43c6 100644 --- a/src/features/core/internal/Voice/index.ts +++ b/src/features/core/internal/Voice/index.ts @@ -1,7 +1,14 @@ -export { Voice, getVoiceInstance } from './internal/Voice.class.js'; +import { singleton } from '@/features/others/singleton/index.js'; + +import { Voice } from './internal/Voice.class.js'; + +export type { Voice } from './internal/Voice.class.js'; export type { ConnectionState } from './internal/Voice.types.js'; export { getJoinableStateStatus, JOINABLE_STATE_STATUS, } from './internal/funcs/getJoinableStateStatus/index.js'; export { getActorConnectionState } from './internal/funcs/getActorConnectionState/index.js'; + +const createVoiceInstance = () => new Voice(); +export const getVoiceInstance = singleton(createVoiceInstance); diff --git a/src/features/core/internal/Voice/internal/Voice.class.spec.ts b/src/features/core/internal/Voice/internal/Voice.class.spec.ts index 42d89403..cfc41f99 100644 --- a/src/features/core/internal/Voice/internal/Voice.class.spec.ts +++ b/src/features/core/internal/Voice/internal/Voice.class.spec.ts @@ -171,6 +171,59 @@ describe('Voice', () => { ); }); + it('should throw an error if the channel is null', async () => { + const mockedInteraction = { + reply: vi.fn(), + } as unknown as Readonly; + + (getActorId as MockedFunction).mockResolvedValueOnce({ + voice: { channel: null }, + } as GuildMember); + ( + getJoinableStateStatus as MockedFunction + ).mockReturnValueOnce(JOINABLE_STATE_STATUS.ALREADY_JOINED); + + await expect( + voice.join({ interaction: mockedInteraction }) + ).rejects.toThrowError( + 'Channel is null. Please check getJoinableStateStatus()' + ); + }); + + // JOINABLE_STATE_STATUS.ALREADY_JOINED + it('should return false if the channel is already joined', async () => { + const mockedInteraction = { + reply: vi.fn(), + } as unknown as Readonly; + + (getActorId as MockedFunction).mockResolvedValueOnce({ + voice: { + channel: { + id: 'channelId', + guild: { + id: 'guildId', + }, + }, + }, + } as GuildMember); + ( + getJoinableStateStatus as MockedFunction + ).mockReturnValueOnce(JOINABLE_STATE_STATUS.ALREADY_JOINED); + + const result = await voice.join({ interaction: mockedInteraction }); + + expect(getJoinableStateStatus).toHaveBeenCalledWith({ + channel: { + id: 'channelId', + guild: { + id: 'guildId', + }, + }, + }); + + expect(result).toBe(false); + }); + it('should join the voice channel and return true', async () => { const mockedGuildMember = { voice: { @@ -230,7 +283,7 @@ describe('Voice', () => { .mockReturnValueOnce('unknown' as any); await expect(voice.join({ interaction })).rejects.toThrowError( - 'unknown is unexpected value. Should have been never.' + 'Unknown joinable type.' ); }); }); diff --git a/src/features/core/internal/Voice/internal/Voice.class.ts b/src/features/core/internal/Voice/internal/Voice.class.ts index b9f902ea..e818514d 100644 --- a/src/features/core/internal/Voice/internal/Voice.class.ts +++ b/src/features/core/internal/Voice/internal/Voice.class.ts @@ -5,9 +5,8 @@ import type { } from '@/features/library/index.js'; import { isNil, joinVoiceChannel } from '@/features/library/index.js'; import { LogicException } from '@/features/others/Error/LogicException.js'; -import { assertNever } from '@/features/others/assertNever.js'; +import { assertNever } from '@/features/others/assertNever/index.js'; import { getActorId } from '@/features/others/discord/index.js'; -import { singleton } from '@/features/others/singleton/index.js'; import { getActorConnectionState } from './funcs/getActorConnectionState/index.js'; import { @@ -15,9 +14,6 @@ import { getJoinableStateStatus, } from './funcs/getJoinableStateStatus/index.js'; -const createVoiceInstance = () => new Voice(); -export const getVoiceInstance = singleton(createVoiceInstance); - export class Voice { connection: Array<{ guildId: string; @@ -80,7 +76,7 @@ export class Voice { adapterCreator: channel.guild.voiceAdapterCreator, }); this.connection.push({ - guildId: actor.guild.id, + guildId: channel.guildId, connection: connectedChannel, player: undefined, }); @@ -110,10 +106,11 @@ export class Voice { return true; default: - assertNever(joinable); + assertNever(joinable, false); + break; + // HACK: カバレッジを100%にするための処置 } - /* c8 ignore next */ - return; + return Promise.reject(new LogicException('Unknown joinable type.')); } public async leave({ diff --git a/src/features/core/internal/Voice/internal/funcs/getJoinableStateStatus/internal/getJoinableStateStatus.spec.ts b/src/features/core/internal/Voice/internal/funcs/getJoinableStateStatus/internal/getJoinableStateStatus.spec.ts index 5b903fb5..415c3975 100644 --- a/src/features/core/internal/Voice/internal/funcs/getJoinableStateStatus/internal/getJoinableStateStatus.spec.ts +++ b/src/features/core/internal/Voice/internal/funcs/getJoinableStateStatus/internal/getJoinableStateStatus.spec.ts @@ -1,7 +1,7 @@ import type { VoiceBasedChannel } from '@/features/library/index.js'; -import { getJoinableStateStatus } from './getJoinableStateStatus.func.js'; import { JOINABLE_STATE_STATUS } from './getJoinableStateStatus.constants.js'; +import { getJoinableStateStatus } from './getJoinableStateStatus.func.js'; describe('getJoinableStateStatus', () => { it('should return NOT_FOUND if the channel is null', () => { diff --git a/src/features/others/assertNever.ts b/src/features/others/assertNever.ts deleted file mode 100644 index efc231b0..00000000 --- a/src/features/others/assertNever.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const assertNever = (x: never): never => { - throw new Error(`${x} is unexpected value. Should have been never.`); -}; diff --git a/src/features/others/assertNever/index.ts b/src/features/others/assertNever/index.ts new file mode 100644 index 00000000..89d27f92 --- /dev/null +++ b/src/features/others/assertNever/index.ts @@ -0,0 +1 @@ +export { assertNever } from './internal/assertNever.func.js'; diff --git a/src/features/others/assertNever/internal/assertNever.func.ts b/src/features/others/assertNever/internal/assertNever.func.ts new file mode 100644 index 00000000..bfe7f856 --- /dev/null +++ b/src/features/others/assertNever/internal/assertNever.func.ts @@ -0,0 +1,4 @@ +export const assertNever = (x: never, shouldThrow: boolean = true): never => { + if (shouldThrow) throw new Error(`Unexpected object: ${x}`); + return x; +}; diff --git a/src/features/others/assertNever/internal/assertNever.spec.ts b/src/features/others/assertNever/internal/assertNever.spec.ts new file mode 100644 index 00000000..98fec024 --- /dev/null +++ b/src/features/others/assertNever/internal/assertNever.spec.ts @@ -0,0 +1,15 @@ +import { assertNever } from './assertNever.func.js'; + +describe('assertNever', () => { + it('should throw an error with the unexpected object', () => { + const unexpectedObject = {} as never; + expect(() => assertNever(unexpectedObject)).toThrowError( + 'Unexpected object: [object Object]' + ); + }); + + it('should not throw an error when shouldThrow is false', () => { + const unexpectedObject = {} as never; + expect(() => assertNever(unexpectedObject, false)).not.toThrow(); + }); +});