mirror of
https://github.com/TiagoVal97/cheatspecter.git
synced 2026-10-23 19:15:54 +02:00
A quality pass after 0.4.0 was tried on a real console. - Fix the Learn page crashing in current browsers when changing lesson steps - Clear feedback for every search outcome; real progress with time left and Cancel - Dialogs scroll inside the screen with Save and Cancel always in view - Fix a console error on every closed connection to the payload - Copy buttons work when the page is served from the PS5 - The practice game sits beside the lesson's tools and lasts between steps - Damaged cheat files, vanishing error messages, unreadable memory shown as zeros - Phone layout: one-line header, larger switches, readable rows - Browser tests under test/ui and a guard against effects that return values
36 lines
1.6 KiB
JavaScript
36 lines
1.6 KiB
JavaScript
// A React effect may return a cleanup function and nothing else. An effect written as a bare
|
|
// expression (`useEffect(() => window.scrollTo(0, 0))`) returns whatever the call returns, and
|
|
// newer browsers return a promise from scroll methods: React then tries to call that promise as
|
|
// the cleanup and the page breaks. So effects are written with a block body, or return a function.
|
|
|
|
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import fs from 'node:fs';
|
|
import path from 'node:path';
|
|
import { fileURLToPath } from 'node:url';
|
|
|
|
const root = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'src');
|
|
|
|
function* sources(dir) {
|
|
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
const full = path.join(dir, entry.name);
|
|
if (entry.isDirectory()) yield* sources(full);
|
|
else if (/\.tsx?$/.test(entry.name)) yield full;
|
|
}
|
|
}
|
|
|
|
test('no effect returns the value of an expression', () => {
|
|
const bad = [];
|
|
for (const file of sources(root)) {
|
|
const text = fs.readFileSync(file, 'utf8');
|
|
// `() => {` (a block) and `() => () =>` (a cleanup function) are the two allowed openings.
|
|
for (const m of text.matchAll(/use(?:Layout|Insertion)?Effect\(\s*(?:async\s*)?\(\)\s*=>\s*(?=\S)(?!\{|\(\)\s*=>)/g)) {
|
|
bad.push(`${path.relative(root, file)}:${text.slice(0, m.index).split('\n').length}`);
|
|
}
|
|
for (const m of text.matchAll(/use(?:Layout|Insertion)?Effect\(\s*async\b/g)) {
|
|
bad.push(`${path.relative(root, file)}:${text.slice(0, m.index).split('\n').length} (async effect)`);
|
|
}
|
|
}
|
|
assert.deepEqual(bad, [], 'write these effects with a block body');
|
|
});
|