Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions e2e/drivers/svelte.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,17 @@ const STEP_FOR_TAB: Record<Exclude<MainTab, 'Configuration'>, string> = {
Export: 'export',
};

/** The workflow step whose Inspector panel holds each slider. */
const STEP_FOR_SLIDER: Record<SliderName, string> = {
'num-slices': 'slices',
'camera-distance': 'preview',
'max-distance': 'preview',
'focal-length': 'preview',
'ground-distance': 'ground',
displacement: 'export',
'number-of-frames': 'export',
};

export class SvelteDriver implements UiDriver {
readonly target: UiTarget = 'svelte';

Expand Down Expand Up @@ -502,6 +513,13 @@ export class SvelteDriver implements UiDriver {
await expect(this.page.locator('html')).toHaveAttribute('data-theme', 'dark');
}

/** Shows the step panel that holds `testId`, unless it is already visible. */
private async revealStep(step: string, testId: string): Promise<void> {
if (await this.page.getByTestId(testId).isVisible()) return;
await this.page.getByTestId(`step-${step}`).click();
await expect(this.page.getByTestId(testId)).toBeVisible();
}

async expectSliderValue(name: SliderName, value: number): Promise<void> {
const input = this.page.getByTestId(name);
await expect(input).toHaveValue(String(value));
Expand All @@ -511,12 +529,14 @@ export class SvelteDriver implements UiDriver {
* Native `<input type=range>` elements (unlike Dash's rc-slider) have no
* `aria-valuestep` quirk to work around, but the same "step directly from
* the current value, never via Home" rationale from DashDriver.setSlider
* still applies here (ExportTab.svelte's camera/displacement sliders are
* committed together - see its own doc comment), so this mirrors that
* still applies here (the camera/displacement sliders are committed
* together - see state/cameraDraft.svelte.ts), so this mirrors that
* driver's technique with real keyboard events (`ArrowRight`/`ArrowLeft`)
* rather than any synthetic value assignment.
*/
async setSlider(name: SliderName, value: number): Promise<void> {
if (name === 'num-slices') await this.openSplitByDepth();
else await this.revealStep(STEP_FOR_SLIDER[name], name);
const input = this.page.getByTestId(name);
await input.focus();
const min = Number(await input.getAttribute('min'));
Expand Down Expand Up @@ -552,6 +572,7 @@ export class SvelteDriver implements UiDriver {
}

async fitGround(): Promise<void> {
await this.revealStep('ground', 'ground-fit');
await this.page.getByTestId('ground-fit').click();
await expect(this.log()).toContainText('Fitted the ground plane');
}
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/lib/components/canvas/ToolOptionsBar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
const queued = $derived(segmentation?.queuedPoints.length ?? 0);
const objectMode = $derived(uiStore.segmentationMode === 'segment');
const canNavigate = $derived((view?.slices.length ?? 0) > 0);
const hasGround = $derived(view?.slices.some((s) => s.isGround) ?? false);

const CAMERA_BUTTONS: { direction: CameraDirection; label: string; icon: typeof ArrowUp }[] = [
{ direction: 'left', label: 'Move camera left', icon: ArrowLeft },
Expand Down Expand Up @@ -144,6 +145,18 @@
</span>
{/if}
<span class="hint">Drag the line to where the ground meets the sky.</span>
{#if hasGround}
<button
type="button"
class="btn btn-sm"
data-testid="options-fit-ground"
title="Put the horizon on the ground's top edge and the ground under the nearest object"
disabled={isBusy()}
onclick={() => void workflow.fitGround()}
>
Fit ground
</button>
{/if}
{:else}
<span class="hint">Drag to pan · scroll to zoom</span>
{/if}
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/lib/components/canvas/ToolOptionsBar.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,4 +281,20 @@ describe('ToolOptionsBar', () => {
expect(JSON.parse(call![1]!.body as string)).toEqual({ direction: 'left' });
});
});

describe('Horizon tool', () => {
beforeEach(() => uiStore.setTool('horizon'));

it('offers Fit ground only once a ground slice exists', () => {
projectStore.applyView(makeView({ slices: [{ index: 0, depth: 0 } as unknown as SliceView] }));
const { unmount } = render(ToolOptionsBar);
expect(screen.queryByTestId('options-fit-ground')).toBeNull();
unmount();

projectStore.applyView(makeView({ slices: [{ index: 0, depth: 0, isGround: true } as unknown as SliceView] }));
render(ToolOptionsBar);
expect(screen.getByTestId('options-fit-ground')).toBeEnabled();
});
});
});

Loading
Loading