Skip to content

Commit 509675f

Browse files
committed
First commit. Create API tools, shared Playwright config and global setup.
0 parents  commit 509675f

File tree

7 files changed

+339
-0
lines changed

7 files changed

+339
-0
lines changed

package.json

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{
2+
"name": "@wpsyntex/e2e-test-utils",
3+
"version": "0.1.0",
4+
"description": "End-to-end test utilities for Polylang projects.",
5+
"main": "src/index.js",
6+
"scripts": {
7+
"lint:js": "wp-scripts lint-js"
8+
},
9+
"keywords": [
10+
"polylang",
11+
"e2e",
12+
"playwright",
13+
"wordpress"
14+
],
15+
"author": "WP Syntex",
16+
"license": "GPL-2.0-or-later",
17+
"peerDependencies": {
18+
"@playwright/test": ">=1"
19+
},
20+
"devDependencies": {
21+
"@wordpress/scripts": "^30.14.1"
22+
}
23+
}

src/config/index.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { defineConfig, devices } from '@playwright/test';
2+
import path from 'path';
3+
4+
const STORAGE_STATE_PATH =
5+
process.env.STORAGE_STATE_PATH ||
6+
path.join( process.cwd(), 'artifacts/storage-states/admin.json' );
7+
8+
/**
9+
* Returns a Playwright config object.
10+
*
11+
* @since 0.1.0
12+
*
13+
* @param {import('@playwright/test').PlaywrightTestConfig} options Options to merge with the default config.
14+
* @return {import('@playwright/test').PlaywrightTestConfig} Playwright config object.
15+
*/
16+
export function getPlaywrightConfig( options = {} ) {
17+
return defineConfig( {
18+
testDir: './specs',
19+
globalSetup: require.resolve( '../setup/global.setup.js' ),
20+
fullyParallel: false,
21+
forbidOnly: !! process.env.CI,
22+
retries: process.env.CI ? 2 : 0,
23+
workers: 1,
24+
reporter: 'html',
25+
use: {
26+
baseURL: 'http://localhost:8889',
27+
ignoreHTTPSErrors: true,
28+
trace: 'on-first-retry',
29+
headless: true,
30+
storageState: STORAGE_STATE_PATH,
31+
...options.use,
32+
},
33+
projects: [
34+
{
35+
name: 'chromium',
36+
use: { ...devices[ 'Desktop Chrome' ] },
37+
},
38+
],
39+
webServer: {
40+
command: 'npm run env:start',
41+
url: 'http://localhost:8889',
42+
reuseExistingServer: true,
43+
timeout: 120 * 1000,
44+
...options.webServer,
45+
},
46+
...options,
47+
} );
48+
}

src/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
export {
2+
getLanguage,
3+
getAllLanguages,
4+
createLanguage,
5+
deleteLanguage,
6+
deleteAllLanguages,
7+
} from './languages';
8+
export { resetAllSettings, setSetting, getSettings } from './settings';
9+
export { getAllTerms, deleteAllTerms, getTermBySlug } from './taxonomies';
10+
export { getPlaywrightConfig } from './config';
11+
export { default as globalSetup } from './setup/global.setup';

