Skip to content

Commit

Permalink
getActorConnectionStateの外だし
Browse files Browse the repository at this point in the history
  • Loading branch information
na2na-p committed Nov 29, 2023
1 parent 4a27e20 commit fb36243
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 33 deletions.
8 changes: 6 additions & 2 deletions src/features/core/internal/Voice/index.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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);
86 changes: 61 additions & 25 deletions src/features/core/internal/Voice/internal/Voice.class.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {
joinVoiceChannel,
getVoiceConnection,
} from '@/features/library/index.js';
import type {
import {
ChatInputCommandInteraction,
GuildMember,
VoiceConnection,
Expand All @@ -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(
Expand Down Expand Up @@ -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<GetActorConnectionStateInterface> =
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<ChatInputCommandInteraction>;
Expand All @@ -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<ChatInputCommandInteraction>;
Expand All @@ -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<ChatInputCommandInteraction>;
Expand All @@ -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<ChatInputCommandInteraction>;
Expand All @@ -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<ChatInputCommandInteraction>;
Expand All @@ -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<ChatInputCommandInteraction>;
Expand All @@ -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<ChatInputCommandInteraction>;
Expand Down Expand Up @@ -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: {
Expand Down Expand Up @@ -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(),
Expand All @@ -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<ChatInputCommandInteraction>;
Expand All @@ -300,27 +339,24 @@ 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<ChatInputCommandInteraction>;

(
getActorConnectionState as MockedFunction<
typeof getActorConnectionState
>
).mockResolvedValueOnce({
connection: {
destroy: vi.fn(),
},
} as unknown as ConnectionState);

const result = await voice.leave({ interaction });

expect(voice['connection']).toEqual([]);
expect(result).toBe(true);
});

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<ChatInputCommandInteraction>;
Expand Down
13 changes: 11 additions & 2 deletions src/features/core/internal/Voice/internal/Voice.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand Down Expand Up @@ -118,7 +127,7 @@ export class Voice {
}: {
interaction: Readonly<ChatInputCommandInteraction>;
}): Promise<boolean> {
const actorConnectionState = await getActorConnectionState({
const actorConnectionState = await this.getActorConnectionState({
interaction,
connections: this.connection,
});
Expand Down
Original file line number Diff line number Diff line change
@@ -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';
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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<ChatInputCommandInteraction>;
connections: Array<ConnectionState>;
Expand Down

0 comments on commit fb36243

Please sign in to comment.