This is an automated email from the ASF dual-hosted git repository.

reiern70 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/wicket.git

commit 5ee0217fd0a8cb82c31dee54aeeb98873c88d863
Author: reiern70 <[email protected]>
AuthorDate: Sat Sep 26 09:33:40 2026 -0500

    Add a regression test for Wicket.Palette's moveUp/moveDown
    
    wicket-10.x (10.9.0 through 10.11.0) had a bug where
    Wicket.Palette.moveUpHelper called box.trigger('focus') on a plain
    DOM <select> element, throwing a TypeError and silently discarding
    the reorder before the hidden recorder input was updated. See GitHub
    issue #1618, fixed on wicket-10.x in commit 432a7fee87.
    
    master was never affected - it dropped jQuery from palette.js and
    calls box.focus() directly - but had no test coverage of its own
    that would have caught the same class of regression. Adds a QUnit
    harness for wicket-extensions' client-side JavaScript (none existed;
    only wicket-core's was wired into the grunt/js-test build) and a
    regression test asserting that moveUp/moveDown reorder the selection
    and update the recorder without throwing, run against both the
    JQuery-based and the JQuery-free wicket-ajax engine.
---
 testing/wicket-js-tests/Gruntfile.js          | 19 +++++-
 wicket-extensions/src/test/js/palette-test.js | 88 +++++++++++++++++++++++++++
 wicket-extensions/src/test/js/palette.html    | 67 ++++++++++++++++++++
 3 files changed, 172 insertions(+), 2 deletions(-)

diff --git a/testing/wicket-js-tests/Gruntfile.js 
b/testing/wicket-js-tests/Gruntfile.js
index db599c74b7..e8a255ffba 100644
--- a/testing/wicket-js-tests/Gruntfile.js
+++ b/testing/wicket-js-tests/Gruntfile.js
@@ -47,6 +47,9 @@ module.exports = function(grunt) {
                        "../../wicket-core/src/test/js/event.js",
                        "../../wicket-core/src/test/js/timer.js"
                ],
