From fb362433eef48c1cac76368d4dc05b0c563e5458 Mon Sep 17 00:00:00 2001 From: na2na-p Date: Wed, 29 Nov 2023 22:17:34 +0900 Subject: [PATCH] =?UTF-8?q?getActorConnectionState=E3=81=AE=E5=A4=96?= =?UTF-8?q?=E3=81=A0=E3=81=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/features/core/internal/Voice/index.ts | 8 +- .../Voice/internal/Voice.class.spec.ts | 86 +++++++++++++------ .../internal/Voice/internal/Voice.class.ts | 13 ++- .../funcs/getActorConnectionState/index.ts | 2 +- .../internal/getActorConnectionState.func.ts | 4 +- .../internal/getActorConnectionState.types.ts | 2 +- 6 files changed, 82 insertions(+), 33 deletions(-) diff --git a/src/features/core/internal/Voice/index.ts b/src/features/core/internal/Voice/index.ts index ad4d43c6..05c89142 100644 --- a/src/features/core/internal/Voice/index.ts +++ b/src/features/core/internal/Voice/index.ts @@ -1,4 +1,5 @@ import { singleton } from '@/features/others/singleton/index.js'; +import { getActorConnectionState } from './internal/funcs/getActorConnectionState/index.js'; import { Voice } from './internal/Voice.class.js'; @@ -8,7 +9,10 @@ export { getJoinableStateStatus, JOINABLE_STATE_STATUS, } from './internal/funcs/getJoinableStateStatus/index.js'; -export { getActorConnectionState } from './internal/funcs/getActorConnectionState/index.js'; +export { getActorConnectionState }; -const createVoiceInstance = () => new Voice(); +const createVoiceInstance = () => + new Voice({ + getActorConnectionState: getActorConnectionState, + }); 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 cfc41f99..d5b82312 100644 --- a/src/features/core/internal/Voice/internal/Voice.class.spec.ts +++ b/src/features/core/internal/Voice/internal/Voice.class.spec.ts @@ -4,7 +4,7 @@ import { joinVoiceChannel, getVoiceConnection, } from '@/features/library/index.js'; -import type { +import { ChatInputCommandInteraction, GuildMember, VoiceConnection, @@ -13,12 +13,12 @@ import { LogicException } from '@/features/others/Error/LogicException.js'; import { getActorId } from '@/features/others/discord/index.js'; import { Voice } from './Voice.class.js'; -import type { ConnectionState } from './Voice.types.js'; -import { getActorConnectionState } from './funcs/getActorConnectionState/index.js'; +import { GetActorConnectionStateInterface } from './funcs/getActorConnectionState/index.js'; import { JOINABLE_STATE_STATUS, getJoinableStateStatus, } from './funcs/getJoinableStateStatus/index.js'; +import { ConnectionState } from './Voice.types.js'; vi.mock('@/features/others/discord/index.js', async () => { const actual = (await vi.importActual( @@ -51,25 +51,37 @@ vi.mock('./funcs/getJoinableStateStatus/index.js', async () => { }; }); -vi.mock('./funcs/getActorConnectionState/index.js', () => { - return { - getActorConnectionState: vi.fn(), - }; -}); - -describe('Voice', () => { - let voice: Voice; - - beforeEach(() => { - voice = new Voice(); +const mockedConnection: VoiceConnection = new VoiceConnection( + { + channelId: 'channelId', + group: 'groupId', + guildId: 'guildId', + selfDeaf: false, + selfMute: false, + }, + { + adapterCreator: vi.fn(), + } +); +mockedConnection.destroy = vi.fn().mockReturnValueOnce(false); + +const mockedGetActorConnectionState: MockedFunction = + vi.fn().mockReturnValue({ + connection: mockedConnection, + guildId: 'guildId', + player: undefined, }); +describe('Voice', () => { afterEach(() => { vi.clearAllMocks(); }); describe('join', () => { it('should reply with an error message if the channel is not found', async () => { + const voice = new Voice({ + getActorConnectionState: mockedGetActorConnectionState, + }); const mockedInteraction = { reply: vi.fn(), } as unknown as Readonly; @@ -91,6 +103,9 @@ describe('Voice', () => { }); it('should reply with an error message if the channel is not joinable', async () => { + const voice = new Voice({ + getActorConnectionState: mockedGetActorConnectionState, + }); const mockedInteraction = { reply: vi.fn(), } as unknown as Readonly; @@ -114,6 +129,9 @@ describe('Voice', () => { }); it('should reply with an error message if the channel is not viewable', async () => { + const voice = new Voice({ + getActorConnectionState: mockedGetActorConnectionState, + }); const mockedInteraction = { reply: vi.fn(), } as unknown as Readonly; @@ -137,6 +155,9 @@ describe('Voice', () => { }); it('should throw an error if the channel is null', async () => { + const voice = new Voice({ + getActorConnectionState: mockedGetActorConnectionState, + }); const interaction = { reply: vi.fn(), } as unknown as Readonly; @@ -153,6 +174,9 @@ describe('Voice', () => { }); it('should throw an error if the channel is null', async () => { + const voice = new Voice({ + getActorConnectionState: mockedGetActorConnectionState, + }); const mockedInteraction = { reply: vi.fn(), } as unknown as Readonly; @@ -172,6 +196,9 @@ describe('Voice', () => { }); it('should throw an error if the channel is null', async () => { + const voice = new Voice({ + getActorConnectionState: mockedGetActorConnectionState, + }); const mockedInteraction = { reply: vi.fn(), } as unknown as Readonly; @@ -190,8 +217,10 @@ describe('Voice', () => { ); }); - // JOINABLE_STATE_STATUS.ALREADY_JOINED it('should return false if the channel is already joined', async () => { + const voice = new Voice({ + getActorConnectionState: mockedGetActorConnectionState, + }); const mockedInteraction = { reply: vi.fn(), } as unknown as Readonly; @@ -225,6 +254,9 @@ describe('Voice', () => { }); it('should join the voice channel and return true', async () => { + const voice = new Voice({ + getActorConnectionState: mockedGetActorConnectionState, + }); const mockedGuildMember = { voice: { channel: { @@ -270,6 +302,9 @@ describe('Voice', () => { }); it('should throw an error if the joinable type is unknown', async () => { + const voice = new Voice({ + getActorConnectionState: mockedGetActorConnectionState, + }); const interaction = { voice: { channel: { joinable: true, viewable: true } }, reply: vi.fn(), @@ -290,6 +325,10 @@ describe('Voice', () => { describe('leave', () => { it('should return false if guildId is null', async () => { + mockedGetActorConnectionState.mockResolvedValueOnce(null); + const voice = new Voice({ + getActorConnectionState: mockedGetActorConnectionState, + }); const interaction = { guildId: null, } as unknown as Readonly; @@ -300,20 +339,13 @@ describe('Voice', () => { }); it('should destroy the connection and return true if the target connection exists', async () => { + const voice = new Voice({ + getActorConnectionState: mockedGetActorConnectionState, + }); const interaction = { guildId: 'guildId', } as unknown as Readonly; - ( - getActorConnectionState as MockedFunction< - typeof getActorConnectionState - > - ).mockResolvedValueOnce({ - connection: { - destroy: vi.fn(), - }, - } as unknown as ConnectionState); - const result = await voice.leave({ interaction }); expect(voice['connection']).toEqual([]); @@ -321,6 +353,10 @@ describe('Voice', () => { }); it('should return false if the target connection does not exist and the member does not have a connection', async () => { + mockedGetActorConnectionState.mockResolvedValueOnce(null); + const voice = new Voice({ + getActorConnectionState: mockedGetActorConnectionState, + }); const interaction = { guildId: 'guildId', } as unknown as Readonly; diff --git a/src/features/core/internal/Voice/internal/Voice.class.ts b/src/features/core/internal/Voice/internal/Voice.class.ts index e818514d..31710693 100644 --- a/src/features/core/internal/Voice/internal/Voice.class.ts +++ b/src/features/core/internal/Voice/internal/Voice.class.ts @@ -8,7 +8,7 @@ import { LogicException } from '@/features/others/Error/LogicException.js'; import { assertNever } from '@/features/others/assertNever/index.js'; import { getActorId } from '@/features/others/discord/index.js'; -import { getActorConnectionState } from './funcs/getActorConnectionState/index.js'; +import { GetActorConnectionStateInterface } from './funcs/getActorConnectionState/index.js'; import { JOINABLE_STATE_STATUS, getJoinableStateStatus, @@ -20,6 +20,15 @@ export class Voice { connection: VoiceConnection; player: AudioPlayer | undefined; }> = []; + getActorConnectionState: GetActorConnectionStateInterface; + + constructor({ + getActorConnectionState, + }: { + getActorConnectionState: GetActorConnectionStateInterface; + }) { + this.getActorConnectionState = getActorConnectionState; + } public async join({ interaction, @@ -118,7 +127,7 @@ export class Voice { }: { interaction: Readonly; }): Promise { - const actorConnectionState = await getActorConnectionState({ + const actorConnectionState = await this.getActorConnectionState({ interaction, connections: this.connection, }); diff --git a/src/features/core/internal/Voice/internal/funcs/getActorConnectionState/index.ts b/src/features/core/internal/Voice/internal/funcs/getActorConnectionState/index.ts index e79b2506..20757dd6 100644 --- a/src/features/core/internal/Voice/internal/funcs/getActorConnectionState/index.ts +++ b/src/features/core/internal/Voice/internal/funcs/getActorConnectionState/index.ts @@ -1,2 +1,2 @@ export { getActorConnectionState } from './internal/getActorConnectionState.func.js'; -export type { getActorConnectionStateInterface } from './internal/getActorConnectionState.types.js'; +export type { GetActorConnectionStateInterface } from './internal/getActorConnectionState.types.js'; diff --git a/src/features/core/internal/Voice/internal/funcs/getActorConnectionState/internal/getActorConnectionState.func.ts b/src/features/core/internal/Voice/internal/funcs/getActorConnectionState/internal/getActorConnectionState.func.ts index 38ecd72d..7cf21b5d 100644 --- a/src/features/core/internal/Voice/internal/funcs/getActorConnectionState/internal/getActorConnectionState.func.ts +++ b/src/features/core/internal/Voice/internal/funcs/getActorConnectionState/internal/getActorConnectionState.func.ts @@ -1,8 +1,8 @@ import { isNil, getVoiceConnection } from '@/features/library/index.js'; import { getActorId } from '@/features/others/discord/index.js'; -import { getActorConnectionStateInterface } from './getActorConnectionState.types.js'; +import { GetActorConnectionStateInterface } from './getActorConnectionState.types.js'; -export const getActorConnectionState: getActorConnectionStateInterface = +export const getActorConnectionState: GetActorConnectionStateInterface = async ({ interaction, connections }) => { const guildId = interaction.guildId; if (isNil(guildId)) return null; diff --git a/src/features/core/internal/Voice/internal/funcs/getActorConnectionState/internal/getActorConnectionState.types.ts b/src/features/core/internal/Voice/internal/funcs/getActorConnectionState/internal/getActorConnectionState.types.ts index 9cb4ba39..079a127d 100644 --- a/src/features/core/internal/Voice/internal/funcs/getActorConnectionState/internal/getActorConnectionState.types.ts +++ b/src/features/core/internal/Voice/internal/funcs/getActorConnectionState/internal/getActorConnectionState.types.ts @@ -1,7 +1,7 @@ import { ConnectionState } from '@/features/core/index.js'; import { ChatInputCommandInteraction } from '@/features/library/index.js'; -export interface getActorConnectionStateInterface { +export interface GetActorConnectionStateInterface { (args: { interaction: Readonly; connections: Array;