[IMP] web: backport of new asserts
This rev. is a complement to the partial backport49e78f46ofabf32b8. In addition to the helpers, we also backport the asserts (like isVisible, containsOnce...). closes odoo/odoo#28994
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
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.
|
||||
*/
|
||||
|
||||
var Widget = require('web.Widget');
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 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} w
|
||||
* @param {string} className
|
||||
* @param {boolean} shouldHaveClass
|
||||
* @param {string} [msg]
|
||||
*/
|
||||
function _checkClass(w, className, shouldHaveClass, msg) {
|
||||
var $el = w instanceof Widget ? w.$el :
|
||||
w instanceof HTMLElement ? $(w) :
|
||||
w; // jquery element
|
||||
|
||||
if ($el.length !== 1) {
|
||||
var descr = `${shouldHaveClass ? 'hasClass' : 'doesNotHaveClass'} ${className}`;
|
||||
QUnit.assert.ok(false, `Assertion '${descr}' targets ${$el.length} elements instead of 1`);
|
||||
} else {
|
||||
msg = msg || `target ${$el.selector || ''} should ${shouldHaveClass ? '' : 'not'} have class ${className}`;
|
||||
var hasClass = $el.hasClass(className);
|
||||
var condition = shouldHaveClass ? hasClass : !hasClass;
|
||||
QUnit.assert.ok(condition, 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} w
|
||||
* @param {boolean} shouldBeVisible
|
||||
* @param {string} [msg]
|
||||
*/
|
||||
function _checkVisible(w, shouldBeVisible, msg) {
|
||||
var $el = w instanceof Widget ? w.$el :
|
||||
w instanceof HTMLElement ? $(w) :
|
||||
w; // jquery element
|
||||
|
||||
if ($el.length !== 1) {
|
||||
var descr = `${shouldBeVisible ? 'isVisible' : 'isNotVisible'}`;
|
||||
QUnit.assert.ok(false, `Assertion '${descr}' targets ${$el.length} elements instead of 1`);
|
||||
} else {
|
||||
msg = msg || `target ${$el.selector} should ${shouldBeVisible ? '' : 'not'} be visible`;
|
||||
var isVisible = $el.is(':visible');
|
||||
var 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} w
|
||||
* @param {string} selector
|
||||
* @param {number} n
|
||||
* @param {string} [msg]
|
||||
*/
|
||||
function containsN(w, selector, n, msg) {
|
||||
if (typeof n !== 'number') {
|
||||
throw Error("containsN assert should be called with a number as third argument");
|
||||
}
|
||||
var $el = w instanceof Widget ? w.$el :
|
||||
w instanceof HTMLElement ? $(w) :
|
||||
w; // jquery element
|
||||
|
||||
var $matches = $el.find(selector);
|
||||
if (!msg) {
|
||||
msg = `Selector '${selector}' should have exactly ${n} matches`;
|
||||
if ($el.selector) {
|
||||
msg += ` (inside '${$el.selector}')`;
|
||||
}
|
||||
}
|
||||
QUnit.assert.strictEqual($matches.length, n, msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that the target element (described by widget/jquery or html element)
|
||||
* contains exactly 1 match for the selector.
|
||||
*
|
||||
* @param {Widget|jQuery|HTMLElement} 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)
|
||||
* contains exactly 0 match for the selector.
|
||||
*
|
||||
* @param {Widget|jQuery|HTMLElement} 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)
|
||||
* - 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} 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} 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} w
|
||||
* @param {string} attr
|
||||
* @param {string} value
|
||||
* @param {string} [msg]
|
||||
*/
|
||||
function hasAttrValue(w, attr, value, msg) {
|
||||
var $el = w instanceof Widget ? w.$el :
|
||||
w instanceof HTMLElement ? $(w) :
|
||||
w; // jquery element
|
||||
|
||||
if ($el.length !== 1) {
|
||||
var descr = `hasAttrValue (${attr}: ${value})`;
|
||||
QUnit.assert.ok(false, `Assertion '${descr}' targets ${$el.length} elements instead of 1`);
|
||||
} else {
|
||||
msg = msg || `attribute '${attr}' of target ${$el.selector || ''} 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} 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} w
|
||||
* @param {string} [msg]
|
||||
*/
|
||||
function isNotVisible(w, msg) {
|
||||
_checkVisible(w, false, msg);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Exposed API
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
QUnit.assert.containsOnce = containsOnce;
|
||||
QUnit.assert.containsNone = containsNone;
|
||||
QUnit.assert.containsN = containsN;
|
||||
|
||||
QUnit.assert.hasClass = hasClass;
|
||||
QUnit.assert.doesNotHaveClass = doesNotHaveClass;
|
||||
|
||||
QUnit.assert.hasAttrValue = hasAttrValue;
|
||||
|
||||
QUnit.assert.isVisible = isVisible;
|
||||
QUnit.assert.isNotVisible = isNotVisible;
|
||||
|
||||
});
|
||||
@@ -434,6 +434,8 @@
|
||||
<t t-call-assets="web.assets_common" t-css="false"/>
|
||||
<t t-call-assets="web.assets_backend" t-css="false"/>
|
||||
|
||||
<script type="text/javascript" src="/web/static/tests/helpers/qunit_asserts.js"></script>
|
||||
|
||||
<!-- add lazy-loaded libs to make tests synchronous -->
|
||||
<link rel="stylesheet" href="/web/static/lib/fullcalendar/css/fullcalendar.css"/>
|
||||
<script type="text/javascript" src="/web/static/lib/fullcalendar/js/fullcalendar.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user