Add VectorEngine image generation config and raise request timeouts (env + scripts) from 180000 to 1000000ms. Introduce a reusable CreativeImageInputPanel component with tests and wire up mobile keyboard-focus helpers; update generation views and related tests (CustomWorldGenerationView, BarkBattle editor, Match3D, Puzzle flows). Improve API error handling / VectorEngine request guidance (packages/shared http.ts and docs), and apply multiple backend/frontend fixes for puzzle/match3d/prompt handling. Also include extensive docs and decision-log updates describing UI/UX decisions and verification steps.
78 lines
2.1 KiB
TypeScript
78 lines
2.1 KiB
TypeScript
/* @vitest-environment jsdom */
|
|
|
|
import { describe, expect, it } from 'vitest';
|
|
|
|
import {
|
|
calculateMobileKeyboardFocusShift,
|
|
isEditableKeyboardTarget,
|
|
} from './mobileViewportKeyboardFocus';
|
|
|
|
describe('isEditableKeyboardTarget', () => {
|
|
it('matches controls that open the mobile keyboard', () => {
|
|
const input = document.createElement('input');
|
|
input.type = 'text';
|
|
const textarea = document.createElement('textarea');
|
|
const buttonInput = document.createElement('input');
|
|
buttonInput.type = 'file';
|
|
|
|
expect(isEditableKeyboardTarget(input)).toBe(true);
|
|
expect(isEditableKeyboardTarget(textarea)).toBe(true);
|
|
expect(isEditableKeyboardTarget(buttonInput)).toBe(false);
|
|
});
|
|
|
|
it('ignores disabled and readonly controls', () => {
|
|
const disabledInput = document.createElement('input');
|
|
disabledInput.disabled = true;
|
|
const readonlyInput = document.createElement('input');
|
|
readonlyInput.readOnly = true;
|
|
|
|
expect(isEditableKeyboardTarget(disabledInput)).toBe(false);
|
|
expect(isEditableKeyboardTarget(readonlyInput)).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('calculateMobileKeyboardFocusShift', () => {
|
|
it('moves a bottom input above the visible keyboard area', () => {
|
|
expect(
|
|
calculateMobileKeyboardFocusShift({
|
|
layoutHeight: 800,
|
|
visualTop: 0,
|
|
visualHeight: 500,
|
|
targetTop: 720,
|
|
targetBottom: 770,
|
|
currentShift: 0,
|
|
margin: 20,
|
|
}),
|
|
).toBe(290);
|
|
});
|
|
|
|
it('does not move when the focused input is already visible', () => {
|
|
expect(
|
|
calculateMobileKeyboardFocusShift({
|
|
layoutHeight: 800,
|
|
visualTop: 0,
|
|
visualHeight: 500,
|
|
targetTop: 250,
|
|
targetBottom: 300,
|
|
currentShift: 0,
|
|
margin: 20,
|
|
}),
|
|
).toBe(0);
|
|
});
|
|
|
|
it('caps movement to keyboard inset plus safety margin', () => {
|
|
expect(
|
|
calculateMobileKeyboardFocusShift({
|
|
layoutHeight: 800,
|
|
visualTop: 0,
|
|
visualHeight: 500,
|
|
targetTop: 790,
|
|
targetBottom: 860,
|
|
currentShift: 0,
|
|
margin: 20,
|
|
maxExtraShift: 20,
|
|
}),
|
|
).toBe(320);
|
|
});
|
|
});
|