als-statistics
Version:
Modular JS statistics toolkit for Node.js and the browser: descriptive stats, correlations (Pearson/Spearman/Kendall), t-tests & ANOVA (Student/Welch), reliability (Cronbach’s alpha), regression (linear/logistic), clustering (DBSCAN/HDBSCAN), and table/co
114 lines (92 loc) • 4.08 kB
JavaScript
// tests/cache.test.mjs
import { describe, it, beforeEach } from 'node:test';
import assert from 'node:assert'; // хотели именно assert(..)
import { Cache } from '../../lib/column/cache.js';
describe('Cache', () => {
describe('ленивые вычисления и инвалидация кэша', () => {
let c, calls, SUM;
beforeEach(() => {
c = new Cache([1, 2, 3]);
calls = 0;
SUM = Cache.key('sum');
});
it('кэширует результат $(key, compute)', () => {
const sum = c.$(SUM, ({ values }) => {
calls++;
return values.reduce((a, b) => a + b, 0);
});
assert.strictEqual(sum, 6);
assert.strictEqual(calls, 1, 'compute должен быть вызван один раз');
// Повторный вызов с тем же ключом — берем из кэша
const sum2 = c.$(SUM, () => {
calls++;
return -1;
});
assert.strictEqual(sum2, 6);
assert.strictEqual(calls, 1, 'повтор не должен вычислять заново');
});
it('очищает кэш при изменении values', () => {
c.$(SUM, ({ values }) => {
calls++;
return values.reduce((a, b) => a + b, 0);
});
assert.strictEqual(calls, 1);
c.push(4); // меняем данные -> кэш должен очиститься
const sum2 = c.$(SUM, ({ values }) => {
calls++;
return values.reduce((a, b) => a + b, 0);
});
assert.strictEqual(sum2, 10);
assert.strictEqual(calls, 2, 'после изменения данных должен быть пересчет');
});
});
describe('onchange события и meta.type', () => {
it('эмитит set/undo/redo с прошлым values', () => {
const c = new Cache([1, 2, 3]);
const events = [];
c.onchange((self, prev, meta) => {
events.push({ prev: Array.from(prev), next: Array.from(self.values), type: meta.type });
});
c.push(4); // set
assert.strictEqual(events.length, 1);
assert.deepStrictEqual(events[0], { prev: [1, 2, 3], next: [1, 2, 3, 4], type: 'set' });
});
});
describe('set values(next) игнорирует ту же ссылку', () => {
it('не триггерит событие и не добавляет состояние при той же ссылке', () => {
const arr = [1, 2];
const c = new Cache(arr);
let events = 0;
c.onchange(() => { events++; });
// та же ссылка — ничего не меняется
c.values = arr;
assert.strictEqual(events, 0);
assert.deepStrictEqual(c.values, [1, 2]);
// новая ссылка — событие есть
c.values = [...arr, 3];
assert.strictEqual(events, 1);
assert.deepStrictEqual(c.values, [1, 2, 3]);
});
});
});
describe('Cache API', () => {
it('key/insertAt/setAt/removeAt/splice/push корректно меняют ссылку и валидируют', () => {
const c = new Cache([1, 2, 3]);
let fired = 0;
c.onchange(() => fired++);
c.insertAt(1, 9);
assert.deepEqual(c.values, [1, 9, 2, 3]);
c.setAt(0, 7);
assert.deepEqual(c.values, [7, 9, 2, 3]);
c.removeAt(2, 1);
assert.deepEqual(c.values, [7, 9, 3]);
c.push(2,5);
assert.deepEqual(c.values, [7,9,3,2,5]);
assert.ok(fired >= 4); // операции меняли ссылку
});
it('валидатор отклоняет не числа', () => {
const c = new Cache([1]);
assert.throws(() => c.push('2'), /not valid/i);
assert.throws(() => c.push(NaN), /not valid/i);
});
});