Release test workflow: support WooAF draft releases (#40786)

This commit is contained in:
nigeljamesstevenson 2023-10-17 14:19:46 +01:00 committed by GitHub
commit bfb47ee8aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 393 additions and 207 deletions

View File

@ -0,0 +1,19 @@
module.exports = async ( { github, context, core } ) => {
const { ASSET_ID: asset_id } = process.env;
const { owner, repo } = context.repo;
const fs = require( 'fs' );
const path = require( 'path' );
const response = await github.rest.repos.getReleaseAsset( {
owner,
repo,
asset_id,
headers: { accept: 'application/octet-stream' },
} );
const zipPath = path.resolve( 'tmp', 'woocommerce.zip' );
fs.mkdirSync( 'tmp' );
fs.writeFileSync( zipPath, Buffer.from( response.data ) );
core.setOutput( 'zip-path', zipPath );
};

View File

@ -0,0 +1,51 @@
module.exports = async ( { github, context, core } ) => {
const { RELEASE_VERSION, GITHUB_EVENT_NAME } = process.env;
async function findRelease() {
const { owner, repo } = context.repo;
const list = await github.rest.repos.listReleases( {
owner,
repo,
per_page: 100,
} );
const match = list.data.find( ( { tag_name, name } ) =>
[ tag_name, name ].includes( RELEASE_VERSION )
);
return match;
}
async function handleWorkflowDispatch() {
const match = await findRelease();
if ( match ) {
return match;
}
throw new Error(
`"${ RELEASE_VERSION }" is not a valid release version!`
);
}
function findWooCommerceZipAsset() {
const match = release.assets.find(
( { name } ) => name === 'woocommerce.zip'
);
if ( ! match ) {
throw new Error(
`Release ${ RELEASE_VERSION } does not contain a woocommerce.zip asset!`
);
}
return match;
}
const release =
GITHUB_EVENT_NAME === 'release'
? await findRelease()
: await handleWorkflowDispatch();
const asset = findWooCommerceZipAsset();
core.setOutput( 'version', RELEASE_VERSION );
core.setOutput( 'created', release.created_at );
core.setOutput( 'asset-id', asset.id );
};

View File

@ -5,7 +5,7 @@ on:
workflow_dispatch:
inputs:
tag:
description: 'WooCommerce Release Tag'
description: 'WooCommerce release version'
required: true
concurrency:
group: ${{ github.workflow }}-${{ github.event.release.tag_name || inputs.tag }}
@ -16,55 +16,33 @@ env:
E2E_UPDATE_WC_ARTIFACT: WooCommerce version update test on release smoke test site (run ${{ github.run_number }})
SLACK_BLOCKS_ARTIFACT: slack-blocks
jobs:
get-tag:
name: Get WooCommerce release tag
validate-version:
name: Validate release version
permissions:
contents: read
runs-on: ubuntu-20.04
outputs:
tag: ${{ steps.get-tag.outputs.tag }}
created: ${{ steps.created-at.outputs.created }}
version: ${{ steps.validate-version.outputs.version }}
created: ${{ steps.validate-version.outputs.created }}
asset-id: ${{ steps.validate-version.outputs.asset-id }}
steps:
- name: Validate tag
if: ${{ github.event_name == 'workflow_dispatch' }}
env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
run: gh release view "${{ inputs.tag }}" --repo=woocommerce/woocommerce
- uses: actions/checkout@v3
- name: Get tag from triggered event
id: get-tag
- name: Validate release version
id: validate-version
uses: actions/github-script@v6
env:
RELEASE_TAG: ${{ github.event.release.tag_name || inputs.tag }}
run: |
echo "Triggered event: ${{ github.event_name }}"
echo "Tag from event: $RELEASE_TAG"
echo "tag=$RELEASE_TAG" >> $GITHUB_OUTPUT
- name: Verify woocommerce.zip asset
env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
RELEASE_TAG: ${{ steps.get-tag.outputs.tag }}
run: |
ASSET_NAMES=$(gh release view $RELEASE_TAG --repo woocommerce/woocommerce --json assets --jq ".assets[].name")
if [[ $ASSET_NAMES == *"woocommerce.zip"* ]]
then
echo "$RELEASE_TAG has a valid woocommerce.zip asset."
exit 0
fi
echo "$RELEASE_TAG does not have a valid woocommerce.zip asset."
exit 1
- name: Get 'created-at' of WooCommerce zip
id: created-at
env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
run: echo "created=$(gh release view ${{ steps.get-tag.outputs.tag }} --json assets --jq .assets[0].createdAt --repo woocommerce/woocommerce)" >> $GITHUB_OUTPUT
RELEASE_VERSION: ${{ inputs.tag }}
with:
github-token: ${{ secrets.E2E_GH_TOKEN }}
script: |
const script = require('./.github/workflows/scripts/validate-release-version.js');
await script({ github, context, core });
e2e-update-wc:
name: Test WooCommerce update
runs-on: ubuntu-20.04
needs: [get-tag]
needs: [validate-version]
permissions:
contents: read
env:
@ -94,7 +72,7 @@ jobs:
CUSTOMER_USER: ${{ secrets.RELEASE_TEST_CUSTOMER_USER }}
DEFAULT_TIMEOUT_OVERRIDE: 120000
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
UPDATE_WC: ${{ needs.get-tag.outputs.tag }}
UPDATE_WC: ${{ needs.validate-version.outputs.version }}
- name: Upload Allure artifacts to bucket
if: success() || ( failure() && steps.run-e2e-composite-action.conclusion == 'failure' )
@ -113,10 +91,10 @@ jobs:
ENV_DESCRIPTION: wp-latest
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.E2E_WP_LATEST_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="e2e" \
@ -132,12 +110,12 @@ jobs:
test-name: WC Update test
e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }}
env-slug: wp-latest
release-version: ${{ needs.get-tag.outputs.tag }}
release-version: ${{ needs.validate-version.outputs.version }}
api-wp-latest:
name: API on WP Latest
runs-on: ubuntu-20.04
needs: [get-tag, e2e-update-wc]
needs: [validate-version, e2e-update-wc]
permissions:
contents: read
outputs:
@ -170,7 +148,8 @@ jobs:
API_BASE_URL: ${{ secrets.RELEASE_TEST_URL }}
USER_KEY: ${{ secrets.RELEASE_TEST_ADMIN_USER }}
USER_SECRET: ${{ secrets.RELEASE_TEST_ADMIN_PASSWORD }}
UPDATE_WC: ${{ needs.get-tag.outputs.tag }}
UPDATE_WC: ${{ needs.validate-version.outputs.version }}
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
- name: Upload Allure artifacts to bucket
if: success() || ( failure() && steps.run-api-composite-action.conclusion == 'failure' )
@ -189,10 +168,10 @@ jobs:
ENV_DESCRIPTION: wp-latest
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.API_WP_LATEST_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="api" \
@ -208,12 +187,12 @@ jobs:
test-name: WP Latest
api-result: ${{ steps.run-api-composite-action.outputs.result }}
env-slug: wp-latest
release-version: ${{ needs.get-tag.outputs.tag }}
release-version: ${{ needs.validate-version.outputs.version }}
e2e-wp-latest:
name: E2E on WP Latest
runs-on: ubuntu-20.04
needs: [get-tag, api-wp-latest]
needs: [validate-version, api-wp-latest]
permissions:
contents: read
env:
@ -291,10 +270,10 @@ jobs:
ENV_DESCRIPTION: wp-latest
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.E2E_WP_LATEST_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="e2e" \
@ -311,12 +290,12 @@ jobs:
api-result: ${{ needs.api-wp-latest.outputs.result }}
e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }}
env-slug: wp-latest
release-version: ${{ needs.get-tag.outputs.tag }}
release-version: ${{ needs.validate-version.outputs.version }}
test-wp-latest-1:
name: Test against WP Latest-1
runs-on: ubuntu-20.04
needs: [ get-tag ]
needs: [validate-version]
env:
API_ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/api/allure-report
API_ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/api/allure-results
@ -350,12 +329,20 @@ jobs:
WP_ENV_CORE: WordPress/WordPress#${{ steps.get-wp-latest-1.outputs.version }}
- name: Download release zip
id: download-zip
uses: actions/github-script@v6
env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
run: gh release download ${{ steps.get-wp-latest-1.outputs.version }} --dir tmp
ASSET_ID: ${{ needs.validate-version.outputs.asset-id }}
with:
github-token: ${{ secrets.E2E_GH_TOKEN }}
script: |
const script = require('./.github/workflows/scripts/download-release-zip.js');
await script({ github, context, core });
- name: Replace `plugins/woocommerce` with unzipped woocommerce release build
run: unzip -d plugins -o tmp/woocommerce.zip
run: unzip -d plugins -o ${{ env.ZIP_PATH }}
env:
ZIP_PATH: ${{ steps.download-zip.outputs.zip-path }}
- name: Run API tests
id: run-api-composite-action
@ -387,10 +374,10 @@ jobs:
ENV_DESCRIPTION: wp-latest-1
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.API_WP_LATEST_X_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="api" \
@ -428,10 +415,10 @@ jobs:
ENV_DESCRIPTION: wp-latest-1
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.E2E_WP_LATEST_X_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="e2e" \
@ -451,12 +438,12 @@ jobs:
api-result: ${{ steps.run-api-composite-action.outputs.result }}
e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }}
env-slug: wp-latest-1
release-version: ${{ needs.get-tag.outputs.tag }}
release-version: ${{ needs.validate-version.outputs.version }}
test-php-versions:
name: Test against PHP ${{ matrix.php_version }}
runs-on: ubuntu-20.04
needs: [get-tag]
needs: [validate-version]
strategy:
fail-fast: false
matrix:
@ -490,12 +477,20 @@ jobs:
run: bash verify-php-version.sh
- name: Download release zip
id: download-zip
uses: actions/github-script@v6
env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
run: gh release download ${{ needs.get-tag.outputs.tag }} --dir tmp
ASSET_ID: ${{ needs.validate-version.outputs.asset-id }}
with:
github-token: ${{ secrets.E2E_GH_TOKEN }}
script: |
const script = require('./.github/workflows/scripts/download-release-zip.js');
await script({ github, context, core });
- name: Replace `plugins/woocommerce` with unzipped woocommerce release build
run: unzip -d plugins -o tmp/woocommerce.zip
run: unzip -d plugins -o ${{ env.ZIP_PATH }}
env:
ZIP_PATH: ${{ steps.download-zip.outputs.zip-path }}
- name: Run API tests
id: run-api-composite-action
@ -527,10 +522,10 @@ jobs:
ENV_DESCRIPTION: php-${{ matrix.php_version }}
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.API_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="api" \
@ -568,10 +563,10 @@ jobs:
ENV_DESCRIPTION: php-${{ matrix.php_version }}
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.E2E_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="e2e" \
@ -591,12 +586,12 @@ jobs:
api-result: ${{ steps.run-api-composite-action.outputs.result }}
e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }}
env-slug: php-${{ matrix.php_version }}
release-version: ${{ needs.get-tag.outputs.tag }}
release-version: ${{ needs.validate-version.outputs.version }}
test-plugins:
name: With ${{ matrix.plugin }}
runs-on: ubuntu-20.04
needs: [get-tag]
needs: [validate-version]
env:
ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/allure-results
ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/allure-report
@ -638,12 +633,20 @@ jobs:
run: pnpm run env:test
- name: Download release zip
id: download-zip
uses: actions/github-script@v6
env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
run: gh release download ${{ needs.get-tag.outputs.tag }} --dir tmp
ASSET_ID: ${{ needs.validate-version.outputs.asset-id }}
with:
github-token: ${{ secrets.E2E_GH_TOKEN }}
script: |
const script = require('./.github/workflows/scripts/download-release-zip.js');
await script({ github, context, core });
- name: Replace `plugins/woocommerce` with unzipped woocommerce release build
run: unzip -d plugins -o tmp/woocommerce.zip
run: unzip -d plugins -o ${{ env.ZIP_PATH }}
env:
ZIP_PATH: ${{ steps.download-zip.outputs.zip-path }}
- name: Run 'Upload plugin' test
id: run-upload-test
@ -686,10 +689,10 @@ jobs:
GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }}
run: |
gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \
-f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \
-f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.ARTIFACT_NAME }}" \
-f env_description="${{ matrix.env_description }}" \
-f test_type="e2e" \
@ -704,7 +707,7 @@ jobs:
test-name: With ${{ matrix.plugin }}
e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }}
env-slug: ${{ matrix.env_description }}
release-version: ${{ needs.get-tag.outputs.tag }}
release-version: ${{ needs.validate-version.outputs.version }}
post-slack-summary:
name: Post Slack summary
@ -717,7 +720,7 @@ jobs:
)
needs:
- e2e-wp-latest
- get-tag
- validate-version
- test-php-versions
- test-plugins
- test-wp-latest-1
@ -735,7 +738,7 @@ jobs:
id: run-payload-action
uses: ./.github/actions/tests/slack-summary-on-release/slack-payload
with:
release-version: ${{ needs.get-tag.outputs.tag }}
release-version: ${{ needs.validate-version.outputs.version }}
blocks-dir: ${{ steps.download-slack-blocks.outputs.download-path }}
- name: Send Slack message

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Update release test workflow to support release drafts.

