diff --git a/src/mapml/layers/DebugOverlay.js b/src/mapml/layers/DebugOverlay.js
index caeea2cd1..7f8605487 100644
--- a/src/mapml/layers/DebugOverlay.js
+++ b/src/mapml/layers/DebugOverlay.js
@@ -255,7 +255,7 @@ export var DebugVectors = L.LayerGroup.extend({
.getLayerEl()
.getAttribute('data-testid')
: layers[i].layerBounds &&
- layers[i].options?._leafletLayer?._layerEl.hasAttribute(
+ layers[i].options?._leafletLayer?._layerEl?.hasAttribute(
'data-testid'
)
? layers[i].options._leafletLayer._layerEl.getAttribute(
diff --git a/src/mapml/layers/TemplatedFeaturesLayer.js b/src/mapml/layers/TemplatedFeaturesLayer.js
index af4f08933..5213945fe 100644
--- a/src/mapml/layers/TemplatedFeaturesLayer.js
+++ b/src/mapml/layers/TemplatedFeaturesLayer.js
@@ -65,6 +65,7 @@ export var TemplatedFeaturesLayer = L.Layer.extend({
geometry.bindPopup(c, { autoClose: false, minWidth: 108 });
}
});
+ L.extend(this._features.options, { _leafletLayer: this._features });
} else {
this._features.eachLayer((layer) => layer.addTo(map));
}
diff --git a/test/e2e/elements/map-a/map-a-inline-or-remote-templated-issue-968.test.js b/test/e2e/elements/map-a/map-a-inline-or-remote-templated-issue-968.test.js
new file mode 100644
index 000000000..9d9a12886
--- /dev/null
+++ b/test/e2e/elements/map-a/map-a-inline-or-remote-templated-issue-968.test.js
@@ -0,0 +1,75 @@
+import { test, expect, chromium } from '@playwright/test';
+
+test.describe('map-a loaded inline or remote, directly or via templated map-link tests', () => {
+ let page;
+ let context;
+ test.beforeAll(async function () {
+ context = await chromium.launchPersistentContext('');
+ page =
+ context.pages().find((page) => page.url() === 'about:blank') ||
+ (await context.newPage());
+ await page.goto('map-a.html');
+ });
+
+ const contentLocations = ['inline', 'remote'];
+ for (const inlineOrRemote of contentLocations) {
+ test(`${inlineOrRemote} map-a-wrapped-map-geometry loaded directly creates a hyperlink`, async () => {
+ const directlyLoadedFeaturesLayer = await page.getByTestId(
+ `${inlineOrRemote}-features`
+ );
+ const directlyLoadedFeaturesCount =
+ await directlyLoadedFeaturesLayer.evaluate((l) => {
+ let node = l.hasAttribute('src') ? l.shadowRoot : l;
+ return node.querySelectorAll('map-feature').length;
+ });
+ expect(directlyLoadedFeaturesCount).toBe(2);
+ // one of them contains a map-a wrapping its map-geometry
+ const directlyLoadedHyperlinksCount =
+ await directlyLoadedFeaturesLayer.evaluate((l) => {
+ let node = l.hasAttribute('src') ? l.shadowRoot : l;
+ return node.querySelectorAll('map-feature:has(map-a)').length;
+ });
+ expect(directlyLoadedHyperlinksCount).toBe(1);
+ // all features should have a _groupEl prop (i.e. all features are rendered)
+ const directlyLoadedFeaturesRenderedCount =
+ await directlyLoadedFeaturesLayer.evaluate((l) => {
+ let node = l.hasAttribute('src') ? l.shadowRoot : l;
+ const hasRendering = (f) => Boolean(f._groupEl);
+ return Array.from(node.querySelectorAll('map-feature')).filter(
+ hasRendering
+ ).length;
+ });
+ expect(directlyLoadedFeaturesRenderedCount).toEqual(
+ directlyLoadedFeaturesCount
+ );
+ });
+ test(`${inlineOrRemote} map-a-wrapped-map-geometry loaded via templated map-link creates a hyperlink`, async () => {
+ await page.waitForTimeout(500);
+ const templatedLoadedFeaturesContainer = await page.getByTestId(
+ `${inlineOrRemote}-templated-link`
+ );
+ const templatedLoadedFeaturesCount =
+ await templatedLoadedFeaturesContainer.evaluate((l) => {
+ return l.shadowRoot.querySelectorAll('map-feature').length;
+ });
+ expect(templatedLoadedFeaturesCount).toBe(2);
+ // one of them contains a map-a wrapping its map-geometry
+ const templatedLoadedHyperlinksCount =
+ await templatedLoadedFeaturesContainer.evaluate((l) => {
+ return l.shadowRoot.querySelectorAll('map-feature:has(map-a)').length;
+ });
+ expect(templatedLoadedHyperlinksCount).toBe(1);
+ // all features should have a _groupEl prop (i.e. all features are rendered)
+ const templatedLoadedFeaturesRenderedCount =
+ await templatedLoadedFeaturesContainer.evaluate((l) => {
+ const hasRendering = (f) => Boolean(f._groupEl);
+ return Array.from(
+ l.shadowRoot.querySelectorAll('map-feature')
+ ).filter(hasRendering).length;
+ });
+ expect(templatedLoadedFeaturesRenderedCount).toEqual(
+ templatedLoadedFeaturesCount
+ );
+ });
+ }
+});
diff --git a/test/e2e/elements/map-a/map-a.html b/test/e2e/elements/map-a/map-a.html
new file mode 100644
index 000000000..b011380f0
--- /dev/null
+++ b/test/e2e/elements/map-a/map-a.html
@@ -0,0 +1,98 @@
+
+
+
+ Remote layer with map-link rel=features
+
+
+
+
+
+
+
+
+
+
+ .poi-r1-s1.poi-r1-s2 {opacity:1.0; fill:rebeccapurple; stroke:rebeccapurple; fill-opacity:0.7}
+
+
+
+ -8238848.744948964 4969300.121476209
+
+
+
+
+
+
+ Property name |
+ Property value |
+
+
+
+
+ MAINPAGE |
+ pics/22037829-L.jpg |
+
+
+
+
+
+
+
+
+
+ -8238806.8429565085 4969306.111096254
+
+
+
+
+
+
+
+ Property name |
+ Property value |
+
+
+
+
+ MAINPAGE |
+ pics/22037827-L.jpg |
+
+
+
+
+
+
+
+
+
+
+
+
+ .poi-r1-s1.poi-r1-s2 {opacity:1.0; fill:green; stroke:green; fill-opacity:0.7}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/e2e/elements/map-a/remote-features.mapml b/test/e2e/elements/map-a/remote-features.mapml
new file mode 100644
index 000000000..373fffc74
--- /dev/null
+++ b/test/e2e/elements/map-a/remote-features.mapml
@@ -0,0 +1,61 @@
+
+
+ remote-features.mapml
+
+
+
+
+
+ .poi-r1-s1.poi-r1-s2 {opacity:1.0; fill:red; stroke:red; fill-opacity:0.7}
+
+
+
+
+
+ -8238848.744948964 4969300.121476209
+
+
+
+
+
+
+ Property name |
+ Property value |
+
+
+
+
+ MAINPAGE |
+ pics/22037829-L.jpg |
+
+
+
+
+
+
+
+
+
+ -8238806.8429565085 4969306.111096254
+
+
+
+
+
+
+
+ Property name |
+ Property value |
+
+
+
+
+ MAINPAGE |
+ pics/22037827-L.jpg |
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/e2e/elements/map-a/remote-rel-features.mapml b/test/e2e/elements/map-a/remote-rel-features.mapml
new file mode 100644
index 000000000..e77265996
--- /dev/null
+++ b/test/e2e/elements/map-a/remote-rel-features.mapml
@@ -0,0 +1,20 @@
+
+
+ remote-rel-features.mapml
+
+ .poi-r1-s1.poi-r1-s2 {opacity:1.0; fill:blue; stroke:blue; fill-opacity:0.7}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/server.js b/test/server.js
index fff36e81c..22d184d3e 100644
--- a/test/server.js
+++ b/test/server.js
@@ -10,6 +10,7 @@ app.use(express.static(path.join(__dirname, 'e2e/elements/map-extent')));
app.use(express.static(path.join(__dirname, 'e2e/elements/mapml-viewer')));
app.use(express.static(path.join(__dirname, 'e2e/elements/map')));
app.use(express.static(path.join(__dirname, 'e2e/elements/map-feature')));
+app.use(express.static(path.join(__dirname, 'e2e/elements/map-a')));
app.use(express.static(path.join(__dirname, 'e2e/elements/map-input')));
app.use(express.static(path.join(__dirname, 'e2e/elements/map-link')));
app.use(express.static(path.join(__dirname, 'e2e/elements/map-style')));