199 lines
7.1 KiB
TypeScript
199 lines
7.1 KiB
TypeScript
/**
|
|
* Tests for commands/tts/tts.ts
|
|
*/
|
|
|
|
jest.mock('discord.js', () => {
|
|
const actual = jest.requireActual('discord.js');
|
|
return {
|
|
...actual,
|
|
SlashCommandBuilder: jest.fn().mockImplementation(() => ({
|
|
setName: jest.fn().mockReturnThis(),
|
|
setDescription: jest.fn().mockReturnThis(),
|
|
addStringOption: jest.fn().mockReturnThis(),
|
|
addIntegerOption: jest.fn().mockReturnThis(),
|
|
})),
|
|
EmbedBuilder: jest.fn().mockImplementation(() => ({
|
|
setColor: jest.fn().mockReturnThis(),
|
|
setAuthor: jest.fn().mockReturnThis(),
|
|
setDescription: jest.fn().mockReturnThis(),
|
|
setFooter: jest.fn().mockReturnThis(),
|
|
setTimestamp: jest.fn().mockReturnThis(),
|
|
})),
|
|
AttachmentBuilder: jest.fn().mockImplementation((buffer, options) => {
|
|
const file = { buffer, name: options?.name };
|
|
return {
|
|
...file,
|
|
setName: jest.fn().mockReturnThis(),
|
|
};
|
|
}),
|
|
};
|
|
});
|
|
|
|
jest.mock('../util', () => {
|
|
const actual = jest.requireActual('../util');
|
|
return {
|
|
...actual,
|
|
requestTTSResponse: jest.fn(),
|
|
};
|
|
});
|
|
|
|
jest.mock('../../logging', () => ({
|
|
logError: jest.fn(),
|
|
logInfo: jest.fn(),
|
|
logWarn: jest.fn(),
|
|
}));
|
|
|
|
const ttsCommand = require('../commands/tts/tts');
|
|
const { requestTTSResponse } = require('../util');
|
|
|
|
describe('tts command', () => {
|
|
let mockInteraction: {
|
|
options: { getString: jest.Mock; getInteger: jest.Mock };
|
|
reply: jest.Mock;
|
|
editReply: jest.Mock;
|
|
};
|
|
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
mockInteraction = {
|
|
options: { getString: jest.fn(), getInteger: jest.fn() },
|
|
reply: jest.fn(),
|
|
editReply: jest.fn(),
|
|
};
|
|
});
|
|
|
|
it('should have correct command data structure', () => {
|
|
expect(ttsCommand.data).toBeDefined();
|
|
expect(ttsCommand.data.setName).toBeDefined();
|
|
expect(ttsCommand.execute).toBeDefined();
|
|
expect(ttsCommand.config).toBeDefined();
|
|
});
|
|
|
|
it('should generate TTS audio for valid text with default options', async () => {
|
|
mockInteraction.options.getString.mockImplementation((name: string) => {
|
|
if (name === 'text') return 'Hello world';
|
|
if (name === 'speaker') return null;
|
|
if (name === 'instruct') return null;
|
|
return null;
|
|
});
|
|
mockInteraction.options.getInteger.mockReturnValue(null);
|
|
requestTTSResponse.mockResolvedValue({
|
|
arrayBuffer: jest.fn().mockResolvedValue(new ArrayBuffer(100)),
|
|
});
|
|
|
|
await ttsCommand.execute(mockInteraction);
|
|
|
|
// Should reply with loading embed
|
|
expect(mockInteraction.reply).toHaveBeenCalledWith({
|
|
embeds: [expect.anything()],
|
|
});
|
|
expect(requestTTSResponse).toHaveBeenCalledWith('Hello world', 'Ono_Anna', 0, null);
|
|
// Should edit with final embed and audio file
|
|
expect(mockInteraction.editReply).toHaveBeenCalledTimes(1);
|
|
const editCall = mockInteraction.editReply.mock.calls[0][0];
|
|
expect(editCall.embeds).toBeDefined();
|
|
expect(editCall.files).toBeDefined();
|
|
expect(editCall.files.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('should generate TTS audio with custom speaker', async () => {
|
|
mockInteraction.options.getString.mockImplementation((name: string) => {
|
|
if (name === 'text') return 'Hello world';
|
|
if (name === 'speaker') return 'Miku';
|
|
if (name === 'instruct') return null;
|
|
return null;
|
|
});
|
|
mockInteraction.options.getInteger.mockReturnValue(null);
|
|
requestTTSResponse.mockResolvedValue({
|
|
arrayBuffer: jest.fn().mockResolvedValue(new ArrayBuffer(100)),
|
|
});
|
|
|
|
await ttsCommand.execute(mockInteraction);
|
|
|
|
expect(requestTTSResponse).toHaveBeenCalledWith('Hello world', 'Miku', 0, null);
|
|
});
|
|
|
|
it('should generate TTS audio with custom pitch', async () => {
|
|
mockInteraction.options.getString.mockImplementation((name: string) => {
|
|
if (name === 'text') return 'Hello world';
|
|
if (name === 'speaker') return null;
|
|
if (name === 'instruct') return null;
|
|
return null;
|
|
});
|
|
mockInteraction.options.getInteger.mockReturnValue(12);
|
|
requestTTSResponse.mockResolvedValue({
|
|
arrayBuffer: jest.fn().mockResolvedValue(new ArrayBuffer(100)),
|
|
});
|
|
|
|
await ttsCommand.execute(mockInteraction);
|
|
|
|
expect(requestTTSResponse).toHaveBeenCalledWith('Hello world', 'Ono_Anna', 12, null);
|
|
});
|
|
|
|
it('should generate TTS audio with instruction', async () => {
|
|
mockInteraction.options.getString.mockImplementation((name: string) => {
|
|
if (name === 'text') return 'Hello world';
|
|
if (name === 'speaker') return null;
|
|
if (name === 'instruct') return 'speak softly';
|
|
return null;
|
|
});
|
|
mockInteraction.options.getInteger.mockReturnValue(null);
|
|
requestTTSResponse.mockResolvedValue({
|
|
arrayBuffer: jest.fn().mockResolvedValue(new ArrayBuffer(100)),
|
|
});
|
|
|
|
await ttsCommand.execute(mockInteraction);
|
|
|
|
expect(requestTTSResponse).toHaveBeenCalledWith(
|
|
'Hello world',
|
|
'Ono_Anna',
|
|
0,
|
|
'speak softly'
|
|
);
|
|
});
|
|
|
|
it('should generate TTS audio with all custom options', async () => {
|
|
mockInteraction.options.getString.mockImplementation((name: string) => {
|
|
if (name === 'text') return 'Hello world';
|
|
if (name === 'speaker') return 'Miku';
|
|
if (name === 'instruct') return 'speak softly';
|
|
return null;
|
|
});
|
|
mockInteraction.options.getInteger.mockReturnValue(0);
|
|
requestTTSResponse.mockResolvedValue({
|
|
arrayBuffer: jest.fn().mockResolvedValue(new ArrayBuffer(100)),
|
|
});
|
|
|
|
await ttsCommand.execute(mockInteraction);
|
|
|
|
expect(requestTTSResponse).toHaveBeenCalledWith('Hello world', 'Miku', 0, 'speak softly');
|
|
});
|
|
|
|
it('should handle TTS generation errors', async () => {
|
|
mockInteraction.options.getString.mockImplementation((name: string) => {
|
|
if (name === 'text') return 'Hello world';
|
|
return null;
|
|
});
|
|
mockInteraction.options.getInteger.mockReturnValue(null);
|
|
requestTTSResponse.mockRejectedValue(new Error('TTS failed'));
|
|
|
|
await ttsCommand.execute(mockInteraction);
|
|
|
|
// Should reply with loading embed
|
|
expect(mockInteraction.reply).toHaveBeenCalledWith({
|
|
embeds: [expect.anything()],
|
|
});
|
|
// Should edit with error embed
|
|
expect(mockInteraction.editReply).toHaveBeenCalledWith({
|
|
embeds: [expect.anything()],
|
|
});
|
|
});
|
|
|
|
it('should include TTS configuration', () => {
|
|
expect(ttsCommand.config).toBeDefined();
|
|
expect(ttsCommand.config.ttsSettings).toBeDefined();
|
|
expect(ttsCommand.config.ttsSettings.speaker).toBeDefined();
|
|
expect(ttsCommand.config.ttsSettings.pitch_change_sem).toBeDefined();
|
|
});
|
|
});
|