The released game only ever zoomed in whole steps up to 400%, so a small camera on a large screen stayed far smaller than it could be. The "Click to play" caption was drawn in the 11 px panel title size and was easy to miss. - GAME_SCALE_STEPS gains 300%, 500% and 600%. The game tab picker, Auto in the editor and the game link all read the same list. - The start caption takes its size from the new Theme.captionSize (16) instead of a constant in GameScreen. - The player page keeps the default arrow cursor at all times. It no longer switches to the hand over the caption. Tests: - view.test: Auto for 320x180 in 2000x2000 is now 6, with cases for 3 and 5. play-settings.test takes 2.5 and 8 as invalid steps. - e2e 60 checks the caption against the panel title size and the arrow cursor before and after the start. Module 03 follows the new step list. - ./check.sh 2808 tests, CHECK EXIT 0 (before the last Theme tweak, which changes no test). Full e2e run ALL PASSED, 1574 checks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
77 lines
3.0 KiB
TypeScript
77 lines
3.0 KiB
TypeScript
/**
|
|
* Which scene Play starts and the game view scale (#226): both live in the project now, not in the
|
|
* browser. The start-scene switch is an undo step like every other project setting; the scale is
|
|
* saved but never lands on the undo stack.
|
|
*/
|
|
import { describe, expect, it } from 'vitest';
|
|
import { SetPlayFromCommand } from '../../src/core/commands/projectCommands';
|
|
import { gameScaleOf, playFromOf } from '../../src/core/model/playSettings';
|
|
import { createEmptyProject } from '../../src/core/model/Project';
|
|
import { deserializeProject, serializeProject } from '../../src/core/store/serialize';
|
|
import { EditorState } from '../../src/editor/state';
|
|
|
|
function loaded() {
|
|
const state = new EditorState();
|
|
state.loadProject(createEmptyProject('p', 'P'), 1);
|
|
return state;
|
|
}
|
|
|
|
describe('play settings in the project', () => {
|
|
it('start from the start scene at 100% in a new project and in one written before there were any', () => {
|
|
const fresh = createEmptyProject('p', 'P');
|
|
const old = deserializeProject({ id: 'p', name: 'P', assets: [] });
|
|
expect([fresh.playFrom, fresh.gameScale]).toEqual(['start', 1]);
|
|
expect([old.playFrom, old.gameScale]).toEqual(['start', 1]);
|
|
});
|
|
|
|
it('survive a save and a load', () => {
|
|
const project = {
|
|
...createEmptyProject('p', 'P'),
|
|
playFrom: 'active' as const,
|
|
gameScale: 'auto' as const,
|
|
};
|
|
const back = deserializeProject(serializeProject(project));
|
|
expect([back.playFrom, back.gameScale]).toEqual(['active', 'auto']);
|
|
});
|
|
|
|
it('read untrusted JSON as the defaults unless it is one of the choices', () => {
|
|
expect(playFromOf({ playFrom: 'active' })).toBe('active');
|
|
expect(playFromOf({ playFrom: 'elsewhere' })).toBe('start');
|
|
expect(playFromOf(null)).toBe('start');
|
|
expect(gameScaleOf({ gameScale: 'fit' })).toBe('fit');
|
|
expect(gameScaleOf({ gameScale: 0.25 })).toBe(0.25);
|
|
expect(gameScaleOf({ gameScale: 3 })).toBe(3);
|
|
expect(gameScaleOf({ gameScale: 6 })).toBe(6);
|
|
expect(gameScaleOf({ gameScale: 2.5 })).toBe(1);
|
|
expect(gameScaleOf({ gameScale: 8 })).toBe(1);
|
|
expect(gameScaleOf({ gameScale: '2' })).toBe(1);
|
|
});
|
|
|
|
it('make the start-scene switch one undo step', () => {
|
|
const state = loaded();
|
|
state.execute(new SetPlayFromCommand('active'));
|
|
expect(state.playFrom).toBe('active');
|
|
expect(state.saveStatus).toBe('dirty');
|
|
state.undo();
|
|
expect(state.playFrom).toBe('start');
|
|
});
|
|
|
|
it('save the game view scale without an undo step', () => {
|
|
const state = loaded();
|
|
state.setGameScale(4);
|
|
expect(state.project.gameScale).toBe(4);
|
|
expect(state.saveStatus).toBe('dirty');
|
|
expect(state.commands.canUndo).toBe(false);
|
|
});
|
|
|
|
it('keep a scale picked while playing after Stop', () => {
|
|
const state = loaded();
|
|
state.enterPlay();
|
|
state.setGameScale('fit');
|
|
expect(state.gameScale).toBe('fit');
|
|
state.exitPlay();
|
|
expect(state.gameScale).toBe('fit');
|
|
expect(state.saveStatus).toBe('dirty');
|
|
});
|
|
});
|