mirror of
https://github.com/sern-handler/handler
synced 2026-06-06 01:16:55 +00:00
test: add more tests
This commit is contained in:
@@ -40,7 +40,7 @@ export class CoreContainer<T extends Partial<Dependencies>> extends Container<T,
|
||||
}
|
||||
|
||||
private async callInitHooks(e: { key: keyof T; newContainer: T[keyof T] | null }) {
|
||||
const dep = e.newContainer ;
|
||||
const dep = e.newContainer;
|
||||
|
||||
assert.ok(dep);
|
||||
//Ignore any dependencies that are not objects or array
|
||||
|
||||
14
test/core/contracts.test.ts
Normal file
14
test/core/contracts.test.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { assertType, describe, it, vi } from "vitest";
|
||||
import * as DefaultContracts from '../../src/core/structures/services'
|
||||
import * as Contracts from '../../src/core/contracts/index.js'
|
||||
import { ModuleStore } from "../../src/core";
|
||||
|
||||
describe('default contracts', () => {
|
||||
it('should satisfy contracts', () => {
|
||||
assertType<Contracts.Logging>(new DefaultContracts.DefaultLogging())
|
||||
assertType<Contracts.ErrorHandling>(new DefaultContracts.DefaultErrorHandling())
|
||||
assertType<Contracts.ModuleManager>(new DefaultContracts.DefaultModuleManager(new ModuleStore()))
|
||||
assertType<Contracts.CoreModuleStore>(new ModuleStore())
|
||||
})
|
||||
|
||||
})
|
||||
@@ -1,11 +1,74 @@
|
||||
import { describe, it } from "vitest";
|
||||
import { afterEach, describe, it, vi } from "vitest";
|
||||
import { PluginType, SernOptionsData, controller } from '../../src/index'
|
||||
import { partitionPlugins, treeSearch } from "../../src/core/functions";
|
||||
import { expect } from "chai";
|
||||
import { faker } from '@faker-js/faker';
|
||||
import { ApplicationCommandOptionType } from "discord.js";
|
||||
import { ApplicationCommandOptionType, AutocompleteInteraction } from "discord.js";
|
||||
|
||||
describe('functions', () => {
|
||||
vi.mock('discord.js', () => {
|
||||
|
||||
const Collection = Map
|
||||
const ModalSubmitInteraction = class {
|
||||
customId
|
||||
type = 5
|
||||
isModalSubmit = vi.fn()
|
||||
constructor(customId) {
|
||||
this.customId = customId
|
||||
}
|
||||
}
|
||||
const ButtonInteraction = class {
|
||||
customId
|
||||
type = 3
|
||||
componentType = 2
|
||||
isButton = vi.fn()
|
||||
constructor(customId) {
|
||||
this.customId = customId
|
||||
}
|
||||
}
|
||||
const AutocompleteInteraction = class {
|
||||
type = 4;
|
||||
option: string
|
||||
constructor(s: string) {
|
||||
this.option = s;
|
||||
}
|
||||
options = {
|
||||
getFocused : vi.fn()
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
Collection,
|
||||
ComponentType: {
|
||||
Button: 2
|
||||
},
|
||||
InteractionType : {
|
||||
Ping: 1,
|
||||
ApplicationCommand: 2,
|
||||
MessageComponent: 3,
|
||||
ApplicationCommandAutocomplete:4,
|
||||
ModalSubmit: 5
|
||||
},
|
||||
ApplicationCommandOptionType : {
|
||||
Subcommand : 1,
|
||||
SubcommandGroup : 2,
|
||||
String : 3,
|
||||
Integer : 4,
|
||||
Boolean : 5,
|
||||
User : 6,
|
||||
Channel : 7,
|
||||
Role : 8,
|
||||
Mentionable : 9,
|
||||
Number : 10,
|
||||
Attachment : 11
|
||||
},
|
||||
ModalSubmitInteraction,
|
||||
ButtonInteraction,
|
||||
AutocompleteInteraction
|
||||
};
|
||||
})
|
||||
|
||||
describe('functions', () => {
|
||||
afterEach(() => { vi.clearAllMocks() })
|
||||
function createRandomPlugins(len: number) {
|
||||
const random = () => Math.floor(Math.random()*2)+1; // 1 or 2, plugin enum
|
||||
return Array.from({ length: len }, () => ({ type: random(), execute: () => random() === 1 ? controller.next():controller.stop() }))
|
||||
@@ -28,19 +91,119 @@ describe('functions', () => {
|
||||
})
|
||||
|
||||
it('should tree search options tree depth 1', () => {
|
||||
//@ts-expect-error mocking
|
||||
let autocmpInteraction = new AutocompleteInteraction('autocomplete');
|
||||
const options : SernOptionsData[] = [
|
||||
createRandomChoice(),
|
||||
createRandomChoice(),
|
||||
createRandomChoice(),
|
||||
{ type: ApplicationCommandOptionType.String,
|
||||
{
|
||||
type: ApplicationCommandOptionType.String,
|
||||
name: 'autocomplete',
|
||||
description: 'here',
|
||||
autocomplete: true,
|
||||
command : { onEvent: [], execute:(a) => {} }
|
||||
}
|
||||
];
|
||||
autocmpInteraction.options.getFocused.mockReturnValue(
|
||||
{
|
||||
name: 'autocomplete',
|
||||
value: faker.string.alpha(),
|
||||
focused: true
|
||||
},
|
||||
);
|
||||
const result = treeSearch(autocmpInteraction, options);
|
||||
expect(result == undefined).to.be.false;
|
||||
expect(result.name).to.be.eq('autocomplete');
|
||||
expect(result.command).to.be.not.undefined;
|
||||
|
||||
}),
|
||||
it('should tree search depth 2', () => {
|
||||
//@ts-expect-error mocking
|
||||
let autocmpInteraction = new AutocompleteInteraction('nested');
|
||||
const options : SernOptionsData[] = [
|
||||
{
|
||||
type: ApplicationCommandOptionType.Subcommand,
|
||||
name: faker.string.alpha(),
|
||||
description: faker.string.alpha(),
|
||||
options: [
|
||||
createRandomChoice(),
|
||||
createRandomChoice(),
|
||||
createRandomChoice(),
|
||||
{
|
||||
type: ApplicationCommandOptionType.String,
|
||||
name: 'nested',
|
||||
description: faker.string.alpha(),
|
||||
autocomplete: true,
|
||||
command: {
|
||||
onEvent: [],
|
||||
execute:() => {}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
];
|
||||
autocmpInteraction.options.getFocused.mockReturnValue(
|
||||
{
|
||||
name: 'nested',
|
||||
value: faker.string.alpha(),
|
||||
focused: true
|
||||
}
|
||||
);
|
||||
const result = treeSearch(autocmpInteraction, options);
|
||||
expect(result == undefined).to.be.false;
|
||||
expect(result.name).to.be.eq('nested');
|
||||
expect(result.command).to.be.not.undefined;
|
||||
|
||||
})
|
||||
|
||||
it('should tree search depth n > 2', () => {
|
||||
//@ts-expect-error mocking
|
||||
let autocmpInteraction = new AutocompleteInteraction('nested');
|
||||
const options : SernOptionsData[] = [
|
||||
{
|
||||
|
||||
type: ApplicationCommandOptionType.SubcommandGroup,
|
||||
name: faker.string.alpha(),
|
||||
description: faker.string.alpha(),
|
||||
options: [
|
||||
{
|
||||
type: ApplicationCommandOptionType.Subcommand,
|
||||
name: faker.string.alpha(),
|
||||
description: faker.string.alpha(),
|
||||
options: [
|
||||
createRandomChoice(),
|
||||
createRandomChoice(),
|
||||
createRandomChoice(),
|
||||
{
|
||||
type: ApplicationCommandOptionType.String,
|
||||
name: 'nested',
|
||||
description: faker.string.alpha(),
|
||||
autocomplete: true,
|
||||
command: {
|
||||
onEvent: [],
|
||||
execute:() => {}
|
||||
}
|
||||
}
|
||||
]
|
||||
}]
|
||||
},
|
||||
];
|
||||
autocmpInteraction.options.getFocused.mockReturnValue(
|
||||
{
|
||||
name: 'nested',
|
||||
value: faker.string.alpha(),
|
||||
focused: true
|
||||
}
|
||||
);
|
||||
const result = treeSearch(autocmpInteraction, options);
|
||||
expect(result == undefined).to.be.false;
|
||||
expect(result.name).to.be.eq('nested');
|
||||
expect(result.command).to.be.not.undefined;
|
||||
})
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
|
||||
52
test/core/ioc.test.ts
Normal file
52
test/core/ioc.test.ts
Normal file
@@ -0,0 +1,52 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { CoreContainer } from '../../src/core/structures/container'
|
||||
import { CoreDependencies } from "../../src/core/ioc";
|
||||
import { EventEmitter } from "events";
|
||||
import { DefaultLogging, Init, Logging } from "../../src/core";
|
||||
|
||||
|
||||
describe('ioc container', () => {
|
||||
let container: CoreContainer<{}>;
|
||||
let initDependency: Logging & Init;
|
||||
beforeEach(() => {
|
||||
initDependency = {
|
||||
init: vi.fn(),
|
||||
error(): void {},
|
||||
warning(): void {},
|
||||
info(): void {},
|
||||
debug(): void {},
|
||||
}
|
||||
container = new CoreContainer()
|
||||
|
||||
})
|
||||
|
||||
it('should be ready after calling container.ready()', () => {
|
||||
container.ready()
|
||||
expect(container.isReady()).toBe(true)
|
||||
})
|
||||
it('should container all core dependencies', async () => {
|
||||
const keys = ['@sern/modules', '@sern/emitter', '@sern/logger', '@sern/errors'] satisfies (keyof CoreDependencies)[]
|
||||
container.add({
|
||||
'@sern/logger': () => new DefaultLogging(),
|
||||
'@sern/client': () => new EventEmitter(),
|
||||
})
|
||||
for(const k of keys) {
|
||||
//@ts-expect-error typings for iti are strict
|
||||
expect(() => container.get(k)).not.toThrow();
|
||||
}
|
||||
})
|
||||
it('should init modules', () => {
|
||||
container.upsert({ '@sern/logger': initDependency })
|
||||
container.ready()
|
||||
expect(initDependency.init).to.toHaveBeenCalledOnce()
|
||||
})
|
||||
|
||||
it('should not lazy module', () => {
|
||||
container.upsert({ '@sern/logger': () => initDependency })
|
||||
container.ready()
|
||||
expect(initDependency.init).toHaveBeenCalledTimes(0);
|
||||
})
|
||||
|
||||
|
||||
|
||||
})
|
||||
73
test/core/services.test.ts
Normal file
73
test/core/services.test.ts
Normal file
@@ -0,0 +1,73 @@
|
||||
import { SpyInstance, afterAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { CoreContainer } from '../../src/core/structures/container'
|
||||
import { DefaultLogging } from "../../src/core";
|
||||
import { faker } from '@faker-js/faker'
|
||||
import { commandModule } from "../../src";
|
||||
import { uniqueId } from '../../src/handler/id'
|
||||
import { CommandMeta } from "../../src/core/types/modules";
|
||||
|
||||
describe('services', () => {
|
||||
//@ts-ignore
|
||||
let container: CoreContainer<Dependencies>;
|
||||
let consoleMock : SpyInstance;
|
||||
beforeEach(() => {
|
||||
container = new CoreContainer()
|
||||
container.add({ '@sern/logger': () => new DefaultLogging() })
|
||||
container.ready()
|
||||
consoleMock = vi.spyOn(container.get('@sern/logger'), 'error').mockImplementation(() => {})
|
||||
})
|
||||
|
||||
afterAll(() => {
|
||||
consoleMock.mockReset()
|
||||
});
|
||||
it('module-store.ts', async () => {
|
||||
function createRandomCommandModules() {
|
||||
return commandModule({
|
||||
type: faker.number.int({ min: 1<<0, max: 1<<10 }),
|
||||
description: faker.string.alpha(),
|
||||
name: faker.string.alpha(),
|
||||
execute: ()=>{}
|
||||
})
|
||||
}
|
||||
|
||||
const modules = faker.helpers.multiple(createRandomCommandModules, { count: 40 })
|
||||
|
||||
const paths = faker.helpers.multiple(faker.system.directoryPath, { count: 40 })
|
||||
.map((path,i) => `${path}/${modules[i]}.js`);
|
||||
|
||||
const metadata: CommandMeta[] = modules.map((cm, i) => ({
|
||||
id: cm.name+'_'+uniqueId(cm.type),
|
||||
isClass: false,
|
||||
fullPath: `${paths[i]}/${cm.name}.js`
|
||||
}));
|
||||
const moduleManager = container.get('@sern/modules');
|
||||
let i =0;
|
||||
for(const m of modules) {
|
||||
moduleManager.set(m.name+'_'+uniqueId(m.type), paths[i]);
|
||||
moduleManager.setMetadata(m, metadata[i]);
|
||||
i++
|
||||
}
|
||||
for(const m of modules) {
|
||||
expect(moduleManager.getMetadata(m), "module references do not exist").toBeDefined()
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
//todo add more
|
||||
it('error-handling', () => {
|
||||
const errorHandler = container.get('@sern/errors');
|
||||
expect(() => errorHandler.crash(new Error("poo"))).toThrowError();
|
||||
|
||||
})
|
||||
//todo add more, spy on every instance?
|
||||
it('logger', () => {
|
||||
|
||||
container.get('@sern/logger').error({ message: 'error' })
|
||||
|
||||
expect(consoleMock).toHaveBeenCalledOnce();
|
||||
expect(consoleMock).toHaveBeenLastCalledWith({ message: 'error' })
|
||||
})
|
||||
|
||||
|
||||
|
||||
})
|
||||
Reference in New Issue
Block a user