src/languages/index.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* @typedef {import('@wordpress/e2e-test-utils-playwright').RequestUtils} RequestUtils
3+
*/
4+
5+
const BASE_PATH = '/pll/v1/languages';
6+
7+
/**
8+
* Returns languages list.
9+
*
10+
* @param {RequestUtils} requestUtils Gutenberg request utils object.
11+
* @return {Promise} Request promise.
12+
*/
13+
export async function getAllLanguages( requestUtils ) {
14+
return requestUtils.rest( {
15+
path: BASE_PATH,
16+
method: 'GET',
17+
} );
18+
}
19+
20+
/**
21+
* Returns a language.
22+
*
23+
* @param {RequestUtils} requestUtils Gutenberg request utils object.
24+
* @param {string} slug Language slug to get.
25+
* @return {Promise} Request promise.
26+
*/
27+
export async function getLanguage( requestUtils, slug ) {
28+
return requestUtils.rest( {
29+
path: `${ BASE_PATH }/${ slug }`,
30+
method: 'GET',
31+
} );
32+
}
33+
34+
/**
35+
* Creates a language.
36+
*
37+
* @param {RequestUtils} requestUtils Gutenberg request utils object.
38+
* @param {string} locale Language locale to create.
39+
* @return {Promise} Request promise.
40+
*/
41+
export async function createLanguage( requestUtils, locale ) {
42+
return requestUtils.rest( {
43+
path: BASE_PATH,
44+
method: 'POST',
45+
params: {
46+
locale,
47+
},
48+
} );
49+
}
50+
51+
/**
52+
* Deletes a language.
53+
*
54+
* @param {RequestUtils} requestUtils Gutenberg request utils object.
55+
* @param {string} slug Language slug to delete.
56+
* @return {Promise} Request promise.
57+
*/
58+
export async function deleteLanguage( requestUtils, slug ) {
59+
return requestUtils.rest( {
60+
path: BASE_PATH,
61+
method: 'DELETE',
62+
params: {
63+
slug,
64+
},
65+
} );
66+
}
67+
68+
/**
69+
* Deletes all languages.
70+
*
71+
* @param {RequestUtils} requestUtils Gutenberg request utils object.
72+
* @return {Promise} Request promise.
73+
*/
74+
export async function deleteAllLanguages( requestUtils ) {
75+
const languages = await getAllLanguages( requestUtils );
76+
return requestUtils.batchRest(
77+
// Reverse the languages list to delete the default one last.
78+
languages.reverse().map( ( language ) => ( {
79+
method: 'DELETE',
80+
path: `${ BASE_PATH }/${ language.term_id }`,
81+
} ) )
82+
);
83+
}

src/settings/index.js

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/**
2+
* @typedef {import('@wordpress/e2e-test-utils-playwright').RequestUtils} RequestUtils
3+
*/
4+
5+
const BASE_PATH = '/pll/v1/settings';
6+
7+
let schema;
8+
9+
/**
10+
* Returns all plugin settings.
11+
*
12+
* @param {RequestUtils} requestUtils Gutenberg request utils object.
13+
* @return {Promise} Request promise with the settings values when fulfilled.
14+
*/
15+
export async function getSettings( requestUtils ) {
16+
return requestUtils.rest( {
17+
path: BASE_PATH,
18+
method: 'GET',
19+
} );
20+
}
21+
22+
/**
23+
* Updates a plugin setting.
24+
*
25+
* @param {RequestUtils} requestUtils Gutenberg request utils object.
26+
* @param {string} settingKey Setting key.
27+
* @param {*} settingValue Setting value.
28+
* @return {Promise} Request promise.
29+
*/
30+
export async function setSetting( requestUtils, settingKey, settingValue ) {
31+
return requestUtils.rest( {
32+
path: BASE_PATH,
33+
method: 'PUT',
34+
params: {
35+
[ settingKey ]: settingValue,
36+
},
37+
} );
38+
}
39+
40+
/**
41+
* Resets all plugin settings to default values.
42+
*
43+
* @param {RequestUtils} requestUtils Gutenberg request utils object.
44+
* @return {Promise} Request promise.
45+
*/
46+
export async function resetAllSettings( requestUtils ) {
47+
if ( ! schema ) {
48+
schema = await requestUtils.rest( {
49+
path: BASE_PATH,
50+
method: 'OPTIONS',
51+
} );
52+
}
53+
54+
const params = Object.entries( schema.schema.properties ).reduce(
55+
( acc, [ k, v ] ) => {
56+
if ( v.readonly || v.default === undefined ) {
57+
return acc;
58+
}
59+
60+
acc[ k.toString() ] = v.default;
61+
62+
return acc;
63+
},
64+
{}
65+
);
66+
67+
/*
68+
* Don't mess with the default language.
69+
* If all languages has been deleted, `default_lang` will be set to empty string by the server anyway.
70+
*/
71+
delete params.default_lang;
72+
73+
return requestUtils.rest( {
74+
headers: {
75+
'Content-Type': 'application/json',
76+
},
77+
path: BASE_PATH,
78+
method: 'POST',
79+
data: params,
80+
} );
81+
}

