more tests & enforce structure
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Erik 2023-02-12 18:08:52 +02:00
parent e2503d22a0
commit 4fb0bed436
Signed by: Navy.gif
GPG Key ID: 2532FBBB61C65A68
6 changed files with 81 additions and 8 deletions

View File

@ -12,5 +12,4 @@ steps:
image: node image: node
commands: commands:
- yarn install - yarn install
- yarn build
- yarn test - yarn test

View File

@ -22,7 +22,7 @@
], ],
"scripts": { "scripts": {
"build": "tsc", "build": "tsc",
"test": "jest", "test": "tsc && jest",
"release": "tsc && yarn publish", "release": "tsc && yarn publish",
"lint": "eslint --fix" "lint": "eslint --fix"
} }

View File

@ -15,6 +15,9 @@ abstract class Command implements ICommand {
constructor(def: CommandDefinition) { constructor(def: CommandDefinition) {
if (typeof def !== 'object') throw new Error('Missing command definition');
if (!def.name) throw new Error('Missing name for command');
this.name = def.name; this.name = def.name;
this.aliases = def.aliases || []; this.aliases = def.aliases || [];
@ -24,6 +27,8 @@ abstract class Command implements ICommand {
if (opt instanceof CommandOption) this.options.push(opt); if (opt instanceof CommandOption) this.options.push(opt);
else this.options.push(new CommandOption(opt)); else this.options.push(new CommandOption(opt));
} }
if (this.options.some(opt => [OptionType.SUB_COMMAND, OptionType.SUB_COMMAND_GROUP].includes(opt.type))
&& this.options.some(opt => ![OptionType.SUB_COMMAND, OptionType.SUB_COMMAND_GROUP].includes(opt.type))) throw new Error('Cannot have subcommand(group)s on the same level as an option')
} }

View File

@ -49,17 +49,27 @@ class CommandOption implements ICommandOption {
this.name = def.name; this.name = def.name;
this.aliases = def.aliases || []; this.aliases = def.aliases || [];
this.strict = def.strict || false;
this.type = def.type ?? OptionType.STRING;
this.flag = def.flag || false;
this.options = []; this.options = [];
for (const opt of def.options || []) { for (const opt of def.options || []) {
if (opt instanceof CommandOption) this.options.push(opt); if (opt instanceof CommandOption) this.options.push(opt);
else this.options.push(new CommandOption(opt)); else this.options.push(new CommandOption(opt));
} }
if (this.type === OptionType.SUB_COMMAND_GROUP && this.options.some(opt => opt.type === OptionType.SUB_COMMAND_GROUP)) throw new Error('Cannot nest subcommand groups');
if (this.type === OptionType.SUB_COMMAND && this.options.some(opt => opt.type === OptionType.SUB_COMMAND_GROUP)) throw new Error('Cannot have subcommand groups under a subcommand');
if (this.type === OptionType.SUB_COMMAND && this.options.some(opt => opt.type === OptionType.SUB_COMMAND)) throw new Error('Cannot nest subcommands');
if (![OptionType.SUB_COMMAND, OptionType.SUB_COMMAND_GROUP].includes(this.type)
&& this.options.some(opt => [OptionType.SUB_COMMAND, OptionType.SUB_COMMAND_GROUP].includes(opt.type))) throw new Error('Cannot have subcommand(group)s under an option');
if (this.options.some(opt => [OptionType.SUB_COMMAND, OptionType.SUB_COMMAND_GROUP].includes(opt.type))
&& this.options.some(opt => ![OptionType.SUB_COMMAND, OptionType.SUB_COMMAND_GROUP].includes(opt.type))) throw new Error('Cannot have subcommand(group)s on the same level as an option')
this.choices = def.choices || []; this.choices = def.choices || [];
this.strict = def.strict || false;
this.type = def.type ?? OptionType.STRING;
this.flag = def.flag || false;
this.valueOptional = def.valueOptional || false; this.valueOptional = def.valueOptional || false;
this.defaultValue = def.defaultValue ?? null; this.defaultValue = def.defaultValue ?? null;
this.valueAsAlias = def.valueAsAlias || false; this.valueAsAlias = def.valueAsAlias || false;

View File

@ -20,7 +20,7 @@ const parser = new Parser({
(async () => { (async () => {
const parsed = await parser.parseMessage('test message.author') const parsed = await parser.parseMessage('test message.author')
console.log(parsed) // console.log(parsed)
})(); })();
test('', () => { test('', () => {

View File

@ -1,11 +1,70 @@
const { inspect } = require('node:util'); const { inspect } = require('node:util');
const { Parser, Command, OptionType } = require('../build'); const { Parser, Command, OptionType } = require('../build');
test('Command definition', () => {
expect(() => new Command()).toThrow();
expect(() => new Command({})).toThrow();
expect(() => new Command(235345)).toThrow();
expect(() => new Command({ name: 'create' })).not.toThrow();
expect(() => new Command({
name: 'create',
options: [{
name: 'test',
type: OptionType.SUB_COMMAND,
options: [{
name:'dingus',
type: OptionType.SUB_COMMAND
}]
}]
})).toThrow();
expect(() => new Command({
name: 'create',
options: [{
name: 'test',
type: OptionType.STRING,
options: [{
name:'dingus',
type: OptionType.SUB_COMMAND
}]
}]
})).toThrow();
expect(() => new Command({
name: 'create',
options: [{
name: 'test',
type: OptionType.SUB_COMMAND_GROUP,
options: [{
name:'dingus',
type: OptionType.SUB_COMMAND
}]
}] })).not.toThrow();
})
test('Command Parser', async () => { test('Command Parser', async () => {
const command = new Command({ name: 'create', options: [{ name: 'registration-code', aliases: ['code'], type: OptionType.SUB_COMMAND }, { name: 'test' }] }); const command = new Command({
name: 'create',
options: [{
name: 'registration-code',
aliases: ['code'],
type: OptionType.SUB_COMMAND,
options: [{
name: 'amount',
type: OptionType.INTEGER,
defaultValue: 1,
valueOptional: true
}]
}]
});
const parser = new Parser({ commands: [command], prefix: '' }); const parser = new Parser({ commands: [command], prefix: '' });
await expect(parser.parseMessage('create')).rejects.toThrow(); await expect(parser.parseMessage('create')).rejects.toThrow();
// Cannot have an option at the sub-command level
await expect(parser.parseMessage('create test')).rejects.toThrow();
await expect(parser.parseMessage('create code')).resolves.toHaveProperty('command.name', 'create');
await expect(parser.parseMessage('create code 1')).resolves.toHaveProperty('args.amount.value', 1);
}); });