Added plugin upload functionality
This commit is contained in:
parent
7d3ac49f64
commit
268c07118e
|
@ -39,4 +39,5 @@ 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 }}
|
||||||
run: |
|
run: |
|
||||||
|
npx wc-e2e test:e2e ./tests/e2e/specs/smoke-tests/update-woocommerce.test.js
|
||||||
npx wc-e2e test:e2e
|
npx wc-e2e test:e2e
|
||||||
|
|
|
@ -52,6 +52,7 @@ tests/cli/vendor
|
||||||
/tests/e2e/env/build/
|
/tests/e2e/env/build/
|
||||||
/tests/e2e/env/build-module/
|
/tests/e2e/env/build-module/
|
||||||
/tests/e2e/screenshots
|
/tests/e2e/screenshots
|
||||||
|
/tests/e2e/plugins
|
||||||
/tests/e2e/utils/build/
|
/tests/e2e/utils/build/
|
||||||
/tests/e2e/utils/build-module/
|
/tests/e2e/utils/build-module/
|
||||||
|
|
||||||
|
|
|
@ -9232,7 +9232,9 @@
|
||||||
"app-root-path": "^3.0.0",
|
"app-root-path": "^3.0.0",
|
||||||
"jest": "^25.1.0",
|
"jest": "^25.1.0",
|
||||||
"jest-each": "25.5.0",
|
"jest-each": "25.5.0",
|
||||||
"jest-puppeteer": "^4.4.0"
|
"jest-puppeteer": "^4.4.0",
|
||||||
|
"node-stream-zip": "^1.13.6",
|
||||||
|
"request": "^2.88.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@automattic/puppeteer-utils": {
|
"@automattic/puppeteer-utils": {
|
||||||
|
@ -33239,6 +33241,12 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node-stream-zip": {
|
||||||
|
"version": "1.13.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.13.6.tgz",
|
||||||
|
"integrity": "sha512-c7tRSVkLNOHvasWgmZ2d86cDgTWEygnkuuHNOY9c0mR3yLZtQTTrGvMaJ/fPs6+LOJn3240y30l5sjLaXFtcvw==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"nopt": {
|
"nopt": {
|
||||||
"version": "3.0.6",
|
"version": "3.0.6",
|
||||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
|
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# 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
|
||||||
|
- `getRemotePluginZip( fileUrl )` to get the remote zip. Returns the filepath of the zip location.
|
||||||
|
|
||||||
# 0.2.2
|
# 0.2.2
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,9 @@
|
||||||
"app-root-path": "^3.0.0",
|
"app-root-path": "^3.0.0",
|
||||||
"jest": "^25.1.0",
|
"jest": "^25.1.0",
|
||||||
"jest-each": "25.5.0",
|
"jest-each": "25.5.0",
|
||||||
"jest-puppeteer": "^4.4.0"
|
"jest-puppeteer": "^4.4.0",
|
||||||
|
"request": "^2.88.2",
|
||||||
|
"node-stream-zip": "^1.13.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "7.12.0",
|
"@babel/cli": "7.12.0",
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
const path = require( 'path' );
|
||||||
|
const getAppRoot = require( './app-root' );
|
||||||
|
const fs = require('fs');
|
||||||
|
const mkdirp = require( 'mkdirp' );
|
||||||
|
const request = require('request');
|
||||||
|
const StreamZip = require('node-stream-zip');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upload a plugin zip from a remote location, such as a GitHub URL or other hosted location.
|
||||||
|
*
|
||||||
|
* @param {string} fileUrl The URL where the zip file is located.
|
||||||
|
* @returns {string} The path where the zip file is located.
|
||||||
|
*/
|
||||||
|
const getRemotePluginZip = async ( fileUrl ) => {
|
||||||
|
const appPath = getAppRoot();
|
||||||
|
const savePath = path.resolve( appPath, 'tests/e2e/plugins' );
|
||||||
|
mkdirp.sync( savePath );
|
||||||
|
|
||||||
|
// Pull the filename from the end of the URL
|
||||||
|
let fileName = fileUrl.split('/').pop();
|
||||||
|
let filePath = path.join( savePath, fileName );
|
||||||
|
|
||||||
|
// First, download the zip file
|
||||||
|
await downloadZip( fileUrl, filePath );
|
||||||
|
|
||||||
|
// Check for a nested zip and update the filepath
|
||||||
|
filePath = await checkZip( filePath, savePath );
|
||||||
|
|
||||||
|
return filePath;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check the zip file for any nested zips. If one is found, extract it.
|
||||||
|
*
|
||||||
|
* @param {string} zipFilePath The location of the zip file.
|
||||||
|
* @param {string} savePath The location where to save a nested zip if found.
|
||||||
|
* @returns {string} The path where the zip file is located.
|
||||||
|
*/
|
||||||
|
const checkZip = async ( zipFilePath, savePath ) => {
|
||||||
|
const zip = new StreamZip.async( { file: zipFilePath } );
|
||||||
|
const entries = await zip.entries();
|
||||||
|
|
||||||
|
for (const entry of Object.values( entries )) {
|
||||||
|
if ( entry.name.match( /.zip/ )) {
|
||||||
|
await zip.extract( null, savePath );
|
||||||
|
await zip.close();
|
||||||
|
return path.join( savePath, entry.name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return zipFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Download the zip file from a remote location.
|
||||||
|
*
|
||||||
|
* @param {string} fileUrl The URL where the zip file is located.
|
||||||
|
* @param {string} downloadPath The location where to download the zip to.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
*/
|
||||||
|
const downloadZip = async ( fileUrl, downloadPath ) => {
|
||||||
|
const options = {
|
||||||
|
url: fileUrl,
|
||||||
|
method: 'GET',
|
||||||
|
encoding: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
resolve( body );
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.pipe( fs.createWriteStream( downloadPath ) );
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getRemotePluginZip,
|
||||||
|
};
|
|
@ -1,6 +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 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' );
|
||||||
|
@ -11,6 +12,7 @@ module.exports = {
|
||||||
getAppName,
|
getAppName,
|
||||||
getTestConfig,
|
getTestConfig,
|
||||||
getAdminConfig,
|
getAdminConfig,
|
||||||
|
getRemotePluginZip,
|
||||||
takeScreenshotFor,
|
takeScreenshotFor,
|
||||||
updateReadyPageStatus,
|
updateReadyPageStatus,
|
||||||
...consoleUtils,
|
...consoleUtils,
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
const { merchant } = require( '@woocommerce/e2e-utils' );
|
||||||
|
|
||||||
|
const { getRemotePluginZip } = require( '@woocommerce/e2e-environment' );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
const {
|
||||||
|
it,
|
||||||
|
describe,
|
||||||
|
beforeAll,
|
||||||
|
} = require( '@jest/globals' );
|
||||||
|
|
||||||
|
|
||||||
|
const nightlyZip = 'https://github.com/woocommerce/woocommerce/releases/download/nightly/woocommerce-trunk-nightly.zip';
|
||||||
|
const pluginName = 'WooCommerce';
|
||||||
|
|
||||||
|
let pluginPath;
|
||||||
|
|
||||||
|
describe( 'WooCommerce plugin can be uploaded and activated', () => {
|
||||||
|
beforeAll( async () => {
|
||||||
|
pluginPath = await getRemotePluginZip( nightlyZip );
|
||||||
|
await merchant.login();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll( async () => {
|
||||||
|
await merchant.logout();
|
||||||
|
});
|
||||||
|
|
||||||
|
it( 'can upload and activate the WooCommerce plugin', async () => {
|
||||||
|
await merchant.uploadAndActivatePlugin( pluginPath, pluginName );
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
|
@ -8,6 +8,10 @@
|
||||||
- Added new merchant flows:
|
- Added new merchant flows:
|
||||||
- `openWordPressUpdatesPage()`
|
- `openWordPressUpdatesPage()`
|
||||||
- `installAllUpdates()`
|
- `installAllUpdates()`
|
||||||
|
- Added `getSlug()` helper to return the slug string for a provided string
|
||||||
|
- Added `describeIf()` to conditionally run a test suite
|
||||||
|
- Added `itIf()` to conditionally run a test case.
|
||||||
|
- Added merchant workflows around plugins: `uploadAndActivatePlugin()`, `activatePlugin()`, `deactivatePlugin()`, `deletePlugin()`
|
||||||
|
|
||||||
# 0.1.5
|
# 0.1.5
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,7 @@ This package provides support for enabling retries in tests:
|
||||||
- `WP_ADMIN_WC_SETTINGS` - WooCommerce settings page root
|
- `WP_ADMIN_WC_SETTINGS` - WooCommerce settings page root
|
||||||
- `WP_ADMIN_NEW_SHIPPING_ZONE` - WooCommerce new shipping zone
|
- `WP_ADMIN_NEW_SHIPPING_ZONE` - WooCommerce new shipping zone
|
||||||
- `WP_ADMIN_WC_EXTENSIONS` - WooCommerce extensions page
|
- `WP_ADMIN_WC_EXTENSIONS` - WooCommerce extensions page
|
||||||
|
- `WP_ADMIN_PLUGIN_INSTALL` - WordPress plugin install page
|
||||||
|
|
||||||
#### Front end
|
#### Front end
|
||||||
|
|
||||||
|
|
|
@ -12,8 +12,10 @@ export const WP_ADMIN_LOGIN = baseUrl + 'wp-login.php';
|
||||||
export const WP_ADMIN_DASHBOARD = baseUrl + 'wp-admin/';
|
export const WP_ADMIN_DASHBOARD = baseUrl + 'wp-admin/';
|
||||||
export const WP_ADMIN_WP_UPDATES = WP_ADMIN_DASHBOARD + 'update-core.php';
|
export const WP_ADMIN_WP_UPDATES = WP_ADMIN_DASHBOARD + 'update-core.php';
|
||||||
export const WP_ADMIN_PLUGINS = WP_ADMIN_DASHBOARD + 'plugins.php';
|
export const WP_ADMIN_PLUGINS = WP_ADMIN_DASHBOARD + 'plugins.php';
|
||||||
|
export const WP_ADMIN_PLUGIN_INSTALL = WP_ADMIN_DASHBOARD + 'plugin-install.php';
|
||||||
export const WP_ADMIN_PERMALINK_SETTINGS = WP_ADMIN_DASHBOARD + 'options-permalink.php';
|
export const WP_ADMIN_PERMALINK_SETTINGS = WP_ADMIN_DASHBOARD + 'options-permalink.php';
|
||||||
export const WP_ADMIN_ALL_USERS_VIEW = WP_ADMIN_DASHBOARD + 'users.php';
|
export const WP_ADMIN_ALL_USERS_VIEW = WP_ADMIN_DASHBOARD + 'users.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WooCommerce core post type pages.
|
* WooCommerce core post type pages.
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -27,6 +29,7 @@ export const WP_ADMIN_NEW_ORDER = WP_ADMIN_NEW_POST_TYPE + 'shop_order';
|
||||||
export const WP_ADMIN_ALL_PRODUCTS_VIEW = WP_ADMIN_POST_TYPE + 'product';
|
export const WP_ADMIN_ALL_PRODUCTS_VIEW = WP_ADMIN_POST_TYPE + 'product';
|
||||||
export const WP_ADMIN_NEW_PRODUCT = WP_ADMIN_NEW_POST_TYPE + 'product';
|
export const WP_ADMIN_NEW_PRODUCT = WP_ADMIN_NEW_POST_TYPE + 'product';
|
||||||
export const WP_ADMIN_IMPORT_PRODUCTS = WP_ADMIN_ALL_PRODUCTS_VIEW + '&page=product_importer';
|
export const WP_ADMIN_IMPORT_PRODUCTS = WP_ADMIN_ALL_PRODUCTS_VIEW + '&page=product_importer';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* WooCommerce settings pages.
|
* WooCommerce settings pages.
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -38,6 +41,7 @@ export const WP_ADMIN_ANALYTICS_PAGES = WP_ADMIN_WC_HOME + '&path=%2Fanalytics%2
|
||||||
export const WP_ADMIN_WC_SETTINGS = WP_ADMIN_PLUGIN_PAGE + 'wc-settings&tab=';
|
export const WP_ADMIN_WC_SETTINGS = WP_ADMIN_PLUGIN_PAGE + 'wc-settings&tab=';
|
||||||
export const WP_ADMIN_NEW_SHIPPING_ZONE = WP_ADMIN_WC_SETTINGS + 'shipping&zone_id=new';
|
export const WP_ADMIN_NEW_SHIPPING_ZONE = WP_ADMIN_WC_SETTINGS + 'shipping&zone_id=new';
|
||||||
export const WP_ADMIN_WC_EXTENSIONS = WP_ADMIN_PLUGIN_PAGE + 'wc-addons';
|
export const WP_ADMIN_WC_EXTENSIONS = WP_ADMIN_PLUGIN_PAGE + 'wc-addons';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shop pages.
|
* Shop pages.
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
@ -47,6 +51,7 @@ export const SHOP_PRODUCT_PAGE = baseUrl + '?p=';
|
||||||
export const SHOP_CART_PAGE = baseUrl + 'cart';
|
export const SHOP_CART_PAGE = baseUrl + 'cart';
|
||||||
export const SHOP_CHECKOUT_PAGE = baseUrl + 'checkout/';
|
export const SHOP_CHECKOUT_PAGE = baseUrl + 'checkout/';
|
||||||
export const SHOP_MY_ACCOUNT_PAGE = baseUrl + 'my-account/';
|
export const SHOP_MY_ACCOUNT_PAGE = baseUrl + 'my-account/';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Customer account pages.
|
* Customer account pages.
|
||||||
* @type {string}
|
* @type {string}
|
||||||
|
|
|
@ -6,6 +6,7 @@ const flowExpressions = require( './expressions' );
|
||||||
const merchant = require( './merchant' );
|
const merchant = require( './merchant' );
|
||||||
const shopper = require( './shopper' );
|
const shopper = require( './shopper' );
|
||||||
const { withRestApi } = require( './with-rest-api' );
|
const { withRestApi } = require( './with-rest-api' );
|
||||||
|
const utils = require( './utils' );
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
...flowConstants,
|
...flowConstants,
|
||||||
|
@ -13,4 +14,5 @@ module.exports = {
|
||||||
merchant,
|
merchant,
|
||||||
shopper,
|
shopper,
|
||||||
withRestApi,
|
withRestApi,
|
||||||
|
utils,
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,10 +25,13 @@ const {
|
||||||
WP_ADMIN_ANALYTICS_PAGES,
|
WP_ADMIN_ANALYTICS_PAGES,
|
||||||
WP_ADMIN_ALL_USERS_VIEW,
|
WP_ADMIN_ALL_USERS_VIEW,
|
||||||
WP_ADMIN_IMPORT_PRODUCTS,
|
WP_ADMIN_IMPORT_PRODUCTS,
|
||||||
|
WP_ADMIN_PLUGIN_INSTALL,
|
||||||
WP_ADMIN_WP_UPDATES,
|
WP_ADMIN_WP_UPDATES,
|
||||||
IS_RETEST_MODE,
|
IS_RETEST_MODE,
|
||||||
} = require( './constants' );
|
} = require( './constants' );
|
||||||
|
|
||||||
|
const { getSlug } = require('./utils');
|
||||||
|
|
||||||
const baseUrl = config.get( 'url' );
|
const baseUrl = config.get( 'url' );
|
||||||
const WP_ADMIN_SINGLE_CPT_VIEW = ( postId ) => baseUrl + `wp-admin/post.php?post=${ postId }&action=edit`;
|
const WP_ADMIN_SINGLE_CPT_VIEW = ( postId ) => baseUrl + `wp-admin/post.php?post=${ postId }&action=edit`;
|
||||||
|
|
||||||
|
@ -276,7 +279,101 @@ const merchant = {
|
||||||
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
|
page.waitForNavigation( { waitUntil: 'networkidle0' } ),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/* Uploads and activates a plugin located at the provided file path. This will also deactivate and delete the plugin if it exists.
|
||||||
|
*
|
||||||
|
* @param {string} pluginFilePath The location of the plugin zip file to upload.
|
||||||
|
* @param {string} pluginName The name of the plugin. For example, `WooCommerce`.
|
||||||
|
*/
|
||||||
|
uploadAndActivatePlugin: async ( pluginFilePath, pluginName ) => {
|
||||||
|
await merchant.openPlugins();
|
||||||
|
|
||||||
|
// Deactivate and delete the plugin if it exists
|
||||||
|
let pluginSlug = getSlug( pluginName );
|
||||||
|
if ( await page.$( `a#deactivate-${pluginSlug}` ) !== null ) {
|
||||||
|
await merchant.deactivatePlugin( pluginName, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Open the plugin install page
|
||||||
|
await page.goto( WP_ADMIN_PLUGIN_INSTALL, {
|
||||||
|
waitUntil: 'networkidle0',
|
||||||
|
} );
|
||||||
|
|
||||||
|
// Upload the plugin zip
|
||||||
|
await page.click( 'a.upload-view-toggle' );
|
||||||
|
|
||||||
|
await expect( page ).toMatchElement(
|
||||||
|
'p.install-help',
|
||||||
|
{
|
||||||
|
text: 'If you have a plugin in a .zip format, you may install or update it by uploading it here.'
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const uploader = await page.$( 'input[type=file]' );
|
||||||
|
|
||||||
|
await uploader.uploadFile( pluginFilePath );
|
||||||
|
|
||||||
|
// Manually update the button to `enabled` so we can submit the file
|
||||||
|
await page.evaluate(() => {
|
||||||
|
document.getElementById( 'install-plugin-submit' ).disabled = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Click to upload the file
|
||||||
|
await page.click( '#install-plugin-submit' );
|
||||||
|
|
||||||
|
await page.waitForNavigation( { waitUntil: 'networkidle0' } );
|
||||||
|
|
||||||
|
// Click to activate the plugin
|
||||||
|
await page.click( '.button-primary' );
|
||||||
|
|
||||||
|
await page.waitForNavigation( { waitUntil: 'networkidle0' } );
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Activate a given plugin by the plugin's name.
|
||||||
|
*
|
||||||
|
* @param {string} pluginName The name of the plugin to activate. For example, `WooCommerce`.
|
||||||
|
*/
|
||||||
|
activatePlugin: async ( pluginName ) => {
|
||||||
|
let pluginSlug = getSlug( pluginName );
|
||||||
|
|
||||||
|
await expect( page ).toClick( `a#activate-${pluginSlug}` );
|
||||||
|
|
||||||
|
await page.waitForNavigation( { waitUntil: 'networkidle0' } );
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deactivate a plugin by the plugin's name with the option to delete the plugin as well.
|
||||||
|
*
|
||||||
|
* @param {string} pluginName The name of the plugin to deactivate. For example, `WooCommerce`.
|
||||||
|
* @param {Boolean} deletePlugin Pass in `true` to delete the plugin. Defaults to `false`.
|
||||||
|
*/
|
||||||
|
deactivatePlugin: async ( pluginName, deletePlugin = false ) => {
|
||||||
|
let pluginSlug = getSlug( pluginName );
|
||||||
|
|
||||||
|
await expect( page ).toClick( `a#deactivate-${pluginSlug}` );
|
||||||
|
|
||||||
|
await page.waitForNavigation( { waitUntil: 'networkidle0' } );
|
||||||
|
|
||||||
|
if ( deletePlugin ) {
|
||||||
|
await merchant.deletePlugin( pluginName );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a plugin by the plugin's name.
|
||||||
|
*
|
||||||
|
* @param {string} pluginName The name of the plugin to delete. For example, `WooCommerce`.
|
||||||
|
*/
|
||||||
|
deletePlugin: async ( pluginName ) => {
|
||||||
|
let pluginSlug = getSlug( pluginName );
|
||||||
|
|
||||||
|
await expect( page ).toClick( `a#delete-${pluginSlug}` );
|
||||||
|
|
||||||
|
// Wait for Ajax calls to finish
|
||||||
|
await page.waitForResponse( response => response.status() === 200 );
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = merchant;
|
module.exports = merchant;
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
/**
|
||||||
|
* Take a string name and generate the slug for it.
|
||||||
|
* Example: 'My plugin' => 'my-plugin'
|
||||||
|
*
|
||||||
|
* Sourced from: https://gist.github.com/spyesx/561b1d65d4afb595f295
|
||||||
|
**/
|
||||||
|
export const getSlug = ( text ) => {
|
||||||
|
text = text.trim().toLowerCase();
|
||||||
|
|
||||||
|
// remove accents, swap ñ for n, etc
|
||||||
|
const from = 'åàáãäâèéëêìíïîòóöôùúüûñç·/_,:;';
|
||||||
|
const to = 'aaaaaaeeeeiiiioooouuuunc------';
|
||||||
|
|
||||||
|
for (let i = 0, l = from.length; i < l; i++) {
|
||||||
|
text = text.replace(new RegExp(from.charAt(i), "g"), to.charAt(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return text
|
||||||
|
.replace(/[^a-z0-9 -]/g, '') // remove invalid chars
|
||||||
|
.replace(/\s+/g, '-') // collapse whitespace and replace by -
|
||||||
|
.replace(/-+/g, '-') // collapse dashes
|
||||||
|
.replace(/^-+/, '') // trim - from start of text
|
||||||
|
.replace(/-+$/, '') // trim - from end of text
|
||||||
|
.replace(/-/g, '-');
|
||||||
|
};
|
||||||
|
|
||||||
|
// Conditionally determine whether or not to skip a test suite
|
||||||
|
export const describeIf = ( condition ) =>
|
||||||
|
condition ? describe : describe.skip;
|
||||||
|
|
||||||
|
// Conditionally determine whether or not to skip a test case
|
||||||
|
export const itIf = ( condition ) =>
|
||||||
|
condition ? it : it.skip;
|
Loading…
Reference in New Issue