Dice button picks a random seed in the new-world dialog (t100)

This commit is contained in:
2026-10-29 22:14:40 -04:00
parent de6d2c1b33
commit 974e5a6272
9 changed files with 154 additions and 7 deletions
+92
View File
@@ -0,0 +1,92 @@
"""t100: new-world seed editing, random button and generation, in both looks."""
import pathlib, sys
sys.path.insert(0, str(pathlib.Path(__file__).resolve().parent.parent / 'tools'))
from use_venv import ensure_playwright; ensure_playwright()
from browser import launch, consume_gpu_option
consume_gpu_option()
root = pathlib.Path(__file__).resolve().parent.parent
out = root / 'shots'; out.mkdir(exist_ok=True)
fails = []
def check(name, ok):
print(('PASS ' if ok else 'FAIL ') + name)
if not ok: fails.append(name)
with launch(viewport={'width': 1280, 'height': 800}) as (_, pg, url):
errors = []
pg.on('pageerror', lambda e: errors.append(str(e)))
pg.goto(url)
pg.wait_for_function("!$('title').hidden && CAPS.ready")
pg.click('#btn-new')
seed = pg.locator('#nw-seed')
seed.fill('12'); seed.press('Home'); pg.keyboard.type('a!')
check('typed letters and symbols are ignored', seed.input_value() == '12')
pg.keyboard.type('3')
check('ignoring characters preserves the insertion point', seed.input_value() == '312')
# Real clipboard paste exercises maxlength before the input event.
pg.context.grant_permissions(['clipboard-read', 'clipboard-write'])
def paste(text):
seed.focus(); seed.press('ControlOrMeta+a')
pg.evaluate('text => navigator.clipboard.writeText(text)', text)
seed.press('ControlOrMeta+v')
paste('ab12 cd34!56 ef78')
check('paste keeps all digits even beyond ten source characters', seed.input_value() == '12345678')
paste('4294967296')
check('4294967296 clamps to max', seed.input_value() == '4294967295')
paste('99999999999')
check('eleven digits clamp to max', seed.input_value() == '4294967295')
check('maxlength fits ten digits', seed.get_attribute('maxlength') == '10')
check('clamp hint is shown by the box', pg.locator('#nw-seed-hint').count() == 1 and pg.is_visible('#nw-seed-hint'))
for look in ['pixel', 'smooth']:
pg.evaluate('look => SET.look = look', look)
pg.screenshot(path=str(out / f't100-{look}.png'))
# A drop with text transfer data uses the same editing path.
seed.fill('')
seed.evaluate("""e => {
const data = new DataTransfer(); data.setData('text/plain', 'ab4294967296!');
e.dispatchEvent(new DragEvent('drop', {bubbles:true, cancelable:true, dataTransfer:data}));
}""")
check('dropped text is filtered and clamped', seed.input_value() == '4294967295')
# Also exercise browser drag delivery rather than only a dispatched event.
pg.evaluate("""() => {
const source = document.createElement('div'); source.id = 'seed-drag';
source.textContent = 'Drag seed'; source.draggable = true;
source.style = 'position:fixed;z-index:99999;top:0;left:0;padding:20px;background:white';
source.ondragstart = e => e.dataTransfer.setData('text/plain', 'seed: 1234!');
document.body.append(source);
}""")
seed.fill(''); pg.locator('#seed-drag').drag_to(seed)
check('real text drag keeps only digits', seed.input_value() == '1234')
pg.locator('#seed-drag').evaluate('e => e.remove()')
seed.fill('0')
check('zero stays zero', seed.input_value() == '0')
# Record Generate's arguments without generating several large worlds.
pg.evaluate("""() => {
window.__start = startNewWorld;
startNewWorld = (...args) => { window.__generated = args; };
window.__random = Math.random; Math.random = () => 0.5;
}""")
seed.press('Enter')
check('Enter generates seed zero', pg.evaluate('__generated[0] === 0'))
seed.fill('4294967295'); pg.click('#btn-generate')
check('maximum seed generates without wrapping', pg.evaluate('__generated[0] === 4294967295'))
seed.evaluate("e => e.value = '99999999999'"); pg.click('#btn-generate')
check('Generate applies the same clamp even without an input event', pg.evaluate('__generated[0] === 4294967295'))
seed.fill(''); pg.click('#btn-generate')
check('empty generates a random six-digit seed', pg.evaluate('__generated[0] === 550000'))
dice = pg.get_by_role('button', name='Random seed', exact=True)
check('dice is a labeled button with tooltip', dice.count() == 1 and dice.get_attribute('title') == 'Random seed')
if dice.count():
seed.fill('42'); dice.focus(); pg.keyboard.press('Enter')
check('keyboard dice uses the same random rule', seed.input_value() == '550000')
check('dice updates the automatic name', pg.evaluate("$('nw-name').value === claimName(550000, [])"))
pg.fill('#nw-name', 'My camp'); pg.evaluate('Math.random = () => 0.25'); dice.click()
check('dice changes seed and preserves a typed name', seed.input_value() == '325000' and pg.input_value('#nw-name') == 'My camp')
check('valid input clears clamp hint', not pg.is_visible('#nw-seed-hint'))
# Exercise the real UI-to-worldgen boundary once, including zero's stored seed.
pg.evaluate('() => { startNewWorld = __start; Math.random = __random; SET.look = "pixel"; }')
seed.fill('0'); pg.select_option('#nw-size', '2048x1024'); seed.press('Enter')
pg.wait_for_function('GAME.running', timeout=60000)
check('real generated world retains seed zero', pg.evaluate('worldSeed === 0'))
check('no page errors', not errors)
print('FAILS:', fails)
sys.exit(bool(fails))