@zerospacegg/vynthra
Version:
Discord bot for ZeroSpace.gg data
301 lines (277 loc) • 6.88 kB
text/typescript
import { test } from 'node:test';
import assert from 'node:assert';
import { ChatInputCommandInteraction, CommandInteractionOptionResolver } from 'discord.js';
// Mock undici to prevent node property errors in tests
const undiciMock = {};
// Mock Discord.js module
interface MockCollection {
set: () => void;
get: () => void;
has: () => void;
delete: () => void;
clear: () => void;
size: number;
values: () => any[];
keys: () => any[];
entries: () => any[];
forEach: () => void;
}
const mockCollection = (): MockCollection => ({
set: () => {},
get: () => {},
has: () => {},
delete: () => {},
clear: () => {},
size: 0,
values: () => [],
keys: () => [],
entries: () => [],
forEach: () => {},
});
const createMockSlashCommandBuilder = () => {
let name = "test-command";
let description = "Test command description";
const mockInstance = {
setName: (value: string) => {
name = value;
return mockInstance;
},
setDescription: (value: string) => {
description = value;
return mockInstance;
},
addSubcommand: () => mockInstance,
addStringOption: () => mockInstance,
addBooleanOption: () => mockInstance,
toJSON: () => ({
name,
description,
}),
};
return mockInstance;
};
const mockSlashCommandBuilder = createMockSlashCommandBuilder;
const mockSubcommandBuilder = () => ({
setName: () => mockSubcommandBuilder(),
setDescription: () => mockSubcommandBuilder(),
addStringOption: () => mockSubcommandBuilder(),
addBooleanOption: () => mockSubcommandBuilder(),
addChoices: () => mockSubcommandBuilder(),
setRequired: () => mockSubcommandBuilder(),
});
const mockStringOption = () => ({
setName: () => mockStringOption(),
setDescription: () => mockStringOption(),
setRequired: () => mockStringOption(),
addChoices: () => mockStringOption(),
});
const mockBooleanOption = () => ({
setName: () => mockBooleanOption(),
setDescription: () => mockBooleanOption(),
setRequired: () => mockBooleanOption(),
});
interface MockClient {
commands: MockCollection;
login: () => Promise<string>;
destroy: () => void;
once: () => void;
on: () => void;
user: {
tag: string;
};
guilds: {
cache: {
size: number;
};
};
}
const mockClient = (): MockClient => ({
commands: mockCollection(),
login: async () => "token",
destroy: () => {},
once: () => {},
on: () => {},
user: {
tag: "TestBot#1234",
},
guilds: {
cache: {
size: 5,
},
},
});
const mockInteraction = {
isChatInputCommand: () => true,
commandName: "test-command",
options: {
getSubcommand: () => "stats",
getString: (name: string, required?: boolean) => {
if (name === "query") return "test query";
if (name === "username") return "testuser";
if (required) throw new Error(`Required option ${name} not provided`);
return null;
},
getBoolean: () => false,
},
user: {
tag: "TestUser#5678",
},
reply: async () => undefined,
deferReply: async () => undefined,
editReply: async () => undefined,
followUp: async () => undefined,
replied: false,
deferred: false,
};
const mockREST = () => ({
setToken: () => mockREST(),
put: async () => undefined,
});
// Mock the iolin dependencies
const iolinMock = {
IolinIndex: {
all: {
"unit/lasher/": {
id: "unit/lasher/",
slug: "lasher",
name: "Lasher",
type: "unit",
faction: "protectorate",
tier: "T1",
},
"unit/tank/": {
id: "unit/tank/",
slug: "tank",
name: "Tank",
type: "unit",
faction: "protectorate",
tier: "T2",
},
"building/barracks/": {
id: "building/barracks/",
slug: "barracks",
name: "Barracks",
type: "building",
faction: "protectorate",
tier: "T1",
},
},
ids: {
lasher: "unit/lasher/",
tank: "unit/tank/",
barracks: "building/barracks/",
},
},
};
const iolinAllMock = {
loadFaction: (id: string) => ({
id,
name: "Test Faction",
description: "Mock faction description",
unit: ["lasher", "tank"],
building: ["barracks"],
}),
loadUnit: (id: string) => ({
id,
name: "Test Unit",
hp: 100,
damage: 25,
speed: 5,
hexiteCost: 50,
fluxCost: 25,
}),
};
// Export mocks and utilities
export {
undiciMock,
mockCollection,
mockSlashCommandBuilder,
mockSubcommandBuilder,
mockStringOption,
mockBooleanOption,
mockClient,
mockInteraction,
mockREST,
iolinMock,
iolinAllMock,
test,
assert,
};
// Helper functions
export function createMockBotConfig(overrides: any = {}) {
return {
token: 'test-token',
clientId: 'test-client-id',
guildId: 'test-guild-id',
...overrides,
};
}
export function createMockInteraction(overrides: Partial<ChatInputCommandInteraction> = {}): ChatInputCommandInteraction {
const mockInteraction = {
isChatInputCommand: () => true,
commandName: 'test',
options: {
getSubcommand: () => 'test',
getString: ((name: string, required?: boolean) => {
if (name === 'query') return 'test query';
if (name === 'user') return 'testuser';
if (required) throw new Error(`Required option ${name} not provided`);
return null;
}) as {
(name: string, required: true): string;
(name: string, required?: boolean): string | null;
},
getBoolean: () => true,
client: {} as any,
data: [],
resolved: {},
get: () => null,
getAttachment: () => null,
getChannel: () => null,
getInteger: () => null,
getMember: () => null,
getMentionable: () => null,
getNumber: () => null,
getRole: () => null,
getSubcommandGroup: () => null,
getUser: () => null,
valueOf: () => 'test',
_group: null,
_hoistedOptions: [],
_subcommand: 'test',
_hoistedOptionsData: [],
} as unknown as CommandInteractionOptionResolver,
user: {
tag: 'testuser#1234',
},
reply: async () => ({ fetch: async () => ({}) }),
deferReply: async () => ({}),
editReply: async () => ({}),
followUp: async () => ({}),
deferred: false,
valueOf: () => 'test',
...overrides,
} as unknown as ChatInputCommandInteraction;
return mockInteraction;
}
export function createMockClient() {
return mockClient();
}
// Console mocking utilities
let originalConsole: Console;
export function restoreConsole() {
if (originalConsole) {
global.console = originalConsole;
}
}
export function mockConsole() {
originalConsole = global.console;
global.console = {
...originalConsole,
log: () => {},
error: () => {},
warn: () => {},
info: () => {},
debug: () => {},
};
}