aboutsummaryrefslogtreecommitdiffstats
path: root/prototypes/workbench/baseline.test.mjs
blob: c9ef2de4d27654f298bc62a1defb6ad862dace2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
import test from 'node:test';
import assert from 'node:assert/strict';
import { createChargeModel } from './web/baseline.mjs';

test('reference begins with the authored states and matching scene', () => {
  const model = createChargeModel();
  assert.deepEqual(model.snapshot().states, { holding: 0, charge: 0, y: 240, velocity: 0 });
  assert.deepEqual(model.snapshot().held, []);
  assert.equal(model.snapshot().tick, 0);
  assert.equal(model.snapshot().views.find(view => view.id === 'floor').y, 261);
  assert.equal(model.snapshot().views.find(view => view.id === 'actor').radius, 20);
});

test('press, hold, release, and frame order produce exact expected values', () => {
  const model = createChargeModel();
  model.down(); model.frame(15);
  let expectedCharge = 0;
  for (let frame = 0; frame < 15; frame++) expectedCharge = Math.min(Math.max(expectedCharge + 1 / 60, 0), 1);
  assert.deepEqual(model.snapshot().states, { holding: 1, charge: expectedCharge, y: 240, velocity: 0 });
  model.up();
  const initialVelocity = -(160 + expectedCharge * 300);
  assert.deepEqual(model.snapshot().states, { holding: 0, charge: 0, y: 240, velocity: initialVelocity });
  model.frame();
  const nextVelocity = initialVelocity + 600 * (1 / 60);
  assert.deepEqual(model.snapshot().states, {
    holding: 0, charge: 0, y: 240 + nextVelocity * (1 / 60), velocity: nextVelocity,
  });
});

test('charge clamps at one and explicit floor restores rest', () => {
  const model = createChargeModel();
  model.down(); model.frame(120);
  assert.equal(model.snapshot().states.charge, 1);
  model.up(); assert.equal(model.snapshot().states.velocity, -460);
  model.frame(); assert.equal(model.snapshot().states.y, 232.5);
  model.frame(120);
  assert.deepEqual(model.snapshot().states, { holding: 0, charge: 0, y: 240, velocity: 0 });
});

test('repeat and concurrent physical sources produce only logical edges', () => {
  const model = createChargeModel();
  model.down('jump', 'keyboard'); model.frame(6);
  const charge = model.snapshot().states.charge;
  model.down('jump', 'keyboard'); model.down('jump', 'pointer');
  assert.equal(model.snapshot().states.charge, charge);
  model.up('jump', 'keyboard');
  assert.equal(model.snapshot().states.holding, 1);
  model.up('jump', 'unknown'); assert.equal(model.snapshot().states.holding, 1);
  model.up('jump', 'pointer'); assert.equal(model.snapshot().states.velocity, -(160 + charge * 300));
  const released = model.snapshot(); model.up('jump', 'pointer');
  assert.deepEqual(model.snapshot(), released);
});

test('airborne presses cannot charge or cause another jump', () => {
  const model = createChargeModel(); model.down(); model.up(); model.frame();
  const airborne = model.snapshot().states;
  model.down(); model.up();
  assert.deepEqual(model.snapshot().states, airborne);
});

test('releaseAll emits release and reset clears latches without a jump', () => {
  const model = createChargeModel();
  model.down('jump', 'keyboard'); model.down('jump', 'pointer'); model.frame(10);
  model.releaseAll(); assert.equal(model.snapshot().states.holding, 0);
  assert.ok(model.snapshot().states.velocity < 0); assert.deepEqual(model.snapshot().held, []);
  model.reset(); assert.deepEqual(model.snapshot().states, { holding: 0, charge: 0, y: 240, velocity: 0 });
  assert.equal(model.snapshot().tick, 0);
  model.down(); model.reset(); model.up(); assert.equal(model.snapshot().states.velocity, 0);
});

test('unknown inputs and invalid frame counts reject without mutation', () => {
  const model = createChargeModel(), initial = model.snapshot();
  for (const method of ['down', 'up']) assert.throws(() => model[method]('other'), /Unknown input/);
  for (const count of [-1, .5, 601, Infinity, NaN, '1']) assert.throws(() => model.frame(count), /integer/);
  model.frame(0); assert.deepEqual(model.snapshot(), initial);
  const snapshot = model.snapshot(); snapshot.states.y = -999;
  assert.equal(model.snapshot().states.y, 240);
});