fix: corrections générateur PNJ Traveller et tests Jest
- validateOptions : remplit les champs manquants et corrige les clés invalides (détection précédemment inopérante car getXByKey renvoie l'objet par défaut) - generateCharacteristics : ne mélange plus le tableau avant affectation, la priorité des caractéristiques (high → medium → low) est respectée - Exports manquants : convertSkillToMgt2eFormat, popRandomItems, ERROR_CODES, TravellerNpcError - Tests : import des globals via @jest/globals (obligatoire en ESM), suppression de l'import obsolète buildMgt2eBaseActorSystem, attente corrigée pilot.smallCraft, test des doublons aligné sur le dédoublonnage réel (noms complets, spécialisations conservées) - AGENTS.md : section Testing mise à jour - README.md : ajouté
This commit is contained in:
@@ -723,22 +723,30 @@ export function validateOptions(options = {}) {
|
||||
const errors = [];
|
||||
const validated = { ...options };
|
||||
|
||||
if (validated.citizenCategory && !getCitizenCategoryByKey(validated.citizenCategory)) {
|
||||
// Remplir les valeurs manquantes avec les défauts
|
||||
for (const key of ['citizenCategory', 'experience', 'role', 'gender']) {
|
||||
if (!validated[key]) {
|
||||
validated[key] = DEFAULT_OPTIONS[key];
|
||||
}
|
||||
}
|
||||
|
||||
// Corriger les valeurs invalides (getXByKey renvoie l'objet par défaut si la clé est inconnue)
|
||||
if (getCitizenCategoryByKey(validated.citizenCategory).key !== validated.citizenCategory) {
|
||||
errors.push(`Catégorie de citoyen invalide: ${validated.citizenCategory}`);
|
||||
validated.citizenCategory = DEFAULT_OPTIONS.citizenCategory;
|
||||
}
|
||||
|
||||
if (validated.experience && !getExperienceLevelByKey(validated.experience)) {
|
||||
if (getExperienceLevelByKey(validated.experience).key !== validated.experience) {
|
||||
errors.push(`Niveau d'expérience invalide: ${validated.experience}`);
|
||||
validated.experience = DEFAULT_OPTIONS.experience;
|
||||
}
|
||||
|
||||
if (validated.role && !getRoleByKey(validated.role)) {
|
||||
if (getRoleByKey(validated.role).key !== validated.role) {
|
||||
errors.push(`Rôle invalide: ${validated.role}`);
|
||||
validated.role = DEFAULT_OPTIONS.role;
|
||||
}
|
||||
|
||||
if (validated.gender && !getGenderByKey(validated.gender)) {
|
||||
if (getGenderByKey(validated.gender).key !== validated.gender) {
|
||||
errors.push(`Genre invalide: ${validated.gender}`);
|
||||
validated.gender = DEFAULT_OPTIONS.gender;
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
* un framework de test similaire.
|
||||
*/
|
||||
|
||||
// Import explicite des globals Jest (obligatoire en ESM)
|
||||
import { jest, describe, it, expect, beforeEach } from '@jest/globals';
|
||||
|
||||
// Mock des dépendances Foundry pour l'environnement de test
|
||||
const mockFoundry = {
|
||||
utils: {
|
||||
@@ -85,7 +88,6 @@ import {
|
||||
convertSkillToMgt2eFormat,
|
||||
buildMgt2eCharacteristics,
|
||||
buildMgt2eSkills,
|
||||
buildMgt2eBaseActorSystem,
|
||||
getMgt2eBaseActorSystem,
|
||||
toHex,
|
||||
calculateDm,
|
||||
@@ -579,13 +581,14 @@ describe('generateSkills', () => {
|
||||
expect(eliteLevel3).toBeGreaterThanOrEqual(regularLevel3);
|
||||
});
|
||||
|
||||
it('devrait supprimer les doublons basés sur la compétence de base', () => {
|
||||
it('devrait supprimer les doublons exacts de compétence', () => {
|
||||
const skills = generateSkills('pilot', 'regular');
|
||||
const skillNames = skills.map(s => s.name);
|
||||
const uniqueBases = new Set(skillNames.map(n => n.split('-')[0]));
|
||||
const uniqueNames = new Set(skillNames);
|
||||
|
||||
// Chaque nom de base devrait apparaître une seule fois
|
||||
expect(skillNames.length).toBe(uniqueBases.size);
|
||||
// Le générateur dédoublonne les noms complets mais conserve
|
||||
// les spécialisations (Pilot-Spacecraft, Pilot-Small Craft, ...)
|
||||
expect(skillNames.length).toBe(uniqueNames.size);
|
||||
});
|
||||
|
||||
it('devrait générer des compétences avec le rôle par défaut pour un rôle invalide', () => {
|
||||
@@ -624,7 +627,7 @@ describe('convertSkillToMgt2eFormat', () => {
|
||||
});
|
||||
|
||||
it('devrait gérer les tirets', () => {
|
||||
expect(convertSkillToMgt2eFormat('Pilot-Small Craft')).toBe('pilot.smallcraft');
|
||||
expect(convertSkillToMgt2eFormat('Pilot-Small Craft')).toBe('pilot.smallCraft');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ const SKILL_MAPPING = {
|
||||
* @param {string} skillName - Nom de la compétence
|
||||
* @returns {string} - Nom au format mgt2e
|
||||
*/
|
||||
function convertSkillToMgt2eFormat(skillName) {
|
||||
export function convertSkillToMgt2eFormat(skillName) {
|
||||
// Vérifier d'abord dans le mapping explicite
|
||||
if (SKILL_MAPPING[skillName]) {
|
||||
return SKILL_MAPPING[skillName];
|
||||
@@ -192,8 +192,9 @@ export function generateCharacteristics(citizenCategoryKey, roleKey) {
|
||||
const category = getCitizenCategoryByKey(citizenCategoryKey);
|
||||
const priorities = getCharacteristicPrioritiesForRole(roleKey);
|
||||
|
||||
// Cloner et mélanger l'array de base de la catégorie
|
||||
let characteristicArray = shuffleArray([...category.characteristicArray]);
|
||||
// Le tableau de base de la catégorie est trié par ordre décroissant :
|
||||
// on l'attribue tel quel dans l'ordre de priorité (high → medium → low)
|
||||
let characteristicArray = [...category.characteristicArray];
|
||||
|
||||
const characteristics = {};
|
||||
|
||||
@@ -726,5 +727,9 @@ export {
|
||||
getSkillsForRole,
|
||||
getCharacteristicPrioritiesForRole,
|
||||
validateOptions,
|
||||
DEFAULT_OPTIONS
|
||||
DEFAULT_OPTIONS,
|
||||
popRandomItems
|
||||
} from './data/travellerNpcGenerator.js';
|
||||
|
||||
// Ré-exporter ERROR_CODES et TravellerNpcError utilisés en interne (proviennent de utils)
|
||||
export { ERROR_CODES, TravellerNpcError } from './utils/travellerNpcUtils.js';
|
||||
|
||||
Reference in New Issue
Block a user