Merge branch 'trunk' into update/marketplace-1

This commit is contained in:
And Finally 2021-08-12 09:03:09 +01:00
commit 8a326b24ba
11 changed files with 411 additions and 621 deletions

View File

@ -0,0 +1,46 @@
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
run: |
npx wc-e2e test:e2e ./tests/e2e/specs/smoke-tests/update-woocommerce.js
npx wc-e2e test:e2e

View File

@ -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

View File

@ -1,32 +1,17 @@
/*! /*!
* 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);
@ -35,7 +20,8 @@
// 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,49 +64,46 @@ 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) === ".") {
//If have a base name, try to normalize against it,
//otherwise, assume it is a top-level require that will
//be relative to baseUrl in the end.
if (baseName) {
name = name.split('/'); name = name.split('/');
lastIndex = name.length - 1; 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
// because node allows either .js or non .js to map
// to same file.
if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); 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 ..
break;
} else if (i > 0) { } else if (i > 0) {
name.splice(i - 1, 2); name.splice(i - 1, 2);
i -= 2; i -= 2;
@ -127,7 +112,12 @@ var requirejs, require, define;
} }
//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)
.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.$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">' +
'&times;' + '&times;' +
'</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();
} }
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 { } 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;

View File

@ -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 () => {

View File

@ -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();

View File

@ -6,6 +6,7 @@
- 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
# 0.2.2 # 0.2.2

View File

@ -196,6 +196,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.

View File

@ -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,
}; };

View File

@ -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,

View File

@ -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();
}); });