Skip to content

Commit dd6793b

Browse files
committed
Get link in templated feature working. Update
existing test to pass. Add test. Closes #967
1 parent b1a79c9 commit dd6793b

7 files changed

+257
-1
lines changed

src/mapml/layers/DebugOverlay.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ export var DebugVectors = L.LayerGroup.extend({
255255
.getLayerEl()
256256
.getAttribute('data-testid')
257257
: layers[i].layerBounds &&
258-
layers[i].options?._leafletLayer?._layerEl.hasAttribute(
258+
layers[i].options?._leafletLayer?._layerEl?.hasAttribute(
259259
'data-testid'
260260
)
261261
? layers[i].options._leafletLayer._layerEl.getAttribute(

src/mapml/layers/TemplatedFeaturesLayer.js

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export var TemplatedFeaturesLayer = L.Layer.extend({
6565
geometry.bindPopup(c, { autoClose: false, minWidth: 108 });
6666
}
6767
});
68+
L.extend(this._features.options, { _leafletLayer: this._features });
6869
} else {
6970
this._features.eachLayer((layer) => layer.addTo(map));
7071
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { test, expect, chromium } from '@playwright/test';
2+
3+
test.describe('map-a loaded inline or remote, directly or via templated map-link tests', () => {
4+
let page;
5+
let context;
6+
test.beforeAll(async function () {
7+
context = await chromium.launchPersistentContext('');
8+
page =
9+
context.pages().find((page) => page.url() === 'about:blank') ||
10+
(await context.newPage());
11+
await page.goto('map-a.html');
12+
await page.waitForTimeout(500);
13+
});
14+
15+
const contentLocations = ['inline', 'remote'];
16+
for (const inlineOrRemote of contentLocations) {
17+
test(`${inlineOrRemote} map-a-wrapped-map-geometry loaded directly creates a hyperlink`, async () => {
18+
const directlyLoadedFeaturesLayer = await page.getByTestId(
19+
`${inlineOrRemote}-features`
20+
);
21+
const directlyLoadedFeaturesCount =
22+
await directlyLoadedFeaturesLayer.evaluate((l) => {
23+
let node = l.hasAttribute('src') ? l.shadowRoot : l;
24+
return node.querySelectorAll('map-feature').length;
25+
});
26+
expect(directlyLoadedFeaturesCount).toBe(2);
27+
// one of them contains a map-a wrapping its map-geometry
28+
const directlyLoadedHyperlinksCount =
29+
await directlyLoadedFeaturesLayer.evaluate((l) => {
30+
let node = l.hasAttribute('src') ? l.shadowRoot : l;
31+
return node.querySelectorAll('map-feature:has(map-a)').length;
32+
});
33+
expect(directlyLoadedHyperlinksCount).toBe(1);
34+
// all features should have a _groupEl prop (i.e. all features are rendered)
35+
const directlyLoadedFeaturesRenderedCount =
36+
await directlyLoadedFeaturesLayer.evaluate((l) => {
37+
let node = l.hasAttribute('src') ? l.shadowRoot : l;
38+
const hasRendering = (f) => Boolean(f._groupEl);
39+
return Array.from(node.querySelectorAll('map-feature')).filter(
40+
hasRendering
41+
).length;
42+
});
43+
expect(directlyLoadedFeaturesRenderedCount).toEqual(
44+
directlyLoadedFeaturesCount
45+
);
46+
});
47+
test(`${inlineOrRemote} map-a-wrapped-map-geometry loaded via templated map-link creates a hyperlink`, async () => {
48+
const templatedLoadedFeaturesContainer = await page.getByTestId(
49+
`${inlineOrRemote}-templated-link`
50+
);
51+
const templatedLoadedFeaturesCount =
52+
await templatedLoadedFeaturesContainer.evaluate((l) => {
53+
return l.shadowRoot.querySelectorAll('map-feature').length;
54+
});
55+
expect(templatedLoadedFeaturesCount).toBe(2);
56+
// one of them contains a map-a wrapping its map-geometry
57+
const templatedLoadedHyperlinksCount =
58+
await templatedLoadedFeaturesContainer.evaluate((l) => {
59+
return l.shadowRoot.querySelectorAll('map-feature:has(map-a)').length;
60+
});
61+
expect(templatedLoadedHyperlinksCount).toBe(1);
62+
// all features should have a _groupEl prop (i.e. all features are rendered)
63+
const templatedLoadedFeaturesRenderedCount =
64+
await templatedLoadedFeaturesContainer.evaluate((l) => {
65+
const hasRendering = (f) => Boolean(f._groupEl);
66+
return Array.from(
67+
l.shadowRoot.querySelectorAll('map-feature')
68+
).filter(hasRendering).length;
69+
});
70+
expect(templatedLoadedFeaturesRenderedCount).toEqual(
71+
templatedLoadedFeaturesCount
72+
);
73+
});
74+
}
75+
});

test/e2e/elements/map-a/map-a.html

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>Remote layer with map-link rel=features</title>
5+
<meta charset="UTF-8">
6+
<script type="module" src="mapml-viewer.js"></script>
7+
<style>
8+
html {
9+
height: 100%
10+
}
11+
12+
body {
13+
height: inherit
14+
}
15+
16+
* {
17+
margin: 0;
18+
padding: 0;
19+
}
20+
</style>
21+
</head>
22+
<body>
23+
<mapml-viewer projection="OSMTILE" data-testid="viewer" style="height: 500px;width:500px;" controls zoom="18" lat="40.7075" lon="-74.011" >
24+
<layer- data-testid="inline-features" label="inline-features" checked>
25+
<map-meta name="projection" content="OSMTILE"></map-meta>
26+
<map-meta name="cs" content="pcrs"></map-meta>
27+
<map-meta name="extent" content="top-left-easting=-8238959.40,top-left-northing=4971112.17,bottom-right-easting=-8237812.69,bottom-right-northing=4969300.12"></map-meta>
28+
<map-style>.poi-r1-s1.poi-r1-s2 {opacity:1.0; fill:rebeccapurple; stroke:rebeccapurple; fill-opacity:0.7}</map-style>
29+
<map-feature id="poi.2" class="poi-r1-s1 poi-r1-s2">
30+
<map-geometry>
31+
<map-point>
32+
<map-coordinates>-8238848.744948964 4969300.121476209</map-coordinates>
33+
</map-point>
34+
</map-geometry>
35+
<map-properties>
36+
<table xmlns="http://www.w3.org/1999/xhtml">
37+
<thead>
38+
<tr>
39+
<th role="columnheader" scope="col">Property name</th>
40+
<th role="columnheader" scope="col">Property value</th>
41+
</tr>
42+
</thead>
43+
<tbody>
44+
<tr>
45+
<th scope="row">MAINPAGE</th>
46+
<td itemprop="MAINPAGE">pics/22037829-L.jpg</td>
47+
</tr>
48+
</tbody>
49+
</table>
50+
</map-properties>
51+
</map-feature>
52+
<map-feature id="poi.1" class="poi-r1-s1 poi-r1-s2">
53+
<map-geometry>
54+
<map-a href="https://example.org/" target="_top">
55+
<map-point>
56+
<map-coordinates>-8238806.8429565085 4969306.111096254</map-coordinates>
57+
</map-point>
58+
</map-a>
59+
</map-geometry>
60+
<map-properties>
61+
<table xmlns="http://www.w3.org/1999/xhtml">
62+
<thead>
63+
<tr>
64+
<th role="columnheader" scope="col">Property name</th>
65+
<th role="columnheader" scope="col">Property value</th>
66+
</tr>
67+
</thead>
68+
<tbody>
69+
<tr>
70+
<th scope="row">MAINPAGE</th>
71+
<td itemprop="MAINPAGE">pics/22037827-L.jpg</td>
72+
</tr>
73+
</tbody>
74+
</table>
75+
</map-properties>
76+
</map-feature>
77+
</layer->
78+
<layer- data-testid="remote-features" label="remote-features.mapml" src="remote-features.mapml" checked></layer->
79+
<layer- data-testid="inline-templated" label="inline-rel-features" checked>
80+
<map-meta name="projection" content="OSMTILE"></map-meta>
81+
<map-meta name="cs" content="pcrs"></map-meta>
82+
<map-meta name="extent" content="top-left-easting=-8238959.40,top-left-northing=4971112.17,bottom-right-easting=-8237812.69,bottom-right-northing=4969300.12"></map-meta>
83+
<map-extent units="OSMTILE" checked="checked" hidden="hidden">
84+
<map-style>.poi-r1-s1.poi-r1-s2 {opacity:1.0; fill:green; stroke:green; fill-opacity:0.7}</map-style>
85+
<map-input name="z" type="zoom" min="0" max="18" ></map-input>
86+
<map-input name="xmin" type="location" rel="map" position="top-left" axis="easting" units="pcrs" ></map-input>
87+
<map-input name="ymin" type="location" rel="map" position="bottom-left" axis="northing" units="pcrs"></map-input>
88+
<map-input name="xmax" type="location" rel="map" position="top-right" axis="easting" units="pcrs"></map-input>
89+
<map-input name="ymax" type="location" rel="map" position="top-left" axis="northing" units="pcrs"></map-input>
90+
<map-input name="w" type="width" min="1" max="4096" ></map-input>
91+
<map-input name="h" type="height" min="1" max="4096" ></map-input>
92+
<map-link data-testid="inline-templated-link" rel="features" tref="./remote-features.mapml?format_options=mapmlfeatures:true&amp;request=GetMap&amp;crs=MapML:OSMTILE&amp;bbox={xmin},{ymin},{xmax},{ymax}&amp;format=text/mapml&amp;language=en&amp;version=1.3.0&amp;transparent=true&amp;service=WMS&amp;layers=poi&amp;width={w}&amp;styles=poi&amp;height={h}"></map-link>
93+
</map-extent>
94+
</layer->
95+
<layer- data-testid="remote-templated" src="remote-rel-features.mapml" checked ></layer->
96+
</mapml-viewer>
97+
</body>
98+
</html>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
<mapml- xmlns="http://www.w3.org/1999/xhtml">
2+
<map-head>
3+
<map-title>remote-features.mapml</map-title>
4+
<map-meta charset="UTF-8"/>
5+
<map-meta content="text/mapml" http-equiv="Content-Type"/>
6+
<map-meta name="projection" content="OSMTILE"/>
7+
<map-meta name="cs" content="pcrs"/>
8+
<map-meta name="extent" content="top-left-easting=-8238959.40,top-left-northing=4971112.17,bottom-right-easting=-8237812.69,bottom-right-northing=4969300.12"/>
9+
<map-style>.poi-r1-s1.poi-r1-s2 {opacity:1.0; fill:red; stroke:red; fill-opacity:0.7}</map-style>
10+
</map-head>
11+
<map-body>
12+
<map-feature id="poi.2" class="poi-r1-s1 poi-r1-s2">
13+
<map-geometry>
14+
<map-point>
15+
<map-coordinates>-8238848.744948964 4969300.121476209</map-coordinates>
16+
</map-point>
17+
</map-geometry>
18+
<map-properties>
19+
<table xmlns="http://www.w3.org/1999/xhtml">
20+
<thead>
21+
<tr>
22+
<th role="columnheader" scope="col">Property name</th>
23+
<th role="columnheader" scope="col">Property value</th>
24+
</tr>
25+
</thead>
26+
<tbody>
27+
<tr>
28+
<th scope="row">MAINPAGE</th>
29+
<td itemprop="MAINPAGE">pics/22037829-L.jpg</td>
30+
</tr>
31+
</tbody>
32+
</table>
33+
</map-properties>
34+
</map-feature>
35+
<map-feature id="poi.1" class="poi-r1-s1 poi-r1-s2">
36+
<map-geometry>
37+
<map-a href="https://example.org/" target="_top">
38+
<map-point>
39+
<map-coordinates>-8238806.8429565085 4969306.111096254</map-coordinates>
40+
</map-point>
41+
</map-a>
42+
</map-geometry>
43+
<map-properties>
44+
<table xmlns="http://www.w3.org/1999/xhtml">
45+
<thead>
46+
<tr>
47+
<th role="columnheader" scope="col">Property name</th>
48+
<th role="columnheader" scope="col">Property value</th>
49+
</tr>
50+
</thead>
51+
<tbody>
52+
<tr>
53+
<th scope="row">MAINPAGE</th>
54+
<td itemprop="MAINPAGE">pics/22037827-L.jpg</td>
55+
</tr>
56+
</tbody>
57+
</table>
58+
</map-properties>
59+
</map-feature>
60+
</map-body>
61+
</mapml->
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<mapml- xmlns="http://www.w3.org/1999/xhtml">
2+
<map-head>
3+
<map-title>remote-rel-features.mapml</map-title>
4+
<map-meta charset="utf-8" />
5+
<map-style>.poi-r1-s1.poi-r1-s2 {opacity:1.0; fill:blue; stroke:blue; fill-opacity:0.7}</map-style>
6+
<map-meta name="extent" content="top-left-easting=-8238908, top-left-northing=4969383, bottom-right-easting=-8238758, bottom-right-northing=4969234"></map-meta>
7+
</map-head>
8+
<map-body>
9+
<map-extent units="OSMTILE" checked="checked" hidden="hidden">
10+
<map-input name="z" type="zoom" min="0" max="18" />
11+
<map-input name="xmin" type="location" rel="map" position="top-left" axis="easting" units="pcrs" />
12+
<map-input name="ymin" type="location" rel="map" position="bottom-left" axis="northing" units="pcrs" />
13+
<map-input name="xmax" type="location" rel="map" position="top-right" axis="easting" units="pcrs" />
14+
<map-input name="ymax" type="location" rel="map" position="top-left" axis="northing" units="pcrs" />
15+
<map-input name="w" type="width" min="1" max="4096" />
16+
<map-input name="h" type="height" min="1" max="4096" />
17+
<map-link data-testid="remote-templated-link" rel="features" tref="./remote-features.mapml?format_options=mapmlfeatures:true&amp;request=GetMap&amp;crs=MapML:OSMTILE&amp;bbox={xmin},{ymin},{xmax},{ymax}&amp;format=text/mapml&amp;language=en&amp;version=1.3.0&amp;transparent=true&amp;service=WMS&amp;layers=poi&amp;width={w}&amp;styles=poi&amp;height={h}"></map-link>
18+
</map-extent>
19+
</map-body>
20+
</mapml->

test/server.js

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ app.use(express.static(path.join(__dirname, 'e2e/elements/map-extent')));
1010
app.use(express.static(path.join(__dirname, 'e2e/elements/mapml-viewer')));
1111
app.use(express.static(path.join(__dirname, 'e2e/elements/map')));
1212
app.use(express.static(path.join(__dirname, 'e2e/elements/map-feature')));
13+
app.use(express.static(path.join(__dirname, 'e2e/elements/map-a')));
1314
app.use(express.static(path.join(__dirname, 'e2e/elements/map-input')));
1415
app.use(express.static(path.join(__dirname, 'e2e/elements/map-link')));
1516
app.use(express.static(path.join(__dirname, 'e2e/elements/map-style')));

0 commit comments

Comments
 (0)