const assert = require('node:assert/strict'); const { readFileSync } = require('node:fs'); const { resolve } = require('node:path'); const { test } = require('node:test'); const { runInNewContext } = require('node:vm'); const source = readFileSync(resolve(__dirname, '../../reproxy/web/minecraft/motion.js'), 'utf8'); for (const reduced of [false, true]) { test(`motion controls, reduced motion=${reduced}`, () => { const classes = new Set(); const attributes = {}; let click; let preferenceChanged; const button = { hidden: true, setAttribute: (key, value) => attributes[key] = value, addEventListener: (name, callback) => { assert.equal(name, 'click'); click = callback; } }; runInNewContext(source, { document: { getElementById: () => button, documentElement: { classList: { toggle: (key, value) => value ? classes.add(key) : classes.delete(key), contains: key => classes.has(key), } } }, window: { matchMedia: query => { assert.equal(query, '(prefers-reduced-motion: reduce)'); return { matches: reduced, addEventListener: (name, callback) => { assert.equal(name, 'change'); preferenceChanged = callback; } }; } }, }); assert.equal(button.hidden, false); assert.equal(classes.has('motion-running'), !reduced); assert.equal(attributes['aria-pressed'], String(reduced)); click(); assert.equal(classes.has('motion-running'), reduced); assert.equal(button.textContent, reduced ? 'Остановить механизмы' : 'Запустить механизмы'); click(); assert.equal(classes.has('motion-running'), !reduced); preferenceChanged({ matches: true }); assert.equal(classes.has('motion-running'), false); assert.equal(attributes['aria-pressed'], 'true'); }); }