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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 10 additions & 20 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,19 @@
name: Run tests
on: [push]
env:
NODE_VERSION: 20.x
on: [push, pull_request]
jobs:
tests:
runs-on: ubuntu-latest

permissions:
id-token: write
contents: read

steps:
- name: checkout commit
uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: true

- name: Use Node.js 20.x
uses: actions/setup-node@v4
- uses: actions/setup-node@v6
with:
node-version: ${{ env.NODE_VERSION }}
node-version: 24
cache: npm

- name: install node deps
run: npm ci

- name: run tests
run: npm test
- run: npm ci
- run: npm run lint
- run: npm test
- run: npm run build
- name: Check fixtures/ is up to date
run: git diff --exit-code fixtures/
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
20
24
135 changes: 0 additions & 135 deletions CHANGELOG.md

This file was deleted.

87 changes: 30 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

[![Run tests](https://github.com/mapbox/mvt-fixtures/actions/workflows/test.yml/badge.svg)](https://github.com/mapbox/mvt-fixtures/actions/workflows/test.yml)

A `require()`able suite of valid and invalid vector tile fixtures for testing [Mapbox Vector Tile](https://github.com/mapbox/vector-tile-spec) encoders and decoders. You can view a list of all fixtures at [FIXTURES.md](FIXTURES.md).
An ESM suite of valid and invalid vector tile fixtures for testing [Mapbox Vector Tile](https://github.com/mapbox/vector-tile-spec) encoders and decoders. You can view a list of all fixtures at [FIXTURES.md](FIXTURES.md).

# Usage

mvt-fixtures can be used in two distinct ways

1. **javascript interface**: use the javascript interface to generate fixtures on the fly
1. **raw fixtures** use the raw fixtures directly via the /fixtures directory.
1. **JavaScript interface**: use the ESM API to generate fixtures on the fly
1. **raw fixtures**: use the pre-built files in the `/fixtures` directory

The Javascript API is recommended if you are working in Javascript or Node.js. The raw fixtures are provided for those using this outside of a Javascript application. The recommended workflow is to have your encoder or decoder loop through every fixture and either expect to successfully decode/encode valid fixtures, or fail to decode/encode invalid fixtures. When new fixtures are added to this repository, you simply need to update the version of the module (or your submodule) to get the new fixtures and re-run tests.
The JavaScript API is recommended if you are working in JavaScript or Node.js. The raw fixtures are provided for those using this outside of a JavaScript application. The recommended workflow is to have your encoder or decoder loop through every fixture and either expect to successfully decode/encode valid fixtures, or fail to decode/encode invalid fixtures. When new fixtures are added to this repository, you simply need to update the version of the module (or your submodule) to get the new fixtures and re-run tests.

**Validity:** each fixture includes information about whether they are valid according to the specification versions and possible error outcomes if they are invalid. If any of the fixtures are invalid, they must include an `error` field describing how to recover (or not) from the error. These can be found in the `validity` field of the fixture and info.json files. The following checks:

Expand All @@ -30,12 +30,12 @@ npm install @mapbox/mvt-fixtures --save-dev
```

```javascript
const mvtf = require('@mapbox/mvt-fixtures');
const decoder = require('your-mvt-decoder');
import * as mvtf from '@mapbox/mvt-fixtures';
import decoder from 'your-mvt-decoder';

// assert on every single buffer
mvtf.each(function(fixture) {
let output = decoder(fixture.buffer);
mvtf.each((fixture) => {
const output = decoder(fixture.buffer);
assert.equal(output.layers.length, fixture.json.layers.length, 'expected number of layers');
// ... more tests
});
Expand All @@ -44,7 +44,7 @@ mvtf.each(function(fixture) {
const output = decoder(mvtf.get('043').buffer);

// or you can build a fixture inline
const { buffer } = mvtf.create({
const {buffer} = mvtf.create({
layers: [
{
version: 2,
Expand Down Expand Up @@ -103,27 +103,35 @@ npm install -g documentation

### Adding a new fixture

All fixtures have a source file in the /src directory. This file is a module that exports an object with the following parameters:
All fixtures have a source file in the /src directory. Each is a JSON file with the following shape:

```javascript
module.exports = {
description: 'DESCRIPTION',
specification_reference: 'SPECIFICATION_URL',
validity: {
v1: false,
v2: false,
error: 'ERROR_TYPE'
```json
{
"description": "DESCRIPTION",
"specification_reference": "SPECIFICATION_URL",
"validity": {
"v1": false,
"v2": false,
"error": "ERROR_TYPE"
},
json: {...},
proto: '2.1'
};
"json": { },
"proto": "2.1"
}
```

The `proto` field can be:

- a spec version string like `"2.1"` or `"1.0.1"` — the matching `vector-tile-spec/<version>/vector_tile.proto` is used as-is
- a 3-element array `["2.1", "before", "after"]` — the spec proto for the given version is loaded and a single `replace(before, after)` is applied (useful for fixtures that intentionally violate the spec by tweaking field types)
- a full `.proto` schema string — used directly

A fixture may also set `"syntax": "3"` to encode with proto3 instead of the default proto2.

A new fixture can be created by running the command, which will auto-increment the ID:

```shell
npm run new
# New file created: /src/003.js.
# New file created: /src/003.json.
```

### Building fixtures
Expand All @@ -136,41 +144,6 @@ npm run build

### Debugging fixtures

There are couple scripts included for debugging the fixtures as you create them.

**protoc specification dump** allows you to dump mvt fixtures to the text-based representation supported by the google protoc tool. This can be very useful for debugging fixtures to ensure you've created what you expected (particularly for tiles designed to be invalid to parse).

```bash
$ ./scripts/dump fixtures/002/tile.mvt
layers {
name: "hello"
features {
type: POINT
geometry: 9
geometry: 50
geometry: 34
}
extent: 4096
version: 2
}
```

**raw protoc dump** allows you to dump the raw contents of a buffer. This particularly useful for tiles that don't match the vector_tile.proto format and you want to view which tags are generated

```bash
$ ./scripts/dump fixtures/002/tile.mvt --raw
3 {
15: 2
1: "hello"
2 {
2: ""
3: 1
4: "\t2\""
}
5: 4096
}
```

**[vtvalidate](https://github.com/mapbox/vtvalidate)** is a node C++ addon that can be installed via npm separately. This uses vtzero to parse a vector tile buffer and has a CLI available for quick use.

```bash
Expand Down
19 changes: 19 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import mourner from 'eslint-config-mourner';

export default [
...mourner,
{
rules: {
'@stylistic/indent': [2, 2, {flatTernaryExpressions: true}],
// snake_case fixture/protobuf field names are part of the public API/spec
'camelcase': 0
}
},
{
files: ['scripts/**'],
rules: {
// sequential network/IO in build scripts is intentional
'no-await-in-loop': 0
}
}
];
Binary file modified fixtures/003/tile.mvt
Binary file not shown.
Binary file modified fixtures/004/tile.mvt
Binary file not shown.
Binary file modified fixtures/006/tile.mvt
Binary file not shown.
6 changes: 5 additions & 1 deletion fixtures/007/info.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,9 @@
"v2": false,
"error": "fatal"
},
"proto": "package vector_tile;\n\noption optimize_for = LITE_RUNTIME;\n\nmessage Tile {\n\n // GeomType is described in section 4.3.4 of the specification\n enum GeomType {\n UNKNOWN = 0;\n POINT = 1;\n LINESTRING = 2;\n POLYGON = 3;\n }\n\n // Variant type encoding\n // The use of values is described in section 4.1 of the specification\n message Value {\n // Exactly one of these values must be present in a valid message\n optional string string_value = 1;\n optional float float_value = 2;\n optional double double_value = 3;\n optional int64 int_value = 4;\n optional uint64 uint_value = 5;\n optional sint64 sint_value = 6;\n optional bool bool_value = 7;\n\n extensions 8 to max;\n }\n\n // Features are described in section 4.2 of the specification\n message Feature {\n optional uint64 id = 1 [ default = 0 ];\n\n // Tags of this feature are encoded as repeated pairs of\n // integers.\n // A detailed description of tags is located in sections\n // 4.2 and 4.4 of the specification\n repeated uint32 tags = 2 [ packed = true ];\n\n // The type of geometry stored in this feature.\n optional GeomType type = 3 [ default = UNKNOWN ];\n\n // Contains a stream of commands and parameters (vertices).\n // A detailed description on geometry encoding is located in \n // section 4.3 of the specification.\n repeated uint32 geometry = 4 [ packed = true ];\n }\n\n // Layers are described in section 4.1 of the specification\n message Layer {\n // Any compliant implementation must first read the version\n // number encoded in this message and choose the correct\n // implementation for this version number before proceeding to\n // decode other parts of this message.\n required string version = 15 [ default = 1 ];\n\n required string name = 1;\n\n // The actual features in this tile.\n repeated Feature features = 2;\n\n // Dictionary encoding for keys\n repeated string keys = 3;\n\n // Dictionary encoding for values\n repeated Value values = 4;\n\n // Although this is an \"optional\" field it is required by the specification.\n // See https://github.com/mapbox/vector-tile-spec/issues/47\n optional uint32 extent = 5 [ default = 4096 ];\n\n extensions 16 to max;\n }\n\n repeated Layer layers = 3;\n\n extensions 16 to 8191;\n}\n"
"proto": [
"2.1",
"required uint32 version",
"required string version"
]
}
Binary file modified fixtures/007/tile.mvt
Binary file not shown.
6 changes: 5 additions & 1 deletion fixtures/008/info.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,9 @@
"v2": false,
"error": "fatal"
},
"proto": "package vector_tile;\n\noption optimize_for = LITE_RUNTIME;\n\nmessage Tile {\n\n // GeomType is described in section 4.3.4 of the specification\n enum GeomType {\n UNKNOWN = 0;\n POINT = 1;\n LINESTRING = 2;\n POLYGON = 3;\n }\n\n // Variant type encoding\n // The use of values is described in section 4.1 of the specification\n message Value {\n // Exactly one of these values must be present in a valid message\n optional string string_value = 1;\n optional float float_value = 2;\n optional double double_value = 3;\n optional int64 int_value = 4;\n optional uint64 uint_value = 5;\n optional sint64 sint_value = 6;\n optional bool bool_value = 7;\n\n extensions 8 to max;\n }\n\n // Features are described in section 4.2 of the specification\n message Feature {\n optional uint64 id = 1 [ default = 0 ];\n\n // Tags of this feature are encoded as repeated pairs of\n // integers.\n // A detailed description of tags is located in sections\n // 4.2 and 4.4 of the specification\n repeated uint32 tags = 2 [ packed = true ];\n\n // The type of geometry stored in this feature.\n optional GeomType type = 3 [ default = UNKNOWN ];\n\n // Contains a stream of commands and parameters (vertices).\n // A detailed description on geometry encoding is located in \n // section 4.3 of the specification.\n repeated uint32 geometry = 4 [ packed = true ];\n }\n\n // Layers are described in section 4.1 of the specification\n message Layer {\n // Any compliant implementation must first read the version\n // number encoded in this message and choose the correct\n // implementation for this version number before proceeding to\n // decode other parts of this message.\n required uint32 version = 15 [ default = 1 ];\n\n required string name = 1;\n\n // The actual features in this tile.\n repeated Feature features = 2;\n\n // Dictionary encoding for keys\n repeated string keys = 3;\n\n // Dictionary encoding for values\n repeated Value values = 4;\n\n // Although this is an \"optional\" field it is required by the specification.\n // See https://github.com/mapbox/vector-tile-spec/issues/47\n optional string extent = 5 [ default = 4096 ];\n\n extensions 16 to max;\n }\n\n repeated Layer layers = 3;\n\n extensions 16 to 8191;\n}\n"
"proto": [
"2.1",
"optional uint32 extent",
"optional string extent"
]
}
Binary file modified fixtures/008/tile.mvt
Binary file not shown.
Binary file modified fixtures/009/tile.mvt
Binary file not shown.
Loading
Loading