From e1e26b5f44ebfc9001b3d68d8713a79dd50c9f58 Mon Sep 17 00:00:00 2001 From: Ton Sharp <45160296+66Ton99@users.noreply.github.com> Date: Fri, 28 Aug 2026 03:23:21 +0300 Subject: [PATCH] fix(tests): build the detached registration the sweep cannot reach "registerForm" drops the registrations of a model whose markup has left the document, so the two registrations the "removeDetachedForms" test set up - render, remove, render again - became one, and the test failed on main. The test now removes the node after the last registration, which is the only way a detached registration survives to be swept, and a second test covers the sweep that registering does on its own. The documentation said the registry keeps growing without an explicit removal, which that sweep already made untrue. --- src/Resources/doc/3_24.md | 12 ++++++-- .../public/js/SvarohJsFormValidator.test.js | 28 ++++++++++++++++--- 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/Resources/doc/3_24.md b/src/Resources/doc/3_24.md index d1f5578..5a07d14 100644 --- a/src/Resources/doc/3_24.md +++ b/src/Resources/doc/3_24.md @@ -3,9 +3,15 @@ A page that fetches rendered forms and swaps them into the document - a single page CRUD, a modal that loads its form, a wizard step - initializes a model per render. `addModel()` keeps every render in the registry, so the ones whose -markup the application has removed have to be taken back out, otherwise the -registry keeps growing and `getFormInstances()` keeps answering with elements -of nodes that are gone. +markup the application has removed have to be taken back out, otherwise +`getFormInstances()` keeps answering with elements of nodes that are gone. + +Registering a form drops the registrations of that model whose markup has left +the document, so a page that swaps a form for a new one does not grow a +registration per swap on its own. That only covers the renders a later +registration of the same model passes over: a form the page removed and did not +render again, and every other model, stay in the registry until they are taken +out. Three methods take a registration back. Each one detaches the model from the DOM nodes it was attached to and removes the submit listener this library put diff --git a/src/Resources/public/js/SvarohJsFormValidator.test.js b/src/Resources/public/js/SvarohJsFormValidator.test.js index 60fc087..1eec9b5 100644 --- a/src/Resources/public/js/SvarohJsFormValidator.test.js +++ b/src/Resources/public/js/SvarohJsFormValidator.test.js @@ -1511,11 +1511,16 @@ describe('SvarohJsFormValidator model teardown', () => { }); test('removeDetachedForms drops the registrations of nodes that left the document', () => { - renderProfile(); - const gone = document.getElementById('profile'); + document.body.innerHTML = + '
' + + '
'; + window.SvarohJsFormValidator.addModel(profileModel(), false); + window.SvarohJsFormValidator.addModel(profileModel(), false); + + const [gone, kept] = Array.from(document.querySelectorAll('form')); + // The node leaves after the last registration, so the sweep that + // registering does on its own has not seen it gone.remove(); - renderProfile(); - const kept = document.getElementById('profile'); expect(window.SvarohJsFormValidator.getFormInstances('profile')).toHaveLength(2); expect(window.SvarohJsFormValidator.removeDetachedForms()).toBe(1); @@ -1526,6 +1531,21 @@ describe('SvarohJsFormValidator model teardown', () => { expect(window.SvarohJsFormValidator.forms.profile.domNode).toBe(kept); }); + // Registering sweeps on its own, so a page that swaps a form for a new one + // does not grow a registration per swap even when it never asks + test('registering a form drops the registrations of nodes that left the document', () => { + renderProfile(); + document.getElementById('profile').remove(); + renderProfile(); + const kept = document.getElementById('profile'); + + const instances = window.SvarohJsFormValidator.getFormInstances('profile'); + expect(instances).toHaveLength(1); + expect(instances[0].domNode).toBe(kept); + expect(window.SvarohJsFormValidator.forms.profile.domNode).toBe(kept); + expect(window.SvarohJsFormValidator.removeDetachedForms()).toBe(0); + }); + test('initializing the same markup again does not validate the form twice', () => { renderProfile(); const form = document.getElementById('profile');