pokemon-showdown/test/assert.js
Ben Davies 54d0ff203a Performance: replace direct references to arguments with rest parametres (#2818)
Replacing direct references to the arguments object of functions with rest
parametres prevents the function from being deoptimized while still allowing
use of arbitrary arguments. This may also fix some minor memory leaks related
to mishandling the arguments object.
2016-10-04 16:29:14 -07:00

166 lines
4.5 KiB
JavaScript

'use strict';
const baseAssert = require('assert');
const AssertionError = baseAssert.AssertionError;
const assert = exports = module.exports = function assert(value, message) {
return baseAssert(value, message);
};
Object.assign(assert, baseAssert);
assert.bounded = function (value, range, message) {
if (value >= range[0] && value <= range[1]) return;
throw new AssertionError({
actual: value,
expected: `[${value[0]}, ${value[1]}]`,
operator: '\u2208',
message: message,
stackStartFunction: assert.bounded,
});
};
assert.atLeast = function (value, threshold, message) {
if (value >= threshold) return;
throw new AssertionError({
actual: value,
expected: `${threshold}`,
operator: '>=',
message: message,
stackStartFunction: assert.atLeast,
});
};
assert.atMost = function (value, threshold, message) {
if (value <= threshold) return;
throw new AssertionError({
actual: value,
expected: `${threshold}`,
operator: '<=',
message: message,
stackStartFunction: assert.atMost,
});
};
assert.species = function (pokemon, species, message) {
const actual = pokemon.template.species;
if (actual === species) return;
throw new AssertionError({
message: message || `Expected ${pokemon} species to be ${species}, not ${actual}.`,
stackStartFunction: assert.species,
});
};
assert.fainted = function (pokemon, message) {
if (!pokemon.hp) return;
throw new AssertionError({
message: message || `Expected ${pokemon} to be fainted.`,
stackStartFunction: assert.fainted,
});
};
assert.fullHP = function (pokemon, message) {
if (pokemon.hp === pokemon.maxhp) return;
throw new AssertionError({
message: message || `Expected ${pokemon} to be fully healed, not at ${pokemon.hp}/${pokemon.maxhp}.`,
stackStartFunction: assert.fullHP,
});
};
assert.holdsItem = function (pokemon, message) {
if (pokemon.item) return;
throw new AssertionError({
message: message || `Expected ${pokemon} to hold an item`,
stackStartFunction: assert.holdsItem,
});
};
assert.statStage = function (pokemon, statName, stage, message) {
const actual = pokemon.boosts[statName];
if (actual === stage) return;
throw new AssertionError({
message: message || `Expected ${pokemon}'s ${statName} at stage ${stage}, not at ${actual}.`,
stackStartFunction: assert.statStage,
});
};
assert.hurts = function (pokemon, fn, message) {
const prevHP = pokemon.hp;
fn();
if (pokemon.hp < prevHP) return;
throw new AssertionError({
actual: pokemon.hp,
expected: `${prevHP}`,
operator: '<',
message: message || `Expected ${pokemon} to be hurt.`,
stackStartFunction: assert.hurts,
});
};
assert.hurtsBy = function (pokemon, damage, fn, message) {
// Support of healing effects is intentional.
const prevHP = pokemon.hp;
fn();
const actual = prevHP - pokemon.hp;
if (actual === damage) return;
throw new AssertionError({
actual: actual,
expected: damage,
operator: '===',
message: message || `Expected ${pokemon} to be hurt by ${damage}, not by ${actual}.`,
stackStartFunction: assert.hurtsBy,
});
};
assert.constant = function (getter, fn, message) {
const initialValue = getter();
fn();
const finalValue = getter();
if (finalValue === initialValue) return;
throw new AssertionError({
message: message || `Expected value to remain as ${initialValue}, not to change to ${finalValue}.`,
stackStartFunction: assert.constant,
});
};
assert.sets = function (getter, value, fn, message) {
assert.notStrictEqual(getter(), value, `Function was prematurely equal to ${value}.`);
fn();
const finalValue = getter();
if (finalValue === value) return;
throw new AssertionError({
actual: finalValue,
expected: value,
operator: '===',
message: message,
stackStartFunction: assert.sets,
});
};
const assertMethods = Object.getOwnPropertyNames(assert).concat(Object.getOwnPropertyNames(baseAssert)).filter(methodName => {
return methodName !== 'constructor' && methodName !== 'AssertionError' && typeof assert[methodName] === 'function';
});
assert.false = function (value, message) {
if (!value) return;
throw new AssertionError({
actual: `!${value}`,
expected: true,
operator: '===',
message: message,
stackStartFunction: assert.false,
});
};
for (let methodName of assertMethods) {
const lastArgIndex = assert[methodName].length - 1;
assert.false[methodName] = function (...args) {
try {
assert[methodName].apply(null, args);
} catch (err) {
return;
}
throw new AssertionError({
message: lastArgIndex < args.length ? args[lastArgIndex] : `Expected '${methodName}' assertion to fail.`,
stackStartFunction: assert.false[methodName],
});
};
}