Compare commits

..

17 Commits

Author SHA1 Message Date
Yuri Astrakhan 17eaa3f204 Rename primary branch to main (#837)
Co-authored-by: Harel M <harel.mazor@gmail.com>
2023-12-18 00:09:10 +02:00
Harel M 1df2e36dbb Replace WebDriverIO with Cypress (#831)
This does the following:
1. Moves the WDIO code from javascript to typescript
2. Moves to use files that are `cy.ts` instead of `index.js`
3. Replace e2e to use cypress
4. Introduce back some skipped tests

This is in continue to the conversation here:
https://github.com/HarelM/editor/pull/3

Before:
```
 "spec" Reporter:
------------------------------------------------------------------
[chrome 120.0.6099.71 linux #0-0] Running: chrome (v120.0.6099.71) on linux
[chrome 120.0.6099.71 linux #0-0] Session ID: ee9a87bcfce007ac7721929c6e6234d0
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0] » /test/functional/index.js
[chrome 120.0.6099.71 linux #0-0] maputnik
[chrome 120.0.6099.71 linux #0-0]     history
[chrome 120.0.6099.71 linux #0-0]        - undo/redo
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]     layers
[chrome 120.0.6099.71 linux #0-0]         ops
[chrome 120.0.6099.71 linux #0-0]            ✓ delete
[chrome 120.0.6099.71 linux #0-0]            ✓ duplicate
[chrome 120.0.6099.71 linux #0-0]            ✓ hide
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]         background
[chrome 120.0.6099.71 linux #0-0]            ✓ add
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]             modify
[chrome 120.0.6099.71 linux #0-0]                 layer
[chrome 120.0.6099.71 linux #0-0]                    - expand/collapse
[chrome 120.0.6099.71 linux #0-0]                    ✓ id
[chrome 120.0.6099.71 linux #0-0]                    ✓ min-zoom
[chrome 120.0.6099.71 linux #0-0]                    ✓ max-zoom
[chrome 120.0.6099.71 linux #0-0]                    ✓ comments
[chrome 120.0.6099.71 linux #0-0]                    - color
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]                 filter
[chrome 120.0.6099.71 linux #0-0]                    - expand/collapse
[chrome 120.0.6099.71 linux #0-0]                    - compound filter
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]                 paint
[chrome 120.0.6099.71 linux #0-0]                    - expand/collapse
[chrome 120.0.6099.71 linux #0-0]                    - color
[chrome 120.0.6099.71 linux #0-0]                    - pattern
[chrome 120.0.6099.71 linux #0-0]                    - opacity
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]                 json-editor
[chrome 120.0.6099.71 linux #0-0]                    - expand/collapse
[chrome 120.0.6099.71 linux #0-0]                    - modify
[chrome 120.0.6099.71 linux #0-0]                    - parse error
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]         fill
[chrome 120.0.6099.71 linux #0-0]            ✓ add
[chrome 120.0.6099.71 linux #0-0]            - change source
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]         line
[chrome 120.0.6099.71 linux #0-0]            ✓ add
[chrome 120.0.6099.71 linux #0-0]            - groups
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]         symbol
[chrome 120.0.6099.71 linux #0-0]            ✓ add
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]         raster
[chrome 120.0.6099.71 linux #0-0]            ✓ add
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]         circle
[chrome 120.0.6099.71 linux #0-0]            ✓ add
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]         fill extrusion
[chrome 120.0.6099.71 linux #0-0]            ✓ add
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]         groups
[chrome 120.0.6099.71 linux #0-0]            ✓ simple
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]     map
[chrome 120.0.6099.71 linux #0-0]         zoom level
[chrome 120.0.6099.71 linux #0-0]            - via url
[chrome 120.0.6099.71 linux #0-0]            - via map controls
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]     modals
[chrome 120.0.6099.71 linux #0-0]         open
[chrome 120.0.6099.71 linux #0-0]            ✓ close
[chrome 120.0.6099.71 linux #0-0]            - upload
[chrome 120.0.6099.71 linux #0-0]            ✓ load from url
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]         shortcuts
[chrome 120.0.6099.71 linux #0-0]            ✓ open/close
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]         export
[chrome 120.0.6099.71 linux #0-0]            ✓ close
[chrome 120.0.6099.71 linux #0-0]            - download
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]         sources
[chrome 120.0.6099.71 linux #0-0]            - active sources
[chrome 120.0.6099.71 linux #0-0]            - public source
[chrome 120.0.6099.71 linux #0-0]            - add new source
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]         inspect
[chrome 120.0.6099.71 linux #0-0]            ✓ toggle
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]         style settings
[chrome 120.0.6099.71 linux #0-0]            ✓ name
[chrome 120.0.6099.71 linux #0-0]            ✓ owner
[chrome 120.0.6099.71 linux #0-0]            ✓ sprite url
[chrome 120.0.6099.71 linux #0-0]            ✓ glyphs url
[chrome 120.0.6099.71 linux #0-0]            ✓ maptiler access token
[chrome 120.0.6099.71 linux #0-0]            ✓ thunderforest access token
[chrome 120.0.6099.71 linux #0-0]            ✓ style renderer
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]         sources
[chrome 120.0.6099.71 linux #0-0]            - toggle
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]     screenshots
[chrome 120.0.6099.71 linux #0-0]        ✓ front_page
[chrome 120.0.6099.71 linux #0-0]        ✓ open
[chrome 120.0.6099.71 linux #0-0]        ✓ export
[chrome 120.0.6099.71 linux #0-0]        ✓ sources
[chrome 120.0.6099.71 linux #0-0]        ✓ style settings
[chrome 120.0.6099.71 linux #0-0]        ✓ inspect
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]     accessibility
[chrome 120.0.6099.71 linux #0-0]         skip links
[chrome 120.0.6099.71 linux #0-0]            ✓ skip link to layer list
[chrome 120.0.6099.71 linux #0-0]            ✓ skip link to layer editor
[chrome 120.0.6099.71 linux #0-0]            ✓ skip link to map view
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0]     keyboard
[chrome 120.0.6099.71 linux #0-0]         shortcuts
[chrome 120.0.6099.71 linux #0-0]            ✓ ESC should unfocus
[chrome 120.0.6099.71 linux #0-0]            ✓ '?' should show shortcuts modal
[chrome 120.0.6099.71 linux #0-0]            ✓ 'o' should show open modal
[chrome 120.0.6099.71 linux #0-0]            ✓ 'e' should show export modal
[chrome 120.0.6099.71 linux #0-0]            ✓ 'd' should show sources modal
[chrome 120.0.6099.71 linux #0-0]            ✓ 's' should show settings modal
[chrome 120.0.6099.71 linux #0-0]            - 'i' should change map to inspect mode
[chrome 120.0.6099.71 linux #0-0]            ✓ 'm' should focus map
[chrome 120.0.6099.71 linux #0-0]            ✓ '!' should show debug modal
[chrome 120.0.6099.71 linux #0-0]
[chrome 120.0.6099.71 linux #0-0] 44 passing (58.8s)
[chrome 120.0.6099.71 linux #0-0] 23 skipped
```

After:
```
accessibility
    skip links
      - skip link to layer list
      - skip link to layer editor
      - skip link to map view

history
    ✓ undo/redo (4894ms)

keyboard
    shortcuts
      ✓ ESC should unfocus (1912ms)
      ✓ '?' should show shortcuts modal (458ms)
      ✓ 'o' should show open modal (710ms)
      ✓ 'e' should show export modal (692ms)
      ✓ 'd' should show sources modal (588ms)
      ✓ 's' should show settings modal (894ms)
      ✓ 'i' should change map to inspect mode (804ms)
      ✓ 'm' should focus map (837ms)
      ✓ '!' should show debug modal (607ms)

layers
    ops
      ✓ delete (4313ms)
      ✓ duplicate (1780ms)
      ✓ hide (1862ms)
    background
      ✓ add (1675ms)
      modify
        layer
          - expand/collapse
          ✓ id (3735ms)
          ✓ min-zoom (2209ms)
          ✓ max-zoom (2127ms)
          ✓ comments (2515ms)
          ✓ color (2022ms)
        filter
          - expand/collapse
          - compound filter
        paint
          - expand/collapse
          - color
          - pattern
          - opacity
        json-editor
          - expand/collapse
          - modify
          - parse error
    fill
      ✓ add (1831ms)
      - change source
    line
      ✓ add (1844ms)
      ✓ groups (687ms)
    symbol
      ✓ add (2035ms)
    raster
      ✓ add (1814ms)
    circle
      ✓ add (1867ms)
    fill extrusion
      ✓ add (1963ms)
    groups
      ✓ simple (2653ms)

map
    zoom level
      ✓ via url (2279ms)
      ✓ via map controls (733ms)

modals
    open
      ✓ close (2519ms)
      - upload
      ✓ load from url (1557ms)
    shortcuts
      ✓ open/close (1136ms)
    export
      ✓ close (755ms)
      - download
    sources
      - active sources
      - public source
      - add new source
    inspect
      ✓ toggle (1020ms)
    style settings
      ✓ name (1085ms)
      ✓ owner (1060ms)
      ✓ sprite url (1214ms)
      ✓ glyphs url (1553ms)
      ✓ maptiler access token (1111ms)
      ✓ thunderforest access token (1102ms)
      ✓ style renderer (922ms)
    sources
      - toggle



      Spec                                              Tests  Passing  Failing  Pending  Skipped  
  ┌────────────────────────────────────────────────────────────────────────────────────────────────┐
  │ ✔  accessibility.cy.ts                       52ms        3        -        -        3        - │
  ├────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ ✔  history.cy.ts                            00:06        1        1        -        -        - │
  ├────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ ✔  keyboard.cy.ts                           00:10        9        9        -        -        - │
  ├────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ ✔  layers.cy.ts                             00:39       28       17        -       11        - │
  ├────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ ✔  map.cy.ts                                00:04        2        2        -        -        - │
  ├────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ ✔  modals.cy.ts                             00:16       18       12        -        6        - │
  └────────────────────────────────────────────────────────────────────────────────────────────────┘
    ✔  All specs passed!                        01:18       61       41        -       20        -  
```

---------

Co-authored-by: Yuri Astrakhan <yuriastrakhan@gmail.com>
2023-12-17 21:49:23 +02:00
Birk Skyum 0c46affda9 Add dependabot (#826)
It has a low limit on how many PRs it's allowed to open at a time, so it
should not flood the repo.
2023-12-17 01:16:47 -05:00
Harel M 18f45e932b Use driver pattern for e2e tests (#829)
I've moved all the logic relevant to WBIO into a single file in order to
be able to replace it.
I have tried to upgrade WDIO in order to use the latest version and it
got stuck on my computer.
Furthermore, I was not able to run it locally which made this whole
cycle very long.
After this will be merged I will replace WDIO with cypress.
This doesn't change anything, only moves some code in the tests to a
single file, removes unneeded files and uses the driver pattern, which
will later allow switching the underline WDIO with Cypress.

cc: @nyurik
2023-12-17 01:14:23 -05:00
Yuri Astrakhan 31d56c9fae Bump CI versions (#830) 2023-12-17 00:49:34 -05:00
Birk Skyum b7838ad6e1 Use latest firefox (#825) 2023-10-23 08:06:02 +02:00
Birk Skyum c92fd12854 Bump to node 18 (#824) 2023-10-22 22:11:06 +02:00
Birk Skyum eb55796461 Merge pull request #823 from birkskyum/new-webdriver
Chrome new headless
2023-10-22 20:20:26 +02:00
Yuri Astrakhan 4b97f82980 Revert "Revert "Resolve #821 (#822)""
This reverts commit e4d559f953.
2023-10-21 18:33:48 -04:00
Yuri Astrakhan 5d0b6e3201 Revert "Revert "Added checkbox for cluster attribute (#810)""
This reverts commit 52f949e152.
2023-10-21 18:33:46 -04:00
Birk Skyum 5ab9be9fdb update node version 2023-10-22 00:27:41 +02:00
Birk Skyum 9659d41b83 chrome new headless 2023-10-22 00:20:55 +02:00
Yuri Astrakhan 52f949e152 Revert "Added checkbox for cluster attribute (#810)"
This reverts commit 393f4a38b9.
2023-10-21 18:19:24 -04:00
Yuri Astrakhan e4d559f953 Revert "Resolve #821 (#822)"
This reverts commit 577663f706.
2023-10-21 18:19:21 -04:00
zstadler 577663f706 Resolve #821 (#822)
Please see code analysis at
https://github.com/maputnik/editor/issues/821#issuecomment-1772360990
2023-10-20 11:01:20 -04:00
Eliav-B 393f4a38b9 Added checkbox for cluster attribute (#810)
* Added additional checkbox to set the cluster attribute when adding a GeoJson source

* Fixed default source function in the 'geojson_json' case

---------

Co-authored-by: shimon <ruisuhsh100@gmail.com>
2023-10-20 10:54:40 -04:00
Kevin Schaul 3727c9ad5e 814/remove mapbox references (#816)
Fixes #814

* fix: remove outdated references to mapbox
* docs: fix references in readme
* chore: fix mapbox references in tests
* chore: fix mapbox references in stories, webpack config
* chore: remove empty array
2023-08-28 22:17:49 -04:00
72 changed files with 3096 additions and 8370 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ assignees: ''
<!-- Thanks for your feedback! Please complete the following information: -->
**Maputnik version**:<!-- e.g v1.7.0, master -->
**Maputnik version**:<!-- e.g v1.7.0, main -->
**Browser**:
**OS**:<!-- (Windows, macOS, Linux) -->
+14
View File
@@ -0,0 +1,14 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 2
versioning-strategy: increase
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 2
versioning-strategy: increase
+21 -53
View File
@@ -2,9 +2,9 @@ name: ci
on:
pull_request:
branches: [ master ]
branches: [ main ]
push:
branches: [ master ]
branches: [ main ]
jobs:
@@ -34,8 +34,8 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v2
- run: docker build -t docker.pkg.github.com/maputnik/editor/editor:master .
- uses: actions/checkout@v4
- run: docker build -t docker.pkg.github.com/maputnik/editor/editor:main .
# build the editor
build-node:
@@ -48,10 +48,10 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [16.x]
node-version: [18.x]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
@@ -74,10 +74,10 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest]
node-version: [16.x]
node-version: [18.x]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node-version }}
@@ -115,7 +115,7 @@ jobs:
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
uses: actions/checkout@v4
with:
repository: maputnik/desktop
ref: master
@@ -141,53 +141,21 @@ jobs:
with:
name: maputnik-windows
path: ./src/github.com/maputnik/desktop/bin/windows/
# build and test the editor
test_selenium_standalone:
name: "test/standalone-${{ matrix.browser }} (${{ matrix.os }})"
runs-on: ${{ matrix.os }}
if: ${{ github.event_name == 'push' || github.event_name == 'pull_request' }}
cypress-run:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
node-version: [16]
browser: [chrome, firefox]
container:
image: node:${{ matrix.node-version }}
options: --network-alias testhost
services:
selenium:
# geckodriver-0.31 seems to have problems as of 2022 May 1
image: selenium/standalone-${{ matrix.browser == 'firefox' && 'firefox:99.0-geckodriver-0.30-20220427' || matrix.browser }}
ports:
- 4444:4444
options: --shm-size=2gb
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- uses: actions/cache@v1
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- run: npm ci
- run: BROWSER=${{ matrix.browser }} TEST_NETWORK=testhost DOCKER_HOST=selenium npm run test
- if: ${{ matrix.browser == 'chrome' }}
run: ./node_modules/.bin/istanbul report --include build/coverage/coverage.json --dir build/coverage html lcov
- if: ${{ matrix.browser == 'chrome' }}
name: artifacts/coverage
uses: actions/upload-artifact@v1
with:
name: coverage
path: build/coverage
- name: artifacts/screenshots
uses: actions/upload-artifact@v1
with:
name: screenshots-${{ matrix.browser }}
path: build/screenshots
- name: Checkout
uses: actions/checkout@v4
- run: npm ci
- name: Cypress run
uses: cypress-io/github-action@v6
with:
build: npm run build
start: npm run start
browser: ${{ matrix.browser }}
+5 -6
View File
@@ -2,13 +2,13 @@ name: deploy
on:
push:
branches: [ master ]
branches: [ main ]
push:
tags:
- 'v*'
jobs:
# publish docker to github registry
# publish docker to GitHub registry
deploy-docker:
name: deploy/docker
runs-on: ${{ matrix.os }}
@@ -21,8 +21,7 @@ jobs:
os: [ubuntu-latest]
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- run: echo "${{ secrets.GITHUB_TOKEN }}" | docker login docker.pkg.github.com -u orangemug --password-stdin
- run: docker build -t docker.pkg.github.com/maputnik/editor/editor:master .
- run: docker push docker.pkg.github.com/maputnik/editor/editor:master
- run: docker build -t docker.pkg.github.com/maputnik/editor/editor:main .
- run: docker push docker.pkg.github.com/maputnik/editor/editor:main
+1
View File
@@ -33,3 +33,4 @@ public
/errorShots
/old
/build
/cypress/screenshots
+1 -1
View File
@@ -1,4 +1,4 @@
FROM node:10 as builder
FROM node:18 as builder
WORKDIR /maputnik
# Only copy package.json to prevent npm install from running on every build
+13 -8
View File
@@ -7,7 +7,7 @@
[github-action-ci]: https://github.com/maputnik/editor/actions?query=workflow%3Aci
[license]: https://tldrlegal.com/license/mit-license
A free and open visual editor for the [Mapbox GL styles](https://www.mapbox.com/mapbox-gl-style-spec/)
A free and open visual editor for the [MapLibre GL styles](https://maplibre.org/maplibre-style-spec/)
targeted at developers and map designers.
@@ -36,7 +36,7 @@ The documentation can be found in the [Wiki](https://github.com/maputnik/editor/
## Develop
Maputnik is written in ES6 and is using [React](https://github.com/facebook/react) and [Mapbox GL JS](https://www.mapbox.com/mapbox-gl-js/api/).
Maputnik is written in ES6 and is using [React](https://github.com/facebook/react) and [MapLibre GL JS](https://maplibre.org/projects/maplibre-gl-js/).
We ensure building and developing Maputnik works with the [current active LTS Node.js version and above](https://github.com/nodejs/Release#release-schedule).
@@ -76,9 +76,9 @@ npm run lint-styles
## Tests
For testing we use [webdriverio](https://webdriver.io) and [selenium-standalone](https://github.com/webdriverio/selenium-standalone).
For E2E testing we use [Cypress](https://www.cypress.io/)
[selenium-standalone](https://github.com/webdriverio/selenium-standalone) starts a server that will launch browsers on your local machine. You need to have Java installed on your machine as well as *chrome* or *firefox*.
[Cypress](https://www.cypress.io/) doesn't starts a server so you'll need to start one manually by running `npm run start`.
Now open a terminal and run the following using *chrome*:
@@ -87,10 +87,16 @@ npm run test
```
or *firefox*:
```
BROWSER=firefox npm run test
npm run test -- --browser firefox
```
After some time you should see a browser launch which will be automated by the test runner.
See the following docs for more info: (Launching Browsers)[https://docs.cypress.io/guides/guides/launching-browsers]
You can also see the tests as they run or select which suites to run by executing:
```
npm run cy:open
```
## Related Projects
@@ -155,6 +161,5 @@ Sina Martinelli, Nicholas Doiron, Neil Cawse, Urs42, Benedikt Groß, Manuel Roth
Maputnik is [licensed under MIT](LICENSE) and is Copyright (c) Lukas Martinelli and contributors.
**Disclaimer** This project is not affiliated with Mapbox or Mapbox Studio. It is an independent style editor for the
open source technology in the Mapbox GL ecosystem.
**Disclaimer** This is an independent style editor.
As contributor please take extra care of not violating any Mapbox trademarks. Do not get inspired by Mapbox Studio and make your own decisions for a good style editor.
-47
View File
@@ -1,47 +0,0 @@
var webpack = require("webpack");
var WebpackDevServer = require("webpack-dev-server");
var webpackConfig = require("./webpack.config");
var testConfig = require("../test/config/specs");
var artifacts = require("../test/artifacts");
var server;
var SCREENSHOT_PATH = artifacts.pathSync("screenshots");
exports.config = {
runner: 'local',
path: '/wd/hub',
specs: [
'./test/functional/index.js'
],
maxInstances: 10,
capabilities: [
{
maxInstances: 5,
browserName: (process.env.BROWSER || 'chrome'),
}
],
// geckodriver-0.31 seems to have problems as of 2022 May 1
services: process.env.DOCKER_HOST ? [] : [ ['selenium-standalone', { drivers: { firefox: '0.30.0', chrome: 'latest' } } ] ],
logLevel: 'info',
bail: 0,
screenshotPath: SCREENSHOT_PATH,
hostname: process.env.DOCKER_HOST || "0.0.0.0",
framework: 'mocha',
reporters: ['spec'],
mochaOpts: {
ui: 'bdd',
// Because we don't know how long the initial build will take...
timeout: 4*60*1000,
},
onPrepare: async function (config, capabilities) {
webpackConfig.devServer.host = testConfig.testNetwork;
webpackConfig.devServer.port = testConfig.port;
const compiler = webpack(webpackConfig);
server = new WebpackDevServer(webpackConfig.devServer, compiler);
await server.start();
},
onComplete: async function (exitCode, config, capabilities) {
await server.stop();
}
}
-3
View File
@@ -25,9 +25,6 @@ module.exports = {
extensions: ['.js', '.jsx']
},
module: {
noParse: [
/mapbox-gl\/dist\/mapbox-gl.js/
],
rules: rules
},
node: {
+1 -6
View File
@@ -6,16 +6,14 @@ var HtmlWebpackInlineSVGPlugin = require('html-webpack-inline-svg-plugin');
var WebpackCleanupPlugin = require('webpack-cleanup-plugin');
var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
var CopyWebpackPlugin = require('copy-webpack-plugin');
var artifacts = require("../test/artifacts");
var OUTPATH = artifacts.pathSync("/build");
module.exports = {
entry: {
app: './src/index.jsx',
},
output: {
path: OUTPATH,
path: path.join(__dirname, '..', 'build', 'build'),
filename: '[name].[contenthash].js',
chunkFilename: '[contenthash].js'
},
@@ -23,9 +21,6 @@ module.exports = {
extensions: ['.js', '.jsx']
},
module: {
noParse: [
/mapbox-gl\/dist\/mapbox-gl.js/
],
rules: rules
},
node: {
+2 -4
View File
@@ -1,13 +1,11 @@
const webpackProdConfig = require('./webpack.production.config');
const artifacts = require("../test/artifacts");
const OUTPATH = artifacts.pathSync("/profiling");
var path = require('path');
module.exports = {
...webpackProdConfig,
output: {
...webpackProdConfig.output,
path: OUTPATH,
path: path.join(__dirname, '..', 'build', 'profiling'),
},
resolve: {
...webpackProdConfig.resolve,
+9
View File
@@ -0,0 +1,9 @@
import { defineConfig } from "cypress";
export default defineConfig({
e2e: {
setupNodeEvents(on, config) {
// implement node event listeners here
},
},
});
+41
View File
@@ -0,0 +1,41 @@
import driver from "./driver";
describe("accessibility", () => {
// skipped due to the following issue with cypress: https://github.com/cypress-io/cypress/issues/299
describe.skip("skip links", () => {
beforeEach(() => {
driver.beforeEach();
driver.setStyle("layer");
});
it("skip link to layer list", () => {
const selector = driver.getDataAttribute("root:skip:layer-list");
driver.isExists(selector);
driver.typeKeys('{tab}');
driver.isFocused(selector);
driver.click(selector);
driver.isFocused("#skip-target-layer-list");
});
it("skip link to layer editor", () => {
const selector = driver.getDataAttribute("root:skip:layer-editor");
driver.isExists(selector);
driver.typeKeys('{tab}{tab}');
driver.isFocused(selector);
driver.click(selector);
driver.isFocused("#skip-target-layer-editor");
});
it("skip link to map view", () => {
const selector = driver.getDataAttribute("root:skip:map-view");
driver.isExists(selector);
driver.typeKeys('{tab}{tab}{tab}');
driver.isFocused(selector);
driver.click(selector);
driver.isFocused(".maplibregl-canvas");
});
});
})
+170
View File
@@ -0,0 +1,170 @@
import {v1 as uuid} from "uuid";
export default {
isMac() {
return Cypress.platform === "darwin";
},
beforeEach() {
this.setupInterception();
this.setStyle('both');
},
setupInterception() {
cy.intercept('GET', 'http://localhost:8888/example-style.json', { fixture: 'example-style.json' }).as('example-style.json');
cy.intercept('GET', 'http://localhost:8888/example-layer-style.json', { fixture: 'example-layer-style.json' });
cy.intercept('GET', 'http://localhost:8888/geojson-style.json', { fixture: 'geojson-style.json' });
cy.intercept('GET', 'http://localhost:8888/raster-style.json', { fixture: 'raster-style.json' });
cy.intercept('GET', 'http://localhost:8888/geojson-raster-style.json', { fixture: 'geojson-raster-style.json' });
cy.intercept({method: 'GET', url: '*example.local/*' }, []);
cy.intercept({method: 'GET', url: '*example.com/*' }, []);
},
setStyle(styleProperties: 'geojson' | 'raster' | 'both' | 'layer' | '', zoom? : number) {
let url = "?debug";
switch (styleProperties) {
case "geojson":
url += "&style=http://localhost:8888/geojson-style.json";
break;
case "raster":
url += "&style=http://localhost:8888/raster-style.json";
break;
case "both":
url += "&style=http://localhost:8888/geojson-raster-style.json";
break;
case "layer":
url += "&style=http://localhost:8888/example-layer-style.json";
break;
}
if (zoom) {
url += "#" + zoom + "/41.3805/2.1635";
}
cy.visit("http://localhost:8888/" + url);
if (styleProperties) {
cy.on('window:confirm', () => true)
}
cy.get(".maputnik-toolbar-link").should("be.visible");
},
getDataAttribute(key: string, selector?: string) {
return `*[data-wd-key='${key}'] ${selector || ''}`;
},
closeModal(key: string) {
const selector = this.getDataAttribute(key);
this.isDisplayedInViewport(selector);
this.click(this.getDataAttribute(key + ".close-modal"));
this.doesNotExists(selector);
},
openLayersModal() {
cy.get(this.getDataAttribute('layer-list:add-layer')).click();
cy.get(this.getDataAttribute('modal:add-layer')).should('exist');
cy.get(this.getDataAttribute('modal:add-layer')).should('be.visible');
},
getStyleFromWindow(win: Window) {
const styleId = win.localStorage.getItem("maputnik:latest_style");
const styleItem = win.localStorage.getItem(`maputnik:style:${styleId}`)
const obj = JSON.parse(styleItem || "");
return obj;
},
isStyleStoreEqual(getter: (obj:any) => any, styleObj: any) {
cy.window().then((win: any) => {
const obj = this.getStyleFromWindow(win);
assert.deepEqual(getter(obj), styleObj);
});
},
isStyleStoreEqualToExampleFileData() {
cy.window().then((win: any) => {
const obj = this.getStyleFromWindow(win);
cy.fixture('example-style.json').should('deep.equal', obj);
});
},
fillLayersModal(opts: any) {
var type = opts.type;
var layer = opts.layer;
var id;
if(opts.id) {
id = opts.id
}
else {
id = `${type}:${uuid()}`;
}
cy.get(this.getDataAttribute('add-layer.layer-type', "select")).select(type);
cy.get(this.getDataAttribute("add-layer.layer-id", "input")).type(id);
if(layer) {
cy.get(this.getDataAttribute("add-layer.layer-source-block", "input")).type(layer);
}
cy.get(this.getDataAttribute("add-layer")).click();
return id;
},
typeKeys(keys: string) {
cy.get('body').type(keys);
},
click(selector: string) {
cy.get(selector).click();
},
select(selector: string, value: string) {
cy.get(selector).select(value);
},
isSelected(selector: string, value: string) {
cy.get(selector).find(`option[value="${value}"]`).should("be.selected");
},
focus(selector: string) {
cy.get(selector).focus();
},
isFocused(selector: string) {
cy.get(selector).should('have.focus');
},
isDisplayedInViewport(selector: string) {
cy.get(selector).should('be.visible');
},
isNotDisplayedInViewport(selector: string) {
cy.get(selector).should('not.be.visible');
},
setValue(selector: string, text: string) {
cy.get(selector).clear().type(text, {parseSpecialCharSequences: false});
},
isExists(selector: string) {
cy.get(selector).should('exist');
},
doesNotExists(selector: string) {
cy.get(selector).should('not.exist');
},
chooseExampleFile() {
cy.get("input[type='file']").selectFile('cypress/fixtures/example-style.json', {force: true});
},
getExampleFileUrl() {
return "http://localhost:8888/example-style.json";
},
waitForExampleFileRequset() {
cy.wait('@example-style.json');
}
}
+80
View File
@@ -0,0 +1,80 @@
import driver from "./driver";
describe("history", () => {
let undoKeyCombo: string;
let redoKeyCombo: string;
before(() => {
const isMac = driver.isMac();
undoKeyCombo = isMac ? '{meta}z' : '{ctrl}z';
redoKeyCombo = isMac ? '{meta}{shift}z' : '{ctrl}y';
driver.beforeEach();
});
it("undo/redo", () => {
driver.setStyle('geojson');
driver.openLayersModal();
driver.isStyleStoreEqual((a: any) => a.layers, []);
driver.fillLayersModal({
id: "step 1",
type: "background"
})
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": "step 1",
"type": 'background'
}
]);
driver.openLayersModal();
driver.fillLayersModal({
id: "step 2",
type: "background"
})
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": "step 1",
"type": 'background'
},
{
"id": "step 2",
"type": 'background'
}
]);
driver.typeKeys(undoKeyCombo);
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": "step 1",
"type": 'background'
}
]);
driver.typeKeys(undoKeyCombo)
driver.isStyleStoreEqual((a: any) => a.layers, []);
driver.typeKeys(redoKeyCombo)
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": "step 1",
"type": 'background'
}
]);
driver.typeKeys(redoKeyCombo)
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": "step 1",
"type": 'background'
},
{
"id": "step 2",
"type": 'background'
}
]);
});
})
+60
View File
@@ -0,0 +1,60 @@
import driver from "./driver";
describe("keyboard", () => {
describe("shortcuts", () => {
beforeEach(() => {
driver.setupInterception();
driver.setStyle('');
})
it("ESC should unfocus", () => {
const targetSelector = driver.getDataAttribute("nav:inspect") + " select";
driver.focus(targetSelector);
driver.isFocused(targetSelector);
//driver.typeKeys("{esc}");
//driver.isFocused('body');
});
it("'?' should show shortcuts modal", () => {
driver.typeKeys("?");
driver.isDisplayedInViewport(driver.getDataAttribute("modal:shortcuts"));
});
it("'o' should show open modal", () => {
driver.typeKeys("o");
driver.isDisplayedInViewport(driver.getDataAttribute("modal:open"));
});
it("'e' should show export modal", () => {
driver.typeKeys("e");
driver.isDisplayedInViewport(driver.getDataAttribute("modal:export"));
});
it("'d' should show sources modal", () => {
driver.typeKeys("d");
driver.isDisplayedInViewport(driver.getDataAttribute("modal:sources"));
});
it("'s' should show settings modal", () => {
driver.typeKeys("s");
driver.isDisplayedInViewport(driver.getDataAttribute("modal:settings"));
});
it("'i' should change map to inspect mode", () => {
driver.typeKeys("i");
driver.isSelected(driver.getDataAttribute("nav:inspect"), "inspect");
});
it("'m' should focus map", () => {
driver.typeKeys("m");
driver.isFocused(".maplibregl-canvas");
});
it("'!' should show debug modal", () => {
driver.typeKeys("!");
driver.isDisplayedInViewport(driver.getDataAttribute("modal:debug"));
});
});
});
+427
View File
@@ -0,0 +1,427 @@
var assert = require("assert");
import driver from "./driver";
import { v1 as uuid } from 'uuid';
describe("layers", () => {
beforeEach(() => {
driver.beforeEach();
driver.setStyle('both');
driver.openLayersModal();
});
describe("ops", () => {
it("delete", () => {
var id = driver.fillLayersModal({
type: "background"
})
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": id,
"type": 'background'
},
]);
driver.click(driver.getDataAttribute("layer-list-item:"+id+":delete", ""))
driver.isStyleStoreEqual((a: any) => a.layers, []);
});
it("duplicate", () => {
var styleObj;
var id = driver.fillLayersModal({
type: "background"
})
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": id,
"type": 'background'
},
]);
driver.click(driver.getDataAttribute("layer-list-item:"+id+":copy", ""));
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": id+"-copy",
"type": "background"
},
{
"id": id,
"type": "background"
},
]);
});
it("hide", () => {
var styleObj;
var id = driver.fillLayersModal({
type: "background"
})
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": id,
"type": 'background'
},
]);
driver.click(driver.getDataAttribute("layer-list-item:"+id+":toggle-visibility", ""));
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": id,
"type": "background",
"layout": {
"visibility": "none"
}
},
]);
driver.click(driver.getDataAttribute("layer-list-item:"+id+":toggle-visibility", ""));
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": id,
"type": "background",
"layout": {
"visibility": "visible"
}
},
]);
})
})
describe('background', () => {
it("add", () => {
var id = driver.fillLayersModal({
type: "background"
})
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": id,
"type": 'background'
}
]);
});
describe("modify", () => {
function createBackground() {
// Setup
var id = uuid();
driver.select(driver.getDataAttribute("add-layer.layer-type", "select"), "background");
driver.setValue(driver.getDataAttribute("add-layer.layer-id", "input"), "background:"+id);
driver.click(driver.getDataAttribute("add-layer"));
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": 'background:'+id,
"type": 'background'
}
]);
return id;
}
// ====> THESE SHOULD BE FROM THE SPEC
describe("layer", () => {
it("expand/collapse");
it("id", () => {
var bgId = createBackground();
driver.click(driver.getDataAttribute("layer-list-item:background:"+bgId));
var id = uuid();
driver.setValue(driver.getDataAttribute("layer-editor.layer-id", "input"), "foobar:"+id)
driver.click(driver.getDataAttribute("min-zoom"));
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": 'foobar:'+id,
"type": 'background'
}
]);
});
it("min-zoom", () => {
var bgId = createBackground();
driver.click(driver.getDataAttribute("layer-list-item:background:"+bgId));
driver.setValue(driver.getDataAttribute("min-zoom", 'input[type="text"]'), "1");
driver.click(driver.getDataAttribute("layer-editor.layer-id", "input"));
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": 'background:'+bgId,
"type": 'background',
"minzoom": 1
}
]);
// AND RESET!
// driver.setValue(driver.getDataAttribute("min-zoom", "input"), "")
// driver.click(driver.getDataAttribute("max-zoom", "input"));
// driver.isStyleStoreEqual((a: any) => a.layers, [
// {
// "id": 'background:'+bgId,
// "type": 'background'
// }
// ]);
});
it("max-zoom", () => {
var bgId = createBackground();
driver.click(driver.getDataAttribute("layer-list-item:background:"+bgId));
driver.setValue(driver.getDataAttribute("max-zoom", 'input[type="text"]'), "1")
driver.click(driver.getDataAttribute("layer-editor.layer-id", "input"));
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": 'background:'+bgId,
"type": 'background',
"maxzoom": 1
}
]);
});
it("comments", () => {
var bgId = createBackground();
var id = uuid();
driver.click(driver.getDataAttribute("layer-list-item:background:"+bgId));
driver.setValue(driver.getDataAttribute("layer-comment", "textarea"), id);
driver.click(driver.getDataAttribute("layer-editor.layer-id", "input"));
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": 'background:'+bgId,
"type": 'background',
metadata: {
'maputnik:comment': id
}
}
]);
// Unset it again.
// TODO: This fails
// driver.setValue(driver.getDataAttribute("layer-comment", "textarea"), "");
// driver.click(driver.getDataAttribute("min-zoom", "input"));
// driver.isStyleStoreEqual((a: any) => a.layers, [
// {
// "id": 'background:'+bgId,
// "type": 'background'
// }
// ]);
});
it("color", () => {
var bgId = createBackground();
driver.click(driver.getDataAttribute("layer-list-item:background:"+bgId));
driver.click(driver.getDataAttribute("spec-field:background-color", "input"));
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": 'background:'+bgId,
"type": 'background'
}
]);
})
})
describe("filter", () => {
it("expand/collapse");
it("compound filter");
})
describe("paint", () => {
it("expand/collapse");
it("color");
it("pattern");
it("opacity");
})
// <=====
describe("json-editor", () => {
it("expand/collapse");
it("modify");
// TODO
it.skip("parse error", () => {
var bgId = createBackground();
driver.click(driver.getDataAttribute("layer-list-item:background:"+bgId));
var errorSelector = ".CodeMirror-lint-marker-error";
driver.doesNotExists(errorSelector);
driver.click(".CodeMirror");
driver.typeKeys("\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013 {");
driver.isExists(errorSelector);
driver.click(driver.getDataAttribute("layer-editor.layer-id"));
});
});
})
});
describe('fill', () => {
it("add", () => {
var id = driver.fillLayersModal({
type: "fill",
layer: "example"
});
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": id,
"type": 'fill',
"source": "example"
}
]);
})
// TODO: Change source
it("change source")
});
describe('line', () => {
it("add", () => {
var id = driver.fillLayersModal({
type: "line",
layer: "example"
});
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": id,
"type": "line",
"source": "example",
}
]);
});
it("groups", () => {
// TODO
// Click each of the layer groups.
})
});
describe('symbol', () => {
it("add", () => {
var id = driver.fillLayersModal({
type: "symbol",
layer: "example"
});
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": id,
"type": "symbol",
"source": "example",
}
]);
});
});
describe('raster', () => {
it("add", () => {
var id = driver.fillLayersModal({
type: "raster",
layer: "raster"
});
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": id,
"type": "raster",
"source": "raster",
}
]);
});
});
describe('circle', () => {
it("add", () => {
var id = driver.fillLayersModal({
type: "circle",
layer: "example"
});
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": id,
"type": "circle",
"source": "example",
}
]);
});
});
describe('fill extrusion', () => {
it("add", () => {
var id = driver.fillLayersModal({
type: "fill-extrusion",
layer: "example"
});
driver.isStyleStoreEqual((a: any) => a.layers, [
{
"id": id,
"type": 'fill-extrusion',
"source": "example"
}
]);
});
});
describe("groups", () => {
it("simple", () => {
driver.setStyle("geojson");
driver.openLayersModal();
driver.fillLayersModal({
id: "foo",
type: "background"
})
driver.openLayersModal();
driver.fillLayersModal({
id: "foo_bar",
type: "background"
})
driver.openLayersModal();
driver.fillLayersModal({
id: "foo_bar_baz",
type: "background"
})
driver.isDisplayedInViewport(driver.getDataAttribute("layer-list-item:foo"));
driver.isNotDisplayedInViewport(driver.getDataAttribute("layer-list-item:foo_bar"));
driver.isNotDisplayedInViewport(driver.getDataAttribute("layer-list-item:foo_bar_baz"));
driver.click(driver.getDataAttribute("layer-list-group:foo-0"));
driver.isDisplayedInViewport(driver.getDataAttribute("layer-list-item:foo"));
driver.isDisplayedInViewport(driver.getDataAttribute("layer-list-item:foo_bar"));
driver.isDisplayedInViewport(driver.getDataAttribute("layer-list-item:foo_bar_baz"));
})
})
});
+25
View File
@@ -0,0 +1,25 @@
import driver from "./driver";
describe("map", () => {
describe("zoom level", () => {
beforeEach(() => {
driver.beforeEach();
});
it("via url", () => {
var zoomLevel = 12.37;
driver.setStyle("geojson", zoomLevel);
driver.isDisplayedInViewport(".maplibregl-ctrl-zoom");
// HM TODO
//driver.getText(".maplibregl-ctrl-zoom") === "Zoom "+(zoomLevel);
})
it("via map controls", () => {
var zoomLevel = 12.37;
driver.setStyle("geojson", zoomLevel);
driver.click(".maplibregl-ctrl-zoom-in");
driver.isDisplayedInViewport(".maplibregl-ctrl-zoom");
// HM TODO
//driver.getText(".maplibregl-ctrl-zoom") === "Zoom "+(zoomLevel + 1);
})
})
})
+137
View File
@@ -0,0 +1,137 @@
import driver from "./driver";
describe("modals", () => {
beforeEach(() => {
driver.beforeEach();
driver.setStyle('');
});
describe("open", () => {
beforeEach(() => {
driver.click(driver.getDataAttribute("nav:open"));
});
it("close", () => {
driver.closeModal("modal:open");
});
it.skip("upload", () => {
// HM: I was not able to make the following choose file actually to select a file and close the modal...
driver.chooseExampleFile();
driver.isStyleStoreEqualToExampleFileData();
});
it("load from url", () => {
var styleFileUrl = driver.getExampleFileUrl();
driver.setValue(driver.getDataAttribute("modal:open.url.input"), styleFileUrl);
driver.click(driver.getDataAttribute("modal:open.url.button"))
driver.waitForExampleFileRequset();
driver.isStyleStoreEqualToExampleFileData();
});
})
describe("shortcuts", () => {
it("open/close", () => {
driver.setStyle('');
driver.typeKeys("?");
driver.isDisplayedInViewport(driver.getDataAttribute("modal:shortcuts"));
driver.closeModal("modal:shortcuts");
});
});
describe("export", () => {
beforeEach(() => {
driver.click(driver.getDataAttribute("nav:export"));
});
it("close", () => {
driver.closeModal("modal:export");
});
// TODO: Work out how to download a file and check the contents
it("download")
})
describe("sources", () => {
it("active sources")
it("public source")
it("add new source")
})
describe("inspect", () => {
it("toggle", () => {
driver.setStyle('geojson');
driver.select(driver.getDataAttribute("nav:inspect", "select"), "inspect");
})
})
describe("style settings", () => {
beforeEach(() => {
driver.click(driver.getDataAttribute("nav:settings"));
});
it("name", () => {
driver.setValue(driver.getDataAttribute("modal:settings.name"), "foobar");
driver.click(driver.getDataAttribute("modal:settings.owner"));
driver.isStyleStoreEqual((obj) => obj.name, "foobar");
})
it("owner", () => {
driver.setValue(driver.getDataAttribute("modal:settings.owner"), "foobar")
driver.click(driver.getDataAttribute("modal:settings.name"));
driver.isStyleStoreEqual((obj) => obj.owner, "foobar");
})
it("sprite url", () => {
driver.setValue(driver.getDataAttribute("modal:settings.sprite"), "http://example.com")
driver.click(driver.getDataAttribute("modal:settings.name"));
driver.isStyleStoreEqual((obj) => obj.sprite, "http://example.com");
})
it("glyphs url", () => {
var glyphsUrl = "http://example.com/{fontstack}/{range}.pbf"
driver.setValue(driver.getDataAttribute("modal:settings.glyphs"), glyphsUrl);
driver.click(driver.getDataAttribute("modal:settings.name"));
driver.isStyleStoreEqual((obj) => obj.glyphs, glyphsUrl);
})
it("maptiler access token", () => {
var apiKey = "testing123";
driver.setValue(driver.getDataAttribute("modal:settings.maputnik:openmaptiles_access_token"), apiKey);
driver.click(driver.getDataAttribute("modal:settings.name"));
driver.isStyleStoreEqual((obj) => obj.metadata["maputnik:openmaptiles_access_token"], apiKey);
})
it("thunderforest access token", () => {
var apiKey = "testing123";
driver.setValue(driver.getDataAttribute("modal:settings.maputnik:thunderforest_access_token"), apiKey);
driver.click(driver.getDataAttribute("modal:settings.name"));
driver.isStyleStoreEqual((obj) => obj.metadata["maputnik:thunderforest_access_token"], apiKey);
})
it("style renderer", () => {
cy.on('uncaught:exception', () => false); // this is due to the fact that this is an invalid style for openlayers
driver.select(driver.getDataAttribute("modal:settings.maputnik:renderer"), "ol");
driver.isSelected(driver.getDataAttribute("modal:settings.maputnik:renderer"), "ol");
driver.click(driver.getDataAttribute("modal:settings.name"));
driver.isStyleStoreEqual((obj) => obj.metadata["maputnik:renderer"], "ol");
})
})
describe("sources", () => {
it("toggle")
})
})
@@ -3,7 +3,7 @@
"version": 8,
"name": "Test Style",
"metadata": {
"maputnik:renderer": "mbgljs"
"maputnik:renderer": "mlgljs"
},
"sources": {},
"glyphs": "https://example.local/fonts/{fontstack}/{range}.pbf",
@@ -3,7 +3,7 @@
"version": 8,
"name": "Test Style",
"metadata": {
"maputnik:renderer": "mbgljs"
"maputnik:renderer": "mlgljs"
},
"sources": {},
"glyphs": "https://example.local/fonts/{fontstack}/{range}.pbf",
@@ -0,0 +1,34 @@
{
"id": "test-style",
"version": 8,
"name": "Test Style",
"metadata": {
"maputnik:renderer": "mlgljs"
},
"sources": {
"example": {
"type": "vector",
"data": {
"type": "FeatureCollection",
"features":[{
"type": "Feature",
"properties": {
"name": "Dinagat Islands"
},
"geometry":{
"type": "Point",
"coordinates": [125.6, 10.1]
}
}]
}
},
"raster": {
"tileSize": 256,
"tiles": ["http://localhost/example/{x}/{y}/{z}"],
"type": "raster"
}
},
"glyphs": "https://example.local/fonts/{fontstack}/{range}.pbf",
"sprites": "https://example.local/fonts/{fontstack}/{range}.pbf",
"layers": []
}
+29
View File
@@ -0,0 +1,29 @@
{
"id": "test-style",
"version": 8,
"name": "Test Style",
"metadata": {
"maputnik:renderer": "mlgljs"
},
"sources": {
"example": {
"type": "vector",
"data": {
"type": "FeatureCollection",
"features":[{
"type": "Feature",
"properties": {
"name": "Dinagat Islands"
},
"geometry":{
"type": "Point",
"coordinates": [125.6, 10.1]
}
}]
}
}
},
"glyphs": "https://example.local/fonts/{fontstack}/{range}.pbf",
"sprites": "https://example.local/fonts/{fontstack}/{range}.pbf",
"layers": []
}
+18
View File
@@ -0,0 +1,18 @@
{
"id": "test-style",
"version": 8,
"name": "Test Style",
"metadata": {
"maputnik:renderer": "mlgljs"
},
"sources": {
"raster": {
"tileSize": 256,
"tiles": ["http://localhost/example/{x}/{y}/{z}"],
"type": "raster"
}
},
"glyphs": "https://example.local/fonts/{fontstack}/{range}.pbf",
"sprites": "https://example.local/fonts/{fontstack}/{range}.pbf",
"layers": []
}
+37
View File
@@ -0,0 +1,37 @@
/// <reference types="cypress" />
// ***********************************************
// This example commands.ts shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
//
// declare global {
// namespace Cypress {
// interface Chainable {
// login(email: string, password: string): Chainable<void>
// drag(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// dismiss(subject: string, options?: Partial<TypeOptions>): Chainable<Element>
// visit(originalFn: CommandOriginalFn, url: string, options: Partial<VisitOptions>): Chainable<Element>
// }
// }
// }
+20
View File
@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/e2e.ts is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************
// Import commands.js using ES2015 syntax:
import './commands'
// Alternatively you can use CommonJS syntax:
// require('./commands')
+1730 -6593
View File
File diff suppressed because it is too large Load Diff
+14 -17
View File
@@ -4,19 +4,19 @@
"description": "A MapLibre GL visual style editor",
"main": "''",
"scripts": {
"stats": "webpack --config config/webpack.production.config.js --progress=profile --json > stats.json",
"build": "webpack --config config/webpack.production.config.js --progress=profile --color",
"profiling-build": "webpack --config config/webpack.profiling.config.js --progress=profile --color",
"test": "cross-env NODE_ENV=test wdio config/wdio.conf.js",
"test-watch": "cross-env NODE_ENV=test wdio config/wdio.conf.js --watch",
"start": "webpack-dev-server --progress=profile --color --config config/webpack.config.js",
"start-prod": "webpack-dev-server --progress=profile --color --config config/webpack.production.config.js",
"start-sandbox": "webpack-dev-server --disable-host-check --host 0.0.0.0 --progress=profile --color --config config/webpack.production.config.js",
"stats": "cross-env NODE_OPTIONS=--openssl-legacy-provider webpack --config config/webpack.production.config.js --progress=profile --json > stats.json",
"build": "cross-env NODE_OPTIONS=--openssl-legacy-provider webpack --config config/webpack.production.config.js --progress=profile --color",
"profiling-build": "cross-env NODE_OPTIONS=--openssl-legacy-provider webpack --config config/webpack.profiling.config.js --progress=profile --color",
"test": "cypress run",
"cy:open": "cypress open",
"start": "cross-env NODE_OPTIONS=--openssl-legacy-provider webpack-dev-server --progress=profile --color --config config/webpack.config.js",
"start-prod": "cross-env NODE_OPTIONS=--openssl-legacy-provider webpack-dev-server --progress=profile --color --config config/webpack.production.config.js",
"start-sandbox": "cross-env NODE_OPTIONS=--openssl-legacy-provider webpack-dev-server --disable-host-check --host 0.0.0.0 --progress=profile --color --config config/webpack.production.config.js",
"lint-js": "eslint --ext js --ext jsx src test",
"lint-css": "stylelint \"src/styles/*.scss\"",
"lint": "npm run lint-js && npm run lint-css",
"storybook": "start-storybook -h 0.0.0.0 -p 6006",
"build-storybook": "build-storybook -o build/storybook"
"storybook": "cross-env NODE_OPTIONS=--openssl-legacy-provider start-storybook -h 0.0.0.0 -p 6006",
"build-storybook": "cross-env NODE_OPTIONS=--openssl-legacy-provider build-storybook -o build/storybook"
},
"repository": {
"type": "git",
@@ -133,11 +133,8 @@
"@storybook/addons": "^6.4.20",
"@storybook/react": "^6.4.20",
"@storybook/theming": "^6.4.20",
"@wdio/cli": "^7.19.3",
"@wdio/local-runner": "^7.19.3",
"@wdio/mocha-framework": "^7.19.3",
"@wdio/selenium-standalone-service": "^7.19.1",
"@wdio/spec-reporter": "^7.19.1",
"@types/cors": "^2.8.17",
"@types/uuid": "^9.0.7",
"babel-loader": "^8.2.4",
"babel-plugin-istanbul": "^6.1.1",
"babel-plugin-static-fs": "^3.0.0",
@@ -145,6 +142,7 @@
"cors": "^2.8.5",
"cross-env": "^7.0.3",
"css-loader": "^5.2.7",
"cypress": "^13.6.1",
"eslint": "^8.12.0",
"eslint-plugin-react": "^7.29.4",
"express": "^4.17.3",
@@ -163,9 +161,8 @@
"stylelint-scss": "^4.2.0",
"svg-inline-loader": "^0.8.2",
"transform-loader": "^0.2.4",
"typescript": "^4.6.3",
"typescript": "^4.9.5",
"uuid": "^8.3.2",
"webdriverio": "^7.19.3",
"webpack": "^4.46.0",
"webpack-bundle-analyzer": "^4.5.0",
"webpack-cleanup-plugin": "^0.5.1",
+13 -13
View File
@@ -9,7 +9,7 @@ import {arrayMoveMutable} from 'array-move'
import url from 'url'
import hash from "string-hash";
import MapMapboxGl from './MapMapboxGl'
import MapMaplibreGl from './MapMaplibreGl'
import MapOpenLayers from './MapOpenLayers'
import LayerList from './LayerList'
import LayerEditor from './LayerEditor'
@@ -136,7 +136,7 @@ export default class App extends React.Component {
{
key: "m",
handler: () => {
document.querySelector(".mapboxgl-canvas").focus();
document.querySelector(".maplibregl-canvas").focus();
}
},
{
@@ -220,7 +220,7 @@ export default class App extends React.Component {
survey: false,
debug: false,
},
mapboxGlDebugOptions: {
maplibreGlDebugOptions: {
showTileBoundaries: false,
showCollisionBoxes: false,
showOverdrawInspector: false,
@@ -290,7 +290,7 @@ export default class App extends React.Component {
// If we're changing renderer reset the map state.
if (
property === 'maputnik:renderer' &&
value !== get(this.state.mapStyle, ['metadata', 'maputnik:renderer'], 'mbgljs')
value !== get(this.state.mapStyle, ['metadata', 'maputnik:renderer'], 'mlgljs')
) {
this.setState({
mapState: 'map'
@@ -547,7 +547,7 @@ export default class App extends React.Component {
...styleObj,
metadata: {
...styleObj.metadata,
'maputnik:renderer': 'mbgljs'
'maputnik:renderer': 'mlgljs'
}
}
return changedStyle
@@ -626,7 +626,7 @@ export default class App extends React.Component {
_getRenderer () {
const metadata = this.state.mapStyle.metadata || {};
return metadata['maputnik:renderer'] || 'mbgljs';
return metadata['maputnik:renderer'] || 'mlgljs';
}
onMapChange = (mapView) => {
@@ -665,9 +665,9 @@ export default class App extends React.Component {
onLayerSelect={this.onLayerSelect}
/>
} else {
mapElement = <MapMapboxGl {...mapProps}
mapElement = <MapMaplibreGl {...mapProps}
onChange={this.onMapChange}
options={this.state.mapboxGlDebugOptions}
options={this.state.maplibreGlDebugOptions}
inspectModeEnabled={this.state.mapState === "inspect"}
highlightedLayer={this.state.mapStyle.layers[this.state.selectedLayerIndex]}
onLayerSelect={this.onLayerSelect} />
@@ -800,10 +800,10 @@ export default class App extends React.Component {
});
}
onChangeMaboxGlDebug = (key, value) => {
onChangeMaplibreGlDebug = (key, value) => {
this.setState({
mapboxGlDebugOptions: {
...this.state.mapboxGlDebugOptions,
maplibreGlDebugOptions: {
...this.state.maplibreGlDebugOptions,
[key]: value,
}
});
@@ -870,9 +870,9 @@ export default class App extends React.Component {
const modals = <div>
<ModalDebug
renderer={this._getRenderer()}
mapboxGlDebugOptions={this.state.mapboxGlDebugOptions}
maplibreGlDebugOptions={this.state.maplibreGlDebugOptions}
openlayersDebugOptions={this.state.openlayersDebugOptions}
onChangeMaboxGlDebug={this.onChangeMaboxGlDebug}
onChangeMaplibreGlDebug={this.onChangeMaplibreGlDebug}
onChangeOpenlayersDebug={this.onChangeOpenlayersDebug}
isOpen={this.state.isOpen.debug}
onOpenToggle={this.toggleModal.bind(this, 'debug')}
+2 -2
View File
@@ -133,7 +133,7 @@ export default class AppToolbar extends React.Component {
onSkip = (target) => {
if (target === "map") {
document.querySelector(".mapboxgl-canvas").focus();
document.querySelector(".maplibregl-canvas").focus();
}
else {
const el = document.querySelector("#skip-target-"+target);
@@ -152,7 +152,7 @@ export default class AppToolbar extends React.Component {
id: "inspect",
group: "general",
title: "Inspect",
disabled: this.props.renderer !== 'mbgljs',
disabled: this.props.renderer === 'ol',
},
{
id: "filter-deuteranopia",
+3 -3
View File
@@ -21,14 +21,14 @@ export default class Doc extends React.Component {
const renderValues = (
!!values &&
// HACK: Currently we merge additional values into the stylespec, so this is required
// See <https://github.com/maputnik/editor/blob/master/src/components/fields/PropertyGroup.jsx#L16>
// HACK: Currently we merge additional values into the style spec, so this is required
// See <https://github.com/maputnik/editor/blob/main/src/components/PropertyGroup.jsx#L16>
!Array.isArray(values)
);
return (
<>
{doc &&
{doc &&
<div className="SpecDoc">
<div className="SpecDoc__doc">{doc}</div>
{renderValues &&
+1 -1
View File
@@ -42,7 +42,7 @@ function createStyleFromFilter (filter) {
"id": "tmp",
"version": 8,
"name": "Empty Style",
"metadata": {"maputnik:renderer": "mbgljs"},
"metadata": {"maputnik:renderer": "mlgljs"},
"sources": {
"tmp": {
"type": "geojson",
+1 -1
View File
@@ -32,7 +32,7 @@ function optionsLabelLength(options) {
return sum
}
/** Display any field from the Mapbox GL style spec and
/** Display any field from the Maplibre GL style spec and
* choose the correct field component based on the @{fieldSpec}
* to display @{value}. */
export default class SpecField extends React.Component {
@@ -3,16 +3,16 @@ import PropTypes from 'prop-types'
import ReactDOM from 'react-dom'
import MapLibreGl from 'maplibre-gl'
import MapboxInspect from 'mapbox-gl-inspect'
import MapMapboxGlLayerPopup from './MapMapboxGlLayerPopup'
import MapMapboxGlFeaturePropertyPopup from './MapMapboxGlFeaturePropertyPopup'
import MapMaplibreGlLayerPopup from './MapMaplibreGlLayerPopup'
import MapMaplibreGlFeaturePropertyPopup from './MapMaplibreGlFeaturePropertyPopup'
import tokens from '../config/tokens.json'
import colors from 'mapbox-gl-inspect/lib/colors'
import Color from 'color'
import ZoomControl from '../libs/zoomcontrol'
import { colorHighlightedLayer } from '../libs/highlight'
import 'maplibre-gl/dist/maplibre-gl.css'
import '../mapboxgl.css'
import '../libs/mapbox-rtl'
import '../maplibregl.css'
import '../libs/maplibre-rtl'
const IS_SUPPORTED = MapLibreGl.supported();
@@ -52,7 +52,7 @@ function buildInspectStyle(originalMapStyle, coloredLayers, highlightedLayer) {
return inspectStyle
}
export default class MapMapboxGl extends React.Component {
export default class MapMaplibreGl extends React.Component {
static propTypes = {
onDataChange: PropTypes.func,
onLayerSelect: PropTypes.func.isRequired,
@@ -69,7 +69,6 @@ export default class MapMapboxGl extends React.Component {
onDataChange: () => {},
onLayerSelect: () => {},
onChange: () => {},
mapboxAccessToken: tokens.mapbox,
options: {},
}
@@ -86,7 +85,7 @@ export default class MapMapboxGl extends React.Component {
if(!this.state.map) return
//Mapbox GL now does diffing natively so we don't need to calculate
//Maplibre GL now does diffing natively so we don't need to calculate
//the necessary operations ourselves!
this.state.map.setStyle(
this.props.replaceAccessTokens(props.mapStyle),
@@ -120,7 +119,7 @@ export default class MapMapboxGl extends React.Component {
if (map) {
if (this.props.inspectModeEnabled) {
// HACK: We need to work out why we need to do this and what's causing
// this error. I'm assuming an issue with mapbox-gl update and
// this error. I'm assuming an issue with maplibre-gl update and
// mapbox-gl-inspect.
try {
this.state.inspect.render();
@@ -182,9 +181,9 @@ export default class MapMapboxGl extends React.Component {
buildInspectStyle: (originalMapStyle, coloredLayers) => buildInspectStyle(originalMapStyle, coloredLayers, this.props.highlightedLayer),
renderPopup: features => {
if(this.props.inspectModeEnabled) {
return renderPopup(<MapMapboxGlFeaturePropertyPopup features={features} />, tmpNode);
return renderPopup(<MapMaplibreGlFeaturePropertyPopup features={features} />, tmpNode);
} else {
return renderPopup(<MapMapboxGlLayerPopup features={features} onLayerSelect={this.onLayerSelectById} zoom={this.state.zoom} />, tmpNode);
return renderPopup(<MapMaplibreGlLayerPopup features={features} onLayerSelect={this.onLayerSelectById} zoom={this.state.zoom} />, tmpNode);
}
}
})
@@ -238,7 +237,7 @@ export default class MapMapboxGl extends React.Component {
className="maputnik-map maputnik-map--error"
>
<div className="maputnik-map__error-message">
Error: Cannot load MapboxGL, WebGL is either unsupported or disabled
Error: Cannot load MaplibreGL, WebGL is either unsupported or disabled
</div>
</div>
}
+3 -3
View File
@@ -3,7 +3,7 @@ import {throttle} from 'lodash';
import PropTypes from 'prop-types'
import { loadJSON } from '../libs/urlopen'
import MapMapboxGlLayerPopup from './MapMapboxGlLayerPopup';
import MapMaplibreGlLayerPopup from './MapMaplibreGlLayerPopup';
import 'ol/ol.css'
import {apply} from 'ol-mapbox-style';
@@ -146,13 +146,13 @@ export default class MapOpenLayers extends React.Component {
className="maputnik-popup"
>
<button
className="mapboxgl-popup-close-button"
className="maplibregl-popup-close-button"
onClick={this.closeOverlay}
aria-label="Close popup"
>
×
</button>
<MapMapboxGlLayerPopup
<MapMaplibreGlLayerPopup
features={this.state.selectedFeatures || []}
onLayerSelect={this.props.onLayerSelect}
/>
+3 -3
View File
@@ -11,7 +11,7 @@ export default class ModalDebug extends React.Component {
onChangeMaboxGlDebug: PropTypes.func.isRequired,
onChangeOpenlayersDebug: PropTypes.func.isRequired,
onOpenToggle: PropTypes.func.isRequired,
mapboxGlDebugOptions: PropTypes.object,
maplibreGlDebugOptions: PropTypes.object,
openlayersDebugOptions: PropTypes.object,
mapView: PropTypes.object,
}
@@ -31,9 +31,9 @@ export default class ModalDebug extends React.Component {
>
<section className="maputnik-modal-section maputnik-modal-shortcuts">
<h1>Options</h1>
{this.props.renderer === 'mbgljs' &&
{this.props.renderer === 'mlgljs' &&
<ul>
{Object.entries(this.props.mapboxGlDebugOptions).map(([key, val]) => {
{Object.entries(this.props.maplibreGlDebugOptions).map(([key, val]) => {
return <li key={key}>
<label>
<input type="checkbox" checked={val} onClick={(e) => this.props.onChangeMaboxGlDebug(key, e.target.checked)} /> {key}
+5 -12
View File
@@ -14,7 +14,7 @@ import style from '../libs/style'
import fieldSpecAdditional from '../libs/field-spec-additional'
const MAPBOX_GL_VERSION = pkgLockJson.dependencies["mapbox-gl"].version;
const MAPLIBRE_GL_VERSION = pkgLockJson.dependencies["maplibre-gl"].version;
export default class ModalExport extends React.Component {
@@ -58,8 +58,8 @@ export default class ModalExport extends React.Component {
<meta charset="utf-8" />
<title>${htmlTitle}</title>
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
<script src="https://api.mapbox.com/mapbox-gl-js/v${MAPBOX_GL_VERSION}/mapbox-gl.js"></script>
<link href="https://api.mapbox.com/mapbox-gl-js/v${MAPBOX_GL_VERSION}/mapbox-gl.css" rel="stylesheet" />
<script src="https://unpkg.com/maplibre-gl@${MAPLIBRE_GL_VERSION}/dist/maplibre-gl.js"></script>
<link href="https://unpkg.com/maplibre-gl@${MAPLIBRE_GL_VERSION}/dist/maplibre-gl.css" rel="stylesheet" />
<style>
body { margin: 0; padding: 0; }
#map { position: absolute; top: 0; bottom: 0; width: 100%; }
@@ -68,12 +68,11 @@ export default class ModalExport extends React.Component {
<body>
<div id="map"></div>
<script>
mapboxgl.accessToken = 'access_token';
const map = new mapboxgl.Map({
const map = new maplibregl.Map({
container: 'map',
style: ${tokenStyle},
});
map.addControl(new mapboxgl.NavigationControl());
map.addControl(new maplibregl.NavigationControl());
</script>
</body>
</html>
@@ -119,12 +118,6 @@ export default class ModalExport extends React.Component {
</p>
<div>
<FieldString
label={fieldSpecAdditional.maputnik.mapbox_access_token.label}
fieldSpec={fieldSpecAdditional.maputnik.mapbox_access_token}
value={(this.props.mapStyle.metadata || {})['maputnik:mapbox_access_token']}
onChange={this.changeMetadataProperty.bind(this, "maputnik:mapbox_access_token")}
/>
<FieldString
label={fieldSpecAdditional.maputnik.maptiler_access_token.label}
fieldSpec={fieldSpecAdditional.maputnik.maptiler_access_token}
+2 -10
View File
@@ -117,14 +117,6 @@ export default class ModalSettings extends React.Component {
onChange={this.changeStyleProperty.bind(this, "glyphs")}
/>
<FieldString {...inputProps}
label={fieldSpecAdditional.maputnik.mapbox_access_token.label}
fieldSpec={fieldSpecAdditional.maputnik.mapbox_access_token}
data-wd-key="modal:settings.maputnik:mapbox_access_token"
value={metadata['maputnik:mapbox_access_token']}
onChange={onChangeMetadataProperty.bind(this, "maputnik:mapbox_access_token")}
/>
<FieldString {...inputProps}
label={fieldSpecAdditional.maputnik.maptiler_access_token.label}
fieldSpec={fieldSpecAdditional.maputnik.maptiler_access_token}
@@ -241,10 +233,10 @@ export default class ModalSettings extends React.Component {
fieldSpec={fieldSpecAdditional.maputnik.style_renderer}
data-wd-key="modal:settings.maputnik:renderer"
options={[
['mbgljs', 'MapboxGL JS'],
['mlgljs', 'MapLibreGL JS'],
['ol', 'Open Layers (experimental)'],
]}
value={metadata['maputnik:renderer'] || 'mbgljs'}
value={metadata['maputnik:renderer'] || 'mlgljs'}
onChange={onChangeMetadataProperty.bind(this, 'maputnik:renderer')}
/>
</div>
+1
View File
@@ -128,6 +128,7 @@ class AddSource extends React.Component {
}
case 'geojson_json': return {
type: 'geojson',
cluster: source.cluster || false,
data: {}
}
case 'tilejson_vector': return {
+26 -13
View File
@@ -8,6 +8,7 @@ import FieldSelect from './FieldSelect'
import FieldDynamicArray from './FieldDynamicArray'
import FieldArray from './FieldArray'
import FieldJson from './FieldJson'
import FieldCheckbox from './FieldCheckbox'
class TileJSONSourceEditor extends React.Component {
@@ -80,7 +81,7 @@ class TileURLSourceEditor extends React.Component {
})}
/>
{this.props.children}
</div>
</div>
}
}
@@ -205,23 +206,35 @@ class GeoJSONSourceFieldJsonEditor extends React.Component {
}
render() {
return <Block label={"GeoJSON"} fieldSpec={latest.source_geojson.data}>
<FieldJson
layer={this.props.source.data}
maxHeight={200}
mode={{
name: "javascript",
json: true
}}
lint={true}
onChange={data => {
return <div>
<Block label={"GeoJSON"} fieldSpec={latest.source_geojson.data}>
<FieldJson
layer={this.props.source.data}
maxHeight={200}
mode={{
name: "javascript",
json: true
}}
lint={true}
onChange={data => {
this.props.onChange({
...this.props.source,
data,
})
}}
/>
</Block>
<FieldCheckbox
label={'Cluster'}
value={this.props.source.cluster}
onChange={cluster => {
this.props.onChange({
...this.props.source,
data,
cluster: cluster,
})
}}
/>
</Block>
</div>
}
}
-1
View File
@@ -1,5 +1,4 @@
{
"mapbox": "pk.eyJ1IjoibW9yZ2Vua2FmZmVlIiwiYSI6ImNpeHJmNXNmZTAwNHIycXBid2NqdTJibjMifQ.Dv1-GDpTWi0NP6xW9Fct1w",
"openmaptiles": "KDhMfHvorAFkFe64wlZb",
"thunderforest": "b71f7f0ba4064f5eb9e903859a9cf5c6"
}
-4
View File
@@ -1,9 +1,5 @@
const spec = {
maputnik: {
mapbox_access_token: {
label: "Mapbox Access Token",
doc: "Public access token for Mapbox services."
},
maptiler_access_token: {
label: "MapTiler Access Token",
doc: "Public access token for MapTiler Cloud."
+1 -1
View File
@@ -32,7 +32,7 @@ export function changeProperty(layer, group, property, newValue) {
if(group) {
const newLayer = {
...layer,
// Change object so the diff works in ./src/components/map/MapboxGlMap.jsx
// Change object so the diff works in ./src/components/map/MaplibreGlMap.jsx
[group]: {
...layer[group]
}
+2 -2
View File
@@ -21,8 +21,8 @@ export default class LayerWatcher {
const previousSources = { ...this._sources }
Object.keys(map.style.sourceCaches).forEach(sourceId => {
//NOTE: This heavily depends on the internal API of Mapbox GL
//so this breaks between Mapbox GL JS releases
//NOTE: This heavily depends on the internal API of Maplibre GL
//so this breaks between Maplibre GL JS releases
this._sources[sourceId] = map.style.sourceCaches[sourceId]._source.vectorLayerIds
})
-1
View File
@@ -116,7 +116,6 @@ function stripAccessTokens(mapStyle) {
const changedMetadata = {
...mapStyle.metadata
};
delete changedMetadata['maputnik:mapbox_access_token'];
delete changedMetadata['maputnik:openmaptiles_access_token'];
return {
...mapStyle,
+1 -1
View File
@@ -2,7 +2,7 @@ export default class ZoomControl {
onAdd(map) {
this._map = map;
this._container = document.createElement('div');
this._container.className = 'mapboxgl-ctrl mapboxgl-ctrl-group mapboxgl-ctrl-zoom';
this._container.className = 'maplibregl-ctrl maplibregl-ctrl-group maplibregl-ctrl-zoom';
this._container.innerHTML = `
Zoom: <span></span>
`;
+21 -23
View File
@@ -1,93 +1,91 @@
/* TODO */
.mapboxgl-popup-anchor-top .mapboxgl-popup-tip {
.maplibregl-popup-anchor-top .maplibregl-popup-tip {
border-bottom-color: rgb(28, 31, 36);
}
.mapboxgl-popup-anchor-left .mapboxgl-popup-tip {
.maplibregl-popup-anchor-left .maplibregl-popup-tip {
border-right-color: rgb(28, 31, 36);
}
.mapboxgl-popup-anchor-right .mapboxgl-popup-tip {
.maplibregl-popup-anchor-right .maplibregl-popup-tip {
border-left-color: rgb(28, 31, 36);
}
.mapboxgl-popup-anchor-bottom .mapboxgl-popup-tip {
.maplibregl-popup-anchor-bottom .maplibregl-popup-tip {
border-top-color: rgb(28, 31, 36);
}
.mapboxgl-popup-anchor-top-left .mapboxgl-popup-tip {
.maplibregl-popup-anchor-top-left .maplibregl-popup-tip {
border-bottom-color: rgb(28, 31, 36);
}
.mapboxgl-popup-anchor-top-right .mapboxgl-popup-tip {
.maplibregl-popup-anchor-top-right .maplibregl-popup-tip {
border-bottom-color: rgb(28, 31, 36);
}
.mapboxgl-popup-anchor-bottom-left .mapboxgl-popup-tip {
.maplibregl-popup-anchor-bottom-left .maplibregl-popup-tip {
border-top-color: rgb(28, 31, 36);
}
.mapboxgl-popup-anchor-bottom-right .mapboxgl-popup-tip {
.maplibregl-popup-anchor-bottom-right .maplibregl-popup-tip {
border-top-color: rgb(28, 31, 36);
}
.mapboxgl-popup-content {
.maplibregl-popup-content {
background-color: rgb(28, 31, 36);
box-shadow: rgba(0, 0, 0, 0.298039) 0px 0px 5px 0px;
padding: 0px;
}
.mapboxgl-popup-close-button {
.maplibregl-popup-close-button {
color: white;
}
.mapboxgl-ctrl-zoom {
.maplibregl-ctrl-zoom {
color: #a4a4a4;
font-weight: bold;
padding: 4px 8px;
user-select: none;
}
.mapboxgl-ctrl-group {
.maplibregl-ctrl-group {
background: rgb(28, 31, 36);
}
.mapboxgl-ctrl-group > button {
.maplibregl-ctrl-group > button {
background-color: rgb(28, 31, 36);
border-color: rgb(28, 31, 36);
}
.mapboxgl-ctrl button:not(:disabled):hover {
.maplibregl-ctrl button:not(:disabled):hover {
background-color: rgb(86, 83, 83);
}
.mapboxgl-ctrl-zoom-in {
.maplibregl-ctrl-zoom-in {
border-radius: 4px 4px 0 0;
}
.mapboxgl-ctrl-compass {
.maplibregl-ctrl-compass {
border-radius: 0 0 4px 4px;
}
.mapboxgl-ctrl button.mapboxgl-ctrl-zoom-in .mapboxgl-ctrl-icon {
.maplibregl-ctrl button.maplibregl-ctrl-zoom-in .maplibregl-ctrl-icon {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0A%20%20%3Cpath%20style%3D%27fill%3A%23a4a4a4%3B%27%20d%3D%27M%2010%206%20C%209.446%206%209%206.4459904%209%207%20L%209%209%20L%207%209%20C%206.446%209%206%209.446%206%2010%20C%206%2010.554%206.446%2011%207%2011%20L%209%2011%20L%209%2013%20C%209%2013.55401%209.446%2014%2010%2014%20C%2010.554%2014%2011%2013.55401%2011%2013%20L%2011%2011%20L%2013%2011%20C%2013.554%2011%2014%2010.554%2014%2010%20C%2014%209.446%2013.554%209%2013%209%20L%2011%209%20L%2011%207%20C%2011%206.4459904%2010.554%206%2010%206%20z%27%20%2F%3E%0A%3C%2Fsvg%3E%0A")
}
.mapboxgl-ctrl button.mapboxgl-ctrl-zoom-out .mapboxgl-ctrl-icon {
.maplibregl-ctrl button.maplibregl-ctrl-zoom-out .maplibregl-ctrl-icon {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20viewBox%3D%270%200%2020%2020%27%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%3E%0A%20%20%3Cpath%20style%3D%27fill%3A%23a4a4a4%3B%27%20d%3D%27m%207%2C9%20c%20-0.554%2C0%20-1%2C0.446%20-1%2C1%200%2C0.554%200.446%2C1%201%2C1%20l%206%2C0%20c%200.554%2C0%201%2C-0.446%201%2C-1%200%2C-0.554%20-0.446%2C-1%20-1%2C-1%20z%27%20%2F%3E%0A%3C%2Fsvg%3E%0A")
}
.mapboxgl-ctrl button.mapboxgl-ctrl-compass .mapboxgl-ctrl-icon {
.maplibregl-ctrl button.maplibregl-ctrl-compass .maplibregl-ctrl-icon {
background-image: url("data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2020%2020%27%3E%0A%09%3Cpolygon%20fill%3D%27%23a4a4a4%27%20points%3D%276%2C9%2010%2C1%2014%2C9%27%2F%3E%0A%09%3Cpolygon%20fill%3D%27%23545454%27%20points%3D%276%2C11%2010%2C19%2014%2C11%20%27%2F%3E%0A%3C%2Fsvg%3E");
background-size: 18px;
}
.mapboxgl-ctrl-inspect {
.maplibregl-ctrl-inspect {
background-image: url('data:image/svg+xml;charset=utf8,<svg%20xmlns="http://www.w3.org/2000/svg"%20fill="#8e8e8e%22%20preserveAspectRatio=%22xMidYMid%20meet%22%20viewBox=%22-10%20-10%2060%2060%22%3E%3Cg%3E%3Cpath%20d=%22m15%2021.6q0-2%201.5-3.5t3.5-1.5%203.5%201.5%201.5%203.5-1.5%203.6-3.5%201.4-3.5-1.4-1.5-3.6z%20m18.4%2011.1l-6.4-6.5q1.4-2.1%201.4-4.6%200-3.4-2.5-5.8t-5.9-2.4-5.9%202.4-2.5%205.8%202.5%205.9%205.9%202.5q2.4%200%204.6-1.4l7.4%207.4q-0.9%200.6-2%200.6h-20q-1.3%200-2.3-0.9t-1.1-2.3l0.1-26.8q0-1.3%201-2.3t2.3-0.9h13.4l10%2010v19.3z%22%3E%3C/path%3E%3C/g%3E%3C/svg%3E');
}
.mapboxgl-ctrl-map {
.maplibregl-ctrl-map {
background-image: url('data:image/svg+xml;charset=utf8,<svg%20xmlns="http://www.w3.org/2000/svg"%20fill="#8e8e8e%22%20viewBox=%22-10%20-10%2060%2060%22%20preserveAspectRatio=%22xMidYMid%20meet%22%3E%3Cg%3E%3Cpath%20d=%22m25%2031.640000000000004v-19.766666666666673l-10-3.511666666666663v19.766666666666666z%20m9.140000000000008-26.640000000000004q0.8599999999999923%200%200.8599999999999923%200.8600000000000003v25.156666666666666q0%200.625-0.625%200.783333333333335l-9.375%203.1999999999999993-10-3.5133333333333354-8.906666666666668%203.4383333333333326-0.2333333333333334%200.07833333333333314q-0.8616666666666664%200-0.8616666666666664-0.8599999999999994v-25.156666666666663q0-0.625%200.6233333333333331-0.7833333333333332l9.378333333333334-3.198333333333334%2010%203.5133333333333336%208.905000000000001-3.4383333333333344z%22%3E%3C/path%3E%3C/g%3E%3C/svg%3E');
}
-7
View File
@@ -18,13 +18,6 @@
@import 'codemirror';
@import 'react-collapse';
/**
* Hacks for webdriverio isVisibleWithinViewport
*/
#app {
height: 100vh;
}
.maputnik-layout {
height: 100vh;
}
@@ -1,13 +1,13 @@
import React from 'react';
import MapMapboxGl from '../src/components/MapMapboxGl';
import MapMaplibreGl from '../src/components/MapMaplibreGl';
import {action} from '@storybook/addon-actions';
import {Wrapper} from './ui';
import {withA11y} from '@storybook/addon-a11y';
export default {
title: 'MapMapboxGl',
component: MapMapboxGl,
title: 'MapMaplibreGl',
component: MapMaplibreGl,
decorators: [withA11y],
};
@@ -98,7 +98,7 @@ const mapStyle = {
export const Basic = () => {
return <div style={{height: "100vh", width: "100vw"}}>
<MapMapboxGl
<MapMaplibreGl
mapStyle={mapStyle}
inspectModeEnabled={false}
replaceAccessTokens={(s) => s}
+2 -2
View File
@@ -16,8 +16,8 @@ export const Basic = () => (
<div style={{maxHeight: "200px"}}>
<ModalDebug
isOpen={true}
renderer="mbgljs"
mapboxGlDebugOptions={{}}
renderer="mlgljs"
maplibreGlDebugOptions={{}}
mapView={{zoom: 1, center: {lat: 0, lng: 0}}}
/>
</div>
-39
View File
@@ -1,39 +0,0 @@
var path = require("path");
var mkdirp = require("mkdirp");
function genPath(subPath) {
subPath = subPath || ".";
var buildPath;
if(process.env.CIRCLECI) {
buildPath = path.join("/tmp/artifacts", subPath);
}
else {
buildPath = path.join(__dirname, '..', 'build', subPath);
}
return buildPath;
}
module.exports.path = function(subPath) {
var dirPath = genPath(subPath);
return new Promise(function(resolve, reject) {
mkdirp(dirPath, function(err) {
if(err) {
reject(err);
}
else {
resolve(dirPath);
}
});
});
}
module.exports.pathSync = function(subPath) {
var dirPath = genPath(subPath);
mkdirp.sync(dirPath);
return dirPath;
}
-6
View File
@@ -1,6 +0,0 @@
var config = {};
config.testNetwork = process.env.TEST_NETWORK || "localhost";
config.port = 9001;
config.baseUrl = "http://"+config.testNetwork+":"+config.port;
module.exports = config;
-3
View File
@@ -1,3 +0,0 @@
describe("accessibility", function () {
require("./skip-links");
})
@@ -1,51 +0,0 @@
var assert = require("assert");
var config = require("../../config/specs");
var helper = require("../helper");
var wd = require("../../wd-helper");
describe("skip links", function() {
beforeEach(async function () {
await browser.url(config.baseUrl+"?debug&style="+helper.getGeoServerUrl("example-layer-style.json"));
await browser.acceptAlert();
});
it("skip link to layer list", async function() {
const selector = wd.$("root:skip:layer-list")
const elem = await $(selector);
assert(await elem.isExisting());
await browser.keys(['Tab']);
assert(await elem.isFocused());
await elem.click();
const targetEl = await $("#skip-target-layer-list");
assert(await targetEl.isFocused());
});
it("skip link to layer editor", async function() {
const selector = wd.$("root:skip:layer-editor")
const elem = await $(selector);
assert(await elem.isExisting());
await browser.keys(['Tab']);
await browser.keys(['Tab']);
assert(await elem.isFocused());
await elem.click();
const targetEl = await $("#skip-target-layer-editor");
assert(await targetEl.isFocused());
});
it("skip link to map view", async function() {
const selector = wd.$("root:skip:map-view")
const elem = await $(selector);
assert(await elem.isExisting());
await browser.keys(['Tab']);
await browser.keys(['Tab']);
await browser.keys(['Tab']);
assert(await elem.isFocused());
await elem.click();
const targetEl = await $(".mapboxgl-canvas");
assert(await targetEl.isFocused());
});
});
-86
View File
@@ -1,86 +0,0 @@
var wd = require("../wd-helper");
var {v1: uuid} = require('uuid');
var geoServer = require("../geojson-server");
var testNetwork = process.env.TEST_NETWORK || "localhost";
var geoserver;
module.exports = {
startGeoserver: function(done) {
geoserver = geoServer.listen(9002, "0.0.0.0", done);
},
stopGeoserver: function(done) {
geoserver.close(done);
geoserver = undefined;
},
getStyleUrl: function(styles) {
var port = geoserver.address().port;
return "http://"+testNetwork+":"+port+"/styles/empty/"+styles.join(",");
},
getGeoServerUrl: function(urlPath) {
var port = geoserver.address().port;
return "http://"+testNetwork+":"+port+"/"+urlPath;
},
getStyleStore: async function(browser) {
return await browser.executeAsync(function(done) {
window.debug.get("maputnik", "styleStore").latestStyle(done);
});
},
getRevisionStore: async function(browser) {
var result = await browser.execute(function() {
var rs = window.debug.get("maputnik", "revisionStore")
return {
currentIdx: rs.currentIdx,
revisions: rs.revisions
};
})
return result.value;
},
modal: {
addLayer: {
open: async function() {
const selector = await $(wd.$('layer-list:add-layer'));
await selector.click();
// Wait for events
await browser.flushReactUpdates();
const elem = await $(wd.$('modal:add-layer'));
await elem.waitForExist();
await elem.isDisplayed();
await elem.isDisplayedInViewport();
// Wait for events
await browser.flushReactUpdates();
},
fill: async function(opts) {
var type = opts.type;
var layer = opts.layer;
var id;
if(opts.id) {
id = opts.id
}
else {
id = type+":"+uuid();
}
const selectBox = await $(wd.$("add-layer.layer-type", "select"));
await selectBox.selectByAttribute('value', type);
await browser.flushReactUpdates();
await browser.setValueSafe(wd.$("add-layer.layer-id", "input"), id);
if(layer) {
await browser.setValueSafe(wd.$("add-layer.layer-source-block", "input"), layer);
}
await browser.flushReactUpdates();
const elem_addLayer = await $(wd.$("add-layer"));
await elem_addLayer.click();
return id;
}
}
}
}
-112
View File
@@ -1,112 +0,0 @@
var assert = require("assert");
var config = require("../../config/specs");
var helper = require("../helper");
describe("history", function() {
let undoKeyCombo;
let undoKeyComboReset;
let redoKeyCombo;
let redoKeyComboReset;
before(async function() {
const isMac = await browser.execute(function() {
return navigator.platform.toUpperCase().indexOf('MAC') >= 0;
});
undoKeyCombo = ['Meta', 'z'];
undoKeyComboReset = ['Meta'];
redoKeyCombo = isMac ? ['Meta', 'Shift', 'z'] : ['Meta', 'y'];
redoKeyComboReset = isMac ? ['Meta', 'Shift'] : ['Meta'];
});
/**
* See <https://github.com/webdriverio/webdriverio/issues/1126>
*/
it.skip("undo/redo", async function() {
var styleObj;
await browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([
"geojson:example"
]));
await browser.acceptAlert();
await helper.modal.addLayer.open();
styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, []);
await helper.modal.addLayer.fill({
id: "step 1",
type: "background"
})
styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": "step 1",
"type": 'background'
}
]);
await helper.modal.addLayer.open();
await helper.modal.addLayer.fill({
id: "step 2",
type: "background"
})
styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": "step 1",
"type": 'background'
},
{
"id": "step 2",
"type": 'background'
}
]);
await browser.keys(undoKeyCombo)
await browser.keys(undoKeyComboReset);
styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": "step 1",
"type": 'background'
}
]);
await browser.keys(undoKeyCombo)
await browser.keys(undoKeyComboReset);
styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
]);
await browser.keys(redoKeyCombo)
await browser.keys(redoKeyComboReset);
styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": "step 1",
"type": 'background'
}
]);
await browser.keys(redoKeyCombo)
await browser.keys(redoKeyComboReset);
styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": "step 1",
"type": 'background'
},
{
"id": "step 2",
"type": 'background'
}
]);
});
})
-46
View File
@@ -1,46 +0,0 @@
var config = require("../config/specs");
var helper = require("./helper");
var extendWebdriverIO = require("./util/webdriverio-ext");
describe('maputnik', function() {
before(async function(done) {
await extendWebdriverIO();
helper.startGeoserver(done);
});
after(function(done) {
helper.stopGeoserver(done);
});
beforeEach(async function() {
await browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([
"geojson:example",
"raster:raster"
]));
await browser.acceptAlert();
await browser.execute(function() {
localStorage.setItem("survey", true);
});
const elem = await $(".maputnik-toolbar-link");
await elem.waitForExist();
await browser.flushReactUpdates();
});
// -------- setup --------
require("./util/coverage");
// -----------------------
// ---- All the tests ----
require("./history");
require("./layers");
require("./map");
require("./modals");
require("./screenshots");
require("./accessibility");
require("./keyboard");
// ------------------------
});
-56
View File
@@ -1,56 +0,0 @@
var assert = require("assert");
var wd = require("../../wd-helper");
describe("keyboard", function() {
describe("shortcuts", function() {
it("ESC should unfocus", async function() {
const tmpTargetEl = await $(wd.$("nav:inspect") + " select");
await tmpTargetEl.click();
assert(await tmpTargetEl.isFocused());
await browser.keys(["Escape"]);
assert(await (await $("body")).isFocused());
});
it("'?' should show shortcuts modal", async function() {
await browser.keys(["?"]);
assert(await (await $(wd.$("modal:shortcuts"))).isDisplayed());
});
it("'o' should show open modal", async function() {
await browser.keys(["o"]);
assert(await (await $(wd.$("modal:open"))).isDisplayed());
});
it("'e' should show export modal", async function() {
await browser.keys(["e"]);
assert(await (await $(wd.$("modal:export"))).isDisplayed());
});
it("'d' should show sources modal", async function() {
await browser.keys(["d"]);
assert(await (await $(wd.$("modal:sources"))).isDisplayed());
});
it("'s' should show settings modal", async function() {
await browser.keys(["s"]);
assert(await (await $(wd.$("modal:settings"))).isDisplayed());
});
it.skip("'i' should change map to inspect mode", async function() {
// await browser.keys(["i"]);
});
it("'m' should focus map", async function() {
await browser.keys(["m"]);
assert(await (await $(".mapboxgl-canvas")).isFocused());
});
it("'!' should show debug modal", async function() {
await browser.keys(["!"]);
assert(await (await $(wd.$("modal:debug"))).isDisplayed());
});
});
});
-488
View File
@@ -1,488 +0,0 @@
var assert = require("assert");
var config = require("../../config/specs");
var helper = require("../helper");
var {v1: uuid} = require('uuid');
var wd = require("../../wd-helper");
describe("layers", function() {
beforeEach(async function() {
await browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([
"geojson:example",
"raster:raster"
]));
await browser.acceptAlert();
const elem = await $(".maputnik-toolbar-link");
await elem.waitForExist();
await browser.flushReactUpdates();
await helper.modal.addLayer.open();
});
describe("ops", function() {
it("delete", async function() {
var styleObj;
var id = await helper.modal.addLayer.fill({
type: "background"
})
styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": id,
"type": 'background'
},
]);
const elem = await $(wd.$("layer-list-item:"+id+":delete", ""));
await elem.click();
styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
]);
});
it("duplicate", async function() {
var styleObj;
var id = await helper.modal.addLayer.fill({
type: "background"
})
styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": id,
"type": 'background'
},
]);
const elem = await $(wd.$("layer-list-item:"+id+":copy", ""));
await elem.click();
styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": id+"-copy",
"type": "background"
},
{
"id": id,
"type": "background"
},
]);
});
it("hide", async function() {
var styleObj;
var id = await helper.modal.addLayer.fill({
type: "background"
})
styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": id,
"type": 'background'
},
]);
const elem = await $(wd.$("layer-list-item:"+id+":toggle-visibility", ""));
await elem.click();
styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": id,
"type": "background",
"layout": {
"visibility": "none"
}
},
]);
await elem.click();
styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": id,
"type": "background",
"layout": {
"visibility": "visible"
}
},
]);
})
})
describe("tooltips", function() {
})
describe("help", function() {
})
describe('background', function () {
it("add", async function() {
var id = await helper.modal.addLayer.fill({
type: "background"
})
var styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": id,
"type": 'background'
}
]);
});
describe("modify", function() {
async function createBackground() {
// Setup
var id = uuid();
const selectBox = await $(wd.$("add-layer.layer-type", "select"));
await selectBox.selectByAttribute('value', "background");
await browser.flushReactUpdates();
await browser.setValueSafe(wd.$("add-layer.layer-id", "input"), "background:"+id);
const elem = await $(wd.$("add-layer"));
await elem.click();
var styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": 'background:'+id,
"type": 'background'
}
]);
return id;
}
// ====> THESE SHOULD BE FROM THE SPEC
describe("layer", function() {
it("expand/collapse");
it("id", async function() {
var bgId = await createBackground();
const elem = await $(wd.$("layer-list-item:background:"+bgId));
await elem.click();
var id = uuid();
await browser.setValueSafe(wd.$("layer-editor.layer-id", "input"), "foobar:"+id)
const elem2 = await $(wd.$("min-zoom"));
await elem2.click();
var styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": 'foobar:'+id,
"type": 'background'
}
]);
});
it("min-zoom", async function() {
var bgId = await createBackground();
const elem = await $(wd.$("layer-list-item:background:"+bgId));
await elem.click();
await browser.setValueSafe(wd.$("min-zoom", 'input[type="text"]'), 1)
const elem2 = await $(wd.$("layer-editor.layer-id", "input"));
await elem2.click();
var styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": 'background:'+bgId,
"type": 'background',
"minzoom": 1
}
]);
// AND RESET!
// await browser.setValueSafe(wd.$("min-zoom", "input"), "")
// await browser.click(wd.$("max-zoom", "input"));
// var styleObj = await helper.getStyleStore(browser);
// assert.deepEqual(styleObj.layers, [
// {
// "id": 'background:'+bgId,
// "type": 'background'
// }
// ]);
});
it("max-zoom", async function() {
var bgId = await createBackground();
const elem = await $(wd.$("layer-list-item:background:"+bgId));
await elem.click();
await browser.setValueSafe(wd.$("max-zoom", 'input[type="text"]'), 1)
const elem2 = await $(wd.$("layer-editor.layer-id", "input"));
await elem2.click();
var styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": 'background:'+bgId,
"type": 'background',
"maxzoom": 1
}
]);
});
it("comments", async function() {
var bgId = await createBackground();
var id = uuid();
const elem = await $(wd.$("layer-list-item:background:"+bgId));
await elem.click();
await browser.setValueSafe(wd.$("layer-comment", "textarea"), id);
const elem2 = await $(wd.$("layer-editor.layer-id", "input"));
await elem2.click();
var styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": 'background:'+bgId,
"type": 'background',
metadata: {
'maputnik:comment': id
}
}
]);
// Unset it again.
// TODO: This fails
// await browser.setValueSafe(wd.$("layer-comment", "textarea"), "");
// await browser.click(wd.$("min-zoom", "input"));
// await browser.flushReactUpdates();
// var styleObj = await helper.getStyleStore(browser);
// assert.deepEqual(styleObj.layers, [
// {
// "id": 'background:'+bgId,
// "type": 'background'
// }
// ]);
});
it("color", null, async function() {
var bgId = await createBackground();
await browser.click(wd.$("layer-list-item:background:"+bgId));
await browser.click(wd.$("spec-field:background-color", "input"))
// await browser.debug();
var styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": 'background:'+bgId,
"type": 'background'
}
]);
})
})
describe("filter", function() {
it("expand/collapse");
it("compound filter");
})
describe("paint", function() {
it("expand/collapse");
it("color");
it("pattern");
it("opacity");
})
// <=====
describe("json-editor", function() {
it("expand/collapse");
it("modify");
// TODO
it.skip("parse error", async function() {
var bgId = await createBackground();
await browser.click(wd.$("layer-list-item:background:"+bgId));
var errorSelector = ".CodeMirror-lint-marker-error";
assert.equal(await browser.isExisting(errorSelector), false);
await browser.click(".CodeMirror")
await browser.keys("\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013\uE013 {");
await browser.waitForExist(errorSelector)
await browser.click(wd.$("layer-editor.layer-id"));
});
});
})
});
describe('fill', function () {
it("add", async function() {
// await browser.debug();
var id = await helper.modal.addLayer.fill({
type: "fill",
layer: "example"
});
var styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": id,
"type": 'fill',
"source": "example"
}
]);
})
// TODO: Change source
it("change source")
});
describe('line', function () {
it("add", async function() {
var id = await helper.modal.addLayer.fill({
type: "line",
layer: "example"
});
var styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": id,
"type": "line",
"source": "example",
}
]);
});
it("groups", null, function() {
// TODO
// Click each of the layer groups.
})
});
describe('symbol', function () {
it("add", async function() {
var id = await helper.modal.addLayer.fill({
type: "symbol",
layer: "example"
});
var styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": id,
"type": "symbol",
"source": "example",
}
]);
});
});
describe('raster', function () {
it("add", async function() {
var id = await helper.modal.addLayer.fill({
type: "raster",
layer: "raster"
});
var styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": id,
"type": "raster",
"source": "raster",
}
]);
});
});
describe('circle', function () {
it("add", async function() {
var id = await helper.modal.addLayer.fill({
type: "circle",
layer: "example"
});
var styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": id,
"type": "circle",
"source": "example",
}
]);
});
});
describe('fill extrusion', function () {
it("add", async function() {
var id = await helper.modal.addLayer.fill({
type: "fill-extrusion",
layer: "example"
});
var styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleObj.layers, [
{
"id": id,
"type": 'fill-extrusion',
"source": "example"
}
]);
});
});
describe("groups", function() {
it("simple", async function() {
await browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([
"geojson:example"
]));
await browser.acceptAlert();
await helper.modal.addLayer.open();
await helper.modal.addLayer.fill({
id: "foo",
type: "background"
})
await helper.modal.addLayer.open();
await helper.modal.addLayer.fill({
id: "foo_bar",
type: "background"
})
await helper.modal.addLayer.open();
await helper.modal.addLayer.fill({
id: "foo_bar_baz",
type: "background"
})
const groupEl = await $(wd.$("layer-list-group:foo-0"));
await groupEl.isDisplayed();
assert.equal(await (await $(wd.$("layer-list-item:foo"))).isDisplayedInViewport(), true);
assert.equal(await (await $(wd.$("layer-list-item:foo_bar"))).isDisplayedInViewport(), false);
assert.equal(await (await $(wd.$("layer-list-item:foo_bar_baz"))).isDisplayedInViewport(), false);
await groupEl.click();
assert.equal(await (await $(wd.$("layer-list-item:foo"))).isDisplayedInViewport(), true);
assert.equal(await (await $(wd.$("layer-list-item:foo_bar"))).isDisplayedInViewport(), true);
assert.equal(await (await $(wd.$("layer-list-item:foo_bar_baz"))).isDisplayedInViewport(), true);
})
})
});
-35
View File
@@ -1,35 +0,0 @@
var config = require("../../config/specs");
var helper = require("../helper");
describe("map", function() {
describe.skip("zoom level", function() {
it("via url", async function() {
var zoomLevel = "12.37"
await browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([
"geojson:example"
])+"#"+zoomLevel+"/41.3805/2.1635");
await browser.alertAccept();
await browser.waitUntil(async function () {
return (
await browser.isVisible(".mapboxgl-ctrl-zoom")
&& await browser.getText(".mapboxgl-ctrl-zoom") === "Zoom level: "+(zoomLevel)
);
}, 10*1000)
})
it("via map controls", async function() {
var zoomLevel = 12.37;
await browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([
"geojson:example"
])+"#"+zoomLevel+"/41.3805/2.1635");
await browser.alertAccept();
await browser.click(".mapboxgl-ctrl-zoom-in")
await browser.waitUntil(async function () {
var text = await browser.getText(".mapboxgl-ctrl-zoom")
return text === "Zoom level: "+(zoomLevel+1);
}, 10*1000)
})
})
})
-237
View File
@@ -1,237 +0,0 @@
var assert = require('assert');
var fs = require("fs");
var wd = require("../../wd-helper");
var config = require("../../config/specs");
var helper = require("../helper");
async function closeModal(wdKey) {
const selector = wd.$(wdKey);
await browser.waitUntil(async function() {
const elem = await $(selector);
return await elem.isDisplayedInViewport();
});
const closeBtnSelector = await $(wd.$(wdKey+".close-modal"));
await closeBtnSelector.click();
await browser.waitUntil(async function() {
return await browser.execute((selector) => {
return !document.querySelector(selector);
}, selector);
});
}
describe("modals", function() {
describe("open", function() {
var styleFilePath = __dirname+"/../../example-style.json";
var styleFileData = JSON.parse(fs.readFileSync(styleFilePath));
beforeEach(async function() {
await browser.url(config.baseUrl+"?debug");
const elem = await $(".maputnik-toolbar-link");
await elem.waitForExist();
await browser.flushReactUpdates();
const elem2 = await $(wd.$("nav:open"));
await elem2.click();
await browser.flushReactUpdates();
});
it("close", async function() {
await closeModal("modal:open");
});
// "chooseFile" command currently not available for wdio v5 https://github.com/webdriverio/webdriverio/pull/3632
it.skip("upload", async function() {
const elem = await $("*[type='file']");
await elem.waitForExist();
await browser.chooseFile("*[type='file']", styleFilePath);
var styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleFileData, styleObj);
});
it("load from url", async function() {
var styleFileUrl = helper.getGeoServerUrl("example-style.json");
await browser.setValueSafe(wd.$("modal:open.url.input"), styleFileUrl);
const selector = await $(wd.$("modal:open.url.button"));
await selector.click();
// Allow the network request to happen
// NOTE: Its localhost so this should be fast.
await browser.pause(300);
var styleObj = await helper.getStyleStore(browser);
assert.deepEqual(styleFileData, styleObj);
});
// TODO: Need to work out how to mock out the end points
it("gallery")
})
describe("shortcuts", function() {
it("open/close", async function() {
await browser.url(config.baseUrl+"?debug");
const elem = await $(".maputnik-toolbar-link");
await elem.waitForExist();
await browser.flushReactUpdates();
await browser.keys(["?"]);
const modalEl = await $(wd.$("modal:shortcuts"))
assert(await modalEl.isDisplayed());
await closeModal("modal:shortcuts");
});
});
describe("export", function() {
beforeEach(async function() {
await browser.url(config.baseUrl+"?debug");
const elem = await $(".maputnik-toolbar-link");
await elem.waitForExist();
await browser.flushReactUpdates();
const elem2 = await $(wd.$("nav:export"));
await elem2.click();
await browser.flushReactUpdates();
});
it("close", async function() {
await closeModal("modal:export");
});
// TODO: Work out how to download a file and check the contents
it("download")
})
describe("sources", function() {
it("active sources")
it("public source")
it("add new source")
})
describe("inspect", function() {
it("toggle", async function() {
await browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([
"geojson:example"
]));
await browser.acceptAlert();
const selectBox = await $(wd.$("nav:inspect", "select"));
await selectBox.selectByAttribute('value', "inspect");
})
})
describe("style settings", function() {
beforeEach(async function() {
await browser.url(config.baseUrl+"?debug");
const elem = await $(".maputnik-toolbar-link");
await elem.waitForExist();
await browser.flushReactUpdates();
const elem2 = await $(wd.$("nav:settings"));
await elem2.click();
await browser.flushReactUpdates();
});
it("name", async function() {
await browser.setValueSafe(wd.$("modal:settings.name"), "foobar")
const elem = await $(wd.$("modal:settings.owner"));
await elem.click();
await browser.flushReactUpdates();
var styleObj = await helper.getStyleStore(browser);
assert.equal(styleObj.name, "foobar");
})
it("owner", async function() {
await browser.setValueSafe(wd.$("modal:settings.owner"), "foobar")
const elem = await $(wd.$("modal:settings.name"));
await elem.click();
await browser.flushReactUpdates();
var styleObj = await helper.getStyleStore(browser);
assert.equal(styleObj.owner, "foobar");
})
it("sprite url", async function() {
await browser.setValueSafe(wd.$("modal:settings.sprite"), "http://example.com")
const elem = await $(wd.$("modal:settings.name"));
await elem.click();
await browser.flushReactUpdates();
var styleObj = await helper.getStyleStore(browser);
assert.equal(styleObj.sprite, "http://example.com");
})
it("glyphs url", async function() {
var glyphsUrl = "http://example.com/{fontstack}/{range}.pbf"
await browser.setValueSafe(wd.$("modal:settings.glyphs"), glyphsUrl)
const elem = await $(wd.$("modal:settings.name"));
await elem.click();
await browser.flushReactUpdates();
var styleObj = await helper.getStyleStore(browser);
assert.equal(styleObj.glyphs, glyphsUrl);
})
it("mapbox access token", async function() {
var apiKey = "testing123";
await browser.setValueSafe(wd.$("modal:settings.maputnik:mapbox_access_token"), apiKey);
const elem = await $(wd.$("modal:settings.name"));
await elem.click();
await browser.flushReactUpdates();
var styleObj = await helper.getStyleStore(browser);
await browser.waitUntil(function() {
return styleObj.metadata["maputnik:mapbox_access_token"] == apiKey;
})
})
it("maptiler access token", async function() {
var apiKey = "testing123";
await browser.setValueSafe(wd.$("modal:settings.maputnik:openmaptiles_access_token"), apiKey);
const elem = await $(wd.$("modal:settings.name"));
await elem.click();
await browser.flushReactUpdates();
var styleObj = await helper.getStyleStore(browser);
assert.equal(styleObj.metadata["maputnik:openmaptiles_access_token"], apiKey);
})
it("thunderforest access token", async function() {
var apiKey = "testing123";
await browser.setValueSafe(wd.$("modal:settings.maputnik:thunderforest_access_token"), apiKey);
const elem = await $(wd.$("modal:settings.name"));
await elem.click();
await browser.flushReactUpdates();
var styleObj = await helper.getStyleStore(browser);
assert.equal(styleObj.metadata["maputnik:thunderforest_access_token"], apiKey);
})
it("style renderer", async function() {
const selector = await $(wd.$("modal:settings.maputnik:renderer"));
await selector.selectByAttribute('value', "ol");
const elem = await $(wd.$("modal:settings.name"));
await elem.click();
await browser.flushReactUpdates();
var styleObj = await helper.getStyleStore(browser);
assert.equal(styleObj.metadata["maputnik:renderer"], "ol");
})
})
describe("sources", function() {
it("toggle")
})
})
-111
View File
@@ -1,111 +0,0 @@
var config = require("../../config/specs");
var helper = require("../helper");
var wd = require("../../wd-helper");
// These will get used in the marketing material. They are also useful to do a quick manual check of the styling across browsers
// NOTE: These duplicate some of the tests, however this is indended becuase it's likely these will change for aesthetic reasons over time
describe('screenshots', function() {
beforeEach(async function() {
await browser.setWindowSize(1280, 800)
})
it("front_page", async function() {
await browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([
"geojson:example"
]));
await browser.acceptAlert();
const elem = await $(".maputnik-toolbar-link");
await elem.waitForExist();
await browser.flushReactUpdates();
await browser.takeScreenShot("/front_page.png")
})
it("open", async function() {
await browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([
"geojson:example"
]));
await browser.acceptAlert();
const elem = await $(".maputnik-toolbar-link");
await elem.waitForExist();
await browser.flushReactUpdates();
const nav_open = await $(wd.$("nav:open"));
await nav_open.click();
await nav_open.waitForExist();
await browser.flushReactUpdates();
await browser.takeScreenShot("/open.png")
})
it("export", async function() {
await browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([
"geojson:example"
]));
await browser.acceptAlert();
const elem = await $(".maputnik-toolbar-link")
await elem.waitForExist()
await browser.flushReactUpdates();
const nav_export = await $(wd.$("nav:export"));
await nav_export.click();
await nav_export.waitForExist();
await browser.flushReactUpdates();
await browser.takeScreenShot("/export.png")
})
it("sources", async function() {
await browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([
"geojson:example"
]));
await browser.acceptAlert();
const elem = await $(".maputnik-toolbar-link")
await elem.waitForExist()
await browser.flushReactUpdates();
const nav_sources = await $(wd.$("nav:sources"));
await nav_sources.click();
await nav_sources.waitForExist();
await browser.flushReactUpdates();
await browser.takeScreenShot("/sources.png")
})
it("style settings", async function() {
await browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([
"geojson:example"
]));
await browser.acceptAlert();
const elem = await $(".maputnik-toolbar-link")
await elem.waitForExist()
await browser.flushReactUpdates();
const nav_settings = await $(wd.$("nav:settings"));
await nav_settings.click();
await nav_settings.waitForExist();
await browser.flushReactUpdates();
await browser.takeScreenShot("/settings.png")
})
it("inspect", async function() {
await browser.url(config.baseUrl+"?debug&style="+helper.getStyleUrl([
"geojson:example"
]));
await browser.acceptAlert();
const elem = await $(".maputnik-toolbar-link")
await elem.waitForExist()
await browser.flushReactUpdates();
const selectBox = await $(wd.$("nav:inspect", "select"));
await selectBox.selectByAttribute('value', 'inspect');
await browser.flushReactUpdates();
await browser.takeScreenShot("/inspect.png")
})
})
-56
View File
@@ -1,56 +0,0 @@
var artifacts = require("../../artifacts");
var fs = require("fs");
var istanbulCov = require('istanbul-lib-coverage');
var COVERAGE_PATH = artifacts.pathSync("/coverage");
var coverage = istanbulCov.createCoverageMap({});
// Capture the coverage after each test
afterEach(async function() {
// Code coverage
var results = await browser.execute(function() {
return window.__coverage__;
});
if (results) {
coverage.merge(results);
}
})
// Dump the coverage to a file
after(function() {
// Sometimes istanbul copies same location entry with null values
// crashing the final coverage step. This is just a workaround for now,
// since istanbul will be replaced by nyc.
const coverageJson = JSON.stringify(coverage, null, 2);
let newCoverage = JSON.parse(coverageJson);
Object.values(newCoverage).forEach(fileCov => {
if (fileCov.branchMap) {
Object.values(fileCov.branchMap).forEach(branchMapEntry => {
let prevLocation = {};
branchMapEntry.locations.forEach(curLocation => {
if (curLocation.start && curLocation.end &&
curLocation.start.column && curLocation.start.line &&
curLocation.end.column && curLocation.end.line)
{
prevLocation = curLocation;
}
else
{
curLocation.start.column = prevLocation.start.column;
curLocation.start.line = prevLocation.start.line;
curLocation.end.column = prevLocation.end.column;
curLocation.end.line = prevLocation.end.line;
}
})
})
}
})
const newCoverageJson = JSON.stringify(newCoverage, null, 2);
fs.writeFileSync(COVERAGE_PATH+"/coverage.json", newCoverageJson);
})
-63
View File
@@ -1,63 +0,0 @@
var artifacts = require("../../artifacts");
var path = require("path");
const extendWebdriverIO = async function() {
await browser.setTimeout({ 'script': 20 * 1000 });
await browser.setTimeout({ 'implicit': 20 * 1000 });
var SCREENSHOTS_PATH = artifacts.pathSync("/screenshots");
/**
* Sometimes chrome driver can result in the wrong text.
*
* See <https://github.com/webdriverio/webdriverio/issues/1886>
*/
try {
await browser.addCommand('setValueSafe', async function (selector, text) {
for (var i = 0; i < 10; i++) {
const elem = await $(selector);
await elem.waitForDisplayed(500);
var elements = await browser.findElements("css selector", selector);
if (elements.length > 1) {
throw "Too many elements found";
}
const elem2 = await $(selector);
await elem2.setValue(text);
var browserText = await elem2.getValue();
if (browserText == text) {
return;
}
else {
console.error("Warning: setValue failed, trying again");
}
}
// Wait for change events to fire and state updated
await browser.flushReactUpdates();
})
await browser.addCommand('takeScreenShot', async function (filepath) {
var savepath = path.join(SCREENSHOTS_PATH, filepath);
await browser.saveScreenshot(savepath);
});
await browser.addCommand('flushReactUpdates', async function () {
await browser.executeAsync(function (done) {
// For any events to propagate
setTimeout(function () {
// For the DOM to be updated.
setTimeout(done, 0);
}, 0)
})
})
} catch (err) {
console.error(">>> Ignored error: " + err);
}
}
module.exports = extendWebdriverIO;
-98
View File
@@ -1,98 +0,0 @@
const cors = require("cors");
const express = require("express");
const fs = require("fs");
const sourceData = require("./sources");
var app = express();
app.use(cors());
function buildStyle(opts) {
opts = opts || {};
opts = Object.assign({
sources: {}
}, opts);
return {
"id": "test-style",
"version": 8,
"name": "Test Style",
"metadata": {
"maputnik:renderer": "mbgljs"
},
"sources": opts.sources,
"glyphs": "https://example.local/fonts/{fontstack}/{range}.pbf",
"sprites": "https://example.local/fonts/{fontstack}/{range}.pbf",
"layers": []
}
}
function buildGeoJSONSource(data) {
return {
type: "vector",
data: data
};
}
function buildResterSource(req, key) {
return {
"tileSize": 256,
"tiles": [
req.protocol + '://' + req.get('host') + "/" + key + "/{x}/{y}/{z}"
],
"type": "raster"
};
}
app.get("/sources/raster/{x}/{y}/{z}", function(req, res) {
res.status(404).end();
})
app.get("/styles/empty/:sources", function(req, res) {
var reqSources = req.params.sources.split(",");
var sources = {};
reqSources.forEach(function(key) {
var parts = key.split(":");
var type = parts[0];
var key = parts[1];
if(type === "geojson") {
sources[key] = buildGeoJSONSource(sourceData[key]);
}
else if(type === "raster") {
sources[key] = buildResterSource(req, key);
}
else {
console.error("ERR: Invalid type: %s", type);
throw "Invalid type"
}
});
var json = buildStyle({
sources: sources
});
res.send(json);
})
app.get("/example-layer-style.json", function(req, res) {
res.json(
JSON.parse(
fs.readFileSync(__dirname+"/example-layer-style.json").toString()
)
);
})
app.get("/example-style.json", function(req, res) {
res.json(
JSON.parse(
fs.readFileSync(__dirname+"/example-style.json").toString()
)
);
})
module.exports = app;
-15
View File
@@ -1,15 +0,0 @@
{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"properties": {
"name": "Dinagat Islands"
},
"geometry":{
"type": "Point",
"coordinates": [125.6, 10.1]
}
}
]
}
-3
View File
@@ -1,3 +0,0 @@
module.exports = {
example: require("./example")
};
-6
View File
@@ -1,6 +0,0 @@
module.exports = {
"$": function(key, selector) {
selector = selector || "";
return "*[data-wd-key='"+key+"'] "+selector;
}
}
+103
View File
@@ -0,0 +1,103 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig to read more about this file */
/* Projects */
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
/* Modules */
"module": "commonjs", /* Specify what module code is generated. */
// "rootDir": "./", /* Specify the root folder within your source files. */
// "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
"resolveJsonModule": true, /* Enable importing .json files. */
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
/* Emit */
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
// "outDir": "./", /* Specify an output folder for all emitted files. */
// "removeComments": true, /* Disable emitting comments. */
"noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
/* Type Checking */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
}
}