View File

@ -1,21 +1,19 @@
const { UPDATE_WC, USER_KEY, USER_SECRET } = process.env;
const { test, expect } = require( '@playwright/test' );
const path = require( 'path' );
const { test: setup, expect } = require( '@playwright/test' );
const fs = require( 'fs' );
const { downloadWooCommerceRelease } = require( './utils/plugin-utils' );
const pluginEndpoint = '/wp-json/wp/v2/plugins/woocommerce/woocommerce';
const zipPath = path.resolve( 'tmp', 'woocommerce.zip' );
const downloadURL = `https://github.com/woocommerce/woocommerce/releases/download/${ UPDATE_WC }/woocommerce.zip`;
let zipPath;
test( `Setup remote test site`, async ( { page, request } ) => {
await test.step( `Download WooCommerce build zip`, async () => {
const response = await request.get( downloadURL );
expect( response.ok() ).toBeTruthy();
const body = await response.body();
fs.mkdirSync( 'tmp', { recursive: true } );
fs.writeFileSync( zipPath, body );
setup( `Setup remote test site`, async ( { page, request } ) => {
setup.setTimeout( 5 * 60 * 1000 );
await setup.step( `Download WooCommerce build zip`, async () => {
zipPath = await downloadWooCommerceRelease( { request } );
} );
await test.step( 'Login to wp-admin', async () => {
await setup.step( 'Login to wp-admin', async () => {
const Username = 'Username or Email Address';
const Password = 'Password';
const Log_In = 'Log In';
@ -33,75 +31,92 @@ test( `Setup remote test site`, async ( { page, request } ) => {
).toBeVisible();
} );
await test.step( `Deactivate currently installed WooCommerce version`, async () => {
const response = await request.put(
'/wp-json/wp/v2/plugins/woocommerce/woocommerce',
{
const installed = await setup.step(
`See if there's a WooCommerce plugin installed`,
async () => {
const response = await request.get( pluginEndpoint );
const isOK = response.ok();
const status = response.status();
// Fast-fail if response was neither OK nor 404.
expect( isOK || status === 404 ).toEqual( true );
return isOK;
}
);
await setup.step(
`Deactivate currently installed WooCommerce version`,
async () => {
if ( ! installed ) {
return;
}
const options = {
data: {
status: 'inactive',
},
};
const response = await request.put( pluginEndpoint, options );
expect( response.ok() ).toBeTruthy();
}
);
await setup.step(
`Delete currently installed WooCommerce version`,
async () => {
if ( ! installed ) {
return;
}
);
expect( response.ok() ).toBeTruthy();
} );
await test.step( `Delete currently installed WooCommerce version`, async () => {
const response = await request.delete(
'/wp-json/wp/v2/plugins/woocommerce/woocommerce'
);
expect( response.ok() ).toBeTruthy();
} );
const response = await request.delete( pluginEndpoint );
expect( response.ok() ).toBeTruthy();
}
);
await test.step( `Install WooCommerce ${ UPDATE_WC }`, async () => {
await setup.step( `Install WooCommerce ${ UPDATE_WC }`, async () => {
const Upload_Plugin = 'Upload Plugin';
const Plugin_zip_file = 'Plugin zip file';
const Install_Now = 'Install Now';
const Activate_Plugin = 'Activate Plugin';
const timeout = 3 * 60 * 1000;
await page.goto( '/wp-admin/plugin-install.php' );
await page.getByRole( 'button', { name: Upload_Plugin } ).click();
await page.getByLabel( Plugin_zip_file ).setInputFiles( zipPath );
await page.getByRole( 'button', { name: Install_Now } ).click();
const uploadResponse = await page.waitForResponse(
'**/wp-admin/update.php?action=upload-plugin'
);;
expect( uploadResponse.ok() ).toBeTruthy();
await expect(
page.getByRole( 'link', { name: Activate_Plugin } )
).toBeVisible();
).toBeVisible( { timeout } );
} );
await test.step( `Activate WooCommerce`, async () => {
const response = await request.put(
'/wp-json/wp/v2/plugins/woocommerce/woocommerce',
{
data: {
status: 'active',
},
}
);
await setup.step( `Activate WooCommerce`, async () => {
const options = {
data: {
status: 'active',
},
};
const response = await request.put( pluginEndpoint, options );
expect( response.ok() ).toBeTruthy();
} );
await test.step( `Verify WooCommerce version was installed`, async () => {
const response = await request.get(
'/wp-json/wp/v2/plugins/woocommerce/woocommerce'
);
await setup.step( `Verify WooCommerce version was installed`, async () => {
const response = await request.get( pluginEndpoint );
const { status, version } = await response.json();
expect( status ).toEqual( 'active' );
expect( version ).toEqual( UPDATE_WC );
} );
await test.step( `Verify WooCommerce database version`, async () => {
await setup.step( `Verify WooCommerce database version`, async () => {
const response = await request.get( '/wp-json/wc/v3/system_status' );
const { database } = await response.json();
const { wc_database_version } = database;
const [major, minor] = UPDATE_WC.split( '.' );
const [ major, minor ] = UPDATE_WC.split( '.' );
const pattern = new RegExp( `^${ major }\.${ minor }` );
expect( wc_database_version ).toMatch( pattern );
} );
await test.step( `Delete zip`, async () => {
await setup.step( `Delete zip`, async () => {
fs.unlinkSync( zipPath );
} );
} );

View File

@ -1,4 +1,5 @@
const defaultConfig = require( './playwright.config' );
const { devices } = require( '@playwright/test' );
// Global setup will be done through the 'Setup' project, not through the `globalSetup` property
delete defaultConfig[ 'globalSetup' ];
@ -13,6 +14,7 @@ const config = {
name: 'Setup',
testDir: './',
testMatch: 'ci-release.global-setup.js',
use: { ...devices[ 'Desktop Chrome' ] },
},
{
name: 'API tests',

View File

@ -1,10 +1,25 @@
const { APIRequest } = require( '@playwright/test' );
const { APIRequest, expect } = require( '@playwright/test' );
const axios = require( 'axios' ).default;
const fs = require( 'fs' );
const path = require( 'path' );
const { promisify } = require( 'util' );
const execAsync = promisify( require( 'child_process' ).exec );
/**
* GitHub [release asset](https://docs.github.com/en/rest/releases/assets?apiVersion=2022-11-28) object.
* @typedef {Object} ReleaseAsset
* @property {string} name
* @property {string} url
*/
/**
* GitHub [release](https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28) object.
* @typedef {Object} Release
* @property {ReleaseAsset[]} assets
* @property {string} tag_name
* @property {string} name
*/
/**
* Encode basic auth username and password to be used in HTTP Authorization header.
*
@ -258,3 +273,94 @@ export const installPluginThruWpCli = async ( pluginPath ) => {
await runWpCliCommand( `wp plugin list` );
};
/**
* Download the WooCommerce release zip. Can download draft releases when `token` is specified.
*
* @param {Object} params
* @param {import("@playwright/test").APIRequestContext} params.request
* @param {string} params.version The version indicated in the release `tag_name` or `name` field.
* @param {string} params.token
* @param {string} params.downloadDir
*
* @throws When `version` was not found.
*
* @returns {Promise<string>} Absolute path to the downloaded WooCommerce zip.
*/
export const downloadWooCommerceRelease = async ( {
request,
version = process.env.UPDATE_WC,
token = process.env.GITHUB_TOKEN,
downloadDir = 'tmp',
} ) => {
/**
*
* @returns {Promise<Release>}
*/
const getRelease = async () => {
const url =
'https://api.github.com/repos/woocommerce/woocommerce/releases';
const options = {
params: {
per_page: 100,
},
headers: {
Authorization: token ? `Bearer ${ token }` : undefined,
},
};
const response = await request.get( url, options );
/**
* @type {Release[]}
*/
const releases = await response.json();
const match = releases.find( ( { tag_name, name } ) =>
[ tag_name, name ].includes( version )
);
if ( ! match ) {
throw new Error( `Release ${ version } not found!` );
}
return match;
};
/**
*
* @param {Release} release
* @throws When `release` does not contain a woocommerce zip.
* @returns {ReleaseAsset}
*/
const getWooCommerceZipAsset = ( release ) => {
const zipName =
version.toLowerCase() === 'nightly'
? 'woocommerce-trunk-nightly.zip'
: 'woocommerce.zip';
const asset = release.assets.find( ( { name } ) => name === zipName );
if ( ! asset ) {
throw new Error(
`Release ${ version } does not contain a WooCommerce ZIP asset`
);
}
return asset;
};
const release = await getRelease();
const asset = getWooCommerceZipAsset( release );
const downloadResponse = await request.get( asset.url, {
headers: {
Authorization: token ? `Bearer ${ token }` : undefined,
Accept: 'application/octet-stream',
},
} );
expect( downloadResponse.ok() ).toBeTruthy();
const body = await downloadResponse.body();
const zipPath = path.resolve( downloadDir, asset.name );
fs.mkdirSync( path.resolve( downloadDir ), { recursive: true } );
fs.writeFileSync( zipPath, body );
return zipPath;
};

View File

@ -63,17 +63,17 @@ const getWCDownloadURL = async () => {
throw new Error( error.message );
} );
const releaseWithTagName = response.data.find(
( { tag_name } ) => tag_name === UPDATE_WC
const release = response.data.find( ( { tag_name, name } ) =>
[ tag_name, name ].includes( UPDATE_WC )
);
if ( ! releaseWithTagName ) {
if ( ! release ) {
throw new Error(
`No release with tag_name="${ UPDATE_WC }" found. If "${ UPDATE_WC }" is a draft release, make sure to specify a GITHUB_TOKEN environment variable.`
`Release "${ UPDATE_WC }" not found. If "${ UPDATE_WC }" is a draft release, make sure to specify a GITHUB_TOKEN environment variable.`
);
}
const wcZipAsset = releaseWithTagName.assets.find( ( { name } ) =>
const wcZipAsset = release.assets.find( ( { name } ) =>
name.match( /^woocommerce(-trunk-nightly)?\.zip$/ )
);
@ -82,7 +82,7 @@ const getWCDownloadURL = async () => {
}
throw new Error(
`WooCommerce release with tag "${ UPDATE_WC }" found, but does not have a WooCommerce ZIP asset.`
`Release "${ UPDATE_WC }" found, but does not have a WooCommerce ZIP asset.`
);
};
@ -91,6 +91,8 @@ skipTestIfUndefined();
test.describe.serial( 'WooCommerce update', () => {
test.use( { storageState: ADMINSTATE } );
test.setTimeout( 5 * 60 * 1000 );
test.beforeAll( async () => {
await test.step( 'Download WooCommerce zip from GitHub', async () => {
const url = await getWCDownloadURL();
@ -135,18 +137,15 @@ test.describe.serial( 'WooCommerce update', () => {
await page.waitForLoadState( 'networkidle' );
} );
await test.step(
'Choose the option "Replace current with uploaded"',
async () => {
await page
.locator( '.button-primary.update-from-upload-overwrite' )
.click();
await page.waitForLoadState( 'networkidle' );
await expect(
page.getByText( 'Plugin updated successfully.' )
).toBeVisible();
}
);
await test.step( 'Choose the option "Replace current with uploaded"', async () => {
await page
.locator( '.button-primary.update-from-upload-overwrite' )
.click();
await page.waitForLoadState( 'networkidle' );
await expect(
page.getByText( 'Plugin updated successfully.' )
).toBeVisible();
} );
await test.step( 'Go to "Installed plugins" page', async () => {
await page.goto( 'wp-admin/plugins.php', {
@ -154,45 +153,38 @@ test.describe.serial( 'WooCommerce update', () => {
} );
} );
await test.step(
'Assert that "WooCommerce" is listed and active',
async () => {
await expect(
page.locator( '.plugin-title strong', {
hasText: /^WooCommerce$/,
} )
).toBeVisible();
await expect(
page.locator( '#deactivate-woocommerce' )
).toBeVisible();
}
);
await test.step( 'Assert that "WooCommerce" is listed and active', async () => {
await expect(
page.locator( '.plugin-title strong', {
hasText: /^WooCommerce$/,
} )
).toBeVisible();
await expect(
page.locator( '#deactivate-woocommerce' )
).toBeVisible();
} );
if ( UPDATE_WC !== 'nightly' ) {
await test.step(
'Verify that WooCommerce was updated to the expected version',
async () => {
const api = new wcApi( {
url: baseURL,
consumerKey: process.env.CONSUMER_KEY,
consumerSecret: process.env.CONSUMER_SECRET,
version: 'wc/v3',
await test.step( 'Verify that WooCommerce was updated to the expected version', async () => {
const api = new wcApi( {
url: baseURL,
consumerKey: process.env.CONSUMER_KEY,
consumerSecret: process.env.CONSUMER_SECRET,
version: 'wc/v3',
} );
const response = await api
.get( 'system_status' )
.catch( ( error ) => {
throw new Error( error.message );
} );
const response = await api
.get( 'system_status' )
.catch( ( error ) => {
throw new Error( error.message );
} );
const wcPluginData = response.data.active_plugins.find(
( { plugin } ) => plugin === 'woocommerce/woocommerce.php'
);
const wcPluginData = response.data.active_plugins.find(
( { plugin } ) =>
plugin === 'woocommerce/woocommerce.php'
);
expect( wcPluginData.version ).toEqual( UPDATE_WC );
}
);
expect( wcPluginData.version ).toEqual( UPDATE_WC );
} );
}
} );
@ -208,40 +200,34 @@ test.describe.serial( 'WooCommerce update', () => {
} );
} );
await test.step(
'Skip this test if the "Update WooCommerce Database" button did not appear',
async () => {
test.skip(
! ( await updateButton.isVisible() ),
'The "Update WooCommerce Database" button did not appear after updating WooCommerce. Verify with the team if the WooCommerce version being tested does not really trigger a database update.'
);
}
);
await test.step( 'Skip this test if the "Update WooCommerce Database" button did not appear', async () => {
test.skip(
! ( await updateButton.isVisible() ),
'The "Update WooCommerce Database" button did not appear after updating WooCommerce. Verify with the team if the WooCommerce version being tested does not really trigger a database update.'
);
} );
await test.step( 'Notice appeared. Start DB update', async () => {
await updateButton.click();
await page.waitForLoadState( 'networkidle' );
} );
await test.step(
'Assert that the notice "WooCommerce database update complete." appears',
async () => {
await expect
.poll(
async () => {
await page.goto( 'wp-admin/plugins.php', {
waitUntil: 'networkidle',
} );
await test.step( 'Assert that the notice "WooCommerce database update complete." appears', async () => {
await expect
.poll(
async () => {
await page.goto( 'wp-admin/plugins.php', {
waitUntil: 'networkidle',
} );
return await updateCompleteMessage.isVisible();
},
{
intervals: [ 10_000 ],
timeout: 120_000,
}
)
.toEqual( true );
}
);
return await updateCompleteMessage.isVisible();
},
{
intervals: [ 10_000 ],
timeout: 120_000,
}
)
.toEqual( true );
} );
} );
} );