reorganizage du projet et mise en place d'un vrai build

This commit is contained in:
Puechberty Arthur
2026-04-13 19:42:38 +02:00
parent 0f82c7e287
commit 3eb23eb27a
30 changed files with 823 additions and 307 deletions
+19
View File
@@ -0,0 +1,19 @@
import assert from "node:assert/strict";
import test from "node:test";
import { tokenizePrefixInput } from "../src/framework/commands/argParser.js";
test("tokenizePrefixInput parse les quotes simples et doubles", () => {
const tokens = tokenizePrefixInput('"hello world" test \'foo bar\'');
assert.deepEqual(tokens, ["hello world", "test", "foo bar"]);
});
test("tokenizePrefixInput conserve les tokens non quotes", () => {
const tokens = tokenizePrefixInput("alpha beta gamma");
assert.deepEqual(tokens, ["alpha", "beta", "gamma"]);
});
test("tokenizePrefixInput gere les quotes echappees", () => {
const tokens = tokenizePrefixInput('"say \\"hello\\"" done');
assert.deepEqual(tokens, ['say "hello"', "done"]);
});
+39
View File
@@ -0,0 +1,39 @@
import assert from "node:assert/strict";
import test from "node:test";
import { defineCommand } from "../src/framework/commands/defineCommand.js";
test("defineCommand refuse un argument requis apres un optionnel", () => {
assert.throws(() => {
defineCommand({
meta: { name: "broken", category: "test" },
args: [
{ name: "optional", type: "string", required: false, descriptionKey: "args.optional" },
{ name: "required", type: "string", required: true, descriptionKey: "args.required" },
],
execute: async () => undefined,
});
});
});
test("defineCommand refuse un cooldown invalide", () => {
assert.throws(() => {
defineCommand({
meta: { name: "brokenCooldown", category: "test" },
cooldown: 0,
execute: async () => undefined,
});
});
});
test("defineCommand applique les valeurs par defaut", () => {
const command = defineCommand({
meta: { name: "ok", category: "test" },
execute: async () => undefined,
});
assert.deepEqual(command.args, []);
assert.deepEqual(command.permissions, []);
assert.deepEqual(command.examples, []);
assert.equal(command.cooldown, undefined);
});
+54
View File
@@ -0,0 +1,54 @@
import assert from "node:assert/strict";
import test from "node:test";
import {
DEFAULT_ACTIVITY_TEXT,
MAX_ACTIVITY_ROTATION_INTERVAL_SECONDS,
MIN_ACTIVITY_ROTATION_INTERVAL_SECONDS,
parsePresenceState,
sanitizeActivityTexts,
sanitizePresenceRotationIntervalSeconds,
} from "../src/framework/presence/presenceTypes.js";
test("sanitizeActivityTexts fallback sur le texte par defaut", () => {
const texts = sanitizeActivityTexts([" ", ""]);
assert.deepEqual(texts, [DEFAULT_ACTIVITY_TEXT]);
});
test("sanitizePresenceRotationIntervalSeconds borne les valeurs", () => {
assert.equal(sanitizePresenceRotationIntervalSeconds(1), MIN_ACTIVITY_ROTATION_INTERVAL_SECONDS);
assert.equal(
sanitizePresenceRotationIntervalSeconds(MAX_ACTIVITY_ROTATION_INTERVAL_SECONDS + 100),
MAX_ACTIVITY_ROTATION_INTERVAL_SECONDS,
);
});
test("parsePresenceState reconstruit un etat valide", () => {
const parsed = parsePresenceState({
status: "online",
activity: {
type: "PLAYING",
texts: ["Hello", "World"],
rotationIntervalSeconds: 20,
},
});
assert.ok(parsed);
assert.equal(parsed?.status, "online");
assert.equal(parsed?.activity.type, "PLAYING");
assert.deepEqual(parsed?.activity.texts, ["Hello", "World"]);
assert.equal(parsed?.activity.rotationIntervalSeconds, 20);
});
test("parsePresenceState retourne null sur statut invalide", () => {
const parsed = parsePresenceState({
status: "invalid",
activity: {
type: "PLAYING",
texts: ["Hello"],
rotationIntervalSeconds: 20,
},
});
assert.equal(parsed, null);
});
+47
View File
@@ -0,0 +1,47 @@
import assert from "node:assert/strict";
import test from "node:test";
import {
extractTemplateVariables,
hasTemplateVariable,
renderTemplate,
} from "../src/framework/utils/templateVariables.js";
test("renderTemplate remplace les variables et applique les alias", () => {
const output = renderTemplate(
"Hello {{name}} from {{guilds}}",
{
name: "Arthur",
guild_count: "42",
},
{
aliases: {
guilds: "guild_count",
},
},
);
assert.equal(output, "Hello Arthur from 42");
});
test("renderTemplate conserve les variables inconnues par defaut", () => {
const output = renderTemplate("Missing {{unknown}}", {}, { keepUnknown: true });
assert.equal(output, "Missing {{unknown}}");
});
test("extractTemplateVariables normalise les alias", () => {
const variables = extractTemplateVariables("{{bot}} {{guilds}}", {
bot: "bot_name",
guilds: "guild_count",
});
assert.deepEqual(variables.sort(), ["bot_name", "guild_count"]);
});
test("hasTemplateVariable detecte les variables connues", () => {
const hasKnown = hasTemplateVariable("{{prefix}} {{other}}", ["prefix", "guild_count"]);
assert.equal(hasKnown, true);
const hasUnknownOnly = hasTemplateVariable("{{other}}", ["prefix", "guild_count"]);
assert.equal(hasUnknownOnly, false);
});