src/setup/global.setup.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import { request } from '@playwright/test';
2+
import { RequestUtils } from '@wordpress/e2e-test-utils-playwright';
3+
import { deleteAllLanguages, resetAllSettings } from '..';
4+
5+
/**
6+
* Partially copied from Gutenberg and converted from Typescript.
7+
* @see https://github.com/WordPress/gutenberg/blob/v20.0.0/test/e2e/config/global-setup.ts
8+
*
9+
* @param {Object} config Playwright config object.
10+
*/
11+
export default async function globalSetup( config ) {
12+
const { storageState, baseURL } = config.projects[ 0 ].use;
13+
const storageStatePath =
14+
typeof storageState === 'string' ? storageState : undefined;
15+
16+
const requestContext = await request.newContext( {
17+
baseURL,
18+
} );
19+
20+
const requestUtils = await RequestUtils.setup( {
21+
storageStatePath,
22+
} );
23+
24+
// Authenticate and save the storageState to disk.
25+
await requestUtils.setupRest();
26+
27+
// Reset the test environment before running the tests.
28+
await Promise.all( [
29+
requestUtils.deleteAllMedia(),
30+
requestUtils.deleteAllPosts(),
31+
requestUtils.deleteAllBlocks(),
32+
requestUtils.resetPreferences(),
33+
deleteAllLanguages( requestUtils ),
34+
resetAllSettings( requestUtils ),
35+
] );
36+
37+
await requestContext.dispose();
38+
}

src/taxonomies/index.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* @typedef {import('@wordpress/e2e-test-utils-playwright').RequestUtils} RequestUtils
3+
*/
4+
5+
const BASE_PATH = '/wp/v2';
6+
7+
/**
8+
* Returns all terms.
9+
*
10+
* @param {RequestUtils} requestUtils Gutenberg request utils object.
11+
* @param {string} taxonomy Taxonomy slug.
12+
* @return {Promise} Request promise.
13+
*/
14+
export const getAllTerms = async ( requestUtils, taxonomy ) => {
15+
return requestUtils.rest( {
16+
path: `${ BASE_PATH }/${ taxonomy }`,
17+
params: {
18+
per_page: 100,
19+
},
20+
} );
21+
};
22+
23+
/**
24+
* Returns a term by slug.
25+
*
26+
* @param {RequestUtils} requestUtils Gutenberg request utils object.
27+
* @param {string} taxonomy Taxonomy slug.
28+
* @param {string} slug Term slug.
29+
* @return {Promise} Request promise.
30+
*/
31+
export const getTermBySlug = async ( requestUtils, taxonomy, slug ) => {
32+
return requestUtils.rest( {
33+
path: `${ BASE_PATH }/${ taxonomy }`,
34+
params: {
35+
slug,
36+
},
37+
} );
38+
};
39+
40+
/**
41+
* Deletes all terms.
42+
*
43+
* @param {RequestUtils} requestUtils Gutenberg request utils object.
44+
* @param {string} taxonomy Taxonomy slug.
45+
* @return {Promise} Request promise.
46+
*/
47+
export const deleteAllTerms = async ( requestUtils, taxonomy ) => {
48+
const terms = await getAllTerms( requestUtils, taxonomy );
49+
await requestUtils.batchRest(
50+
terms.map( ( term ) => ( {
51+
method: 'DELETE',
52+
path: `${ BASE_PATH }/${ taxonomy }/${ term.id }`,
53+
} ) )
54+
);
55+
};

0 commit comments

Comments
 (0)