Files
rebirthlife/test/conditionEvaluator.test.js
T

157 lines
8.1 KiB
JavaScript

import { evaluateCondition, OPS } from '../src/engine/conditionEvaluator.js';
function assert(cond, msg) {
if (!cond) throw new Error(msg);
}
// Test state matching the reference
const state = {
age: 15,
reincarnation: 2,
money: 300,
stats: { body: 30, wisdom: 20, charm: 10, destiny: 5, business: 8, intelligence: 15 },
careers: { student: { level: 120 } },
identity: 'orphan',
worldFlags: { met_taoist: true },
shopItems: { taoist_license: 1 },
artifacts: { immortal_sword: 3 }
};
// Test OPS constant exists
assert(typeof OPS === 'object', 'OPS should be an object');
assert(typeof OPS['>='] === 'function', 'OPS[">="] should be a function');
// === age conditions ===
assert(evaluateCondition({ type: 'age', op: '>=', value: 14 }, state) === true, 'age >= 14 should be true');
assert(evaluateCondition({ type: 'age', op: '>=', value: 16 }, state) === false, 'age >= 16 should be false');
assert(evaluateCondition({ type: 'age', op: '==', value: 15 }, state) === true, 'age == 15 should be true');
assert(evaluateCondition({ type: 'age', op: '>', value: 10 }, state) === true, 'age > 10 should be true');
assert(evaluateCondition({ type: 'age', op: '<', value: 20 }, state) === true, 'age < 20 should be true');
assert(evaluateCondition({ type: 'age', op: '<=', value: 15 }, state) === true, 'age <= 15 should be true');
assert(evaluateCondition({ type: 'age', op: '!=', value: 10 }, state) === true, 'age != 10 should be true');
// === stat conditions ===
assert(evaluateCondition({ type: 'stat', stat: 'body', op: '>=', value: 20 }, state) === true, 'stat body >= 20 should be true');
assert(evaluateCondition({ type: 'stat', stat: 'body', op: '>=', value: 40 }, state) === false, 'stat body >= 40 should be false');
assert(evaluateCondition({ type: 'stat', stat: 'wisdom', op: '==', value: 20 }, state) === true, 'stat wisdom == 20 should be true');
assert(evaluateCondition({ type: 'stat', stat: 'charm', op: '<', value: 20 }, state) === true, 'stat charm < 20 should be true');
assert(evaluateCondition({ type: 'stat', stat: 'destiny', op: '>', value: 0 }, state) === true, 'stat destiny > 0 should be true');
// Missing stat defaults to 0
assert(evaluateCondition({ type: 'stat', stat: 'nonexistent', op: '==', value: 0 }, state) === true, 'missing stat == 0 should be true');
// === careerLevel conditions ===
assert(evaluateCondition({ type: 'careerLevel', careerId: 'student', op: '>=', value: 100 }, state) === true, 'careerLevel student >= 100 should be true');
assert(evaluateCondition({ type: 'careerLevel', careerId: 'student', op: '>=', value: 200 }, state) === false, 'careerLevel student >= 200 should be false');
assert(evaluateCondition({ type: 'careerLevel', careerId: 'student', op: '==', value: 120 }, state) === true, 'careerLevel student == 120 should be true');
// Missing career defaults to 0
assert(evaluateCondition({ type: 'careerLevel', careerId: 'missing', op: '==', value: 0 }, state) === true, 'missing career level == 0 should be true');
// === money conditions ===
assert(evaluateCondition({ type: 'money', op: '>=', value: 200 }, state) === true, 'money >= 200 should be true');
assert(evaluateCondition({ type: 'money', op: '>=', value: 500 }, state) === false, 'money >= 500 should be false');
assert(evaluateCondition({ type: 'money', op: '==', value: 300 }, state) === true, 'money == 300 should be true');
assert(evaluateCondition({ type: 'money', op: '<', value: 500 }, state) === true, 'money < 500 should be true');
// === identity conditions ===
assert(evaluateCondition({ type: 'identity', value: 'orphan' }, state) === true, 'identity orphan should be true');
assert(evaluateCondition({ type: 'identity', value: 'noble' }, state) === false, 'identity noble should be false');
// === worldFlag conditions ===
assert(evaluateCondition({ type: 'worldFlag', flag: 'met_taoist', value: true }, state) === true, 'worldFlag met_taoist == true should be true');
assert(evaluateCondition({ type: 'worldFlag', flag: 'met_taoist' }, state) === true, 'worldFlag met_taoist (no value) should be true');
assert(evaluateCondition({ type: 'worldFlag', flag: 'met_king', value: true }, state) === false, 'worldFlag met_king == true should be false');
assert(evaluateCondition({ type: 'worldFlag', flag: 'met_king' }, state) === false, 'worldFlag met_king (no value) should be false');
// === hasItem conditions ===
assert(evaluateCondition({ type: 'hasItem', itemId: 'taoist_license' }, state) === true, 'hasItem taoist_license should be true');
assert(evaluateCondition({ type: 'hasItem', itemId: 'missing_item' }, state) === false, 'hasItem missing_item should be false');
// === hasArtifact conditions ===
assert(evaluateCondition({ type: 'hasArtifact', artifactId: 'immortal_sword' }, state) === true, 'hasArtifact immortal_sword should be true');
assert(evaluateCondition({ type: 'hasArtifact', artifactId: 'immortal_sword', op: '>=', value: 3 }, state) === true, 'hasArtifact immortal_sword >= 3 should be true');
assert(evaluateCondition({ type: 'hasArtifact', artifactId: 'immortal_sword', op: '>', value: 5 }, state) === false, 'hasArtifact immortal_sword > 5 should be false');
assert(evaluateCondition({ type: 'hasArtifact', artifactId: 'missing_artifact' }, state) === false, 'hasArtifact missing_artifact should be false');
assert(evaluateCondition({ type: 'hasArtifact', artifactId: 'missing_artifact', op: '==', value: 0 }, state) === true, 'hasArtifact missing_artifact == 0 should be true');
// === reincarnation conditions ===
assert(evaluateCondition({ type: 'reincarnation', op: '>=', value: 1 }, state) === true, 'reincarnation >= 1 should be true');
assert(evaluateCondition({ type: 'reincarnation', op: '>=', value: 5 }, state) === false, 'reincarnation >= 5 should be false');
assert(evaluateCondition({ type: 'reincarnation', op: '==', value: 2 }, state) === true, 'reincarnation == 2 should be true');
// === and conditions ===
assert(evaluateCondition({
type: 'and',
conditions: [
{ type: 'age', op: '>=', value: 14 },
{ type: 'stat', stat: 'body', op: '>=', value: 20 }
]
}, state) === true, 'and with two true conditions should be true');
assert(evaluateCondition({
type: 'and',
conditions: [
{ type: 'age', op: '>=', value: 14 },
{ type: 'stat', stat: 'body', op: '>=', value: 50 }
]
}, state) === false, 'and with one false condition should be false');
assert(evaluateCondition({
type: 'and',
conditions: []
}, state) === true, 'and with empty conditions should be true (vacuous truth)');
// === or conditions ===
assert(evaluateCondition({
type: 'or',
conditions: [
{ type: 'age', op: '>=', value: 20 },
{ type: 'stat', stat: 'body', op: '>=', value: 20 }
]
}, state) === true, 'or with one true condition should be true');
assert(evaluateCondition({
type: 'or',
conditions: [
{ type: 'age', op: '>=', value: 20 },
{ type: 'stat', stat: 'body', op: '>=', value: 50 }
]
}, state) === false, 'or with all false conditions should be false');
assert(evaluateCondition({
type: 'or',
conditions: []
}, state) === false, 'or with empty conditions should be false');
// === not conditions ===
assert(evaluateCondition({
type: 'not',
condition: { type: 'age', op: '>=', value: 20 }
}, state) === true, 'not of false condition should be true');
assert(evaluateCondition({
type: 'not',
condition: { type: 'age', op: '>=', value: 14 }
}, state) === false, 'not of true condition should be false');
// === nested compound conditions ===
assert(evaluateCondition({
type: 'and',
conditions: [
{ type: 'or', conditions: [
{ type: 'age', op: '>=', value: 20 },
{ type: 'identity', value: 'orphan' }
]},
{ type: 'not', condition: { type: 'stat', stat: 'body', op: '<', value: 10 }}
]
}, state) === true, 'nested compound condition should be true');
// === invalid/edge cases ===
assert(evaluateCondition(null, state) === false, 'null condition should be false');
assert(evaluateCondition({}, state) === false, 'empty object should be false');
assert(evaluateCondition({ type: 'unknown' }, state) === false, 'unknown type should be false');
assert(evaluateCondition({ type: 'age', op: 'invalid', value: 10 }, state) === false, 'invalid operator should be false');
console.log('All conditionEvaluator tests PASS');