From 46488f811887cda667e3580cdda05caeafce8a29 Mon Sep 17 00:00:00 2001 From: Anro Date: Fri, 6 Sep 2024 15:12:40 +0200 Subject: [PATCH 1/3] fix: replace DOMSubtreeModified with MutationObserver & add delay to dynamic url widget mutation test --- webapp/src/js/enketo/widgets/dynamic-url.js | 15 ++++++++++++++- .../karma/js/enketo/widgets/dynamic-url.spec.ts | 7 +++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/webapp/src/js/enketo/widgets/dynamic-url.js b/webapp/src/js/enketo/widgets/dynamic-url.js index 18d460e5f8d..8608fe098cc 100644 --- a/webapp/src/js/enketo/widgets/dynamic-url.js +++ b/webapp/src/js/enketo/widgets/dynamic-url.js @@ -17,7 +17,20 @@ class DynamicUrlWidget extends Widget { const urlElement = currentElement.find('.url'); const setHref = () => currentElement.attr('href', urlElement.text()); setHref(); - urlElement.on('DOMSubtreeModified', setHref); + + const observer = new MutationObserver(mutationList => { + mutationList.forEach(mutation => { + if (mutation.type === 'childList' || mutation.type === 'characterData') { + setHref(); + } + }); + }); + + observer.observe(urlElement[0], { + childList: true, // Monitor direct child nodes + characterData: true, // Monitor text content changes + subtree: true // Monitor all descendants + }); } } diff --git a/webapp/tests/karma/js/enketo/widgets/dynamic-url.spec.ts b/webapp/tests/karma/js/enketo/widgets/dynamic-url.spec.ts index 7e3914740bf..d6cdf3f2b0d 100644 --- a/webapp/tests/karma/js/enketo/widgets/dynamic-url.spec.ts +++ b/webapp/tests/karma/js/enketo/widgets/dynamic-url.spec.ts @@ -40,14 +40,17 @@ describe('Enketo: Dynamic URL Widget', () => { expect($(DynamicUrlWidget.selector).attr('href')).to.equal('http://google.com?q='); }); - it('should update the href for the dynamically generated URL when the dynamic value changes', () => { + it('should update the href for the dynamically generated URL when the dynamic value changes', (done) => { buildHtml('helloWorld'); new DynamicUrlWidget($(DynamicUrlWidget.selector)[0]); const dynamic = 'worldHello'; $('.url span').text(dynamic); - expect($(DynamicUrlWidget.selector).attr('href')).to.equal(`http://google.com?q=${dynamic}`); + setTimeout(() => { + expect($(DynamicUrlWidget.selector).attr('href')).to.equal(`http://google.com?q=${dynamic}`); + done(); + }, 0); }); it('should not modify elements besides dynamic-url links', () => { From a8e6aa5f6ddade4743feeb26d151a858191b9c6b Mon Sep 17 00:00:00 2001 From: Joshua Kuestersteffen Date: Fri, 6 Sep 2024 16:24:46 -0500 Subject: [PATCH 2/3] Add simple integration test for dynamic-url functionality --- .../default/dynamic-url-widget.wdio-spec.js | 17 ++++++++ .../default/forms/dynamic-url-widget.xlsx | Bin 0 -> 7993 bytes .../default/forms/dynamic-url-widget.xml | 39 ++++++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 tests/integration/cht-form/default/dynamic-url-widget.wdio-spec.js create mode 100644 tests/integration/cht-form/default/forms/dynamic-url-widget.xlsx create mode 100644 tests/integration/cht-form/default/forms/dynamic-url-widget.xml diff --git a/tests/integration/cht-form/default/dynamic-url-widget.wdio-spec.js b/tests/integration/cht-form/default/dynamic-url-widget.wdio-spec.js new file mode 100644 index 00000000000..cf223e08428 --- /dev/null +++ b/tests/integration/cht-form/default/dynamic-url-widget.wdio-spec.js @@ -0,0 +1,17 @@ +const mockConfig = require('../mock-config'); +const commonEnketoPage = require('@page-objects/default/enketo/common-enketo.wdio.page'); +const genericForm = require('@page-objects/default/enketo/generic-form.wdio.page'); + +describe('cht-form web component - Dynamic URL Widget', () => { + it('supports displaying a dynamic markdown link in a note', async () => { + const searchQuery = 'why is Java best'; + + await mockConfig.loadForm('default', 'test', 'dynamic-url-widget'); + await commonEnketoPage.setInputValue('Enter your search query', searchQuery); + await genericForm.nextPage(); + + expect(await commonEnketoPage.isElementDisplayed('label', `Click the link to search: ${searchQuery}`)).to.be.true; + const linkValue = await(await $('a.dynamic-url')).getAttribute('href'); + expect(linkValue).to.equal(`http://google.com?q=${searchQuery}`); + }); +}); diff --git a/tests/integration/cht-form/default/forms/dynamic-url-widget.xlsx b/tests/integration/cht-form/default/forms/dynamic-url-widget.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..7ba9a4c94c3a5320e9fdf757175eada88f310191 GIT binary patch literal 7993 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 F{{Rx_fyDp- literal 0 HcmV?d00001 diff --git a/tests/integration/cht-form/default/forms/dynamic-url-widget.xml b/tests/integration/cht-form/default/forms/dynamic-url-widget.xml new file mode 100644 index 00000000000..5c85eebaeeb --- /dev/null +++ b/tests/integration/cht-form/default/forms/dynamic-url-widget.xml @@ -0,0 +1,39 @@ + + + + Dynamic URL + + + + + Enter your search query + + + Click the link to search: [](http://google.com?q=) + + + + + + + + + + + + + + + + + + + + + + From 9e3145c333166d942df20e952e99fb1523804de4 Mon Sep 17 00:00:00 2001 From: Anro Date: Mon, 9 Sep 2024 10:20:27 +0200 Subject: [PATCH 3/3] fix: remove unnecessary checks --- webapp/src/js/enketo/widgets/dynamic-url.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/webapp/src/js/enketo/widgets/dynamic-url.js b/webapp/src/js/enketo/widgets/dynamic-url.js index 8608fe098cc..3dd6dd39b71 100644 --- a/webapp/src/js/enketo/widgets/dynamic-url.js +++ b/webapp/src/js/enketo/widgets/dynamic-url.js @@ -19,16 +19,13 @@ class DynamicUrlWidget extends Widget { setHref(); const observer = new MutationObserver(mutationList => { - mutationList.forEach(mutation => { - if (mutation.type === 'childList' || mutation.type === 'characterData') { - setHref(); - } + mutationList.forEach(() => { + setHref(); }); }); observer.observe(urlElement[0], { childList: true, // Monitor direct child nodes - characterData: true, // Monitor text content changes subtree: true // Monitor all descendants }); }