Merge branch 'main' into sidebar-resize-panels

This commit is contained in:
Harel M
2026-09-09 18:04:52 +03:00
committed by GitHub
26 changed files with 823 additions and 597 deletions
+16
View File
@@ -0,0 +1,16 @@
{
"version": 8,
"name": "Grouped layers",
"sources": {},
"layers": [
{ "id": "background", "type": "background" },
{ "id": "park-a", "type": "background" },
{ "id": "park-b", "type": "background" },
{ "id": "park-c", "type": "background" },
{ "id": "road", "type": "background" },
{ "id": "park-d", "type": "background" },
{ "id": "park-e", "type": "background" },
{ "id": "water-a", "type": "background" },
{ "id": "water-b", "type": "background" }
]
}
+16 -1
View File
@@ -289,6 +289,20 @@ describe("layer editor", () => {
});
});
test("should leave a plain editable value after deleting a stop", async () => {
await when.setFunctionStopValue("circle-radius", "Output value", 1, "0");
await when.deleteFunctionStop("circle-radius");
await then(get.elementByTestId("spec-field:circle-radius")).shouldBeVisible();
await then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [{ id, paint: { "circle-radius": 0 } }],
});
await when.setValue("spec-field-input:circle-radius", "7");
await then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [{ id, paint: { "circle-radius": 7 } }],
});
});
test("should set the base", async () => {
await when.setFunctionBase("circle-radius", "2");
await then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
@@ -310,8 +324,9 @@ describe("layer editor", () => {
});
});
test("should convert to an expression", async () => {
test("should convert to an expression without crashing", async () => {
await when.makeExpression("circle-radius");
await then(get.element("[data-wd-key='spec-field-container:circle-radius'] .maputnik-expression-editor")).shouldBeVisible();
await then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [{ id, paint: { "circle-radius": ["interpolate", ["linear"], ["zoom"], 6, 5, 10, 5] } }],
});
+78 -1
View File
@@ -1,4 +1,4 @@
import { beforeEach, describe, test } from "./utils/fixtures";
import { beforeEach, describe, expect, test } from "./utils/fixtures";
import { MaputnikDriver } from "./maputnik-driver";
describe("layers list", () => {
@@ -47,6 +47,14 @@ describe("layers list", () => {
});
});
test("should title the visibility button with the action it performs", async () => {
const key = "layer-list-item:" + id + ":toggle-visibility";
// A visible layer is about to be hidden, and a hidden one to be shown.
await expect(get.elementByTestId(key)).toHaveAttribute("title", "hide");
await when.click(key);
await expect(get.elementByTestId(key)).toHaveAttribute("title", "show");
});
describe("when clicking hide", () => {
beforeEach(async () => {
await when.click("layer-list-item:" + id + ":toggle-visibility");
@@ -298,6 +306,75 @@ describe("layers list", () => {
});
describe("groups", () => {
for (const control of ["menu", "trash"] as const) {
describe(`after deletion using ${control}`, () => {
beforeEach(async () => {
await when.setStyle("grouped_layers");
});
test("keeps all groups expanded when an earlier layer is deleted", async () => {
await when.click("skip-target-layer-list");
await then(get.elementByTestId("layer-list-item:park-b")).shouldBeVisible();
await when.deleteLayer("background", control);
await then(get.elementByTestId("layer-list-item:background")).shouldNotExist();
await then(get.elementByTestId("layer-list-group:park-0")).shouldExist();
await expect(get.elementByTestId("layer-list-group:water-6").getByRole("button")).toHaveAttribute("aria-expanded", "true");
await then(get.elementByTestId("layer-list-item:park-b")).shouldBeVisible();
await then(get.elementByTestId("layer-list-item:park-e")).shouldBeVisible();
await then(get.elementByTestId("layer-list-item:water-b")).shouldBeVisible();
});
test("preserves separate states for groups with the same prefix", async () => {
await when.click("layer-list-group:park-1");
await when.deleteLayer("background", control);
await then(get.elementByTestId("layer-list-group:park-0")).shouldExist();
await when.click("layer-list-item:road");
await expect(get.elementByTestId("layer-list-group:park-0").getByRole("button")).toHaveAttribute("aria-expanded", "true");
await expect(get.elementByTestId("layer-list-group:park-4").getByRole("button")).toHaveAttribute("aria-expanded", "false");
await then(get.elementByTestId("layer-list-item:park-b")).shouldBeVisible();
await then(get.elementByTestId("layer-list-item:park-e")).shouldNotBeVisible();
});
test("keeps a group expanded when its first layer is deleted", async () => {
await when.click("layer-list-group:park-1");
await when.deleteLayer("park-a", control);
await then(get.elementByTestId("layer-list-item:park-a")).shouldNotExist();
await when.click("layer-list-item:road");
await expect(get.elementByTestId("layer-list-group:park-1").getByRole("button")).toHaveAttribute("aria-expanded", "true");
await then(get.elementByTestId("layer-list-item:park-c")).shouldBeVisible();
});
for (const expandedGroup of ["park-1", "park-5"]) {
test(`keeps a merged group expanded when ${expandedGroup} was expanded`, async () => {
await when.click("layer-list-group:" + expandedGroup);
await when.deleteLayer("road", control);
await then(get.elementByTestId("layer-list-item:road")).shouldNotExist();
await expect(get.elementByTestId("layer-list-group:park-1").getByRole("button")).toHaveAttribute("aria-expanded", "true");
await then(get.elementByTestId("layer-list-item:park-b")).shouldBeVisible();
await then(get.elementByTestId("layer-list-item:park-e")).shouldBeVisible();
});
}
test("keeps a merged group collapsed when both groups were collapsed", async () => {
await when.deleteLayer("road", control);
await then(get.elementByTestId("layer-list-item:road")).shouldNotExist();
await when.click("layer-list-item:background");
await expect(get.elementByTestId("layer-list-group:park-1").getByRole("button")).toHaveAttribute("aria-expanded", "false");
await then(get.elementByTestId("layer-list-item:park-b")).shouldNotBeVisible();
await then(get.elementByTestId("layer-list-item:park-e")).shouldNotBeVisible();
});
test("preserves later groups after deleting an entire group", async () => {
await when.click("skip-target-layer-list");
await when.deleteLayer("park-a", control);
await when.deleteLayer("park-b", control);
await when.deleteLayer("park-c", control);
await expect(get.elementByTestId("layer-list-group:water-4").getByRole("button")).toHaveAttribute("aria-expanded", "true");
await then(get.elementByTestId("layer-list-item:water-b")).shouldBeVisible();
});
});
}
test("simple", async () => {
await when.setStyle("geojson");
+15
View File
@@ -39,6 +39,7 @@ export class MaputnikDriver {
"example-style-with-zoom-7-and-center-0-51.json",
"example-style-with-zoom-5-and-center-50-50.json",
"access-token-style.json",
"grouped-layers-style.json",
];
for (const fixture of styleFixtures) {
await this.helper.given.interceptAndMockResponse({
@@ -63,6 +64,18 @@ export class MaputnikDriver {
modal: this.modalDriver.when,
deleteLayer: async (id: string, control: "menu" | "trash" = "menu") => {
if (control === "trash") {
await this.helper.when.hover("layer-list-item:" + id);
await this.helper.when.click("layer-list-item:" + id + ":delete");
return;
}
await this.helper.when.click("layer-list-item:" + id);
await this.helper.when.click("skip-target-layer-editor");
await this.helper.when.click("menu-delete-layer");
},
setStyle: async (
styleProperties:
| "geojson"
@@ -73,6 +86,7 @@ export class MaputnikDriver {
| "font"
| "zoom_7_center_0_51"
| "access_tokens"
| "grouped_layers"
| "",
zoom?: number
) => {
@@ -85,6 +99,7 @@ export class MaputnikDriver {
font: "example-style-with-fonts.json",
zoom_7_center_0_51: "example-style-with-zoom-7-and-center-0-51.json",
access_tokens: "access-token-style.json",
grouped_layers: "grouped-layers-style.json",
};
const url = new URL(baseUrl);