+               extensionsTestsJs = [
+                       "../../wicket-extensions/src/test/js/palette-test.js"
+               ],
                gymTestsJs = [
                        
"../../wicket-examples/src/main/webapp/js-test/tests/ajax/form.js",
                        
"../../wicket-examples/src/main/webapp/js-test/tests/bean-validation/birthdate.js",
@@ -74,6 +77,7 @@ module.exports = function(grunt) {
                        extensions: extensionsJs,
                        nativeWebSocket: nativeWebSocketJs,
                        testsJs: testsJs,
+                       extensionsTestsJs: extensionsTestsJs,
                        gymTestsJs: gymTestsJs,
                        grunt: gruntJs,
 
@@ -108,7 +112,8 @@ module.exports = function(grunt) {
                        all: {
                                options: {
                                        urls: [
-                                               
'http://localhost:38887/test/js/all.html?4.0.0'
+                                               
'http://localhost:38887/test/js/all.html?4.0.0',
+                                               
'http://localhost:38888/wicket-extensions/src/test/js/palette.html?4.0.0'
                                        ],
                                        puppeteer: {
                                                headless: true,
@@ -124,7 +129,8 @@ module.exports = function(grunt) {
                        vanilla: {
                                options: {
                                        urls: [
-                                               
'http://localhost:38887/test/js/all.html?vanilla'
+                                               
'http://localhost:38887/test/js/all.html?vanilla',
+                                               
'http://localhost:38888/wicket-extensions/src/test/js/palette.html?vanilla'
                                        ],
                                        puppeteer: {
                                                headless: true,
@@ -152,6 +158,15 @@ module.exports = function(grunt) {
                                          },
                                        base: '../../wicket-core/src'
                                }
+                       },
+                       // serves wicket-extensions' own JavaScript and its 
QUnit tests; a separate
+                       // target because they live outside the wicket-core/src 
root above
+                       extensions: {
+                               options: {
+                                       port: 38888,
+                                       debug: true,
+                                       base: '../..'
+                               }
                        }
                }
        });
diff --git a/wicket-extensions/src/test/js/palette-test.js 
b/wicket-extensions/src/test/js/palette-test.js
new file mode 100644
index 0000000000..2216658382
--- /dev/null
+++ b/wicket-extensions/src/test/js/palette-test.js
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*global QUnit: true */
+
+Wicket.Event.add(window, 'domready', function() {
+       "use strict";
+
+       const { module, test } = QUnit;
+
+       function selectionOptionValues() {
+               var selection = document.getElementById('paletteSelection');
+               return Array.prototype.map.call(selection.options, 
function(option) {
+                       return option.value;
+               });
+       }
+
+       function selectOnly(selection, value) {
+               Array.prototype.forEach.call(selection.options, 
function(option) {
+                       option.selected = (option.value === value);
+               });
+       }
+
+       module("Wicket.Palette", {
+               beforeEach: function() {
+                       var selection = 
document.getElementById('paletteSelection');
+                       selection.innerHTML =
+                               '<option value="1">one</option>' +
+                               '<option value="2">two</option>' +
+                               '<option value="3">three</option>';
+                       document.getElementById('paletteRecorder').value = 
'1,2,3';
+               }
+       });
+
+       test("moveUp reorders the selected option without throwing", assert => {
+               var selection = document.getElementById('paletteSelection');
+               selectOnly(selection, '3');
+
+               Wicket.Palette.moveUp('paletteChoices', 'paletteSelection', 
'paletteRecorder');
+
+               assert.deepEqual(selectionOptionValues(), ['1', '3', '2'],
+                       "moveUp did not move the selected option in front of 
its predecessor");
+       });
+
+       test("moveUp updates the hidden recorder input", assert => {
+               var selection = document.getElementById('paletteSelection');
+               selectOnly(selection, '3');
+
+               Wicket.Palette.moveUp('paletteChoices', 'paletteSelection', 
'paletteRecorder');
+
+               assert.equal(document.getElementById('paletteRecorder').value, 
'1,3,2',
+                       "the recorder was not updated, so the server never sees 
the new order");
+       });
+
+       test("moveUp on the first option is a no-op and does not throw", assert 
=> {
+               var selection = document.getElementById('paletteSelection');
+               selectOnly(selection, '1');
+
+               Wicket.Palette.moveUp('paletteChoices', 'paletteSelection', 
'paletteRecorder');
+
+               assert.deepEqual(selectionOptionValues(), ['1', '2', '3'],
+                       "the order should not have changed");
+       });
+
+       test("moveDown reorders the selected option without throwing", assert 
=> {
+               var selection = document.getElementById('paletteSelection');
+               selectOnly(selection, '1');
+
+               Wicket.Palette.moveDown('paletteChoices', 'paletteSelection', 
'paletteRecorder');
+
+               assert.deepEqual(selectionOptionValues(), ['2', '1', '3'],
+                       "moveDown did not move the selected option behind its 
successor");
+       });
+});
diff --git a/wicket-extensions/src/test/js/palette.html 
b/wicket-extensions/src/test/js/palette.html
new file mode 100644
index 0000000000..606c56358e
--- /dev/null
+++ b/wicket-extensions/src/test/js/palette.html
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<html>
+
+<head>
+       <title id="titleId">Wicket.Palette JavaScript tests</title>
+       <meta http-equiv="content-type" content="text/html; charset=UTF-8">
+       <link rel="stylesheet" href="/wicket-core/src/test/js/qunit/qunit.css" 
type="text/css" media="screen" />
+</head>
+
+<body>
+       <div id="qunit"></div>
+
+       <div id="qunit-fixture">
+               <select id="paletteChoices" multiple="multiple">
+                       <option value="4">four</option>
+               </select>
+               <select id="paletteSelection" multiple="multiple">
+                       <option value="1">one</option>
+                       <option value="2">two</option>
+                       <option value="3">three</option>
+               </select>
+               <input type="hidden" id="paletteRecorder" value="1,2,3"/>
+       </div>
+
+       <script>
+               // version lies between question mark and first ampersand (or 
end).
+               // 'vanilla' (palette.html?vanilla) selects the jQuery-free 
wicket-ajax.js
+               // engine instead of the default JQuery + wicket-ajax-jquery.js 
combination
+               // (palette.html?4.0.0, palette.html?3.7.1, ...).
+               var version = location.search.match(/\?(.*?)(&|$)/)[1];
+               var useVanilla = (version === 'vanilla');
+
+               if (!useVanilla) {
+                       document.write("<scr"+"ipt 
src='/wicket-core/src/main/java/org/apache/wicket/resource/jquery/jquery-"+version+".js'></scr"+"ipt>");
+               }
+       </script>
+       <script>
+               if (!useVanilla) {
+                       document.write("<scr"+"ipt 
src='/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax-jquery.js'></scr"+"ipt>");
+               } else {
+                       document.write("<scr"+"ipt 
src='/wicket-core/src/main/java/org/apache/wicket/ajax/res/js/wicket-ajax.js'></scr"+"ipt>");
+               }
+       </script>
+       <script type="text/javascript" 
src="/wicket-core/src/test/js/qunit/qunit.js"></script>
+
+       <!-- the module under test -->
+       <script type="text/javascript" 
src="/wicket-extensions/src/main/java/org/apache/wicket/extensions/markup/html/form/palette/palette.js"></script>
+
+       <script type="text/javascript" src="palette-test.js"></script>
+</body>
+</html>

Reply via email to