Merge branch 'trunk' into fix/unit-tests
This commit is contained in:
commit
6feac59adf
|
@ -40,6 +40,7 @@ jobs:
|
||||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||||
E2E_SLACK_CHANNEL: ${{ secrets.SMOKE_TEST_SLACK_CHANNEL }}
|
E2E_SLACK_CHANNEL: ${{ secrets.SMOKE_TEST_SLACK_CHANNEL }}
|
||||||
UPDATE_WC: 1
|
UPDATE_WC: 1
|
||||||
|
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||||
run: |
|
run: |
|
||||||
npx wc-e2e test:e2e ./tests/e2e/specs/smoke-tests/update-woocommerce.js
|
npx wc-e2e test:e2e ./tests/e2e/specs/smoke-tests/update-woocommerce.js
|
||||||
npx wc-e2e test:e2e
|
npx wc-e2e test:e2e
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
name: Smoke test release
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
jobs:
|
||||||
|
login-run:
|
||||||
|
name: Daily smoke test on release.
|
||||||
|
runs-on: ubuntu-18.04
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: Create dirs.
|
||||||
|
run: |
|
||||||
|
mkdir -p code/woocommerce
|
||||||
|
mkdir -p package/woocommerce
|
||||||
|
mkdir -p tmp/woocommerce
|
||||||
|
mkdir -p node_modules
|
||||||
|
|
||||||
|
- name: Checkout code.
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
ref: trunk
|
||||||
|
|
||||||
|
- name: Install prerequisites.
|
||||||
|
run: |
|
||||||
|
npm install
|
||||||
|
composer install --no-dev
|
||||||
|
npm run build:assets
|
||||||
|
npm install jest
|
||||||
|
|
||||||
|
- name: Run smoke test.
|
||||||
|
env:
|
||||||
|
SMOKE_TEST_URL: ${{ secrets.RELEASE_TEST_URL }}
|
||||||
|
SMOKE_TEST_ADMIN_USER: ${{ secrets.RELEASE_TEST_ADMIN_USER }}
|
||||||
|
SMOKE_TEST_ADMIN_PASSWORD: ${{ secrets.RELEASE_TEST_ADMIN_PASSWORD }}
|
||||||
|
SMOKE_TEST_ADMIN_USER_EMAIL: ${{ secrets.RELEASE_TEST_ADMIN_USER_EMAIL }}
|
||||||
|
SMOKE_TEST_CUSTOMER_USER: ${{ secrets.RELEASE_TEST_CUSTOMER_USER }}
|
||||||
|
SMOKE_TEST_CUSTOMER_PASSWORD: ${{ secrets.RELEASE_TEST_CUSTOMER_PASSWORD }}
|
||||||
|
WC_E2E_SCREENSHOTS: 1
|
||||||
|
E2E_RETEST: 1
|
||||||
|
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||||
|
E2E_SLACK_CHANNEL: ${{ secrets.SMOKE_TEST_SLACK_CHANNEL }}
|
||||||
|
TEST_RELEASE: 1
|
||||||
|
UPDATE_WC: 1
|
||||||
|
DEFAULT_TIMEOUT_OVERRIDE: 120000
|
||||||
|
run: |
|
||||||
|
npx wc-e2e test:e2e ./tests/e2e/specs/smoke-tests/update-woocommerce.js
|
||||||
|
npx wc-e2e test:e2e
|
|
@ -5,6 +5,8 @@ on:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
stale:
|
stale:
|
||||||
|
if: |
|
||||||
|
! contains(github.event.issue.labels.*.name, 'enhancement')
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/stale@v3
|
- uses: actions/stale@v3
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,41 +1,27 @@
|
||||||
/*!
|
/*!
|
||||||
* SelectWoo 1.0.9
|
* Select2 4.0.3
|
||||||
* https://github.com/woocommerce/selectWoo
|
* https://select2.github.io
|
||||||
*
|
*
|
||||||
* Released under the MIT license
|
* Released under the MIT license
|
||||||
* https://github.com/woocommerce/selectWoo/blob/master/LICENSE.md
|
* https://github.com/select2/select2/blob/master/LICENSE.md
|
||||||
*/
|
*/
|
||||||
(function (factory) {
|
(function (factory) {
|
||||||
if (typeof define === 'function' && define.amd) {
|
if (typeof define === 'function' && define.amd) {
|
||||||
// AMD. Register as an anonymous module.
|
// AMD. Register as an anonymous module.
|
||||||
define(['jquery'], factory);
|
define(['jquery'], factory);
|
||||||
} else if (typeof module === 'object' && module.exports) {
|
} else if (typeof exports === 'object') {
|
||||||
// Node/CommonJS
|
// Node/CommonJS
|
||||||
module.exports = function (root, jQuery) {
|
factory(require('jquery'));
|
||||||
if (jQuery === undefined) {
|
|
||||||
// require('jQuery') returns a factory that requires window to
|
|
||||||
// build a jQuery instance, we normalize how we use modules
|
|
||||||
// that require this pattern but the window provided is a noop
|
|
||||||
// if it's defined (how jquery works)
|
|
||||||
if (typeof window !== 'undefined') {
|
|
||||||
jQuery = require('jquery');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
jQuery = require('jquery')(root);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
factory(jQuery);
|
|
||||||
return jQuery;
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
// Browser globals
|
// Browser globals
|
||||||
factory(jQuery);
|
factory(jQuery);
|
||||||
}
|
}
|
||||||
} (function (jQuery) {
|
}(function (jQuery) {
|
||||||
// This is needed so we can catch the AMD loader configuration and use it
|
// This is needed so we can catch the AMD loader configuration and use it
|
||||||
// The inner file should be wrapped (by `banner.start.js`) in a function that
|
// The inner file should be wrapped (by `banner.start.js`) in a function that
|
||||||
// returns the AMD loader references.
|
// returns the AMD loader references.
|
||||||
var S2 =(function () {
|
var S2 =
|
||||||
|
(function () {
|
||||||
// Restore the Select2 AMD loader so it can be used
|
// Restore the Select2 AMD loader so it can be used
|
||||||
// Needed mostly in the language files, where the loader is not inserted
|
// Needed mostly in the language files, where the loader is not inserted
|
||||||
if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {
|
if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {
|
||||||
|
@ -44,11 +30,13 @@
|
||||||
var S2;(function () { if (!S2 || !S2.requirejs) {
|
var S2;(function () { if (!S2 || !S2.requirejs) {
|
||||||
if (!S2) { S2 = {}; } else { require = S2; }
|
if (!S2) { S2 = {}; } else { require = S2; }
|
||||||
/**
|
/**
|
||||||
* @license almond 0.3.3 Copyright jQuery Foundation and other contributors.
|
* @license almond 0.3.1 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
|
||||||
* Released under MIT license, http://github.com/requirejs/almond/LICENSE
|
* Available via the MIT or new BSD license.
|
||||||
|
* see: http://github.com/jrburke/almond for details
|
||||||
*/
|
*/
|
||||||
//Going sloppy to avoid 'use strict' string cost, but strict practices should
|
//Going sloppy to avoid 'use strict' string cost, but strict practices should
|
||||||
//be followed.
|
//be followed.
|
||||||
|
/*jslint sloppy: true */
|
||||||
/*global setTimeout: false */
|
/*global setTimeout: false */
|
||||||
|
|
||||||
var requirejs, require, define;
|
var requirejs, require, define;
|
||||||
|
@ -76,58 +64,60 @@ var requirejs, require, define;
|
||||||
*/
|
*/
|
||||||
function normalize(name, baseName) {
|
function normalize(name, baseName) {
|
||||||
var nameParts, nameSegment, mapValue, foundMap, lastIndex,
|
var nameParts, nameSegment, mapValue, foundMap, lastIndex,
|
||||||
foundI, foundStarMap, starI, i, j, part, normalizedBaseParts,
|
foundI, foundStarMap, starI, i, j, part,
|
||||||
baseParts = baseName && baseName.split("/"),
|
baseParts = baseName && baseName.split("/"),
|
||||||
map = config.map,
|
map = config.map,
|
||||||
starMap = (map && map['*']) || {};
|
starMap = (map && map['*']) || {};
|
||||||
|
|
||||||
//Adjust any relative paths.
|
//Adjust any relative paths.
|
||||||
if (name) {
|
if (name && name.charAt(0) === ".") {
|
||||||
name = name.split('/');
|
//If have a base name, try to normalize against it,
|
||||||
lastIndex = name.length - 1;
|
//otherwise, assume it is a top-level require that will
|
||||||
|
//be relative to baseUrl in the end.
|
||||||
|
if (baseName) {
|
||||||
|
name = name.split('/');
|
||||||
|
lastIndex = name.length - 1;
|
||||||
|
|
||||||
// If wanting node ID compatibility, strip .js from end
|
// Node .js allowance:
|
||||||
// of IDs. Have to do this here, and not in nameToUrl
|
if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
|
||||||
// because node allows either .js or non .js to map
|
name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
|
||||||
// to same file.
|
}
|
||||||
if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
|
|
||||||
name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Starts with a '.' so need the baseName
|
//Lop off the last part of baseParts, so that . matches the
|
||||||
if (name[0].charAt(0) === '.' && baseParts) {
|
//"directory" and not name of the baseName's module. For instance,
|
||||||
//Convert baseName to array, and lop off the last part,
|
//baseName of "one/two/three", maps to "one/two/three.js", but we
|
||||||
//so that . matches that 'directory' and not name of the baseName's
|
//want the directory, "one/two" for this normalization.
|
||||||
//module. For instance, baseName of 'one/two/three', maps to
|
name = baseParts.slice(0, baseParts.length - 1).concat(name);
|
||||||
//'one/two/three.js', but we want the directory, 'one/two' for
|
|
||||||
//this normalization.
|
|
||||||
normalizedBaseParts = baseParts.slice(0, baseParts.length - 1);
|
|
||||||
name = normalizedBaseParts.concat(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
//start trimDots
|
//start trimDots
|
||||||
for (i = 0; i < name.length; i++) {
|
for (i = 0; i < name.length; i += 1) {
|
||||||
part = name[i];
|
part = name[i];
|
||||||
if (part === '.') {
|
if (part === ".") {
|
||||||
name.splice(i, 1);
|
name.splice(i, 1);
|
||||||
i -= 1;
|
i -= 1;
|
||||||
} else if (part === '..') {
|
} else if (part === "..") {
|
||||||
// If at the start, or previous value is still ..,
|
if (i === 1 && (name[2] === '..' || name[0] === '..')) {
|
||||||
// keep them so that when converted to a path it may
|
//End of the line. Keep at least one non-dot
|
||||||
// still work when converted to a path, even though
|
//path segment at the front so it can be mapped
|
||||||
// as an ID it is less than ideal. In larger point
|
//correctly to disk. Otherwise, there is likely
|
||||||
// releases, may be better to just kick out an error.
|
//no path mapping for a path starting with '..'.
|
||||||
if (i === 0 || (i === 1 && name[2] === '..') || name[i - 1] === '..') {
|
//This can still fail, but catches the most reasonable
|
||||||
continue;
|
//uses of ..
|
||||||
} else if (i > 0) {
|
break;
|
||||||
name.splice(i - 1, 2);
|
} else if (i > 0) {
|
||||||
i -= 2;
|
name.splice(i - 1, 2);
|
||||||
|
i -= 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
//end trimDots
|
||||||
//end trimDots
|
|
||||||
|
|
||||||
name = name.join('/');
|
name = name.join("/");
|
||||||
|
} else if (name.indexOf('./') === 0) {
|
||||||
|
// No baseName, so this is ID is resolved relative
|
||||||
|
// to baseUrl, pull off the leading dot.
|
||||||
|
name = name.substring(2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Apply map config if available.
|
//Apply map config if available.
|
||||||
|
@ -240,39 +230,32 @@ var requirejs, require, define;
|
||||||
return [prefix, name];
|
return [prefix, name];
|
||||||
}
|
}
|
||||||
|
|
||||||
//Creates a parts array for a relName where first part is plugin ID,
|
|
||||||
//second part is resource ID. Assumes relName has already been normalized.
|
|
||||||
function makeRelParts(relName) {
|
|
||||||
return relName ? splitPrefix(relName) : [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a name map, normalizing the name, and using a plugin
|
* Makes a name map, normalizing the name, and using a plugin
|
||||||
* for normalization if necessary. Grabs a ref to plugin
|
* for normalization if necessary. Grabs a ref to plugin
|
||||||
* too, as an optimization.
|
* too, as an optimization.
|
||||||
*/
|
*/
|
||||||
makeMap = function (name, relParts) {
|
makeMap = function (name, relName) {
|
||||||
var plugin,
|
var plugin,
|
||||||
parts = splitPrefix(name),
|
parts = splitPrefix(name),
|
||||||
prefix = parts[0],
|
prefix = parts[0];
|
||||||
relResourceName = relParts[1];
|
|
||||||
|
|
||||||
name = parts[1];
|
name = parts[1];
|
||||||
|
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
prefix = normalize(prefix, relResourceName);
|
prefix = normalize(prefix, relName);
|
||||||
plugin = callDep(prefix);
|
plugin = callDep(prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Normalize according
|
//Normalize according
|
||||||
if (prefix) {
|
if (prefix) {
|
||||||
if (plugin && plugin.normalize) {
|
if (plugin && plugin.normalize) {
|
||||||
name = plugin.normalize(name, makeNormalize(relResourceName));
|
name = plugin.normalize(name, makeNormalize(relName));
|
||||||
} else {
|
} else {
|
||||||
name = normalize(name, relResourceName);
|
name = normalize(name, relName);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
name = normalize(name, relResourceName);
|
name = normalize(name, relName);
|
||||||
parts = splitPrefix(name);
|
parts = splitPrefix(name);
|
||||||
prefix = parts[0];
|
prefix = parts[0];
|
||||||
name = parts[1];
|
name = parts[1];
|
||||||
|
@ -319,14 +302,13 @@ var requirejs, require, define;
|
||||||
};
|
};
|
||||||
|
|
||||||
main = function (name, deps, callback, relName) {
|
main = function (name, deps, callback, relName) {
|
||||||
var cjsModule, depName, ret, map, i, relParts,
|
var cjsModule, depName, ret, map, i,
|
||||||
args = [],
|
args = [],
|
||||||
callbackType = typeof callback,
|
callbackType = typeof callback,
|
||||||
usingExports;
|
usingExports;
|
||||||
|
|
||||||
//Use name if no relName
|
//Use name if no relName
|
||||||
relName = relName || name;
|
relName = relName || name;
|
||||||
relParts = makeRelParts(relName);
|
|
||||||
|
|
||||||
//Call the callback to define the module, if necessary.
|
//Call the callback to define the module, if necessary.
|
||||||
if (callbackType === 'undefined' || callbackType === 'function') {
|
if (callbackType === 'undefined' || callbackType === 'function') {
|
||||||
|
@ -335,7 +317,7 @@ var requirejs, require, define;
|
||||||
//Default to [require, exports, module] if no deps
|
//Default to [require, exports, module] if no deps
|
||||||
deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
|
deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
|
||||||
for (i = 0; i < deps.length; i += 1) {
|
for (i = 0; i < deps.length; i += 1) {
|
||||||
map = makeMap(deps[i], relParts);
|
map = makeMap(deps[i], relName);
|
||||||
depName = map.f;
|
depName = map.f;
|
||||||
|
|
||||||
//Fast path CommonJS standard dependencies.
|
//Fast path CommonJS standard dependencies.
|
||||||
|
@ -391,7 +373,7 @@ var requirejs, require, define;
|
||||||
//deps arg is the module name, and second arg (if passed)
|
//deps arg is the module name, and second arg (if passed)
|
||||||
//is just the relName.
|
//is just the relName.
|
||||||
//Normalize module name, if it contains . or ..
|
//Normalize module name, if it contains . or ..
|
||||||
return callDep(makeMap(deps, makeRelParts(callback)).f);
|
return callDep(makeMap(deps, callback).f);
|
||||||
} else if (!deps.splice) {
|
} else if (!deps.splice) {
|
||||||
//deps is a config object, not an array.
|
//deps is a config object, not an array.
|
||||||
config = deps;
|
config = deps;
|
||||||
|
@ -755,12 +737,6 @@ S2.define('select2/utils',[
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Utils.entityDecode = function (html) {
|
|
||||||
var txt = document.createElement('textarea');
|
|
||||||
txt.innerHTML = html;
|
|
||||||
return txt.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Append an array of jQuery nodes to a given element.
|
// Append an array of jQuery nodes to a given element.
|
||||||
Utils.appendMany = function ($element, $nodes) {
|
Utils.appendMany = function ($element, $nodes) {
|
||||||
// jQuery 1.7.x does not support $.fn.append() with an array
|
// jQuery 1.7.x does not support $.fn.append() with an array
|
||||||
|
@ -778,14 +754,6 @@ S2.define('select2/utils',[
|
||||||
$element.append($nodes);
|
$element.append($nodes);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Determine whether the browser is on a touchscreen device.
|
|
||||||
Utils.isTouchscreen = function() {
|
|
||||||
if ('undefined' === typeof Utils._isTouchscreenCache) {
|
|
||||||
Utils._isTouchscreenCache = 'ontouchstart' in document.documentElement;
|
|
||||||
}
|
|
||||||
return Utils._isTouchscreenCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Utils;
|
return Utils;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -805,7 +773,7 @@ S2.define('select2/results',[
|
||||||
|
|
||||||
Results.prototype.render = function () {
|
Results.prototype.render = function () {
|
||||||
var $results = $(
|
var $results = $(
|
||||||
'<ul class="select2-results__options" role="listbox" tabindex="-1"></ul>'
|
'<ul class="select2-results__options" role="tree"></ul>'
|
||||||
);
|
);
|
||||||
|
|
||||||
if (this.options.get('multiple')) {
|
if (this.options.get('multiple')) {
|
||||||
|
@ -828,7 +796,7 @@ S2.define('select2/results',[
|
||||||
this.hideLoading();
|
this.hideLoading();
|
||||||
|
|
||||||
var $message = $(
|
var $message = $(
|
||||||
'<li role="alert" aria-live="assertive"' +
|
'<li role="treeitem" aria-live="assertive"' +
|
||||||
' class="select2-results__option"></li>'
|
' class="select2-results__option"></li>'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -890,9 +858,9 @@ S2.define('select2/results',[
|
||||||
|
|
||||||
Results.prototype.highlightFirstItem = function () {
|
Results.prototype.highlightFirstItem = function () {
|
||||||
var $options = this.$results
|
var $options = this.$results
|
||||||
.find('.select2-results__option[data-selected]');
|
.find('.select2-results__option[aria-selected]');
|
||||||
|
|
||||||
var $selected = $options.filter('[data-selected=true]');
|
var $selected = $options.filter('[aria-selected=true]');
|
||||||
|
|
||||||
// Check if there are any selected options
|
// Check if there are any selected options
|
||||||
if ($selected.length > 0) {
|
if ($selected.length > 0) {
|
||||||
|
@ -916,7 +884,7 @@ S2.define('select2/results',[
|
||||||
});
|
});
|
||||||
|
|
||||||
var $options = self.$results
|
var $options = self.$results
|
||||||
.find('.select2-results__option[data-selected]');
|
.find('.select2-results__option[aria-selected]');
|
||||||
|
|
||||||
$options.each(function () {
|
$options.each(function () {
|
||||||
var $option = $(this);
|
var $option = $(this);
|
||||||
|
@ -928,9 +896,9 @@ S2.define('select2/results',[
|
||||||
|
|
||||||
if ((item.element != null && item.element.selected) ||
|
if ((item.element != null && item.element.selected) ||
|
||||||
(item.element == null && $.inArray(id, selectedIds) > -1)) {
|
(item.element == null && $.inArray(id, selectedIds) > -1)) {
|
||||||
$option.attr('data-selected', 'true');
|
$option.attr('aria-selected', 'true');
|
||||||
} else {
|
} else {
|
||||||
$option.attr('data-selected', 'false');
|
$option.attr('aria-selected', 'false');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -962,18 +930,17 @@ S2.define('select2/results',[
|
||||||
option.className = 'select2-results__option';
|
option.className = 'select2-results__option';
|
||||||
|
|
||||||
var attrs = {
|
var attrs = {
|
||||||
'role': 'option',
|
'role': 'treeitem',
|
||||||
'data-selected': 'false',
|
'aria-selected': 'false'
|
||||||
'tabindex': -1
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data.disabled) {
|
if (data.disabled) {
|
||||||
delete attrs['data-selected'];
|
delete attrs['aria-selected'];
|
||||||
attrs['aria-disabled'] = 'true';
|
attrs['aria-disabled'] = 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.id == null) {
|
if (data.id == null) {
|
||||||
delete attrs['data-selected'];
|
delete attrs['aria-selected'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data._resultId != null) {
|
if (data._resultId != null) {
|
||||||
|
@ -985,8 +952,9 @@ S2.define('select2/results',[
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.children) {
|
if (data.children) {
|
||||||
|
attrs.role = 'group';
|
||||||
attrs['aria-label'] = data.text;
|
attrs['aria-label'] = data.text;
|
||||||
delete attrs['data-selected'];
|
delete attrs['aria-selected'];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var attr in attrs) {
|
for (var attr in attrs) {
|
||||||
|
@ -1003,7 +971,6 @@ S2.define('select2/results',[
|
||||||
|
|
||||||
var $label = $(label);
|
var $label = $(label);
|
||||||
this.template(data, label);
|
this.template(data, label);
|
||||||
$label.attr('role', 'presentation');
|
|
||||||
|
|
||||||
var $children = [];
|
var $children = [];
|
||||||
|
|
||||||
|
@ -1016,11 +983,10 @@ S2.define('select2/results',[
|
||||||
}
|
}
|
||||||
|
|
||||||
var $childrenContainer = $('<ul></ul>', {
|
var $childrenContainer = $('<ul></ul>', {
|
||||||
'class': 'select2-results__options select2-results__options--nested',
|
'class': 'select2-results__options select2-results__options--nested'
|
||||||
'role': 'listbox'
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$childrenContainer.append($children);
|
$childrenContainer.append($children);
|
||||||
$option.attr('role', 'list');
|
|
||||||
|
|
||||||
$option.append(label);
|
$option.append(label);
|
||||||
$option.append($childrenContainer);
|
$option.append($childrenContainer);
|
||||||
|
@ -1116,7 +1082,7 @@ S2.define('select2/results',[
|
||||||
|
|
||||||
var data = $highlighted.data('data');
|
var data = $highlighted.data('data');
|
||||||
|
|
||||||
if ($highlighted.attr('data-selected') == 'true') {
|
if ($highlighted.attr('aria-selected') == 'true') {
|
||||||
self.trigger('close', {});
|
self.trigger('close', {});
|
||||||
} else {
|
} else {
|
||||||
self.trigger('select', {
|
self.trigger('select', {
|
||||||
|
@ -1128,7 +1094,7 @@ S2.define('select2/results',[
|
||||||
container.on('results:previous', function () {
|
container.on('results:previous', function () {
|
||||||
var $highlighted = self.getHighlightedResults();
|
var $highlighted = self.getHighlightedResults();
|
||||||
|
|
||||||
var $options = self.$results.find('[data-selected]');
|
var $options = self.$results.find('[aria-selected]');
|
||||||
|
|
||||||
var currentIndex = $options.index($highlighted);
|
var currentIndex = $options.index($highlighted);
|
||||||
|
|
||||||
|
@ -1162,7 +1128,7 @@ S2.define('select2/results',[
|
||||||
container.on('results:next', function () {
|
container.on('results:next', function () {
|
||||||
var $highlighted = self.getHighlightedResults();
|
var $highlighted = self.getHighlightedResults();
|
||||||
|
|
||||||
var $options = self.$results.find('[data-selected]');
|
var $options = self.$results.find('[aria-selected]');
|
||||||
|
|
||||||
var currentIndex = $options.index($highlighted);
|
var currentIndex = $options.index($highlighted);
|
||||||
|
|
||||||
|
@ -1190,8 +1156,7 @@ S2.define('select2/results',[
|
||||||
});
|
});
|
||||||
|
|
||||||
container.on('results:focus', function (params) {
|
container.on('results:focus', function (params) {
|
||||||
params.element.addClass('select2-results__option--highlighted').attr('aria-selected', 'true');
|
params.element.addClass('select2-results__option--highlighted');
|
||||||
self.$results.attr('aria-activedescendant', params.element.attr('id'));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
container.on('results:message', function (params) {
|
container.on('results:message', function (params) {
|
||||||
|
@ -1223,13 +1188,13 @@ S2.define('select2/results',[
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$results.on('mouseup', '.select2-results__option[data-selected]',
|
this.$results.on('mouseup', '.select2-results__option[aria-selected]',
|
||||||
function (evt) {
|
function (evt) {
|
||||||
var $this = $(this);
|
var $this = $(this);
|
||||||
|
|
||||||
var data = $this.data('data');
|
var data = $this.data('data');
|
||||||
|
|
||||||
if ($this.attr('data-selected') === 'true') {
|
if ($this.attr('aria-selected') === 'true') {
|
||||||
if (self.options.get('multiple')) {
|
if (self.options.get('multiple')) {
|
||||||
self.trigger('unselect', {
|
self.trigger('unselect', {
|
||||||
originalEvent: evt,
|
originalEvent: evt,
|
||||||
|
@ -1248,13 +1213,12 @@ S2.define('select2/results',[
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$results.on('mouseenter', '.select2-results__option[data-selected]',
|
this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
|
||||||
function (evt) {
|
function (evt) {
|
||||||
var data = $(this).data('data');
|
var data = $(this).data('data');
|
||||||
|
|
||||||
self.getHighlightedResults()
|
self.getHighlightedResults()
|
||||||
.removeClass('select2-results__option--highlighted')
|
.removeClass('select2-results__option--highlighted');
|
||||||
.attr('aria-selected', 'false');
|
|
||||||
|
|
||||||
self.trigger('results:focus', {
|
self.trigger('results:focus', {
|
||||||
data: data,
|
data: data,
|
||||||
|
@ -1281,7 +1245,7 @@ S2.define('select2/results',[
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var $options = this.$results.find('[data-selected]');
|
var $options = this.$results.find('[aria-selected]');
|
||||||
|
|
||||||
var currentIndex = $options.index($highlighted);
|
var currentIndex = $options.index($highlighted);
|
||||||
|
|
||||||
|
@ -1359,7 +1323,7 @@ S2.define('select2/selection/base',[
|
||||||
|
|
||||||
BaseSelection.prototype.render = function () {
|
BaseSelection.prototype.render = function () {
|
||||||
var $selection = $(
|
var $selection = $(
|
||||||
'<span class="select2-selection" ' +
|
'<span class="select2-selection" role="combobox" ' +
|
||||||
' aria-haspopup="true" aria-expanded="false">' +
|
' aria-haspopup="true" aria-expanded="false">' +
|
||||||
'</span>'
|
'</span>'
|
||||||
);
|
);
|
||||||
|
@ -1385,7 +1349,6 @@ S2.define('select2/selection/base',[
|
||||||
|
|
||||||
var id = container.id + '-container';
|
var id = container.id + '-container';
|
||||||
var resultsId = container.id + '-results';
|
var resultsId = container.id + '-results';
|
||||||
var searchHidden = this.options.get('minimumResultsForSearch') === Infinity;
|
|
||||||
|
|
||||||
this.container = container;
|
this.container = container;
|
||||||
|
|
||||||
|
@ -1427,11 +1390,7 @@ S2.define('select2/selection/base',[
|
||||||
self.$selection.removeAttr('aria-activedescendant');
|
self.$selection.removeAttr('aria-activedescendant');
|
||||||
self.$selection.removeAttr('aria-owns');
|
self.$selection.removeAttr('aria-owns');
|
||||||
|
|
||||||
// This needs to be delayed as the active element is the body when the
|
self.$selection.focus();
|
||||||
// key is pressed.
|
|
||||||
window.setTimeout(function () {
|
|
||||||
self.$selection.trigger( 'focus' );
|
|
||||||
}, 1);
|
|
||||||
|
|
||||||
self._detachCloseHandler(container);
|
self._detachCloseHandler(container);
|
||||||
});
|
});
|
||||||
|
@ -1481,14 +1440,8 @@ S2.define('select2/selection/base',[
|
||||||
}
|
}
|
||||||
|
|
||||||
var $element = $this.data('element');
|
var $element = $this.data('element');
|
||||||
$element.select2('close');
|
|
||||||
|
|
||||||
// Remove any focus when dropdown is closed by clicking outside the select area.
|
$element.select2('close');
|
||||||
// Timeout of 1 required for close to finish wrapping up.
|
|
||||||
setTimeout(function(){
|
|
||||||
$this.find('*:focus').blur();
|
|
||||||
$target.focus();
|
|
||||||
}, 1);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1547,21 +1500,8 @@ S2.define('select2/selection/single',[
|
||||||
|
|
||||||
var id = container.id + '-container';
|
var id = container.id + '-container';
|
||||||
|
|
||||||
this.$selection.find('.select2-selection__rendered')
|
this.$selection.find('.select2-selection__rendered').attr('id', id);
|
||||||
.attr('id', id)
|
this.$selection.attr('aria-labelledby', id);
|
||||||
.attr('role', 'textbox')
|
|
||||||
.attr('aria-readonly', 'true');
|
|
||||||
|
|
||||||
var label = this.options.get( 'label' );
|
|
||||||
|
|
||||||
if ( typeof( label ) === 'string' ) {
|
|
||||||
this.$selection.attr( 'aria-label', label );
|
|
||||||
} else {
|
|
||||||
this.$selection.attr( 'aria-labelledby', id );
|
|
||||||
}
|
|
||||||
|
|
||||||
// This makes single non-search selects work in screen readers. If it causes problems elsewhere, remove.
|
|
||||||
this.$selection.attr('role', 'combobox');
|
|
||||||
|
|
||||||
this.$selection.on('mousedown', function (evt) {
|
this.$selection.on('mousedown', function (evt) {
|
||||||
// Only respond to left clicks
|
// Only respond to left clicks
|
||||||
|
@ -1578,20 +1518,13 @@ S2.define('select2/selection/single',[
|
||||||
// User focuses on the container
|
// User focuses on the container
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$selection.on('keydown', function (evt) {
|
|
||||||
// If user starts typing an alphanumeric key on the keyboard, open if not opened.
|
|
||||||
if (!container.isOpen() && evt.which >= 48 && evt.which <= 90) {
|
|
||||||
container.open();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.$selection.on('blur', function (evt) {
|
this.$selection.on('blur', function (evt) {
|
||||||
// User exits the container
|
// User exits the container
|
||||||
});
|
});
|
||||||
|
|
||||||
container.on('focus', function (evt) {
|
container.on('focus', function (evt) {
|
||||||
if (!container.isOpen()) {
|
if (!container.isOpen()) {
|
||||||
self.$selection.trigger( 'focus' );
|
self.$selection.focus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1624,9 +1557,9 @@ S2.define('select2/selection/single',[
|
||||||
var selection = data[0];
|
var selection = data[0];
|
||||||
|
|
||||||
var $rendered = this.$selection.find('.select2-selection__rendered');
|
var $rendered = this.$selection.find('.select2-selection__rendered');
|
||||||
var formatted = Utils.entityDecode(this.display(selection, $rendered));
|
var formatted = this.display(selection, $rendered);
|
||||||
|
|
||||||
$rendered.empty().text(formatted);
|
$rendered.empty().append(formatted);
|
||||||
$rendered.prop('title', selection.title || selection.text);
|
$rendered.prop('title', selection.title || selection.text);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1650,7 +1583,7 @@ S2.define('select2/selection/multiple',[
|
||||||
$selection.addClass('select2-selection--multiple');
|
$selection.addClass('select2-selection--multiple');
|
||||||
|
|
||||||
$selection.html(
|
$selection.html(
|
||||||
'<ul class="select2-selection__rendered" aria-live="polite" aria-relevant="additions removals" aria-atomic="true"></ul>'
|
'<ul class="select2-selection__rendered"></ul>'
|
||||||
);
|
);
|
||||||
|
|
||||||
return $selection;
|
return $selection;
|
||||||
|
@ -1687,18 +1620,6 @@ S2.define('select2/selection/multiple',[
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
this.$selection.on('keydown', function (evt) {
|
|
||||||
// If user starts typing an alphanumeric key on the keyboard, open if not opened.
|
|
||||||
if (!container.isOpen() && evt.which >= 48 && evt.which <= 90) {
|
|
||||||
container.open();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Focus on the search field when the container is focused instead of the main container.
|
|
||||||
container.on( 'focus', function(){
|
|
||||||
self.focusOnSearch();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MultipleSelection.prototype.clear = function () {
|
MultipleSelection.prototype.clear = function () {
|
||||||
|
@ -1715,7 +1636,7 @@ S2.define('select2/selection/multiple',[
|
||||||
MultipleSelection.prototype.selectionContainer = function () {
|
MultipleSelection.prototype.selectionContainer = function () {
|
||||||
var $container = $(
|
var $container = $(
|
||||||
'<li class="select2-selection__choice">' +
|
'<li class="select2-selection__choice">' +
|
||||||
'<span class="select2-selection__choice__remove" role="presentation" aria-hidden="true">' +
|
'<span class="select2-selection__choice__remove" role="presentation">' +
|
||||||
'×' +
|
'×' +
|
||||||
'</span>' +
|
'</span>' +
|
||||||
'</li>'
|
'</li>'
|
||||||
|
@ -1724,24 +1645,6 @@ S2.define('select2/selection/multiple',[
|
||||||
return $container;
|
return $container;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Focus on the search field instead of the main multiselect container.
|
|
||||||
*/
|
|
||||||
MultipleSelection.prototype.focusOnSearch = function() {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
if ('undefined' !== typeof self.$search) {
|
|
||||||
// Needs 1 ms delay because of other 1 ms setTimeouts when rendering.
|
|
||||||
setTimeout(function(){
|
|
||||||
// Prevent the dropdown opening again when focused from this.
|
|
||||||
// This gets reset automatically when focus is triggered.
|
|
||||||
self._keyUpPrevented = true;
|
|
||||||
|
|
||||||
self.$search.focus();
|
|
||||||
}, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MultipleSelection.prototype.update = function (data) {
|
MultipleSelection.prototype.update = function (data) {
|
||||||
this.clear();
|
this.clear();
|
||||||
|
|
||||||
|
@ -1755,14 +1658,9 @@ S2.define('select2/selection/multiple',[
|
||||||
var selection = data[d];
|
var selection = data[d];
|
||||||
|
|
||||||
var $selection = this.selectionContainer();
|
var $selection = this.selectionContainer();
|
||||||
var removeItemTag = $selection.html();
|
|
||||||
var formatted = this.display(selection, $selection);
|
var formatted = this.display(selection, $selection);
|
||||||
if ('string' === typeof formatted) {
|
|
||||||
formatted = Utils.entityDecode(formatted.trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
$selection.text(formatted);
|
$selection.append(formatted);
|
||||||
$selection.prepend(removeItemTag);
|
|
||||||
$selection.prop('title', selection.title || selection.text);
|
$selection.prop('title', selection.title || selection.text);
|
||||||
|
|
||||||
$selection.data('data', selection);
|
$selection.data('data', selection);
|
||||||
|
@ -1801,7 +1699,7 @@ S2.define('select2/selection/placeholder',[
|
||||||
Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {
|
Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {
|
||||||
var $placeholder = this.selectionContainer();
|
var $placeholder = this.selectionContainer();
|
||||||
|
|
||||||
$placeholder.text(Utils.entityDecode(this.display(placeholder)));
|
$placeholder.html(this.display(placeholder));
|
||||||
$placeholder.addClass('select2-selection__placeholder')
|
$placeholder.addClass('select2-selection__placeholder')
|
||||||
.removeClass('select2-selection__choice');
|
.removeClass('select2-selection__choice');
|
||||||
|
|
||||||
|
@ -1938,8 +1836,8 @@ S2.define('select2/selection/search',[
|
||||||
Search.prototype.render = function (decorated) {
|
Search.prototype.render = function (decorated) {
|
||||||
var $search = $(
|
var $search = $(
|
||||||
'<li class="select2-search select2-search--inline">' +
|
'<li class="select2-search select2-search--inline">' +
|
||||||
'<input class="select2-search__field" type="text" tabindex="-1"' +
|
'<input class="select2-search__field" type="search" tabindex="-1"' +
|
||||||
' autocomplete="off" autocorrect="off" autocapitalize="none"' +
|
' autocomplete="off" autocorrect="off" autocapitalize="off"' +
|
||||||
' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
|
' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
|
||||||
'</li>'
|
'</li>'
|
||||||
);
|
);
|
||||||
|
@ -1956,19 +1854,16 @@ S2.define('select2/selection/search',[
|
||||||
|
|
||||||
Search.prototype.bind = function (decorated, container, $container) {
|
Search.prototype.bind = function (decorated, container, $container) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var resultsId = container.id + '-results';
|
|
||||||
|
|
||||||
decorated.call(this, container, $container);
|
decorated.call(this, container, $container);
|
||||||
|
|
||||||
container.on('open', function () {
|
container.on('open', function () {
|
||||||
self.$search.attr('aria-owns', resultsId);
|
|
||||||
self.$search.trigger('focus');
|
self.$search.trigger('focus');
|
||||||
});
|
});
|
||||||
|
|
||||||
container.on('close', function () {
|
container.on('close', function () {
|
||||||
self.$search.val('');
|
self.$search.val('');
|
||||||
self.$search.removeAttr('aria-activedescendant');
|
self.$search.removeAttr('aria-activedescendant');
|
||||||
self.$search.removeAttr('aria-owns');
|
|
||||||
self.$search.trigger('focus');
|
self.$search.trigger('focus');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1987,7 +1882,7 @@ S2.define('select2/selection/search',[
|
||||||
});
|
});
|
||||||
|
|
||||||
container.on('results:focus', function (params) {
|
container.on('results:focus', function (params) {
|
||||||
self.$search.attr('aria-activedescendant', params.data._resultId);
|
self.$search.attr('aria-activedescendant', params.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$selection.on('focusin', '.select2-search--inline', function (evt) {
|
this.$selection.on('focusin', '.select2-search--inline', function (evt) {
|
||||||
|
@ -2018,9 +1913,6 @@ S2.define('select2/selection/search',[
|
||||||
|
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
}
|
}
|
||||||
} else if (evt.which === KEYS.ENTER) {
|
|
||||||
container.open();
|
|
||||||
evt.preventDefault();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2109,7 +2001,7 @@ S2.define('select2/selection/search',[
|
||||||
|
|
||||||
this.resizeSearch();
|
this.resizeSearch();
|
||||||
if (searchHadFocus) {
|
if (searchHadFocus) {
|
||||||
this.$search.trigger( 'focus' );
|
this.$search.focus();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3112,15 +3004,8 @@ S2.define('select2/data/base',[
|
||||||
};
|
};
|
||||||
|
|
||||||
BaseAdapter.prototype.generateResultId = function (container, data) {
|
BaseAdapter.prototype.generateResultId = function (container, data) {
|
||||||
var id = '';
|
var id = container.id + '-result-';
|
||||||
|
|
||||||
if (container != null) {
|
|
||||||
id += container.id
|
|
||||||
} else {
|
|
||||||
id += Utils.generateChars(4);
|
|
||||||
}
|
|
||||||
|
|
||||||
id += '-result-';
|
|
||||||
id += Utils.generateChars(4);
|
id += Utils.generateChars(4);
|
||||||
|
|
||||||
if (data.id != null) {
|
if (data.id != null) {
|
||||||
|
@ -3306,7 +3191,7 @@ S2.define('select2/data/select',[
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.id !== undefined) {
|
if (data.id) {
|
||||||
option.value = data.id;
|
option.value = data.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3404,7 +3289,7 @@ S2.define('select2/data/select',[
|
||||||
item.text = item.text.toString();
|
item.text = item.text.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item._resultId == null && item.id) {
|
if (item._resultId == null && item.id && this.container != null) {
|
||||||
item._resultId = this.generateResultId(this.container, item);
|
item._resultId = this.generateResultId(this.container, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3547,7 +3432,7 @@ S2.define('select2/data/ajax',[
|
||||||
|
|
||||||
if (this._request != null) {
|
if (this._request != null) {
|
||||||
// JSONP requests cannot always be aborted
|
// JSONP requests cannot always be aborted
|
||||||
if ( typeof this._request.abort === 'function' ) {
|
if ($.isFunction(this._request.abort)) {
|
||||||
this._request.abort();
|
this._request.abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3572,7 +3457,7 @@ S2.define('select2/data/ajax',[
|
||||||
|
|
||||||
if (self.options.get('debug') && window.console && console.error) {
|
if (self.options.get('debug') && window.console && console.error) {
|
||||||
// Check to make sure that the response included a `results` key.
|
// Check to make sure that the response included a `results` key.
|
||||||
if (!results || !results.results || ! Array.isArray( results.results ) ) {
|
if (!results || !results.results || !$.isArray(results.results)) {
|
||||||
console.error(
|
console.error(
|
||||||
'Select2: The AJAX results did not return an array in the ' +
|
'Select2: The AJAX results did not return an array in the ' +
|
||||||
'`results` key of the response.'
|
'`results` key of the response.'
|
||||||
|
@ -3581,7 +3466,6 @@ S2.define('select2/data/ajax',[
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(results);
|
callback(results);
|
||||||
self.container.focusOnActiveElement();
|
|
||||||
}, function () {
|
}, function () {
|
||||||
// Attempt to detect if a request was aborted
|
// Attempt to detect if a request was aborted
|
||||||
// Only works if the transport exposes a status property
|
// Only works if the transport exposes a status property
|
||||||
|
@ -3631,7 +3515,7 @@ S2.define('select2/data/tags',[
|
||||||
|
|
||||||
decorated.call(this, $element, options);
|
decorated.call(this, $element, options);
|
||||||
|
|
||||||
if ( Array.isArray( tags ) ) {
|
if ($.isArray(tags)) {
|
||||||
for (var t = 0; t < tags.length; t++) {
|
for (var t = 0; t < tags.length; t++) {
|
||||||
var tag = tags[t];
|
var tag = tags[t];
|
||||||
var item = this._normalizeItem(tag);
|
var item = this._normalizeItem(tag);
|
||||||
|
@ -3666,10 +3550,7 @@ S2.define('select2/data/tags',[
|
||||||
}, true)
|
}, true)
|
||||||
);
|
);
|
||||||
|
|
||||||
var optionText = (option.text || '').toUpperCase();
|
var checkText = option.text === params.term;
|
||||||
var paramsTerm = (params.term || '').toUpperCase();
|
|
||||||
|
|
||||||
var checkText = optionText === paramsTerm;
|
|
||||||
|
|
||||||
if (checkText || checkChildren) {
|
if (checkText || checkChildren) {
|
||||||
if (child) {
|
if (child) {
|
||||||
|
@ -3707,7 +3588,7 @@ S2.define('select2/data/tags',[
|
||||||
};
|
};
|
||||||
|
|
||||||
Tags.prototype.createTag = function (decorated, params) {
|
Tags.prototype.createTag = function (decorated, params) {
|
||||||
var term = ( params.term || 0 == params.term ) ? params.term.toString().trim() : '';
|
var term = $.trim(params.term);
|
||||||
|
|
||||||
if (term === '') {
|
if (term === '') {
|
||||||
return null;
|
return null;
|
||||||
|
@ -3800,7 +3681,7 @@ S2.define('select2/data/tokenizer',[
|
||||||
// Replace the search term if we have the search box
|
// Replace the search term if we have the search box
|
||||||
if (this.$search.length) {
|
if (this.$search.length) {
|
||||||
this.$search.val(tokenData.term);
|
this.$search.val(tokenData.term);
|
||||||
this.$search.trigger( 'focus' );
|
this.$search.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
params.term = tokenData.term;
|
params.term = tokenData.term;
|
||||||
|
@ -4006,9 +3887,9 @@ S2.define('select2/dropdown/search',[
|
||||||
|
|
||||||
var $search = $(
|
var $search = $(
|
||||||
'<span class="select2-search select2-search--dropdown">' +
|
'<span class="select2-search select2-search--dropdown">' +
|
||||||
'<input class="select2-search__field" type="text" tabindex="-1"' +
|
'<input class="select2-search__field" type="search" tabindex="-1"' +
|
||||||
' autocomplete="off" autocorrect="off" autocapitalize="none"' +
|
' autocomplete="off" autocorrect="off" autocapitalize="off"' +
|
||||||
' spellcheck="false" role="combobox" aria-autocomplete="list" aria-expanded="true" />' +
|
' spellcheck="false" role="textbox" />' +
|
||||||
'</span>'
|
'</span>'
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -4022,7 +3903,6 @@ S2.define('select2/dropdown/search',[
|
||||||
|
|
||||||
Search.prototype.bind = function (decorated, container, $container) {
|
Search.prototype.bind = function (decorated, container, $container) {
|
||||||
var self = this;
|
var self = this;
|
||||||
var resultsId = container.id + '-results';
|
|
||||||
|
|
||||||
decorated.call(this, container, $container);
|
decorated.call(this, container, $container);
|
||||||
|
|
||||||
|
@ -4046,24 +3926,23 @@ S2.define('select2/dropdown/search',[
|
||||||
|
|
||||||
container.on('open', function () {
|
container.on('open', function () {
|
||||||
self.$search.attr('tabindex', 0);
|
self.$search.attr('tabindex', 0);
|
||||||
self.$search.attr('aria-owns', resultsId);
|
|
||||||
self.$search.trigger( 'focus' );
|
self.$search.focus();
|
||||||
|
|
||||||
window.setTimeout(function () {
|
window.setTimeout(function () {
|
||||||
self.$search.trigger( 'focus' );
|
self.$search.focus();
|
||||||
}, 0);
|
}, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
container.on('close', function () {
|
container.on('close', function () {
|
||||||
self.$search.attr('tabindex', -1);
|
self.$search.attr('tabindex', -1);
|
||||||
self.$search.removeAttr('aria-activedescendant');
|
|
||||||
self.$search.removeAttr('aria-owns');
|
|
||||||
self.$search.val('');
|
self.$search.val('');
|
||||||
});
|
});
|
||||||
|
|
||||||
container.on('focus', function () {
|
container.on('focus', function () {
|
||||||
if (!container.isOpen()) {
|
if (container.isOpen()) {
|
||||||
self.$search.trigger( 'focus' );
|
self.$search.focus();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -4078,10 +3957,6 @@ S2.define('select2/dropdown/search',[
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
container.on('results:focus', function (params) {
|
|
||||||
self.$search.attr('aria-activedescendant', params.data._resultId);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Search.prototype.handleSearch = function (evt) {
|
Search.prototype.handleSearch = function (evt) {
|
||||||
|
@ -4223,7 +4098,7 @@ S2.define('select2/dropdown/infiniteScroll',[
|
||||||
var $option = $(
|
var $option = $(
|
||||||
'<li ' +
|
'<li ' +
|
||||||
'class="select2-results__option select2-results__option--load-more"' +
|
'class="select2-results__option select2-results__option--load-more"' +
|
||||||
'role="option" aria-disabled="true"></li>'
|
'role="treeitem" aria-disabled="true"></li>'
|
||||||
);
|
);
|
||||||
|
|
||||||
var message = this.options.get('translations').get('loadingMore');
|
var message = this.options.get('translations').get('loadingMore');
|
||||||
|
@ -4878,7 +4753,7 @@ S2.define('select2/defaults',[
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( Array.isArray( options.language ) ) {
|
if ($.isArray(options.language)) {
|
||||||
var languages = new Translation();
|
var languages = new Translation();
|
||||||
options.language.push('en');
|
options.language.push('en');
|
||||||
|
|
||||||
|
@ -4941,7 +4816,7 @@ S2.define('select2/defaults',[
|
||||||
|
|
||||||
function matcher (params, data) {
|
function matcher (params, data) {
|
||||||
// Always return the object if there is nothing to compare
|
// Always return the object if there is nothing to compare
|
||||||
if ( params.term == null || params.term.toString().trim() === '' ) {
|
if ($.trim(params.term) === '') {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5469,22 +5344,16 @@ S2.define('select2/core',[
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.on('open', function(){
|
this.on('keypress', function (evt) {
|
||||||
// Focus on the active element when opening dropdown.
|
|
||||||
// Needs 1 ms delay because of other 1 ms setTimeouts when rendering.
|
|
||||||
setTimeout(function(){
|
|
||||||
self.focusOnActiveElement();
|
|
||||||
}, 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
$(document).on('keydown', function (evt) {
|
|
||||||
var key = evt.which;
|
var key = evt.which;
|
||||||
|
|
||||||
if (self.isOpen()) {
|
if (self.isOpen()) {
|
||||||
if (key === KEYS.ESC || (key === KEYS.UP && evt.altKey)) {
|
if (key === KEYS.ESC || key === KEYS.TAB ||
|
||||||
|
(key === KEYS.UP && evt.altKey)) {
|
||||||
self.close();
|
self.close();
|
||||||
|
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
} else if (key === KEYS.ENTER || key === KEYS.TAB) {
|
} else if (key === KEYS.ENTER) {
|
||||||
self.trigger('results:select', {});
|
self.trigger('results:select', {});
|
||||||
|
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
|
@ -5501,42 +5370,17 @@ S2.define('select2/core',[
|
||||||
|
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
var $searchField = self.$dropdown.find('.select2-search__field');
|
|
||||||
if (! $searchField.length) {
|
|
||||||
$searchField = self.$container.find('.select2-search__field');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Move the focus to the selected element on keyboard navigation.
|
|
||||||
// Required for screen readers to work properly.
|
|
||||||
if (key === KEYS.DOWN || key === KEYS.UP) {
|
|
||||||
self.focusOnActiveElement();
|
|
||||||
} else {
|
|
||||||
// Focus on the search if user starts typing.
|
|
||||||
$searchField.focus();
|
|
||||||
// Focus back to active selection when finished typing.
|
|
||||||
// Small delay so typed character can be read by screen reader.
|
|
||||||
setTimeout(function(){
|
|
||||||
self.focusOnActiveElement();
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
} else if (self.hasFocus()) {
|
|
||||||
if (key === KEYS.ENTER || key === KEYS.SPACE ||
|
if (key === KEYS.ENTER || key === KEYS.SPACE ||
|
||||||
key === KEYS.DOWN) {
|
(key === KEYS.DOWN && evt.altKey)) {
|
||||||
self.open();
|
self.open();
|
||||||
|
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
Select2.prototype.focusOnActiveElement = function () {
|
|
||||||
// Don't mess with the focus on touchscreens because it causes havoc with on-screen keyboards.
|
|
||||||
if (this.isOpen() && ! Utils.isTouchscreen()) {
|
|
||||||
this.$results.find('li.select2-results__option--highlighted').focus();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Select2.prototype._syncAttributes = function () {
|
Select2.prototype._syncAttributes = function () {
|
||||||
this.options.set('disabled', this.$element.prop('disabled'));
|
this.options.set('disabled', this.$element.prop('disabled'));
|
||||||
|
|
||||||
|
@ -5724,7 +5568,7 @@ S2.define('select2/core',[
|
||||||
|
|
||||||
var newVal = args[0];
|
var newVal = args[0];
|
||||||
|
|
||||||
if ( Array.isArray( newVal ) ) {
|
if ($.isArray(newVal)) {
|
||||||
newVal = $.map(newVal, function (obj) {
|
newVal = $.map(newVal, function (obj) {
|
||||||
return obj.toString();
|
return obj.toString();
|
||||||
});
|
});
|
||||||
|
@ -5809,11 +5653,11 @@ S2.define('jquery.select2',[
|
||||||
'./select2/core',
|
'./select2/core',
|
||||||
'./select2/defaults'
|
'./select2/defaults'
|
||||||
], function ($, _, Select2, Defaults) {
|
], function ($, _, Select2, Defaults) {
|
||||||
if ($.fn.selectWoo == null) {
|
if ($.fn.select2 == null) {
|
||||||
// All methods that should return the element
|
// All methods that should return the element
|
||||||
var thisMethods = ['open', 'close', 'destroy'];
|
var thisMethods = ['open', 'close', 'destroy'];
|
||||||
|
|
||||||
$.fn.selectWoo = function (options) {
|
$.fn.select2 = function (options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
|
|
||||||
if (typeof options === 'object') {
|
if (typeof options === 'object') {
|
||||||
|
@ -5853,17 +5697,10 @@ S2.define('jquery.select2',[
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($.fn.select2 != null && $.fn.select2.defaults != null) {
|
if ($.fn.select2.defaults == null) {
|
||||||
$.fn.selectWoo.defaults = $.fn.select2.defaults;
|
$.fn.select2.defaults = Defaults;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($.fn.selectWoo.defaults == null) {
|
|
||||||
$.fn.selectWoo.defaults = Defaults;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Also register selectWoo under select2 if select2 is not already present.
|
|
||||||
$.fn.select2 = $.fn.select2 || $.fn.selectWoo;
|
|
||||||
|
|
||||||
return Select2;
|
return Select2;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -5882,7 +5719,6 @@ S2.define('jquery.select2',[
|
||||||
// This allows Select2 to use the internal loader outside of this file, such
|
// This allows Select2 to use the internal loader outside of this file, such
|
||||||
// as in the language files.
|
// as in the language files.
|
||||||
jQuery.fn.select2.amd = S2;
|
jQuery.fn.select2.amd = S2;
|
||||||
jQuery.fn.selectWoo.amd = S2;
|
|
||||||
|
|
||||||
// Return the Select2 instance for anyone who is importing it.
|
// Return the Select2 instance for anyone who is importing it.
|
||||||
return select2;
|
return select2;
|
||||||
|
|
|
@ -68,16 +68,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/flysystem",
|
"name": "league/flysystem",
|
||||||
"version": "1.1.4",
|
"version": "1.1.5",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/thephpleague/flysystem.git",
|
"url": "https://github.com/thephpleague/flysystem.git",
|
||||||
"reference": "f3ad69181b8afed2c9edf7be5a2918144ff4ea32"
|
"reference": "18634df356bfd4119fe3d6156bdb990c414c14ea"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/f3ad69181b8afed2c9edf7be5a2918144ff4ea32",
|
"url": "https://api.github.com/repos/thephpleague/flysystem/zipball/18634df356bfd4119fe3d6156bdb990c414c14ea",
|
||||||
"reference": "f3ad69181b8afed2c9edf7be5a2918144ff4ea32",
|
"reference": "18634df356bfd4119fe3d6156bdb990c414c14ea",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -150,7 +150,7 @@
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/thephpleague/flysystem/issues",
|
"issues": "https://github.com/thephpleague/flysystem/issues",
|
||||||
"source": "https://github.com/thephpleague/flysystem/tree/1.1.4"
|
"source": "https://github.com/thephpleague/flysystem/tree/1.1.5"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
|
@ -158,7 +158,7 @@
|
||||||
"type": "other"
|
"type": "other"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2021-06-23T21:56:05+00:00"
|
"time": "2021-08-17T13:49:42+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/mime-type-detection",
|
"name": "league/mime-type-detection",
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
* Dev - Apply `woocommerce_logout_default_redirect_url` filter to logout for custom endpoint. #29967
|
* Dev - Apply `woocommerce_logout_default_redirect_url` filter to logout for custom endpoint. #29967
|
||||||
* Dev - Added new `woocommerce_email_sent` hook. #30123
|
* Dev - Added new `woocommerce_email_sent` hook. #30123
|
||||||
|
|
||||||
**WooCommerce Admin - 2.5.0**
|
**WooCommerce Admin - 2.5.0 & 2.5.1**
|
||||||
|
|
||||||
- Add - Add a delete option to completed tasks #7300
|
- Add - Add a delete option to completed tasks #7300
|
||||||
- Add - Add unit tests around extended payment gateway controller #7133
|
- Add - Add unit tests around extended payment gateway controller #7133
|
||||||
|
@ -79,6 +79,7 @@
|
||||||
- Fix - Fix analytics overview re-arrangement on initial load. #7475
|
- Fix - Fix analytics overview re-arrangement on initial load. #7475
|
||||||
- Fix - Fixes action button mis-alignment within card footer. #7412
|
- Fix - Fixes action button mis-alignment within card footer. #7412
|
||||||
- Fix - Fix up onboarding profiler not working when opted out of tracking
|
- Fix - Fix up onboarding profiler not working when opted out of tracking
|
||||||
|
- Fix - Fix blank screen by setting a default value #7506
|
||||||
- Tweak - Remove performance indicators when Analytics Flag disabled #7234
|
- Tweak - Remove performance indicators when Analytics Flag disabled #7234
|
||||||
- Tweak - Change event name when installing Google Listings and Ads. #7276
|
- Tweak - Change event name when installing Google Listings and Ads. #7276
|
||||||
- Tweak - Removed unused feature flags #7233 and #7273
|
- Tweak - Removed unused feature flags #7233 and #7273
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
"pelago/emogrifier": "3.1.0",
|
"pelago/emogrifier": "3.1.0",
|
||||||
"psr/container": "1.0.0",
|
"psr/container": "1.0.0",
|
||||||
"woocommerce/action-scheduler": "3.2.1",
|
"woocommerce/action-scheduler": "3.2.1",
|
||||||
"woocommerce/woocommerce-admin": "2.5.0",
|
"woocommerce/woocommerce-admin": "2.5.1",
|
||||||
"woocommerce/woocommerce-blocks": "5.5.1"
|
"woocommerce/woocommerce-blocks": "5.5.1"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "e66790f6451aac2d4cb8f418bb26268e",
|
"content-hash": "f1450dbdfedc77735b411ae8a019b534",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "automattic/jetpack-autoloader",
|
"name": "automattic/jetpack-autoloader",
|
||||||
|
@ -532,16 +532,16 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "woocommerce/woocommerce-admin",
|
"name": "woocommerce/woocommerce-admin",
|
||||||
"version": "2.5.0",
|
"version": "2.5.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/woocommerce/woocommerce-admin.git",
|
"url": "https://github.com/woocommerce/woocommerce-admin.git",
|
||||||
"reference": "99a0bd3a48bf33a054efd3b0df29bf42766761f8"
|
"reference": "093d698d770f49d41df8abe89a716dc897bb9e96"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/99a0bd3a48bf33a054efd3b0df29bf42766761f8",
|
"url": "https://api.github.com/repos/woocommerce/woocommerce-admin/zipball/093d698d770f49d41df8abe89a716dc897bb9e96",
|
||||||
"reference": "99a0bd3a48bf33a054efd3b0df29bf42766761f8",
|
"reference": "093d698d770f49d41df8abe89a716dc897bb9e96",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
|
@ -596,9 +596,9 @@
|
||||||
"homepage": "https://github.com/woocommerce/woocommerce-admin",
|
"homepage": "https://github.com/woocommerce/woocommerce-admin",
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/woocommerce/woocommerce-admin/issues",
|
"issues": "https://github.com/woocommerce/woocommerce-admin/issues",
|
||||||
"source": "https://github.com/woocommerce/woocommerce-admin/tree/v2.5.0"
|
"source": "https://github.com/woocommerce/woocommerce-admin/tree/v2.5.1"
|
||||||
},
|
},
|
||||||
"time": "2021-08-09T21:00:32+00:00"
|
"time": "2021-08-16T14:31:33+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "woocommerce/woocommerce-blocks",
|
"name": "woocommerce/woocommerce-blocks",
|
||||||
|
|
|
@ -226,7 +226,7 @@ final class WC_Cart_Totals {
|
||||||
$item->taxable = 'taxable' === $cart_item['data']->get_tax_status();
|
$item->taxable = 'taxable' === $cart_item['data']->get_tax_status();
|
||||||
$item->price_includes_tax = wc_prices_include_tax();
|
$item->price_includes_tax = wc_prices_include_tax();
|
||||||
$item->quantity = $cart_item['quantity'];
|
$item->quantity = $cart_item['quantity'];
|
||||||
$item->price = wc_add_number_precision_deep( $cart_item['data']->get_price() * $cart_item['quantity'] );
|
$item->price = wc_add_number_precision_deep( (float) $cart_item['data']->get_price() * (float) $cart_item['quantity'] );
|
||||||
$item->product = $cart_item['data'];
|
$item->product = $cart_item['data'];
|
||||||
$item->tax_rates = $this->get_item_tax_rates( $item );
|
$item->tax_rates = $this->get_item_tax_rates( $item );
|
||||||
$this->items[ $cart_item_key ] = $item;
|
$this->items[ $cart_item_key ] = $item;
|
||||||
|
|
|
@ -809,6 +809,7 @@ class WC_Countries {
|
||||||
'AF' => array(
|
'AF' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'AO' => array(
|
'AO' => array(
|
||||||
|
@ -826,6 +827,7 @@ class WC_Countries {
|
||||||
),
|
),
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'AU' => array(
|
'AU' => array(
|
||||||
|
@ -845,6 +847,7 @@ class WC_Countries {
|
||||||
),
|
),
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'BA' => array(
|
'BA' => array(
|
||||||
|
@ -871,7 +874,7 @@ class WC_Countries {
|
||||||
),
|
),
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'label' => __( 'Province', 'woocommerce' ),
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'BH' => array(
|
'BH' => array(
|
||||||
|
@ -880,11 +883,13 @@ class WC_Countries {
|
||||||
),
|
),
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'BI' => array(
|
'BI' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'BO' => array(
|
'BO' => array(
|
||||||
|
@ -949,6 +954,7 @@ class WC_Countries {
|
||||||
'CZ' => array(
|
'CZ' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'DE' => array(
|
'DE' => array(
|
||||||
|
@ -975,6 +981,7 @@ class WC_Countries {
|
||||||
),
|
),
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'FI' => array(
|
'FI' => array(
|
||||||
|
@ -983,6 +990,7 @@ class WC_Countries {
|
||||||
),
|
),
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'FR' => array(
|
'FR' => array(
|
||||||
|
@ -991,6 +999,7 @@ class WC_Countries {
|
||||||
),
|
),
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'GH' => array(
|
'GH' => array(
|
||||||
|
@ -1004,11 +1013,13 @@ class WC_Countries {
|
||||||
'GP' => array(
|
'GP' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'GF' => array(
|
'GF' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'GR' => array(
|
'GR' => array(
|
||||||
|
@ -1082,6 +1093,7 @@ class WC_Countries {
|
||||||
),
|
),
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'IL' => array(
|
'IL' => array(
|
||||||
|
@ -1090,11 +1102,13 @@ class WC_Countries {
|
||||||
),
|
),
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'IM' => array(
|
'IM' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'IN' => array(
|
'IN' => array(
|
||||||
|
@ -1158,11 +1172,13 @@ class WC_Countries {
|
||||||
'KR' => array(
|
'KR' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'KW' => array(
|
'KW' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'LV' => array(
|
'LV' => array(
|
||||||
|
@ -1174,16 +1190,19 @@ class WC_Countries {
|
||||||
'LB' => array(
|
'LB' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'MQ' => array(
|
'MQ' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'MT' => array(
|
'MT' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'MZ' => array(
|
'MZ' => array(
|
||||||
|
@ -1201,7 +1220,7 @@ class WC_Countries {
|
||||||
),
|
),
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'label' => __( 'Province', 'woocommerce' ),
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'NG' => array(
|
'NG' => array(
|
||||||
|
@ -1229,6 +1248,7 @@ class WC_Countries {
|
||||||
),
|
),
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'NP' => array(
|
'NP' => array(
|
||||||
|
@ -1245,6 +1265,7 @@ class WC_Countries {
|
||||||
),
|
),
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'PR' => array(
|
'PR' => array(
|
||||||
|
@ -1259,11 +1280,13 @@ class WC_Countries {
|
||||||
'PT' => array(
|
'PT' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'RE' => array(
|
'RE' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'RO' => array(
|
'RO' => array(
|
||||||
|
@ -1287,6 +1310,7 @@ class WC_Countries {
|
||||||
'SG' => array(
|
'SG' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
'city' => array(
|
'city' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
@ -1298,6 +1322,7 @@ class WC_Countries {
|
||||||
),
|
),
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'SI' => array(
|
'SI' => array(
|
||||||
|
@ -1306,6 +1331,7 @@ class WC_Countries {
|
||||||
),
|
),
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'SR' => array(
|
'SR' => array(
|
||||||
|
@ -1334,11 +1360,13 @@ class WC_Countries {
|
||||||
'LK' => array(
|
'LK' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'LU' => array(
|
'LU' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'MD' => array(
|
'MD' => array(
|
||||||
|
@ -1427,6 +1455,7 @@ class WC_Countries {
|
||||||
'YT' => array(
|
'YT' => array(
|
||||||
'state' => array(
|
'state' => array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
|
'hidden' => true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
'ZA' => array(
|
'ZA' => array(
|
||||||
|
|
|
@ -84,7 +84,7 @@ class WC_Discounts {
|
||||||
$item->object = $cart_item;
|
$item->object = $cart_item;
|
||||||
$item->product = $cart_item['data'];
|
$item->product = $cart_item['data'];
|
||||||
$item->quantity = $cart_item['quantity'];
|
$item->quantity = $cart_item['quantity'];
|
||||||
$item->price = wc_add_number_precision_deep( $item->product->get_price() * $item->quantity );
|
$item->price = wc_add_number_precision_deep( (float) $item->product->get_price() * (float) $item->quantity );
|
||||||
$this->items[ $key ] = $item;
|
$this->items[ $key ] = $item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -160,9 +160,6 @@ class WC_Tracker {
|
||||||
// Template overrides.
|
// Template overrides.
|
||||||
$data['template_overrides'] = self::get_all_template_overrides();
|
$data['template_overrides'] = self::get_all_template_overrides();
|
||||||
|
|
||||||
// Template overrides.
|
|
||||||
$data['admin_user_agents'] = self::get_admin_user_agents();
|
|
||||||
|
|
||||||
// Cart & checkout tech (blocks or shortcodes).
|
// Cart & checkout tech (blocks or shortcodes).
|
||||||
$data['cart_checkout'] = self::get_cart_checkout_info();
|
$data['cart_checkout'] = self::get_cart_checkout_info();
|
||||||
|
|
||||||
|
@ -619,6 +616,8 @@ class WC_Tracker {
|
||||||
'version' => WC()->version,
|
'version' => WC()->version,
|
||||||
'currency' => get_woocommerce_currency(),
|
'currency' => get_woocommerce_currency(),
|
||||||
'base_location' => WC()->countries->get_base_country(),
|
'base_location' => WC()->countries->get_base_country(),
|
||||||
|
'base_state' => WC()->countries->get_base_state(),
|
||||||
|
'base_postcode' => WC()->countries->get_base_postcode(),
|
||||||
'selling_locations' => WC()->countries->get_allowed_countries(),
|
'selling_locations' => WC()->countries->get_allowed_countries(),
|
||||||
'api_enabled' => get_option( 'woocommerce_api_enabled' ),
|
'api_enabled' => get_option( 'woocommerce_api_enabled' ),
|
||||||
'weight_unit' => get_option( 'woocommerce_weight_unit' ),
|
'weight_unit' => get_option( 'woocommerce_weight_unit' ),
|
||||||
|
@ -675,15 +674,6 @@ class WC_Tracker {
|
||||||
return $override_data;
|
return $override_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* When an admin user logs in, there user agent is tracked in user meta and collected here.
|
|
||||||
*
|
|
||||||
* @return array
|
|
||||||
*/
|
|
||||||
private static function get_admin_user_agents() {
|
|
||||||
return array_filter( (array) get_option( 'woocommerce_tracker_ua', array() ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search a specific post for text content.
|
* Search a specific post for text content.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1315,8 +1315,6 @@ class WC_Product_Data_Store_CPT extends WC_Data_Store_WP implements WC_Object_Da
|
||||||
AND p.post_type = 'product'
|
AND p.post_type = 'product'
|
||||||
|
|
||||||
",
|
",
|
||||||
'orderby' => '
|
|
||||||
ORDER BY RAND()',
|
|
||||||
'limits' => '
|
'limits' => '
|
||||||
LIMIT ' . absint( $limit ) . '
|
LIMIT ' . absint( $limit ) . '
|
||||||
',
|
',
|
||||||
|
|
|
@ -3532,9 +3532,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"path-parse": {
|
"path-parse": {
|
||||||
"version": "1.0.6",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
|
||||||
"integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==",
|
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"performance-now": {
|
"performance-now": {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import {
|
||||||
const config = require('config');
|
const config = require('config');
|
||||||
const { HTTPClientFactory } = require('@woocommerce/api');
|
const { HTTPClientFactory } = require('@woocommerce/api');
|
||||||
const { addConsoleSuppression, updateReadyPageStatus } = require( '@woocommerce/e2e-environment' );
|
const { addConsoleSuppression, updateReadyPageStatus } = require( '@woocommerce/e2e-environment' );
|
||||||
|
const { DEFAULT_TIMEOUT_OVERRIDE } = process.env;
|
||||||
|
|
||||||
// @todo: remove this once https://github.com/woocommerce/woocommerce-admin/issues/6992 has been addressed
|
// @todo: remove this once https://github.com/woocommerce/woocommerce-admin/issues/6992 has been addressed
|
||||||
addConsoleSuppression( 'woocommerce_shared_settings' );
|
addConsoleSuppression( 'woocommerce_shared_settings' );
|
||||||
|
@ -38,6 +39,12 @@ async function trashExistingPosts() {
|
||||||
// other posts/comments/etc. aren't dirtying tests and tests don't depend on
|
// other posts/comments/etc. aren't dirtying tests and tests don't depend on
|
||||||
// each other's side-effects.
|
// each other's side-effects.
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
|
||||||
|
if ( DEFAULT_TIMEOUT_OVERRIDE ) {
|
||||||
|
page.setDefaultNavigationTimeout( DEFAULT_TIMEOUT_OVERRIDE );
|
||||||
|
page.setDefaultTimeout( DEFAULT_TIMEOUT_OVERRIDE );
|
||||||
|
}
|
||||||
|
|
||||||
// Update the ready page to prevent concurrent test runs
|
// Update the ready page to prevent concurrent test runs
|
||||||
await updateReadyPageStatus('draft');
|
await updateReadyPageStatus('draft');
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
/* eslint-disable jest/no-export, jest/no-disabled-tests, jest/expect-expect */
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
const {
|
const {
|
||||||
shopper,
|
shopper,
|
||||||
|
withRestApi,
|
||||||
createSimpleProduct,
|
createSimpleProduct,
|
||||||
uiUnblocked
|
uiUnblocked
|
||||||
} = require( '@woocommerce/e2e-utils' );
|
} = require( '@woocommerce/e2e-utils' );
|
||||||
|
@ -26,6 +26,9 @@ const runCartPageTest = () => {
|
||||||
describe('Cart page', () => {
|
describe('Cart page', () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await createSimpleProduct();
|
await createSimpleProduct();
|
||||||
|
await withRestApi.resetSettingsGroupToDefault('general');
|
||||||
|
await withRestApi.resetSettingsGroupToDefault('products');
|
||||||
|
await withRestApi.resetSettingsGroupToDefault('tax');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display no item in the cart', async () => {
|
it('should display no item in the cart', async () => {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/* eslint-disable jest/no-export, jest/no-disabled-tests, jest/expect-expect, jest/no-standalone-expect */
|
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
const {
|
const {
|
||||||
shopper,
|
shopper,
|
||||||
merchant,
|
merchant,
|
||||||
|
withRestApi,
|
||||||
createSimpleProduct,
|
createSimpleProduct,
|
||||||
setCheckbox,
|
setCheckbox,
|
||||||
settingsPageSaveChanges,
|
settingsPageSaveChanges,
|
||||||
|
@ -28,6 +28,9 @@ const runCheckoutPageTest = () => {
|
||||||
describe('Checkout page', () => {
|
describe('Checkout page', () => {
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
await createSimpleProduct();
|
await createSimpleProduct();
|
||||||
|
await withRestApi.resetSettingsGroupToDefault('general');
|
||||||
|
await withRestApi.resetSettingsGroupToDefault('products');
|
||||||
|
await withRestApi.resetSettingsGroupToDefault('tax');
|
||||||
|
|
||||||
// Set free shipping within California
|
// Set free shipping within California
|
||||||
await merchant.login();
|
await merchant.login();
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
# Unreleased
|
# Unreleased
|
||||||
|
|
||||||
- `updateReadyPageStatus` utility to update the status of the ready page
|
- `updateReadyPageStatus` utility to update the status of the ready page.
|
||||||
- Added plugin upload functionality util that provides a method to pull a plugin zip from a remote location
|
- Added plugin upload functionality util that provides a method to pull a plugin zip from a remote location:
|
||||||
- `getRemotePluginZip( fileUrl )` to get the remote zip. Returns the filepath of the zip location.
|
- `getRemotePluginZip( fileUrl )` to get the remote zip. Returns the filepath of the zip location.
|
||||||
- Added plugin zip utility functions:
|
- Added plugin zip utility functions:
|
||||||
- `checkNestedZip( zipFilePath, savePath )` checks a plugin zip file for any nested zip files. If one is found, it is extracted. Returns the path where the zip file is located.
|
- `checkNestedZip( zipFilePath, savePath )` checks a plugin zip file for any nested zip files. If one is found, it is extracted. Returns the path where the zip file is located.
|
||||||
- `downloadZip( fileUrl, downloadPath )` downloads a plugin zip file from a remote location to the provided path.
|
- `downloadZip( fileUrl, downloadPath )` downloads a plugin zip file from a remote location to the provided path.
|
||||||
|
- Added `getLatestReleaseZipUrl( owner, repository, getPrerelease, perPage )` util function to get the latest release zip from a GitHub repository.
|
||||||
|
- Added `DEFAULT_TIMEOUT_OVERRIDE` that allows passing in a time in milliseconds to override the default Jest and Puppeteer timeouts.
|
||||||
|
|
||||||
# 0.2.2
|
# 0.2.2
|
||||||
|
|
||||||
|
|
|
@ -87,6 +87,21 @@ await takeScreenshotFor( 'name of current step' );
|
||||||
|
|
||||||
Screenshots will be saved to `tests/e2e/screenshots`. This folder is cleared at the beginning of each test run.
|
Screenshots will be saved to `tests/e2e/screenshots`. This folder is cleared at the beginning of each test run.
|
||||||
|
|
||||||
|
### Override default test timeout
|
||||||
|
|
||||||
|
To override the default timeout for the tests, you can use the `DEFAULT_TIMEOUT_OVERRIDE` flag and pass in a maximum timeout in milliseconds. For example, you can pass it in when running the tests from the command line:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
DEFAULT_TIMEOUT_OVERRIDE=35000 npx wc-e2e test:e2e
|
||||||
|
```
|
||||||
|
|
||||||
|
This value will override the default Jest timeout as well as pass the timeout to the following Puppeteer methods:
|
||||||
|
|
||||||
|
* page.setDefaultTimeout();
|
||||||
|
* page.setDefaultNavigationTimeout();
|
||||||
|
|
||||||
|
For a list of the methods that the above timeout affects, please see the Puppeteer documentation for [`page.setDefaultTimeout()`](https://pptr.dev/#?product=Puppeteer&version=v10.2.0&show=api-pagesetdefaulttimeouttimeout) and [`page.setDefaultNavigationTimeout`](https://pptr.dev/#?product=Puppeteer&version=v10.2.0&show=api-pagesetdefaultnavigationtimeouttimeout) for more information.
|
||||||
|
|
||||||
### Jest Puppeteer Config
|
### Jest Puppeteer Config
|
||||||
|
|
||||||
The test sequencer uses the following default Puppeteer configuration:
|
The test sequencer uses the following default Puppeteer configuration:
|
||||||
|
@ -196,6 +211,14 @@ The above method also makes use of the following utility methods which can also
|
||||||
- `checkNestedZip( zipFilePath, savePath )` used to check a plugin zip file for any nested zip files. If one is found, it is extracted. Returns the path where the zip file is located.
|
- `checkNestedZip( zipFilePath, savePath )` used to check a plugin zip file for any nested zip files. If one is found, it is extracted. Returns the path where the zip file is located.
|
||||||
- `downloadZip( fileUrl, downloadPath )` can be used to directly download a plugin zip file from a remote location to the provided path.
|
- `downloadZip( fileUrl, downloadPath )` can be used to directly download a plugin zip file from a remote location to the provided path.
|
||||||
|
|
||||||
|
### Get the latest released zip URL
|
||||||
|
|
||||||
|
If you would like to get the latest release zip URL, which can be used in the methods mentioned above, you can use the following helper function to do so:
|
||||||
|
|
||||||
|
`getLatestReleaseZipUrl( owner, repository, getPrerelease, perPage )`
|
||||||
|
|
||||||
|
This will return a string with the latest release URL. Optionally, you can use the `getPrerelease` boolean flag, which defaults to false, on whether or not to get a prerelease instead. The `perPage` flag can be used to return more results when getting the list of releases. The default value is 3.
|
||||||
|
|
||||||
## Additional information
|
## Additional information
|
||||||
|
|
||||||
Refer to [`tests/e2e/core-tests`](https://github.com/woocommerce/woocommerce/tree/trunk/tests/e2e/core-tests) for some test examples, and [`tests/e2e`](https://github.com/woocommerce/woocommerce/tree/trunk/tests/e2e) for general information on e2e tests.
|
Refer to [`tests/e2e/core-tests`](https://github.com/woocommerce/woocommerce/tree/trunk/tests/e2e/core-tests) for some test examples, and [`tests/e2e`](https://github.com/woocommerce/woocommerce/tree/trunk/tests/e2e) for general information on e2e tests.
|
||||||
|
|
|
@ -5,7 +5,7 @@ const program = require( 'commander' );
|
||||||
const path = require( 'path' );
|
const path = require( 'path' );
|
||||||
const fs = require( 'fs' );
|
const fs = require( 'fs' );
|
||||||
const { getAppRoot } = require( '../utils' );
|
const { getAppRoot } = require( '../utils' );
|
||||||
const { WC_E2E_SCREENSHOTS, JEST_PUPPETEER_CONFIG } = process.env;
|
const { WC_E2E_SCREENSHOTS, JEST_PUPPETEER_CONFIG, DEFAULT_TIMEOUT_OVERRIDE } = process.env;
|
||||||
|
|
||||||
program
|
program
|
||||||
.usage( '<file ...> [options]' )
|
.usage( '<file ...> [options]' )
|
||||||
|
@ -43,6 +43,10 @@ let testEnvVars = {
|
||||||
jest_test_timeout: program.dev ? 120000 : 30000,
|
jest_test_timeout: program.dev ? 120000 : 30000,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if ( DEFAULT_TIMEOUT_OVERRIDE ) {
|
||||||
|
testEnvVars.jest_test_timeout = DEFAULT_TIMEOUT_OVERRIDE;
|
||||||
|
}
|
||||||
|
|
||||||
if ( ! JEST_PUPPETEER_CONFIG ) {
|
if ( ! JEST_PUPPETEER_CONFIG ) {
|
||||||
// Use local Puppeteer config if there is one.
|
// Use local Puppeteer config if there is one.
|
||||||
// Load test configuration file into an object.
|
// Load test configuration file into an object.
|
||||||
|
|
|
@ -29,6 +29,52 @@ const getRemotePluginZip = async ( fileUrl ) => {
|
||||||
return filePath;
|
return filePath;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the latest release zip for a plugin from a GiHub repository.
|
||||||
|
*
|
||||||
|
* @param {string} owner The owner of the plugin repository.
|
||||||
|
* @param {string} repository The repository name.
|
||||||
|
* @param {boolean} getPrerelease Flag on whether to get a prelease or not.
|
||||||
|
* @param {number} perPage Limit of entries returned from the latest releases list, defaults to 3.
|
||||||
|
* @returns {Promise<string>}} Returns the URL for the release zip file.
|
||||||
|
*/
|
||||||
|
const getLatestReleaseZipUrl = async ( owner, repository, getPrerelease = false, perPage = 3 ) => {
|
||||||
|
let requesturl;
|
||||||
|
|
||||||
|
if ( getPrerelease ) {
|
||||||
|
requesturl = `https://api.github.com/repos/${owner}/${repository}/releases?per_page=${perPage}`;
|
||||||
|
} else {
|
||||||
|
requesturl = `https://api.github.com/repos/${owner}/${repository}/releases/latest`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
url: requesturl,
|
||||||
|
method: 'GET',
|
||||||
|
json: true,
|
||||||
|
headers: {'user-agent': 'node.js'}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Wrap in a promise to make the request async
|
||||||
|
return new Promise( function( resolve, reject ) {
|
||||||
|
request.get(options, function( err, resp, body ) {
|
||||||
|
if ( err ) {
|
||||||
|
reject( err );
|
||||||
|
} else {
|
||||||
|
if ( getPrerelease ) {
|
||||||
|
// Loop until we find the first pre-release, then return it.
|
||||||
|
body.forEach(release => {
|
||||||
|
if ( release.prerelease ) {
|
||||||
|
resolve( release.zipball_url );
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
resolve( body.zipball_url );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check the zip file for any nested zips. If one is found, extract it.
|
* Check the zip file for any nested zips. If one is found, extract it.
|
||||||
*
|
*
|
||||||
|
@ -80,6 +126,7 @@ const downloadZip = async ( fileUrl, downloadPath ) => {
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getRemotePluginZip,
|
getRemotePluginZip,
|
||||||
|
getLatestReleaseZipUrl,
|
||||||
checkNestedZip,
|
checkNestedZip,
|
||||||
downloadZip,
|
downloadZip,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const getAppRoot = require( './app-root' );
|
const getAppRoot = require( './app-root' );
|
||||||
const { getAppName, getAppBase } = require( './app-name' );
|
const { getAppName, getAppBase } = require( './app-name' );
|
||||||
const { getTestConfig, getAdminConfig } = require( './test-config' );
|
const { getTestConfig, getAdminConfig } = require( './test-config' );
|
||||||
const { getRemotePluginZip } = require('./get-plugin-zip');
|
const { getRemotePluginZip, getLatestReleaseZipUrl } = require('./get-plugin-zip');
|
||||||
const takeScreenshotFor = require( './take-screenshot' );
|
const takeScreenshotFor = require( './take-screenshot' );
|
||||||
const updateReadyPageStatus = require('./update-ready-page');
|
const updateReadyPageStatus = require('./update-ready-page');
|
||||||
const consoleUtils = require( './filter-console' );
|
const consoleUtils = require( './filter-console' );
|
||||||
|
@ -13,6 +13,7 @@ module.exports = {
|
||||||
getTestConfig,
|
getTestConfig,
|
||||||
getAdminConfig,
|
getAdminConfig,
|
||||||
getRemotePluginZip,
|
getRemotePluginZip,
|
||||||
|
getLatestReleaseZipUrl,
|
||||||
takeScreenshotFor,
|
takeScreenshotFor,
|
||||||
updateReadyPageStatus,
|
updateReadyPageStatus,
|
||||||
...consoleUtils,
|
...consoleUtils,
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*/
|
*/
|
||||||
const { merchant, utils } = require( '@woocommerce/e2e-utils' );
|
const { merchant, utils } = require( '@woocommerce/e2e-utils' );
|
||||||
|
|
||||||
const { getRemotePluginZip } = require( '@woocommerce/e2e-environment' );
|
const { getRemotePluginZip, getLatestReleaseZipUrl } = require( '@woocommerce/e2e-environment' );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
|
@ -13,16 +13,23 @@ const {
|
||||||
beforeAll,
|
beforeAll,
|
||||||
} = require( '@jest/globals' );
|
} = require( '@jest/globals' );
|
||||||
|
|
||||||
const { UPDATE_WC } = process.env;
|
const { UPDATE_WC, TEST_RELEASE } = process.env;
|
||||||
|
|
||||||
const nightlyZip = 'https://github.com/woocommerce/woocommerce/releases/download/nightly/woocommerce-trunk-nightly.zip';
|
let zipUrl;
|
||||||
const pluginName = 'WooCommerce';
|
const pluginName = 'WooCommerce';
|
||||||
|
|
||||||
let pluginPath;
|
let pluginPath;
|
||||||
|
|
||||||
utils.describeIf( UPDATE_WC )( 'WooCommerce plugin can be uploaded and activated', () => {
|
utils.describeIf( UPDATE_WC )( 'WooCommerce plugin can be uploaded and activated', () => {
|
||||||
beforeAll( async () => {
|
beforeAll( async () => {
|
||||||
pluginPath = await getRemotePluginZip( nightlyZip );
|
|
||||||
|
if ( TEST_RELEASE ) {
|
||||||
|
zipUrl = await getLatestReleaseZipUrl('woocommerce', 'woocommerce');
|
||||||
|
} else {
|
||||||
|
zipUrl = 'https://github.com/woocommerce/woocommerce/releases/download/nightly/woocommerce-trunk-nightly.zip';
|
||||||
|
}
|
||||||
|
|
||||||
|
pluginPath = await getRemotePluginZip( zipUrl );
|
||||||
await merchant.login();
|
await merchant.login();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -34,4 +41,9 @@ utils.describeIf( UPDATE_WC )( 'WooCommerce plugin can be uploaded and activated
|
||||||
await merchant.uploadAndActivatePlugin( pluginPath, pluginName );
|
await merchant.uploadAndActivatePlugin( pluginPath, pluginName );
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it( 'can run the database update', async () => {
|
||||||
|
// Check for, and run, the database upgrade if needed
|
||||||
|
await merchant.runDatabaseUpdate();
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
- Added `describeIf()` to conditionally run a test suite
|
- Added `describeIf()` to conditionally run a test suite
|
||||||
- Added `itIf()` to conditionally run a test case.
|
- Added `itIf()` to conditionally run a test case.
|
||||||
- Added merchant workflows around plugins: `uploadAndActivatePlugin()`, `activatePlugin()`, `deactivatePlugin()`, `deletePlugin()`
|
- Added merchant workflows around plugins: `uploadAndActivatePlugin()`, `activatePlugin()`, `deactivatePlugin()`, `deletePlugin()`
|
||||||
|
- Added merchant workflows checking for a database update and performing the update if needed: `runDatabaseUpdate()`
|
||||||
- Added `deleteAllOrders()` that goes through and deletes all orders
|
- Added `deleteAllOrders()` that goes through and deletes all orders
|
||||||
- Added `deleteAllShippingClasses()` which permanently deletes all shipping classes using the API
|
- Added `deleteAllShippingClasses()` which permanently deletes all shipping classes using the API
|
||||||
- Added `statuses` optional parameter to `deleteAllRepositoryObjects()` to delete on specific statuses
|
- Added `statuses` optional parameter to `deleteAllRepositoryObjects()` to delete on specific statuses
|
||||||
|
|
|
@ -109,6 +109,7 @@ This package provides support for enabling retries in tests:
|
||||||
| `updateWordPress` | | Install pending WordPress updates on Dashboard -> Updates|
|
| `updateWordPress` | | Install pending WordPress updates on Dashboard -> Updates|
|
||||||
| `updatePlugins` | | Install all pending plugin updates on Dashboard -> Updates|
|
| `updatePlugins` | | Install all pending plugin updates on Dashboard -> Updates|
|
||||||
| `updateThemes` | | Install all pending theme updates on Dashboard -> Updates|
|
| `updateThemes` | | Install all pending theme updates on Dashboard -> Updates|
|
||||||
|
| `runDatabaseUpdate` || Runs the database update if needed |
|
||||||
|
|
||||||
### Shopper `shopper`
|
### Shopper `shopper`
|
||||||
|
|
||||||
|
@ -133,7 +134,7 @@ This package provides support for enabling retries in tests:
|
||||||
| `removeFromCart` | `productTitle` | Remove a product from the cart on the cart page |
|
| `removeFromCart` | `productTitle` | Remove a product from the cart on the cart page |
|
||||||
| `setCartQuantity` | `productTitle, quantityValue` | Change the quantity of a product on the cart page |
|
| `setCartQuantity` | `productTitle, quantityValue` | Change the quantity of a product on the cart page |
|
||||||
| `searchForProduct` | | Searching for a product name and landing on its detail page |
|
| `searchForProduct` | | Searching for a product name and landing on its detail page |
|
||||||
| `emptyCart` | | Removes any products and coupons that are in the cart |
|
| `emptyCart` | | Removes any products and coupons that are in the cart |
|
||||||
|
|
||||||
### REST API `withRestApi`
|
### REST API `withRestApi`
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "@woocommerce/e2e-utils",
|
"name": "@woocommerce/e2e-utils",
|
||||||
"version": "0.1.5",
|
"version": "0.1.5",
|
||||||
"description": "End-To-End (E2E) test utils for WooCommerce",
|
"description": "End-To-End (E2E) test utils for WooCommerce",
|
||||||
"homepage": "https://github.com/woocommerce/woocommerce/tree/trunk/tests/e2e-utils/README.md",
|
"homepage": "https://github.com/woocommerce/woocommerce/tree/trunk/tests/e2e/utils/README.md",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/woocommerce/woocommerce.git"
|
"url": "https://github.com/woocommerce/woocommerce.git"
|
||||||
|
|
|
@ -373,6 +373,34 @@ const merchant = {
|
||||||
|
|
||||||
// Wait for Ajax calls to finish
|
// Wait for Ajax calls to finish
|
||||||
await page.waitForResponse( response => response.status() === 200 );
|
await page.waitForResponse( response => response.status() === 200 );
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs the database update if needed. For example, after uploading the WooCommerce plugin or updating WooCommerce.
|
||||||
|
*/
|
||||||
|
runDatabaseUpdate: async () => {
|
||||||
|
if ( await page.$( '.updated.woocommerce-message.wc-connect' ) !== null ) {
|
||||||
|
await expect( page ).toMatchElement( 'a.wc-update-now', { text: 'Update WooCommerce Database' } );
|
||||||
|
await expect( page ).toClick( 'a.wc-update-now' );
|
||||||
|
await page.waitForNavigation( { waitUntil: 'networkidle0' } );
|
||||||
|
await merchant.checkDatabaseUpdateComplete();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the database update is complete, if not, refresh the page until it is.
|
||||||
|
*/
|
||||||
|
checkDatabaseUpdateComplete: async () => {
|
||||||
|
await page.reload( { waitUntil: [ 'networkidle0', 'domcontentloaded'] } );
|
||||||
|
|
||||||
|
const thanksButtonSelector = 'a.components-button.is-primary';
|
||||||
|
|
||||||
|
if ( await page.$( thanksButtonSelector ) !== null ) {
|
||||||
|
await expect( page ).toMatchElement( thanksButtonSelector, { text: 'Thanks!' } );
|
||||||
|
await expect( page ).toClick( thanksButtonSelector );
|
||||||
|
} else {
|
||||||
|
await merchant.checkDatabaseUpdateComplete();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue