diff --git a/openig-ui/Gruntfile.js b/openig-ui/Gruntfile.js index 9ebed63c1..8077cb245 100644 --- a/openig-ui/Gruntfile.js +++ b/openig-ui/Gruntfile.js @@ -12,9 +12,10 @@ * information: "Portions copyright [year] [name of copyright owner]". * * Copyright 2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ -/* global module, require */ +/* global module, require, process */ module.exports = function (grunt) { grunt.loadNpmTasks("grunt-babel"); @@ -48,7 +49,11 @@ module.exports = function (grunt) { "**/*", "!**/*.less", "!**/*.js" - ]; + ], + // The test page is opened from file:// and the app fetches translations and templates through XHR, + // which Chrome only allows for local files with this flag. Setting puppeteer.args replaces the + // arguments grunt-contrib-qunit would pass itself, so its CI-only --no-sandbox is re-added here. + chromiumArgs = ["--allow-file-access-from-files"].concat(process.env.CI ? ["--no-sandbox"] : []); grunt.initConfig({ eslint: { @@ -89,6 +94,17 @@ module.exports = function (grunt) { }, qunit: { + /** + * Run the QUnit suite in headless Chrome (Puppeteer). + */ + options: { + // Time allowed between two QUnit messages; the first one only arrives once the application has + // initialised and the suites are loaded. + timeout: 30000, + puppeteer: { + args: chromiumArgs + } + }, all: [testTargetDirectory + "/qunit.html"] }, requirejs: { @@ -264,6 +280,17 @@ module.exports = function (grunt) { src: ["*.css"], dest: compositionDirectory + "/css" }] + }, + /** + * Copy the QUnit runtime next to the test page. + */ + qunit: { + files: [{ + expand: true, + cwd: nodeModules + "/qunit/qunit", + src: ["qunit.js", "qunit.css"], + dest: testTargetDirectory + "/libs" + }] } } }); @@ -279,10 +306,17 @@ module.exports = function (grunt) { "babel", "sync:transpiledfiles", "sync:transpiledtestfiles", - //"qunit", "requirejs" ]); + /** + * Run the tests against the output of "build". + */ + grunt.registerTask("test", [ + "copy:qunit", + "qunit" + ]); + grunt.registerTask("build-dev", [ "eslint", "sync:compose", @@ -294,7 +328,7 @@ module.exports = function (grunt) { "babel", "sync:transpiledfiles", "sync:transpiledtestfiles", - "qunit" + "test" ]); grunt.registerTask("dev", ["build-dev", "watch"]); diff --git a/openig-ui/README.md b/openig-ui/README.md index 281ab9ca6..eda62ddd6 100644 --- a/openig-ui/README.md +++ b/openig-ui/README.md @@ -12,6 +12,7 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2016 ForgeRock AS. + Portions Copyright 2026 3A Systems, LLC. --> # OpenIG UI @@ -54,6 +55,16 @@ Final Memory: 18M/59M ------------------------------------------------------------------------ ``` +## Tests + +The QUnit suite in `src/test/js` runs in headless Chrome (Puppeteer downloads it during `npm install`) in the +Maven `test` phase, so `mvn verify` fails on a failing JavaScript test and `-DskipTests` skips the suite. +To run it on its own after a build: + +``` +>$ ./node/node node_modules/grunt-cli/bin/grunt test +``` + # Try It This is as simple as: diff --git a/openig-ui/package.json b/openig-ui/package.json index c19ada1df..97120522a 100644 --- a/openig-ui/package.json +++ b/openig-ui/package.json @@ -13,7 +13,7 @@ "grunt-cli": "1.2.0", "grunt-contrib-copy": "1.0.0", "grunt-contrib-less": "1.3.0", - "grunt-contrib-qunit": "1.3.0", + "grunt-contrib-qunit": "10.2.0", "grunt-contrib-requirejs": "1.0.0", "grunt-contrib-watch": "1.0.0", "grunt-eslint": "19.0.0", @@ -22,6 +22,7 @@ "grunt-sync": "0.8.1", "less-plugin-clean-css": "1.5.1", "lodash": ">=4.18.0", + "qunit": "2.26.0", "requirejs": "2.3.7", "es5-ext": "0.10.53" }, diff --git a/openig-ui/pom.xml b/openig-ui/pom.xml index b411fe776..60d2820f2 100644 --- a/openig-ui/pom.xml +++ b/openig-ui/pom.xml @@ -13,6 +13,7 @@ information: "Portions copyright [year] [name of copyright owner]". Copyright 2014-2016 ForgeRock AS. + Portions Copyright 2026 3A Systems, LLC. --> @@ -92,6 +93,16 @@ build + + grunt-test + + grunt + + test + + test + + @@ -124,7 +135,7 @@ org.openidentityplatform.commons.ui.libs - less,qunit,r + less,r js ${project.build.directory}/compose/libs false @@ -140,7 +151,6 @@ org.openidentityplatform.commons.ui.libs - qunit css ${project.build.directory}/compose/css false @@ -178,20 +188,6 @@ true - - copy-dependencies-qunit - process-resources - - copy-dependencies - - - qunit - ${basedir}/target/test/libs - false - false - true - - unpack-codemirror process-resources @@ -236,18 +232,6 @@ 1.15.4 js - - org.openidentityplatform.commons.ui.libs - qunit - 1.15.0 - js - - - org.openidentityplatform.commons.ui.libs - qunit - 1.15.0 - css - org.openidentityplatform.commons.ui.libs d3 diff --git a/openig-ui/src/main/resources/css/structure.less b/openig-ui/src/main/resources/css/structure.less index 913b8c436..2b140fd52 100644 --- a/openig-ui/src/main/resources/css/structure.less +++ b/openig-ui/src/main/resources/css/structure.less @@ -12,6 +12,7 @@ * information: "Portions copyright [year] [name of copyright owner]". * * Copyright 2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ /* @@ -29,7 +30,7 @@ @import "awesome-bootstrap-checkbox.css"; @import "titatoggle-1.2.6-min.css"; @import "dragula-3.6.7-min.css"; -@import "../libs/CodeMirror-4.10.0/lib/codemirror.css"; +@import "../libs/codemirror5-4.10.0/lib/codemirror.css"; /* forgerock CSS */ @import "common/forgerock-variables.less"; diff --git a/openig-ui/src/test/js/config.js b/openig-ui/src/test/js/config.js index 4f200328e..674862d19 100644 --- a/openig-ui/src/test/js/config.js +++ b/openig-ui/src/test/js/config.js @@ -12,7 +12,7 @@ * information: "Portions copyright [year] [name of copyright owner]". * * Copyright 2016 ForgeRock AS. - * Portions copyright 2025 3A Systems LLC. + * Portions copyright 2025-2026 3A Systems LLC. */ require.config({ @@ -24,6 +24,9 @@ require.config({ }, baseUrl: "../www", paths: { + // The application is started from its unbundled sources: the optimised main.js carries its own copy of + // the libraries this page has already loaded (jQuery, lodash, ...), which would then exist twice. + main: "../compose/main", jquery: "libs/jquery-3.7.1-min", doTimeout: "libs/jquery.ba-dotimeout-1.0-min", lodash: "libs/lodash-3.10.1-min", @@ -42,13 +45,15 @@ require.config({ require([ "jquery", - "org/forgerock/openig/ui/common/main/MockServer" -], ($, MockServer) => { + "org/forgerock/openig/ui/common/main/MockServer", + "../test/run" +], ($, MockServer, run) => { $("head", document).append(""); - require(["main", "../test/run"], (appMain, run) => { - run(MockServer.instance); - }); + // Register for the application's initialisation before starting it, so that the event cannot be missed. + run(MockServer.instance); + + require(["main"]); }); diff --git a/openig-ui/src/test/js/run.js b/openig-ui/src/test/js/run.js index f02c5d1c4..622471f10 100644 --- a/openig-ui/src/test/js/run.js +++ b/openig-ui/src/test/js/run.js @@ -12,6 +12,7 @@ * information: "Portions copyright [year] [name of copyright owner]". * * Copyright 2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ /*global define, require, QUnit, localStorage, Backbone, _ */ @@ -20,62 +21,64 @@ define([ "jquery", "doTimeout", "org/forgerock/commons/ui/common/util/Constants", - "org/forgerock/commons/ui/common/main/EventManager", - "../test/tests/OpenIGValidatorsTests", - "../test/tests/TransformServiceTests", - "../test/tests/DataFilterTests", - "../test/tests/getLoggedUser" + "org/forgerock/commons/ui/common/main/EventManager" ], ( $, doTimeout, constants, - eventManager, - openIGValidatorsTests, - transformServiceTests, - dataFilterTests, - getLoggedUser) => { + eventManager) => { $.doTimeout = function (name, time, func) { func(); // run the function immediately rather than delayed. }; - // TODO: Remove this after upgrade to newer phantomjs - if (!Function.prototype.bind) { - // eslint-disable-next-line no-extend-native - Function.prototype.bind = function (otherThis) { - return _.bind(this, otherThis); - }; - } - return function (server) { eventManager.registerListener(constants.EVENT_APP_INITIALIZED, () => { - require("ThemeManager").getTheme().then(() => { - QUnit.testStart((testDetails) => { - console.log(`Starting ${testDetails.module}":"${testDetails.name}(${testDetails.testNumber})`); - - const vm = require("org/forgerock/commons/ui/common/main/ViewManager"); + // The test suites and their dependencies resolve through the require.config of main.js, so they are + // only loaded here, once the application is up. ViewManager and Configuration are requested explicitly: + // the application itself loads ViewManager asynchronously while navigating to its first view, so a + // synchronous require() from testStart is not guaranteed to find it loaded yet. + require([ + "ThemeManager", + "org/forgerock/commons/ui/common/main/ViewManager", + "org/forgerock/commons/ui/common/main/Configuration", + "../test/tests/OpenIGValidatorsTests", + "../test/tests/TransformServiceTests", + "../test/tests/DataFilterTests", + "../test/tests/getLoggedUser" + ], ( + ThemeManager, + ViewManager, + Configuration, + openIGValidatorsTests, + transformServiceTests, + dataFilterTests, + getLoggedUser) => { + ThemeManager.getTheme().then(() => { + QUnit.testStart((testDetails) => { + console.log(`Starting ${testDetails.module}: ${testDetails.name}`); - vm.currentView = null; - vm.currentDialog = null; - vm.currentViewArgs = null; - vm.currentDialogArgs = null; - - require("org/forgerock/commons/ui/common/main/Configuration").baseTemplate = null; - }); + ViewManager.currentView = null; + ViewManager.currentDialog = null; + ViewManager.currentViewArgs = null; + ViewManager.currentDialogArgs = null; + Configuration.baseTemplate = null; + }); - _.delay(() => { - QUnit.start(); - openIGValidatorsTests.executeAll(server, getLoggedUser()); - transformServiceTests.executeAll(server); - dataFilterTests.executeAll(server); - }, 500); + _.delay(() => { + openIGValidatorsTests.executeAll(server, getLoggedUser()); + transformServiceTests.executeAll(server); + dataFilterTests.executeAll(server); + QUnit.start(); + }, 500); - QUnit.done(() => { - localStorage.clear(); - Backbone.history.stop(); - window.location.hash = ""; + QUnit.done(() => { + localStorage.clear(); + Backbone.history.stop(); + window.location.hash = ""; + }); }); }); }); diff --git a/openig-ui/src/test/js/tests/DataFilterTests.js b/openig-ui/src/test/js/tests/DataFilterTests.js index cca1028f2..0f5890642 100644 --- a/openig-ui/src/test/js/tests/DataFilterTests.js +++ b/openig-ui/src/test/js/tests/DataFilterTests.js @@ -12,6 +12,7 @@ * information: "Portions copyright [year] [name of copyright owner]". * * Copyright 2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ define([ @@ -20,9 +21,9 @@ define([ DataFilter ) => ({ executeAll () { - module("DataFilter Tests"); + QUnit.module("DataFilter Tests"); - QUnit.asyncTest("DataFilter", (assert) => { + QUnit.test("DataFilter", (assert) => { const data = { id: "exampleapp", name: "Example app 1", @@ -78,8 +79,6 @@ define([ testDataFilter("uri:http://app.ex", true); testDataFilter("uri:http://:app.ex", false); testDataFilter("id:exa uri:http://app.ex", true); - - QUnit.start(); }); } }) diff --git a/openig-ui/src/test/js/tests/OpenIGValidatorsTests.js b/openig-ui/src/test/js/tests/OpenIGValidatorsTests.js index f71f4178d..19c357795 100644 --- a/openig-ui/src/test/js/tests/OpenIGValidatorsTests.js +++ b/openig-ui/src/test/js/tests/OpenIGValidatorsTests.js @@ -12,6 +12,7 @@ * information: "Portions copyright [year] [name of copyright owner]". * * Copyright 2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ define([ @@ -24,12 +25,12 @@ define([ OpenIGValidators ) => ({ executeAll () { - module("OpenIG Tests"); + QUnit.module("OpenIG Tests"); // when validators invoke `callback()` without argument, that means the input is valid const isValid = (result) => (result === undefined); - QUnit.asyncTest("BaseURI Validator", (assert) => { + QUnit.test("BaseURI Validator", (assert) => { const testBaseURI = (value, callbackCheck) => { OpenIGValidators.baseURI.validator(undefined, this.fakeInputElement(value), (result) => { assert.ok( @@ -63,11 +64,9 @@ define([ testBaseURI("http://www.example.org:8080/subpath", (result) => ( _.isEqual(result, [i18n.t("common.form.validation.baseURIContainsPath")]) )); - - QUnit.start(); }); - QUnit.asyncTest("urlCompatible Validator", (assert) => { + QUnit.test("urlCompatible Validator", (assert) => { const testURLCompatible = (value, callbackCheck) => { OpenIGValidators.urlCompatible.validator(undefined, this.fakeInputElement(value), (result) => { assert.ok( @@ -98,11 +97,9 @@ define([ testURLCompatible("id=bad", (result) => ( _.isEqual(result, [i18n.t("common.form.validation.notUrlCompatible")]) )); - - QUnit.start(); }); - QUnit.asyncTest("customValidator Validator", (assert) => { + QUnit.test("customValidator Validator", (assert) => { const testCustomValidator = (value, callbackCheck) => { OpenIGValidators.customValidator.validator( undefined, @@ -125,12 +122,10 @@ define([ // Invalid values testCustomValidator(undefined, (result) => (result === undefined)); - - QUnit.start(); }); - QUnit.asyncTest("greaterThanOrEqualMin Validator", (assert) => { + QUnit.test("greaterThanOrEqualMin Validator", (assert) => { const testMinValue = (value, min, callbackCheck) => { OpenIGValidators.greaterThanOrEqualMin.validator( undefined, @@ -167,11 +162,9 @@ define([ } )]) )); - - QUnit.start(); }); - QUnit.asyncTest("lessThanOrEqualMax Validator", (assert) => { + QUnit.test("lessThanOrEqualMax Validator", (assert) => { const testMaxValue = (value, max, callbackCheck) => { OpenIGValidators.lessThanOrEqualMax.validator( undefined, @@ -207,8 +200,6 @@ define([ } )]) )); - - QUnit.start(); }); }, diff --git a/openig-ui/src/test/js/tests/TransformServiceTests.js b/openig-ui/src/test/js/tests/TransformServiceTests.js index d8c202cb9..6b2f40305 100644 --- a/openig-ui/src/test/js/tests/TransformServiceTests.js +++ b/openig-ui/src/test/js/tests/TransformServiceTests.js @@ -12,6 +12,7 @@ * information: "Portions copyright [year] [name of copyright owner]". * * Copyright 2016 ForgeRock AS. + * Portions Copyright 2026 3A Systems, LLC. */ define([ @@ -30,27 +31,30 @@ define([ executeAll () { QUnit.module("TransformService TestSuite"); - QUnit.asyncTest("Should fail when transforming undefined model", (assert) => { + // assert.throws validator: the error is a TransformServiceException of the given type + const transformError = (errorType) => (error) => ( + error.name === "TransformServiceException" && error.errorType === errorType + ); + + QUnit.test("Should fail when transforming undefined model", (assert) => { assert.throws(() => { transformService.transformRoute(undefined); }, - transformService.TransformServiceException("invalidModel"), + transformError("invalidModel"), "Passing an undefined throws an error" ); - QUnit.start(); }); - QUnit.asyncTest("Should fail when transforming null model", (assert) => { + QUnit.test("Should fail when transforming null model", (assert) => { assert.throws(() => { transformService.transformRoute(null); }, - transformService.TransformServiceException("invalidModel"), + transformError("invalidModel"), "Passing a null throws an error" ); - QUnit.start(); }); - QUnit.asyncTest("Should fail when no 'name' attribute is provided", (assert) => { + QUnit.test("Should fail when no 'name' attribute is provided", (assert) => { const applicationWithEmptyName = new RouteModel({ id: "modelID", name: "" @@ -59,13 +63,12 @@ define([ assert.throws(() => { transformService.transformRoute(applicationWithEmptyName); }, - transformService.TransformServiceException("invalidModel"), + transformError("invalidModel"), "Passing model with empty name throws an error" ); - QUnit.start(); }); - QUnit.asyncTest("Should fail when no 'baseURI' attribute is provided", (assert) => { + QUnit.test("Should fail when no 'baseURI' attribute is provided", (assert) => { const applicationWithEmptyBaseUrl = new RouteModel({ id: "modelID", url: "" @@ -74,13 +77,12 @@ define([ assert.throws(() => { transformService.transformRoute(applicationWithEmptyBaseUrl); }, - transformService.TransformServiceException("invalidModel"), + transformError("invalidModel"), "Passing model with empty baseURL throws an error" ); - QUnit.start(); }); - QUnit.asyncTest("Should transform 'path condition' attribute", (assert) => { + QUnit.test("Should transform 'path condition' attribute", (assert) => { const applicationWithPathCondition = new RouteModel({ id: "example", name: "example", @@ -102,10 +104,9 @@ define([ }, "Wrong top level properties" ); - QUnit.start(); }); - QUnit.asyncTest("Should transform 'expression condition' attribute", (assert) => { + QUnit.test("Should transform 'expression condition' attribute", (assert) => { const applicationWithPathCondition = new RouteModel({ id: "example", name: "example", @@ -127,10 +128,9 @@ define([ }, "Wrong top level properties" ); - QUnit.start(); }); - QUnit.asyncTest("Should map basic model properties to top level route attributes", (assert) => { + QUnit.test("Should map basic model properties to top level route attributes", (assert) => { const route = new RouteModel({ id: "modelID", name: "Router", @@ -146,10 +146,9 @@ define([ }, "Wrong top level properties" ); - QUnit.start(); }); - QUnit.asyncTest("Should transform ThrottlingFilter", (assert) => { + QUnit.test("Should transform ThrottlingFilter", (assert) => { assert.deepEqual(transformService.throttlingFilter({ numberOfRequests: 60, durationValue: 1, @@ -167,10 +166,9 @@ define([ }, "Wrong JSON for ThrottlingFilter" ); - QUnit.start(); }); - QUnit.asyncTest("Should transform OAuth2ClientFilter", (assert) => { + QUnit.test("Should transform OAuth2ClientFilter", (assert) => { assert.deepEqual(transformService.oAuth2ClientFilter({ clientEndpoint: "/openid", clientId: "*****", @@ -223,20 +221,18 @@ define([ }, "Wrong JSON for OAuth2ClientFilter" ); - QUnit.start(); }); - QUnit.asyncTest("Should throw exception for unknown filter type", (assert) => { + QUnit.test("Should throw exception for unknown filter type", (assert) => { assert.throws(() => { transformService.transformFilter({ type: "UnknownTypeOfFilter" }); }, - transformService.TransformServiceException("invalidModel"), + transformError("unknownFilterType"), "Passing 'UnknownTypeOfFilter' throws an error" ); - QUnit.start(); }); - QUnit.asyncTest("Should pass even if all filters are disabled", (assert) => { + QUnit.test("Should pass even if all filters are disabled", (assert) => { const route = new RouteModel({ id: "modelID", name: "Router", @@ -261,10 +257,9 @@ define([ }, "Wrong number of filters when all of them are disabled" ); - QUnit.start(); }); - QUnit.asyncTest("Should pass only enabled filters", (assert) => { + QUnit.test("Should pass only enabled filters", (assert) => { const route = new RouteModel({ id: "modelID", name: "Router", @@ -304,10 +299,9 @@ define([ }, "Wrong number of filters when all of them are disabled" ); - QUnit.start(); }); - QUnit.asyncTest("Should activate route level request capture", (assert) => { + QUnit.test("Should activate route level request capture", (assert) => { const route = new RouteModel({ id: "modelID", name: "Router", @@ -330,10 +324,9 @@ define([ }, "Expecting only 'request' for capture" ); - QUnit.start(); }); - QUnit.asyncTest("Should activate route level response capture", (assert) => { + QUnit.test("Should activate route level response capture", (assert) => { const route = new RouteModel({ id: "modelID", name: "Router", @@ -356,10 +349,9 @@ define([ }, "Expecting only 'response' for capture" ); - QUnit.start(); }); - QUnit.asyncTest("Should activate request and response route level capture", (assert) => { + QUnit.test("Should activate request and response route level capture", (assert) => { const route = new RouteModel({ id: "modelID", name: "Router", @@ -382,10 +374,9 @@ define([ }, "Expecting both 'request' & 'response' for capture" ); - QUnit.start(); }); - QUnit.asyncTest("Should activate outbound request capture", (assert) => { + QUnit.test("Should activate outbound request capture", (assert) => { const route = new RouteModel({ id: "modelID", name: "Router", @@ -415,10 +406,9 @@ define([ }, "Expecting only 'request' for capture" ); - QUnit.start(); }); - QUnit.asyncTest("Should activate outbound response capture", (assert) => { + QUnit.test("Should activate outbound response capture", (assert) => { const route = new RouteModel({ id: "modelID", name: "Router", @@ -449,10 +439,9 @@ define([ }, "Expecting only 'response' for capture" ); - QUnit.start(); }); - QUnit.asyncTest("Should activate request and response outbound capture", (assert) => { + QUnit.test("Should activate request and response outbound capture", (assert) => { const route = new RouteModel({ id: "modelID", name: "Router", @@ -483,10 +472,9 @@ define([ }, "Expecting both 'request' & 'response' for capture" ); - QUnit.start(); }); - QUnit.asyncTest("Should activate entity capture", (assert) => { + QUnit.test("Should activate entity capture", (assert) => { const route = new RouteModel({ id: "modelID", name: "Router", @@ -518,10 +506,9 @@ define([ }, "Expecting entity capture enabled" ); - QUnit.start(); }); - QUnit.asyncTest("Should activate entity capture", (assert) => { + QUnit.test("Should activate entity capture", (assert) => { const route = new RouteModel({ id: "modelID", name: "Router", @@ -543,10 +530,9 @@ define([ }, "Expecting entity capture enabled" ); - QUnit.start(); }); - QUnit.asyncTest("Should enable statistics", (assert) => { + QUnit.test("Should enable statistics", (assert) => { const route = new RouteModel({ id: "modelID", name: "Router", @@ -565,10 +551,9 @@ define([ }, "Expecting monitor enabled" ); - QUnit.start(); }); - QUnit.asyncTest("Should enable statistics and add percentiles", (assert) => { + QUnit.test("Should enable statistics and add percentiles", (assert) => { const route = new RouteModel({ id: "modelID", name: "Router", @@ -591,10 +576,9 @@ define([ }, "Expecting monitor enabled with percentiles" ); - QUnit.start(); }); - QUnit.asyncTest("Should disable statistics and remove percentiles", (assert) => { + QUnit.test("Should disable statistics and remove percentiles", (assert) => { const route = new RouteModel({ id: "modelID", name: "Router", @@ -614,10 +598,9 @@ define([ }, "Expecting monitor disabled" ); - QUnit.start(); }); - QUnit.asyncTest("Should produce contextual info for multiple headers", (assert) => { + QUnit.test("Should produce contextual info for multiple headers", (assert) => { const filter = { type: "PolicyEnforcementFilter", openamUrl: "http://openam.example.com/openam", @@ -650,10 +633,9 @@ define([ }, "Expecting policy enforcement filter with headers in environment" ); - QUnit.start(); }); - QUnit.asyncTest("Should not produce contextual info for empty header", (assert) => { + QUnit.test("Should not produce contextual info for empty header", (assert) => { const filter = { type: "PolicyEnforcementFilter", openamUrl: "http://openam.example.com/openam", @@ -682,10 +664,9 @@ define([ }, "Expecting policy enforcement filter with empty environment" ); - QUnit.start(); }); - QUnit.asyncTest("Should produce contextual info with client IP address", (assert) => { + QUnit.test("Should produce contextual info with client IP address", (assert) => { const filter = { type: "PolicyEnforcementFilter", openamUrl: "http://openam.example.com/openam", @@ -717,10 +698,9 @@ define([ }, "Expecting policy enforcement filter with IP in environment" ); - QUnit.start(); }); - QUnit.asyncTest("Should transform PolicyEnforcementFilter with ssoTokenSubject", (assert) => { + QUnit.test("Should transform PolicyEnforcementFilter with ssoTokenSubject", (assert) => { // Optional values omitted intentionally assert.deepEqual(transformService.policyEnforcementFilter( { @@ -741,10 +721,9 @@ define([ }, "Wrong JSON for PolicyEnforcementFilter" ); - QUnit.start(); }); - QUnit.asyncTest("Should transform PolicyEnforcementFilter with jwtSubject", (assert) => { + QUnit.test("Should transform PolicyEnforcementFilter with jwtSubject", (assert) => { // Optional values set to empty strings intentionally assert.deepEqual(transformService.policyEnforcementFilter( { @@ -768,10 +747,9 @@ define([ }, "Wrong JSON for PolicyEnforcementFilter" ); - QUnit.start(); }); - QUnit.asyncTest("Should transform PolicyEnforcementFilter with all properties", (assert) => { + QUnit.test("Should transform PolicyEnforcementFilter with all properties", (assert) => { // Optional values are correctly valued assert.deepEqual(transformService.policyEnforcementFilter( { @@ -800,10 +778,9 @@ define([ }, "Wrong JSON for PolicyEnforcementFilter" ); - QUnit.start(); }); - QUnit.asyncTest("Should fail to transform PolicyEnforcementFilter with no subject", (assert) => { + QUnit.test("Should fail to transform PolicyEnforcementFilter with no subject", (assert) => { const inBlock = () => { transformService.policyEnforcementFilter( { @@ -812,11 +789,10 @@ define([ pepPassword: "secret" }); }; - assert.throws(inBlock, transformService.TransformServiceException("invalidModel"), "Must provide subject"); - QUnit.start(); + assert.throws(inBlock, transformError("invalidModel"), "Must provide subject"); }); - QUnit.asyncTest("Transform SingleSignOnFilter", (assert) => { + QUnit.test("Transform SingleSignOnFilter", (assert) => { assert.deepEqual(transformService.singleSignOnFilter( { type: "SingleSignOnFilter", @@ -852,27 +828,24 @@ define([ }, "SingleSignOnFilter with only openamUrl" ); - QUnit.start(); }); - QUnit.asyncTest("Should return generated expression", (assert) => { + QUnit.test("Should return generated expression", (assert) => { const path = "/myApplication"; assert.deepEqual(transformService.generateCondition(path), "${matches(request.uri.path, '^/myApplication')}", "Expecting condition expression" ); - QUnit.start(); }); - QUnit.asyncTest("Should return undefined if no path defined", (assert) => { + QUnit.test("Should return undefined if no path defined", (assert) => { const path = ""; assert.equal(transformService.generateCondition(path), undefined, "Expecting undefined" ); - QUnit.start(); }); } })); diff --git a/openig-ui/src/test/resources/qunit.html b/openig-ui/src/test/resources/qunit.html index 93c988362..c22428564 100644 --- a/openig-ui/src/test/resources/qunit.html +++ b/openig-ui/src/test/resources/qunit.html @@ -1,11 +1,12 @@ ForgeRock OpenIG UI - QUnit Tests - + @@ -24,7 +25,7 @@ - +