Skip to content

Commit 49b595b

Browse files
Gold856spacey-sooty
authored andcommitted
Prevent slider from going past bounds (PhotonVision#2222)
## Description PhotonVision#1900 updated how the value was handled in pv-slider, and unintentionally removed bounds protection. This restores bounds protection. Unfortunately, there is an edge case that might be rather difficult to solve. If the slider is already at the min/max, you can enter a number through the text field, and while the value won't actually update, the text field keeps the entered value, likely because the model value didn't change, and therefore, a rerender isn't triggered. However, this is an edge case that I doubt many people will actually encounter, so we should still ship this. Fixes PhotonVision#2221. ## Meta Merge checklist: - [x] Pull Request title is [short, imperative summary](https://cbea.ms/git-commit/) of proposed changes - [x] The description documents the _what_ and _why_ - [ ] If this PR changes behavior or adds a feature, user documentation is updated - [ ] If this PR touches photon-serde, all messages have been regenerated and hashes have not changed unexpectedly - [ ] If this PR touches configuration, this is backwards compatible with settings back to v2025.3.2 - [ ] If this PR touches pipeline settings or anything related to data exchange, the frontend typing is updated - [x] If this PR addresses a bug, a regression test for it is added
1 parent a231907 commit 49b595b

File tree

2 files changed

+46
-1
lines changed

2 files changed

+46
-1
lines changed

photon-client/src/components/common/pv-slider.vue

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,13 @@ function debounce(func: (...args: any[]) => void, wait: number) {
2727
}
2828
2929
const debouncedEmit = debounce((v: number) => {
30-
emit("update:modelValue", v);
30+
if (v < props.min) {
31+
emit("update:modelValue", props.min);
32+
} else if (v > props.max) {
33+
emit("update:modelValue", props.max);
34+
} else {
35+
emit("update:modelValue", v);
36+
}
3137
}, 20);
3238
3339
const localValue = computed({

photon-client/tests/input.spec.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { expect } from "@playwright/test";
2+
import { test } from "./fixtures.ts";
3+
4+
test("Camera Gain Slider won't go past max or min", async ({ page }) => {
5+
await page.goto("http://localhost:5800/#/dashboard");
6+
await page.locator("div").filter({ hasText: "Set up some cameras to get started!" }).nth(2).press("Escape");
7+
8+
// Fill in Camera Gain text field with 1000
9+
await page.locator("#input-v-44").fill("1000");
10+
await page.locator("#input-v-44").press("Enter");
11+
await expect(page.locator("#input-v-44")).toHaveValue("100");
12+
13+
// Try using buttons to go past the max
14+
await page.getByRole("button", { name: "appended action" }).nth(2).click();
15+
await expect(page.locator("#input-v-44")).toHaveValue("100");
16+
17+
// Make sure the value is actually properly limited, not just visually
18+
await page.getByRole("button", { name: "prepended action" }).nth(2).click();
19+
await expect(page.locator("#input-v-44")).toHaveValue("99");
20+
21+
await page.locator("#input-v-44").fill("-10");
22+
await page.locator("#input-v-44").press("Enter");
23+
await expect(page.locator("#input-v-44")).toHaveValue("0");
24+
25+
await page.getByRole("button", { name: "prepended action" }).nth(2).click();
26+
await expect(page.locator("#input-v-44")).toHaveValue("0");
27+
28+
// Make sure the value is actually properly limited, not just visually
29+
await page.getByRole("button", { name: "appended action" }).nth(2).click();
30+
await expect(page.locator("#input-v-44")).toHaveValue("1");
31+
32+
// Make sure that the guard actually prevents value setting, instead of just reverting the value
33+
// This can be ensured by making sure the Camera Gain field doesn't disappear (disappears when the value is -1)
34+
await page.getByRole("button", { name: "prepended action" }).nth(2).click();
35+
await page.getByRole("button", { name: "prepended action" }).nth(2).click();
36+
await expect(page.locator("#input-v-44")).toHaveValue("0");
37+
38+
await expect(page.getByText("Camera Gain", { exact: true })).toBeVisible();
39+
});

0 commit comments

Comments
 (0)