summaryrefslogtreecommitdiff
path: root/addons/web/static/tests/helpers/qunit_asserts.js
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/web/static/tests/helpers/qunit_asserts.js
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/web/static/tests/helpers/qunit_asserts.js')
-rw-r--r--addons/web/static/tests/helpers/qunit_asserts.js244
1 files changed, 244 insertions, 0 deletions
diff --git a/addons/web/static/tests/helpers/qunit_asserts.js b/addons/web/static/tests/helpers/qunit_asserts.js
new file mode 100644
index 00000000..69cf2807
--- /dev/null
+++ b/addons/web/static/tests/helpers/qunit_asserts.js
@@ -0,0 +1,244 @@
+odoo.define('web.qunit_asserts', function (require) {
+ "use strict";
+
+ /**
+ * In this file, we extend QUnit by adding some specialized assertions. The goal
+ * of these new assertions is twofold:
+ * - ease of use: they should allow us to simplify some common complex assertions
+ * - safer: these assertions will fail when some preconditions are not met.
+ *
+ * For example, the assert.isVisible assertion will also check that the target
+ * matches exactly one element.
+ */
+
+ const Widget = require('web.Widget');
+
+ /** @todo use testUtilsDom.getNode to extract the element from the 'w' argument */
+
+ //-------------------------------------------------------------------------
+ // Private functions
+ //-------------------------------------------------------------------------
+
+ /**
+ * Helper function, to check if a given element
+ * - is unique (if it is a jquery node set)
+ * - has (or has not) a css class
+ *
+ * @private
+ * @param {Widget|jQuery|HTMLElement|owl.Component} w
+ * @param {string} className
+ * @param {boolean} shouldHaveClass
+ * @param {string} [msg]
+ */
+ function _checkClass(w, className, shouldHaveClass, msg) {
+ if (w instanceof jQuery && w.length !== 1) {
+ const assertion = shouldHaveClass ? 'hasClass' : 'doesNotHaveClass';
+ QUnit.assert.ok(false, `Assertion '${assertion} ${className}' targets ${w.length} elements instead of 1`);
+ }
+
+ const el = w instanceof Widget || w instanceof owl.Component ? w.el :
+ w instanceof jQuery ? w[0] : w;
+
+ msg = msg || `target should ${shouldHaveClass ? 'have' : 'not have'} class ${className}`;
+ const isFalse = className.split(" ").some(cls => {
+ const hasClass = el.classList.contains(cls);
+ return shouldHaveClass ? !hasClass : hasClass;
+ });
+ QUnit.assert.ok(!isFalse, msg);
+ }
+
+ /**
+ * Helper function, to check if a given element
+ * - is unique (if it is a jquery node set)
+ * - is (or not) visible
+ *
+ * @private
+ * @param {Widget|jQuery|HTMLElement|owl.Component} w
+ * @param {boolean} shouldBeVisible
+ * @param {string} [msg]
+ */
+ function _checkVisible(w, shouldBeVisible, msg) {
+ if (w instanceof jQuery && w.length !== 1) {
+ const assertion = shouldBeVisible ? 'isVisible' : 'isNotVisible';
+ QUnit.assert.ok(false, `Assertion '${assertion}' targets ${w.length} elements instead of 1`);
+ }
+
+ const el = w instanceof Widget || w instanceof owl.Component ? w.el :
+ w instanceof jQuery ? w[0] : w;
+
+ msg = msg || `target should ${shouldBeVisible ? '' : 'not'} be visible`;
+ let isVisible = el &&
+ el.offsetWidth &&
+ el.offsetHeight;
+ if (isVisible) {
+ // This computation is a little more heavy and we only want to perform it
+ // if the above assertion has failed.
+ const rect = el.getBoundingClientRect();
+ isVisible = rect.width + rect.height;
+ }
+ const condition = shouldBeVisible ? isVisible : !isVisible;
+ QUnit.assert.ok(condition, msg);
+ }
+
+ //-------------------------------------------------------------------------
+ // Public functions
+ //-------------------------------------------------------------------------
+
+ /**
+ * Checks that the target element (described by widget/jquery or html element)
+ * contains exactly n matches for the selector.
+ *
+ * Example: assert.containsN(document.body, '.modal', 0)
+ *
+ * @param {Widget|jQuery|HTMLElement|owl.Component} w
+ * @param {string} selector
+ * @param {number} n
+ * @param {string} [msg]
+ */
+ function containsN(w, selector, n, msg) {
+ if (typeof n !== 'number') {
+ throw new Error("containsN assert should be called with a number as third argument");
+ }
+ let matches = [];
+ if (w instanceof owl.Component) {
+ if (!w.el) {
+ throw new Error(`containsN assert with selector '${selector}' called on an unmounted component`);
+ }
+ matches = w.el.querySelectorAll(selector);
+ } else {
+ const $el = w instanceof Widget ? w.$el :
+ w instanceof HTMLElement ? $(w) :
+ w; // jquery element
+ matches = $el.find(selector);
+ }
+ if (!msg) {
+ msg = `Selector '${selector}' should have exactly ${n} matches (inside the target)`;
+ }
+ QUnit.assert.strictEqual(matches.length, n, msg);
+ }
+
+ /**
+ * Checks that the target element (described by widget/jquery or html element)
+ * contains exactly 0 match for the selector.
+ *
+ * @param {Widget|jQuery|HTMLElement|owl.Component} w
+ * @param {string} selector
+ * @param {string} [msg]
+ */
+ function containsNone(w, selector, msg) {
+ containsN(w, selector, 0, msg);
+ }
+
+ /**
+ * Checks that the target element (described by widget/jquery or html element)
+ * contains exactly 1 match for the selector.
+ *
+ * @param {Widget|jQuery|HTMLElement|owl.Component} w
+ * @param {string} selector
+ * @param {string} [msg]
+ */
+ function containsOnce(w, selector, msg) {
+ containsN(w, selector, 1, msg);
+ }
+
+ /**
+ * Checks that the target element (described by widget/jquery or html element)
+ * - exists
+ * - is unique
+ * - has the given class (specified by className)
+ *
+ * Note that it uses the hasClass jQuery method, so it can be used to check the
+ * presence of more than one class ('some-class other-class'), but it is a
+ * little brittle, because it depends on the order of these classes:
+ *
+ * div.a.b.c: has class 'a b c', but does not have class 'a c b'
+ *
+ * @param {Widget|jQuery|HTMLElement|owl.Component} w
+ * @param {string} className
+ * @param {string} [msg]
+ */
+ function hasClass(w, className, msg) {
+ _checkClass(w, className, true, msg);
+ }
+
+ /**
+ * Checks that the target element (described by widget/jquery or html element)
+ * - exists
+ * - is unique
+ * - does not have the given class (specified by className)
+ *
+ * @param {Widget|jQuery|HTMLElement|owl.Component} w
+ * @param {string} className
+ * @param {string} [msg]
+ */
+ function doesNotHaveClass(w, className, msg) {
+ _checkClass(w, className, false, msg);
+ }
+
+ /**
+ * Checks that the target element (described by widget/jquery or html element)
+ * - exists
+ * - is unique
+ * - has the given attribute with the proper value
+ *
+ * @param {Widget|jQuery|HTMLElement|owl.Component} w
+ * @param {string} attr
+ * @param {string} value
+ * @param {string} [msg]
+ */
+ function hasAttrValue(w, attr, value, msg) {
+ const $el = w instanceof Widget ? w.$el :
+ w instanceof HTMLElement ? $(w) :
+ w; // jquery element
+
+ if ($el.length !== 1) {
+ const descr = `hasAttrValue (${attr}: ${value})`;
+ QUnit.assert.ok(false,
+ `Assertion '${descr}' targets ${$el.length} elements instead of 1`
+ );
+ } else {
+ msg = msg || `attribute '${attr}' of target should be '${value}'`;
+ QUnit.assert.strictEqual($el.attr(attr), value, msg);
+ }
+ }
+
+ /**
+ * Checks that the target element (described by widget/jquery or html element)
+ * - exists
+ * - is visible (as far as jQuery can tell: not in display none, ...)
+ *
+ * @param {Widget|jQuery|HTMLElement|owl.Component} w
+ * @param {string} [msg]
+ */
+ function isVisible(w, msg) {
+ _checkVisible(w, true, msg);
+ }
+
+ /**
+ * Checks that the target element (described by widget/jquery or html element)
+ * - exists
+ * - is not visible (as far as jQuery can tell: display none, ...)
+ *
+ * @param {Widget|jQuery|HTMLElement|owl.Component} w
+ * @param {string} [msg]
+ */
+ function isNotVisible(w, msg) {
+ _checkVisible(w, false, msg);
+ }
+
+ //-------------------------------------------------------------------------
+ // Exposed API
+ //-------------------------------------------------------------------------
+
+ QUnit.assert.containsN = containsN;
+ QUnit.assert.containsNone = containsNone;
+ QUnit.assert.containsOnce = containsOnce;
+
+ QUnit.assert.hasClass = hasClass;
+ QUnit.assert.doesNotHaveClass = doesNotHaveClass;
+
+ QUnit.assert.hasAttrValue = hasAttrValue;
+
+ QUnit.assert.isVisible = isVisible;
+ QUnit.assert.isNotVisible = isNotVisible;
+});