Compare commits

...

6 Commits

Author SHA1 Message Date
dependabot[bot] 019d1c3dc9 chore(deps-dev): Bump vite from 7.3.2 to 8.1.3
Bumps [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) from 7.3.2 to 8.1.3.
- [Release notes](https://github.com/vitejs/vite/releases)
- [Changelog](https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md)
- [Commits](https://github.com/vitejs/vite/commits/v8.1.3/packages/vite)

---
updated-dependencies:
- dependency-name: vite
  dependency-version: 8.1.3
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-07-09 13:54:03 +00:00
dependabot[bot] c24049cb88 chore(deps): Bump @codemirror/view from 6.43.5 to 6.43.6 (#1993)
Bumps [@codemirror/view](https://github.com/codemirror/view) from 6.43.5
to 6.43.6.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/codemirror/view/commits">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@codemirror/view&package-manager=npm_and_yarn&previous-version=6.43.5&new-version=6.43.6)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-09 13:52:29 +00:00
dependabot[bot] 1047286d9e chore(deps): Bump @codemirror/state from 6.7.0 to 6.7.1 (#1992)
Bumps [@codemirror/state](https://github.com/codemirror/state) from
6.7.0 to 6.7.1.
<details>
<summary>Commits</summary>
<ul>
<li>See full diff in <a
href="https://github.com/codemirror/state/commits">compare view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=@codemirror/state&package-manager=npm_and_yarn&previous-version=6.7.0&new-version=6.7.1)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-09 13:51:55 +00:00
dependabot[bot] 99b5dd785d chore(deps-dev): Bump the vitest group with 2 updates (#1991)
Bumps the vitest group with 2 updates:
[@vitest/coverage-v8](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8)
and
[vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest).

Updates `@vitest/coverage-v8` from 4.1.9 to 4.1.10
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitest-dev/vitest/releases">@​vitest/coverage-v8's
releases</a>.</em></p>
<blockquote>
<h2>v4.1.10</h2>
<h3>   🐞 Bug Fixes</h3>
<ul>
<li><strong>browser</strong>: Check fs access in builtin commands
[backport to v4]  -  by <a
href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a>,
<strong>Hiroshi Ogawa</strong> and <strong>OpenCode
(claude-opus-4-8)</strong> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/10680">vitest-dev/vitest#10680</a>
<a href="https://github.com/vitest-dev/vitest/commit/5c18dd267"><!-- raw
HTML omitted -->(5c18d)<!-- raw HTML omitted --></a></li>
<li><strong>vm</strong>: Fix external module resolve error with deps
optimizer query for encoded URI [backport to v4]  -  by <a
href="https://github.com/SveLil"><code>@​SveLil</code></a> and <a
href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/10661">vitest-dev/vitest#10661</a>
<a href="https://github.com/vitest-dev/vitest/commit/bae52b511"><!-- raw
HTML omitted -->(bae52)<!-- raw HTML omitted --></a></li>
</ul>
<h5>    <a
href="https://github.com/vitest-dev/vitest/compare/v4.1.9...v4.1.10">View
changes on GitHub</a></h5>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/vitest-dev/vitest/commit/db616d227b6e0cb07a94f5d1bba262ee95db7e46"><code>db616d2</code></a>
chore: release v4.1.10 (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-v8/issues/10718">#10718</a>)</li>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/v4.1.10/packages/coverage-v8">compare
view</a></li>
</ul>
</details>
<br />

Updates `vitest` from 4.1.9 to 4.1.10
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/vitest-dev/vitest/releases">vitest's
releases</a>.</em></p>
<blockquote>
<h2>v4.1.10</h2>
<h3>   🐞 Bug Fixes</h3>
<ul>
<li><strong>browser</strong>: Check fs access in builtin commands
[backport to v4]  -  by <a
href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a>,
<strong>Hiroshi Ogawa</strong> and <strong>OpenCode
(claude-opus-4-8)</strong> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/10680">vitest-dev/vitest#10680</a>
<a href="https://github.com/vitest-dev/vitest/commit/5c18dd267"><!-- raw
HTML omitted -->(5c18d)<!-- raw HTML omitted --></a></li>
<li><strong>vm</strong>: Fix external module resolve error with deps
optimizer query for encoded URI [backport to v4]  -  by <a
href="https://github.com/SveLil"><code>@​SveLil</code></a> and <a
href="https://github.com/hi-ogawa"><code>@​hi-ogawa</code></a> in <a
href="https://redirect.github.com/vitest-dev/vitest/issues/10661">vitest-dev/vitest#10661</a>
<a href="https://github.com/vitest-dev/vitest/commit/bae52b511"><!-- raw
HTML omitted -->(bae52)<!-- raw HTML omitted --></a></li>
</ul>
<h5>    <a
href="https://github.com/vitest-dev/vitest/compare/v4.1.9...v4.1.10">View
changes on GitHub</a></h5>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/vitest-dev/vitest/commit/db616d227b6e0cb07a94f5d1bba262ee95db7e46"><code>db616d2</code></a>
chore: release v4.1.10 (<a
href="https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest/issues/10718">#10718</a>)</li>
<li><a
href="https://github.com/vitest-dev/vitest/commit/bae52b5112a6fd8200101b88bf8af9685d077295"><code>bae52b5</code></a>
fix(vm): fix external module resolve error with deps optimizer query for
enco...</li>
<li>See full diff in <a
href="https://github.com/vitest-dev/vitest/commits/v4.1.10/packages/vitest">compare
view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-09 13:51:14 +00:00
Harel M be9456d11b Relocate e2e tests (#1989)
## Launch Checklist

Renames the e2e test and reduces changes as a preparation step from
playwright in the following PR:
- #1988

This is to keep as much history as possible.
<img width="1907" height="933" alt="image"
src="https://github.com/user-attachments/assets/b52075b3-eb3b-45dc-93dc-8c5e9cfd35dd"
/>

 - [x] Briefly describe the changes in this PR.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 11:38:59 +03:00
dependabot[bot] a87a4d8df8 chore(deps-dev): Bump i18next-cli from 1.53.2 to 1.65.0 (#1979)
Bumps [i18next-cli](https://github.com/i18next/i18next-cli) from 1.53.2
to 1.65.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/i18next/i18next-cli/blob/main/CHANGELOG.md">i18next-cli's
changelog</a>.</em></p>
<blockquote>
<h2>1.65.0</h2>
<ul>
<li>fix(extract): respect <code>fallbackNS</code> — keys already
translated in a fallback
namespace are no longer duplicated into the requesting namespace's file
(<a
href="https://redirect.github.com/i18next/i18next-cli/issues/272">#272</a>).
<ul>
<li>Such keys are now attributed to the fallback namespace instead, so
<code>removeUnusedKeys</code> no longer prunes them from the fallback
file (previously
a key like <code>cancel</code> living only in the fallback namespace was
<strong>deleted</strong>
there and re-created in every namespace that used it).</li>
<li>A key that already has a non-empty value in the requesting
namespace's own
file is treated as an intentional per-namespace override and keeps being
extracted there, mirroring the i18next runtime lookup order (requested
namespace first, then the fallback chain). Empty-string placeholders
left
behind by previous extract runs are cleaned up.</li>
<li>Keys not found in any fallback namespace are still added to the
requesting
namespace, like the i18next <code>saveMissing</code> behavior.</li>
</ul>
</li>
<li>feat(extract): <code>fallbackNS</code> now also accepts an array of
namespaces (looked
up in order, like the i18next runtime option) — supported by
<code>extract</code>,
<code>status</code>, and the TypeScript types generator.</li>
</ul>
<h2>1.64.2</h2>
<ul>
<li>fix(status): scope the pass/fail result to the requested locale
(<a
href="https://redirect.github.com/i18next/i18next-cli/issues/271">#271</a>).
<ul>
<li><code>status &lt;locale&gt;</code> now exits based on <strong>that
locale only</strong>, instead of always
evaluating every secondary language. Previously, running e.g.
<code>status en-AU</code> on a fully-translated primary could print
&quot;🎉 All keys
present&quot; and still exit <code>1</code> because an unrelated
secondary (e.g. an empty
<code>de-DE</code>) was incomplete — a summary that contradicted the
exit code.</li>
<li>When the requested locale is the primary, the check still fails only
on
<em>absent</em> keys (empty placeholders are tolerated); for a secondary
it fails
on any untranslated/absent key. The global view (<code>status</code>
with no locale)
is unchanged.</li>
<li>The failure message now names the locale when scoped
(<code>Error: Incomplete translations detected for
&quot;de-DE&quot;.</code>) so the reason is
no longer hidden.</li>
</ul>
</li>
</ul>
<h2>1.64.1</h2>
<ul>
<li>fix(status): align plural reporting with the i18next runtime
(<a
href="https://redirect.github.com/i18next/i18next-cli/issues/270">#270</a>).
<ul>
<li>Plural categories that <code>Intl.PluralRules</code> only selects
for out-of-range
values (e.g. French <code>_many</code>, which fires only for counts ≥
1,000,000) are
now treated as <strong>optional</strong>: a missing or empty variant is
shown as a soft
&quot;optional plural form&quot; note instead of a hard &quot;missing
key&quot; error, so it no
longer fails the check. Categories reachable by typical counts
(including
decimals, e.g. Polish/Russian <code>other</code>) remain required.</li>
<li>With <code>disablePlurals: true</code>, a key used with
<code>count</code> is now considered
satisfied when either its plural variants
(<code>_one</code>/<code>_other</code>) <strong>or</strong> the bare
key exist — mirroring the runtime's <code>key + suffix → key</code>
resolution chain —</li>
</ul>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/i18next/i18next-cli/commit/9497126db21489514db6c2d181ccb667af977281"><code>9497126</code></a>
1.65.0</li>
<li><a
href="https://github.com/i18next/i18next-cli/commit/cebfb66b646ce72d93f888c8438082698f35af6c"><code>cebfb66</code></a>
fix(extract): respect fallbackNS and stop duplicating keys into
namespace fil...</li>
<li><a
href="https://github.com/i18next/i18next-cli/commit/4af3b5b767ba144773419d13d045240ebace36d0"><code>4af3b5b</code></a>
1.64.2</li>
<li><a
href="https://github.com/i18next/i18next-cli/commit/59e5c157b8e6263a7686aa83189169eef4947230"><code>59e5c15</code></a>
fix(status): scope pass/fail to the requested locale <a
href="https://redirect.github.com/i18next/i18next-cli/issues/271">#271</a></li>
<li><a
href="https://github.com/i18next/i18next-cli/commit/58e96acf4d779a60dd49555cfbe7125d370918dd"><code>58e96ac</code></a>
1.64.1</li>
<li><a
href="https://github.com/i18next/i18next-cli/commit/90fb64de7c9973cc2bb93074489a114b3c214a43"><code>90fb64d</code></a>
fix(status): align plural reporting with the i18next runtime <a
href="https://redirect.github.com/i18next/i18next-cli/issues/270">#270</a></li>
<li><a
href="https://github.com/i18next/i18next-cli/commit/4f32c051a6b330e5480bea9c5f1e06bfc057b016"><code>4f32c05</code></a>
1.64.0</li>
<li><a
href="https://github.com/i18next/i18next-cli/commit/9ab66af4796228060d05bda6de5ff7dea92e9c89"><code>9ab66af</code></a>
feat(extract): support trailing wildcards in functions (e.g.
'tProps.*')</li>
<li><a
href="https://github.com/i18next/i18next-cli/commit/3f40d0b904b01546fe86ae14d2e6f54b39ccba78"><code>3f40d0b</code></a>
1.63.1</li>
<li><a
href="https://github.com/i18next/i18next-cli/commit/eac231da589c9690a3bcc1aaf05f10572ae395cb"><code>eac231d</code></a>
fix(init): pin <code>@​inlang/plugin-i18next</code><a
href="https://github.com/6"><code>@​6</code></a>.2.1 (restores Sherlock
annotations)</li>
<li>Additional commits viewable in <a
href="https://github.com/i18next/i18next-cli/compare/v1.53.2...v1.65.0">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-07-07 20:46:33 +00:00
18 changed files with 997 additions and 1175 deletions
+1
View File
@@ -10,6 +10,7 @@ export default defineConfig({
},
e2e: {
specPattern: "e2e/**/*.spec.ts",
setupNodeEvents(on, config) {
// implement node event listeners here
require("@cypress/code-coverage/task")(on, config);
@@ -1,5 +1,7 @@
import { MaputnikDriver } from "./maputnik-driver";
const test = it;
describe("accessibility", () => {
const { beforeAndAfter, get, when, then } = new MaputnikDriver();
beforeAndAfter();
@@ -9,7 +11,7 @@ describe("accessibility", () => {
when.setStyle("layer");
});
it("skip link to layer list", () => {
test("skip link to layer list", () => {
const selector = "root:skip:layer-list";
then(get.elementByTestId(selector)).shouldExist();
when.tab();
@@ -18,7 +20,7 @@ describe("accessibility", () => {
then(get.skipTargetLayerList()).shouldBeFocused();
});
it("skip link to layer editor", () => {
test("skip link to layer editor", () => {
const selector = "root:skip:layer-editor";
then(get.elementByTestId(selector)).shouldExist();
then(get.elementByTestId("skip-target-layer-editor")).shouldExist();
@@ -28,7 +30,7 @@ describe("accessibility", () => {
then(get.skipTargetLayerEditor()).shouldBeFocused();
});
it("skip link to map view", () => {
test("skip link to map view", () => {
const selector = "root:skip:map-view";
then(get.elementByTestId(selector)).shouldExist();
when.tab().tab().tab();
@@ -1,15 +1,17 @@
import { MaputnikDriver } from "./maputnik-driver";
const test = it;
describe("code editor", () => {
const { beforeAndAfter, when, get, then } = new MaputnikDriver();
beforeAndAfter();
it("open code editor", () => {
test("open code editor", () => {
when.click("nav:code-editor");
then(get.element(".maputnik-code-editor")).shouldExist();
});
it("closes code editor", () => {
test("closes code editor", () => {
when.click("nav:code-editor");
then(get.element(".maputnik-code-editor")).shouldExist();
when.click("nav:code-editor");
@@ -1,5 +1,7 @@
import { MaputnikDriver } from "./maputnik-driver";
const test = it;
describe("history", () => {
const { beforeAndAfter, when, get, then } = new MaputnikDriver();
beforeAndAfter();
@@ -13,7 +15,7 @@ describe("history", () => {
redoKeyCombo = isMac ? "{meta}{shift}z" : "{ctrl}y";
});
it("undo/redo", () => {
test("undo/redo", () => {
when.setStyle("geojson");
when.modal.open();
@@ -87,7 +89,7 @@ describe("history", () => {
});
});
it("should not redo after undo and value change", () => {
test("should not redo after undo and value change", () => {
when.setStyle("geojson");
when.modal.open();
when.modal.fillLayers({
+5 -3
View File
@@ -1,17 +1,19 @@
import { MaputnikDriver } from "./maputnik-driver";
const test = it;
describe("i18n", () => {
const { beforeAndAfter, get, when, then } = new MaputnikDriver();
beforeAndAfter();
describe("language detector", () => {
it("English", () => {
test("English", () => {
const url = "?lng=en";
when.visit(url);
then(get.elementByTestId("maputnik-lang-select")).shouldHaveValue("en");
});
it("Japanese", () => {
test("Japanese", () => {
const url = "?lng=ja";
when.visit(url);
then(get.elementByTestId("maputnik-lang-select")).shouldHaveValue("ja");
@@ -23,7 +25,7 @@ describe("i18n", () => {
when.setStyle("layer");
});
it("the language switcher switches to Japanese", () => {
test("the language switcher switches to Japanese", () => {
const selector = "maputnik-lang-select";
then(get.elementByTestId(selector)).shouldExist();
when.select(selector, "ja");
@@ -1,4 +1,5 @@
import { MaputnikDriver } from "./maputnik-driver";
const test = it;
describe("keyboard", () => {
const { beforeAndAfter, given, when, get, then } = new MaputnikDriver();
@@ -9,7 +10,7 @@ describe("keyboard", () => {
when.setStyle("");
});
it("ESC should unfocus", () => {
test("ESC should unfocus", () => {
const targetSelector = "maputnik-select";
when.focus(targetSelector);
then(get.elementByTestId(targetSelector)).shouldBeFocused();
@@ -17,42 +18,42 @@ describe("keyboard", () => {
then(get.elementByTestId(targetSelector)).shouldNotBeFocused();
});
it("'?' should show shortcuts modal", () => {
test("'?' should show shortcuts modal", () => {
when.typeKeys("?");
then(get.elementByTestId("modal:shortcuts")).shouldBeVisible();
});
it("'o' should show open modal", () => {
test("'o' should show open modal", () => {
when.typeKeys("o");
then(get.elementByTestId("modal:open")).shouldBeVisible();
});
it("'e' should show export modal", () => {
test("'e' should show export modal", () => {
when.typeKeys("e");
then(get.elementByTestId("modal:export")).shouldBeVisible();
});
it("'d' should show sources modal", () => {
test("'d' should show sources modal", () => {
when.typeKeys("d");
then(get.elementByTestId("modal:sources")).shouldBeVisible();
});
it("'s' should show settings modal", () => {
test("'s' should show settings modal", () => {
when.typeKeys("s");
then(get.elementByTestId("modal:settings")).shouldBeVisible();
});
it("'i' should change map to inspect mode", () => {
test("'i' should change map to inspect mode", () => {
when.typeKeys("i");
then(get.inputValue("maputnik-select")).shouldEqual("inspect");
});
it("'m' should focus map", () => {
test("'m' should focus map", () => {
when.typeKeys("m");
then(get.canvas()).shouldBeFocused();
});
it("'!' should show debug modal", () => {
test("'!' should show debug modal", () => {
when.typeKeys("!");
then(get.elementByTestId("modal:debug")).shouldBeVisible();
});
@@ -1,6 +1,8 @@
import { MaputnikDriver } from "./maputnik-driver";
import { v1 as uuid } from "uuid";
const test = it;
describe("layer editor", () => {
const { beforeAndAfter, get, when, then } = new MaputnikDriver();
beforeAndAfter();
@@ -28,8 +30,8 @@ describe("layer editor", () => {
return id;
}
it("expand/collapse");
it("id", () => {
test("expand/collapse");
test("id", () => {
const bgId = createBackground();
when.click("layer-list-item:background:" + bgId);
@@ -49,7 +51,7 @@ describe("layer editor", () => {
});
describe("source", () => {
it("should show error when the source is invalid", () => {
test("should show error when the source is invalid", () => {
when.modal.fillLayers({
type: "circle",
layer: "invalid",
@@ -68,7 +70,7 @@ describe("layer editor", () => {
when.click("layer-editor.layer-id");
});
it("should update min-zoom in local storage", () => {
test("should update min-zoom in local storage", () => {
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [
{
@@ -105,7 +107,7 @@ describe("layer editor", () => {
when.click("layer-editor.layer-id");
});
it("should update style in local storage", () => {
test("should update style in local storage", () => {
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [
{
@@ -129,7 +131,7 @@ describe("layer editor", () => {
when.click("layer-editor.layer-id");
});
it("should update style in local storage", () => {
test("should update style in local storage", () => {
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [
{
@@ -149,7 +151,7 @@ describe("layer editor", () => {
when.click("min-zoom.input-text");
});
it("should update style in local storage", () => {
test("should update style in local storage", () => {
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [
{
@@ -170,7 +172,7 @@ describe("layer editor", () => {
when.click("spec-field:background-color");
});
it("should update style in local storage", () => {
test("should update style in local storage", () => {
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [
{
@@ -190,11 +192,11 @@ describe("layer editor", () => {
when.type("spec-field-input:background-opacity", "0.");
});
it("should keep '.' in the input field", () => {
test("should keep '.' in the input field", () => {
then(get.elementByTestId("spec-field-input:background-opacity")).shouldHaveValue("0.");
});
it("should revert to a valid value when focus out", () => {
test("should revert to a valid value when focus out", () => {
when.click("layer-list-item:background:" + bgId);
then(get.elementByTestId("spec-field-input:background-opacity")).shouldHaveValue("0");
});
@@ -203,12 +205,12 @@ describe("layer editor", () => {
describe("filter", () => {
it("expand/collapse");
it("compound filter");
test("expand/collapse");
test("compound filter");
});
describe("layout", () => {
it("text-font", () => {
test("text-font", () => {
when.setStyle("font");
when.collapseGroupInLayerEditor();
when.collapseGroupInLayerEditor(1);
@@ -222,14 +224,14 @@ describe("layer editor", () => {
});
describe("paint", () => {
it("expand/collapse");
it("color");
it("pattern");
it("opacity");
test("expand/collapse");
test("color");
test("pattern");
test("opacity");
});
describe("json-editor", () => {
it("add", () => {
test("add", () => {
const id = when.modal.fillLayers({
type: "circle",
layer: "example",
@@ -254,10 +256,10 @@ describe("layer editor", () => {
});
it("expand/collapse");
it("modify");
test("expand/collapse");
test("modify");
it("parse error", () => {
test("parse error", () => {
const bgId = createBackground();
when.click("layer-list-item:background:" + bgId);
@@ -273,7 +275,7 @@ describe("layer editor", () => {
});
describe("sticky header", () => {
it("should keep layer header visible when scrolling properties", () => {
test("should keep layer header visible when scrolling properties", () => {
// Setup: Create a layer with many properties (e.g., symbol layer)
when.modal.fillLayers({
type: "symbol",
@@ -1,4 +1,5 @@
import { MaputnikDriver } from "./maputnik-driver";
const test = it;
describe("layers list", () => {
const { beforeAndAfter, get, when, then } = new MaputnikDriver();
@@ -16,7 +17,7 @@ describe("layers list", () => {
});
});
it("should update layers in local storage", () => {
test("should update layers in local storage", () => {
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [
{
@@ -31,7 +32,7 @@ describe("layers list", () => {
beforeEach(() => {
when.click("layer-list-item:" + id + ":delete");
});
it("should empty layers in local storage", () => {
test("should empty layers in local storage", () => {
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [],
});
@@ -42,7 +43,7 @@ describe("layers list", () => {
beforeEach(() => {
when.click("layer-list-item:" + id + ":copy");
});
it("should add copy layer in local storage", () => {
test("should add copy layer in local storage", () => {
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [
{
@@ -63,7 +64,7 @@ describe("layers list", () => {
when.click("layer-list-item:" + id + ":toggle-visibility");
});
it("should update visibility to none in local storage", () => {
test("should update visibility to none in local storage", () => {
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [
{
@@ -82,7 +83,7 @@ describe("layers list", () => {
when.click("layer-list-item:" + id + ":toggle-visibility");
});
it("should update visibility to visible in local storage", () => {
test("should update visibility to visible in local storage", () => {
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
layers: [
{
@@ -106,7 +107,7 @@ describe("layers list", () => {
type: "background",
});
});
it("should show the selected layer in the editor", () => {
test("should show the selected layer in the editor", () => {
when.realClick("layer-list-item:" + secondId);
then(get.elementByTestId("layer-editor.layer-id.input")).shouldHaveValue(secondId);
when.realClick("layer-list-item:" + id);
@@ -117,7 +118,7 @@ describe("layers list", () => {
});
describe("background", () => {
it("add", () => {
test("add", () => {
const id = when.modal.fillLayers({
type: "background",
});
@@ -135,7 +136,7 @@ describe("layers list", () => {
});
describe("fill", () => {
it("add", () => {
test("add", () => {
const id = when.modal.fillLayers({
type: "fill",
layer: "example",
@@ -153,11 +154,11 @@ describe("layers list", () => {
});
// TODO: Change source
it("change source");
test("change source");
});
describe("line", () => {
it("add", () => {
test("add", () => {
const id = when.modal.fillLayers({
type: "line",
layer: "example",
@@ -174,7 +175,7 @@ describe("layers list", () => {
});
});
it("groups", () => {
test("groups", () => {
when.modal.open();
const id1 = when.modal.fillLayers({
id: "aa",
@@ -230,7 +231,7 @@ describe("layers list", () => {
});
describe("symbol", () => {
it("add", () => {
test("add", () => {
const id = when.modal.fillLayers({
type: "symbol",
layer: "example",
@@ -247,7 +248,7 @@ describe("layers list", () => {
});
});
it("should show spec info when hovering and clicking single line property", () => {
test("should show spec info when hovering and clicking single line property", () => {
when.modal.fillLayers({
type: "symbol",
layer: "example",
@@ -259,7 +260,7 @@ describe("layers list", () => {
then(get.elementByTestId("spec-field-doc")).shouldContainText("Rotates the ");
});
it("should show spec info when hovering and clicking multi line property", () => {
test("should show spec info when hovering and clicking multi line property", () => {
when.modal.fillLayers({
type: "symbol",
layer: "example",
@@ -271,7 +272,7 @@ describe("layers list", () => {
then(get.elementByTestId("spec-field-doc")).shouldContainText("Offset distance");
});
it("should hide spec info when clicking a second time", () => {
test("should hide spec info when clicking a second time", () => {
when.modal.fillLayers({
type: "symbol",
layer: "example",
@@ -287,7 +288,7 @@ describe("layers list", () => {
});
describe("raster", () => {
it("add", () => {
test("add", () => {
const id = when.modal.fillLayers({
type: "raster",
layer: "raster",
@@ -306,7 +307,7 @@ describe("layers list", () => {
});
describe("circle", () => {
it("add", () => {
test("add", () => {
const id = when.modal.fillLayers({
type: "circle",
layer: "example",
@@ -325,7 +326,7 @@ describe("layers list", () => {
});
describe("fill extrusion", () => {
it("add", () => {
test("add", () => {
const id = when.modal.fillLayers({
type: "fill-extrusion",
layer: "example",
@@ -344,7 +345,7 @@ describe("layers list", () => {
});
describe("hillshade", () => {
it("add", () => {
test("add", () => {
const id = when.modal.fillLayers({
type: "hillshade",
layer: "example",
@@ -361,7 +362,7 @@ describe("layers list", () => {
});
});
it("set hillshade illumination direction array", () => {
test("set hillshade illumination direction array", () => {
const id = when.modal.fillLayers({
type: "hillshade",
layer: "example",
@@ -387,7 +388,7 @@ describe("layers list", () => {
});
});
it("set hillshade highlight color array", () => {
test("set hillshade highlight color array", () => {
const id = when.modal.fillLayers({
type: "hillshade",
layer: "example",
@@ -413,7 +414,7 @@ describe("layers list", () => {
});
describe("color-relief", () => {
it("add", () => {
test("add", () => {
const id = when.modal.fillLayers({
type: "color-relief",
layer: "example",
@@ -430,7 +431,7 @@ describe("layers list", () => {
});
});
it("adds elevation expression when clicking the elevation button", () => {
test("adds elevation expression when clicking the elevation button", () => {
when.modal.fillLayers({
type: "color-relief",
layer: "example",
@@ -442,7 +443,7 @@ describe("layers list", () => {
});
describe("groups", () => {
it("simple", () => {
test("simple", () => {
when.setStyle("geojson");
when.modal.open();
@@ -478,7 +479,7 @@ describe("layers list", () => {
});
describe("drag and drop", () => {
it("move layer should update local storage", () => {
test("move layer should update local storage", () => {
when.modal.open();
const firstId = when.modal.fillLayers({
id: "a",
@@ -517,7 +518,7 @@ describe("layers list", () => {
});
describe("sticky header", () => {
it("should keep header visible when scrolling layer list", () => {
test("should keep header visible when scrolling layer list", () => {
// Setup: Create multiple layers to enable scrolling
for (let i = 0; i < 20; i++) {
when.modal.open();
+8 -6
View File
@@ -1,10 +1,12 @@
import { MaputnikDriver } from "./maputnik-driver";
const test = it;
describe("map", () => {
const { beforeAndAfter, get, when, then } = new MaputnikDriver();
beforeAndAfter();
describe("zoom level", () => {
it("via url", () => {
test("via url", () => {
const zoomLevel = 12.37;
when.setStyle("geojson", zoomLevel);
then(get.elementByTestId("maplibre:ctrl-zoom")).shouldBeVisible();
@@ -13,7 +15,7 @@ describe("map", () => {
);
});
it("via map controls", () => {
test("via map controls", () => {
const zoomLevel = 12.37;
when.setStyle("geojson", zoomLevel);
then(get.elementByTestId("maplibre:ctrl-zoom")).shouldBeVisible();
@@ -23,7 +25,7 @@ describe("map", () => {
);
});
it("via style file definition", () => {
test("via style file definition", () => {
when.setStyle("zoom_7_center_0_51");
then(get.elementByTestId("maplibre:ctrl-zoom")).shouldBeVisible();
then(get.elementByTestId("maplibre:ctrl-zoom")).shouldContainText(
@@ -40,7 +42,7 @@ describe("map", () => {
});
describe("search", () => {
it("should exist", () => {
test("should exist", () => {
then(get.searchControl()).shouldBeVisible();
});
});
@@ -50,12 +52,12 @@ describe("map", () => {
when.setStyle("rectangles");
then(get.locationHash().should("exist"));
});
it("should open on feature click", () => {
test("should open on feature click", () => {
when.clickCenter("maplibre:map");
then(get.elementByTestId("feature-layer-popup")).shouldBeVisible();
});
it("should open a second feature after closing popup", () => {
test("should open a second feature after closing popup", () => {
when.clickCenter("maplibre:map");
then(get.elementByTestId("feature-layer-popup")).shouldBeVisible();
when.closePopup();
+40 -39
View File
@@ -1,5 +1,6 @@
import { MaputnikDriver } from "./maputnik-driver";
import tokens from "../../src/config/tokens.json" with {type: "json"};
import tokens from "../src/config/tokens.json" with {type: "json"};
const test = it;
describe("modals", () => {
const { beforeAndAfter, when, get, given, then } = new MaputnikDriver();
@@ -13,17 +14,17 @@ describe("modals", () => {
when.click("nav:open");
});
it("close", () => {
test("close", () => {
when.modal.close("modal:open");
then(get.elementByTestId("modal:open")).shouldNotExist();
});
it("upload", () => {
test("upload", () => {
when.chooseExampleFile();
then(get.fixture("example-style.json")).shouldEqualToStoredStyle();
});
it("upload via drag and drop", () => {
test("upload via drag and drop", () => {
when.dropExampleFile();
then(get.fixture("example-style.json")).shouldEqualToStoredStyle();
});
@@ -36,14 +37,14 @@ describe("modals", () => {
when.click("modal:open.url.button");
when.wait(200);
});
it("load from url", () => {
test("load from url", () => {
then(get.responseBody("example-style.json")).shouldEqualToStoredStyle();
});
});
});
describe("shortcuts", () => {
it("open/close", () => {
test("open/close", () => {
when.setStyle("");
when.typeKeys("?");
when.modal.close("modal:shortcuts");
@@ -56,13 +57,13 @@ describe("modals", () => {
when.click("nav:export");
});
it("close", () => {
test("close", () => {
when.modal.close("modal:export");
then(get.elementByTestId("modal:export")).shouldNotExist();
});
// TODO: Work out how to download a file and check the contents
it("download");
test("download");
});
describe("sources", () => {
@@ -71,10 +72,10 @@ describe("modals", () => {
when.click("nav:sources");
});
it("active sources");
it("public source");
test("active sources");
test("public source");
it("add new source", () => {
test("add new source", () => {
const sourceId = "n1z2v3r";
when.setValue("modal:sources.add.source_id", sourceId);
when.select("modal:sources.add.source_type", "tile_vector");
@@ -88,7 +89,7 @@ describe("modals", () => {
});
});
it("add new pmtiles source", () => {
test("add new pmtiles source", () => {
const sourceId = "pmtilestest";
when.setValue("modal:sources.add.source_id", sourceId);
when.select("modal:sources.add.source_type", "pmtiles_vector");
@@ -106,7 +107,7 @@ describe("modals", () => {
});
});
it("add new raster source", () => {
test("add new raster source", () => {
const sourceId = "rastertest";
when.setValue("modal:sources.add.source_id", sourceId);
when.select("modal:sources.add.source_type", "tile_raster");
@@ -123,7 +124,7 @@ describe("modals", () => {
});
describe("inspect", () => {
it("toggle", () => {
test("toggle", () => {
// There is no assertion in this test
when.setStyle("geojson");
when.select("maputnik-select", "inspect");
@@ -140,7 +141,7 @@ describe("modals", () => {
when.click("field-doc-button-Name");
});
it("should show the spec information", () => {
test("should show the spec information", () => {
then(get.elementsText("spec-field-doc")).shouldInclude(
"name for the style"
);
@@ -154,7 +155,7 @@ describe("modals", () => {
when.wait(200);
});
it("show name specifications", () => {
test("show name specifications", () => {
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
name: "foobar",
});
@@ -167,14 +168,14 @@ describe("modals", () => {
when.click("modal:settings.name");
when.wait(200);
});
it("should update owner in local storage", () => {
test("should update owner in local storage", () => {
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
owner: "foobar",
});
});
});
it("sprite url", () => {
test("sprite url", () => {
when.setTextInJsonEditor("\"http://example.com\"");
when.click("modal:settings.name");
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
@@ -182,7 +183,7 @@ describe("modals", () => {
});
});
it("sprite object", () => {
test("sprite object", () => {
when.setTextInJsonEditor(JSON.stringify([{ id: "1", url: "2" }]));
when.click("modal:settings.name");
@@ -191,7 +192,7 @@ describe("modals", () => {
});
});
it("glyphs url", () => {
test("glyphs url", () => {
const glyphsUrl = "http://example.com/{fontstack}/{range}.pbf";
when.setValue("modal:settings.glyphs", glyphsUrl);
when.click("modal:settings.name");
@@ -200,7 +201,7 @@ describe("modals", () => {
});
});
it("maptiler access token", () => {
test("maptiler access token", () => {
const apiKey = "testing123";
when.setValue(
"modal:settings.maputnik:openmaptiles_access_token",
@@ -214,7 +215,7 @@ describe("modals", () => {
});
});
it("thunderforest access token", () => {
test("thunderforest access token", () => {
const apiKey = "testing123";
when.setValue(
"modal:settings.maputnik:thunderforest_access_token",
@@ -226,7 +227,7 @@ describe("modals", () => {
).shouldInclude({ "maputnik:thunderforest_access_token": apiKey });
});
it("stadia access token", () => {
test("stadia access token", () => {
const apiKey = "testing123";
when.setValue(
"modal:settings.maputnik:stadia_access_token",
@@ -238,7 +239,7 @@ describe("modals", () => {
).shouldInclude({ "maputnik:stadia_access_token": apiKey });
});
it("locationiq access token", () => {
test("locationiq access token", () => {
const apiKey = "testing123";
when.setValue(
"modal:settings.maputnik:locationiq_access_token",
@@ -250,14 +251,14 @@ describe("modals", () => {
).shouldInclude({ "maputnik:locationiq_access_token": apiKey });
});
it("style projection mercator", () => {
test("style projection mercator", () => {
when.select("modal:settings.projection", "mercator");
then(
get.styleFromLocalStorage().then((style) => style.projection)
).shouldInclude({ type: "mercator" });
});
it("style projection globe", () => {
test("style projection globe", () => {
when.select("modal:settings.projection", "globe");
then(
get.styleFromLocalStorage().then((style) => style.projection)
@@ -265,7 +266,7 @@ describe("modals", () => {
});
it("style projection vertical-perspective", () => {
test("style projection vertical-perspective", () => {
when.select("modal:settings.projection", "vertical-perspective");
then(
get.styleFromLocalStorage().then((style) => style.projection)
@@ -273,7 +274,7 @@ describe("modals", () => {
});
it("style renderer", () => {
test("style renderer", () => {
cy.on("uncaught:exception", () => false); // this is due to the fact that this is an invalid style for openlayers
when.select("modal:settings.maputnik:renderer", "ol");
then(get.inputValue("modal:settings.maputnik:renderer")).shouldEqual(
@@ -288,7 +289,7 @@ describe("modals", () => {
it("include API key when change renderer", () => {
test("include API key when change renderer", () => {
when.click("modal:settings.close-modal");
when.click("nav:open");
@@ -327,7 +328,7 @@ describe("modals", () => {
when.modal.open();
});
it("shows duplicate id error", () => {
test("shows duplicate id error", () => {
when.setValue("add-layer.layer-id.input", "background");
when.click("add-layer");
then(get.elementByTestId("modal:add-layer")).shouldExist();
@@ -338,7 +339,7 @@ describe("modals", () => {
});
describe("sources", () => {
it("toggle");
test("toggle");
});
describe("global state", () => {
@@ -346,7 +347,7 @@ describe("modals", () => {
when.click("nav:global-state");
});
it("add variable", () => {
test("add variable", () => {
when.wait(100);
when.click("global-state-add-variable");
then(get.styleFromLocalStorage()).shouldDeepNestedInclude({
@@ -355,7 +356,7 @@ describe("modals", () => {
});
it("add multiple variables", () => {
test("add multiple variables", () => {
when.click("global-state-add-variable");
when.click("global-state-add-variable");
when.click("global-state-add-variable");
@@ -365,7 +366,7 @@ describe("modals", () => {
});
});
it("remove variable", () => {
test("remove variable", () => {
when.click("global-state-add-variable");
when.click("global-state-add-variable");
when.click("global-state-add-variable");
@@ -376,7 +377,7 @@ describe("modals", () => {
});
});
it("edit variable key", () => {
test("edit variable key", () => {
when.click("global-state-add-variable");
when.wait(100);
when.setValue("global-state-variable-key:0", "mykey");
@@ -387,7 +388,7 @@ describe("modals", () => {
});
});
it("edit variable value", () => {
test("edit variable value", () => {
when.click("global-state-add-variable");
when.wait(100);
when.setValue("global-state-variable-value:0", "myvalue");
@@ -400,11 +401,11 @@ describe("modals", () => {
});
describe("error panel", () => {
it("not visible when no errors", () => {
test("not visible when no errors", () => {
then(get.element("maputnik-message-panel-error")).shouldNotExist();
});
it("visible on style error", () => {
test("visible on style error", () => {
when.modal.open();
when.modal.fillLayers({
type: "circle",
@@ -415,7 +416,7 @@ describe("modals", () => {
});
describe("Handle localStorage QuotaExceededError", () => {
it("handles quota exceeded error when opening style from URL", () => {
test("handles quota exceeded error when opening style from URL", () => {
// Clear localStorage to start fresh
cy.clearLocalStorage();
+851 -1056
View File
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -28,9 +28,9 @@
"dependencies": {
"@codemirror/lang-json": "^6.0.2",
"@codemirror/lint": "^6.9.7",
"@codemirror/state": "^6.7.0",
"@codemirror/state": "^6.7.1",
"@codemirror/theme-one-dark": "^6.1.3",
"@codemirror/view": "^6.43.5",
"@codemirror/view": "^6.43.6",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
@@ -125,7 +125,7 @@
"@types/string-hash": "^1.1.3",
"@types/wicg-file-system-access": "^2023.10.7",
"@vitejs/plugin-react": "5.2",
"@vitest/coverage-v8": "^4.1.9",
"@vitest/coverage-v8": "^4.1.10",
"cors": "^2.8.6",
"cypress": "^15.18.0",
"cypress-plugin-tab": "^2.0.0",
@@ -133,7 +133,7 @@
"eslint-plugin-react": "^7.37.5",
"eslint-plugin-react-hooks": "^7.1.1",
"eslint-plugin-react-refresh": "^0.5.3",
"i18next-cli": "^1.53.2",
"i18next-cli": "^1.65.0",
"istanbul": "^0.4.5",
"istanbul-lib-coverage": "^3.2.2",
"postcss": "^8.5.16",
@@ -145,8 +145,8 @@
"typescript": "^6.0.3",
"typescript-eslint": "^8.62.1",
"uuid": "^14.0.1",
"vite": "^7.3.2",
"vite": "^8.1.3",
"vite-plugin-istanbul": "^9.0.1",
"vitest": "^4.1.9"
"vitest": "^4.1.10"
}
}
+1 -1
View File
@@ -21,7 +21,7 @@
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src", "cypress/e2e"],
"include": ["src", "cypress/e2e", "e2e/maputnik-cypress-helper.ts"],
"exclude": ["dist"],
"references": [{ "path": "./tsconfig.node.json" }],
// TODO: Remove when issue is resolved https://github.com/cypress-io/cypress/issues/27448
+11
View File
@@ -0,0 +1,11 @@
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
// Only the unit tests that live next to the source are run by Vitest. The
// e2e specs (*.spec.ts) are run by their own runner, and the component
// browser test is run separately.
include: ["src/**/*.test.{ts,tsx}"],
exclude: ["**/node_modules/**", "e2e/**", "**/*.browser.test.tsx"],
},
});