From d4a12326737b3f16ee3746c1558d64fc9e0d5160 Mon Sep 17 00:00:00 2001 From: Bero Date: Thu, 6 Nov 2025 07:10:52 +0100 Subject: [PATCH 1/5] [Website] Prevent Query API defaults from overriding login info provided by the Blueprint --- .../lib/state/url/resolve-blueprint-from-url.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts b/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts index 71101455cd..fcaabee09c 100644 --- a/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts +++ b/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts @@ -215,8 +215,19 @@ function applyQueryOverridesToDeclaration( } } - // Login - if (query.get('login') !== 'no') { + /** + * Apply login query param to blueprint if it doesn't already contain a login step or shorthand. + * Otherwise, the login provided by the blueprint would be overridden. + */ + const containsLoginStep = blueprint.steps?.some( + (step) => typeof step === 'object' && step?.step === 'login' + ); + const containsLoginShorthand = blueprint.login !== undefined; + if ( + query.get('login') !== 'no' && + !containsLoginStep && + !containsLoginShorthand + ) { blueprint.login = true; } From 85404d9e46a8adccfefea48220240fa7444fb0eb Mon Sep 17 00:00:00 2001 From: Bero Date: Thu, 6 Nov 2025 07:41:30 +0100 Subject: [PATCH 2/5] Check if step exists --- .../website/src/lib/state/url/resolve-blueprint-from-url.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts b/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts index fcaabee09c..61df3df0e3 100644 --- a/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts +++ b/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts @@ -216,11 +216,12 @@ function applyQueryOverridesToDeclaration( } /** - * Apply login query param to blueprint if it doesn't already contain a login step or shorthand. + * Apply login Query API default value to blueprint + * only if it doesn't already contain a login step or shorthand. * Otherwise, the login provided by the blueprint would be overridden. */ const containsLoginStep = blueprint.steps?.some( - (step) => typeof step === 'object' && step?.step === 'login' + (step) => step && typeof step === 'object' && step?.step === 'login' ); const containsLoginShorthand = blueprint.login !== undefined; if ( From 5834f58df6184fe54e0fe04bba0c1c47b6a5fd67 Mon Sep 17 00:00:00 2001 From: Bero Date: Thu, 6 Nov 2025 10:44:13 +0100 Subject: [PATCH 3/5] Allow login=yes to override Blueprint login step and shorhand --- .../state/url/resolve-blueprint-from-url.ts | 45 +++++++++++++------ 1 file changed, 31 insertions(+), 14 deletions(-) diff --git a/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts b/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts index 61df3df0e3..b17bdea7ad 100644 --- a/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts +++ b/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts @@ -215,20 +215,37 @@ function applyQueryOverridesToDeclaration( } } - /** - * Apply login Query API default value to blueprint - * only if it doesn't already contain a login step or shorthand. - * Otherwise, the login provided by the blueprint would be overridden. - */ - const containsLoginStep = blueprint.steps?.some( - (step) => step && typeof step === 'object' && step?.step === 'login' - ); - const containsLoginShorthand = blueprint.login !== undefined; - if ( - query.get('login') !== 'no' && - !containsLoginStep && - !containsLoginShorthand - ) { + const shouldSetLoginToTrue = () => { + /** + * Allow the Query API to explicitly set login + * if the login query param is provided. + */ + if (query.get('login') === 'no') { + return false; + } + if (query.get('login') === 'yes') { + return true; + } + + /** + * Set login to true by default in the Blueprint + * only if it doesn't already contain a login step or shorthand. + * Otherwise, the login provided by the blueprint would be overridden. + */ + if ( + blueprint.steps?.some( + (step) => + step && typeof step === 'object' && step?.step === 'login' + ) + ) { + return false; + } + if (blueprint.login !== undefined) { + return false; + } + return true; + }; + if (shouldSetLoginToTrue()) { blueprint.login = true; } From 1e8cc53689d228e4fdf9a12147f45923d5af382b Mon Sep 17 00:00:00 2001 From: Bero Date: Wed, 19 Nov 2025 06:00:37 +0100 Subject: [PATCH 4/5] Add should login a non-admin user if a login step with a non-admin username is provided test --- .../website/playwright/e2e/blueprints.spec.ts | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/packages/playground/website/playwright/e2e/blueprints.spec.ts b/packages/playground/website/playwright/e2e/blueprints.spec.ts index 0eab24a074..55921852af 100644 --- a/packages/playground/website/playwright/e2e/blueprints.spec.ts +++ b/packages/playground/website/playwright/e2e/blueprints.spec.ts @@ -597,6 +597,34 @@ test('should login the user in if a login step is provided', async ({ await expect(wordpress.locator('body')).toContainText('Dashboard'); }); +test('should login a non-admin user if a login step with a non-admin username is provided', async ({ + website, + wordpress, +}) => { + const blueprint: Blueprint = { + landingPage: '/wp-admin/profile.php', + extraLibraries: ['wp-cli'], + steps: [ + { + step: 'wp-cli', + command: + "wp user create user user@example.com --user_pass='password'", + }, + { + step: 'login', + username: 'user', + password: 'password', + }, + ], + }; + + const encodedBlueprint = JSON.stringify(blueprint); + await website.goto(`./#${encodedBlueprint}`); + await expect(wordpress.locator('#profile-page #email')).toHaveValue( + 'user@example.com' + ); +}); + ['/wp-admin/', '/wp-admin/post.php?post=1&action=edit'].forEach((path) => { test(`should correctly redirect encoded wp-admin url to ${path}`, async ({ website, From 07300567186e450d90bedb2bc58b348187a3d3f2 Mon Sep 17 00:00:00 2001 From: Bero Date: Wed, 19 Nov 2025 09:12:24 +0100 Subject: [PATCH 5/5] Prepend the default login step to allow Blueprints to override it --- .../blueprints/src/lib/v1/compile.ts | 6 +++- .../state/url/resolve-blueprint-from-url.ts | 33 ++----------------- 2 files changed, 7 insertions(+), 32 deletions(-) diff --git a/packages/playground/blueprints/src/lib/v1/compile.ts b/packages/playground/blueprints/src/lib/v1/compile.ts index b2b3b7bb89..9539b0b0df 100644 --- a/packages/playground/blueprints/src/lib/v1/compile.ts +++ b/packages/playground/blueprints/src/lib/v1/compile.ts @@ -224,8 +224,12 @@ function compileBlueprintJson( })) as StepDefinition[]; blueprint.steps!.unshift(...steps); } + + /** + * Prepend a login step to enable Blueprints to override the default login step. + */ if (blueprint.login) { - blueprint.steps!.push({ + blueprint.steps!.unshift({ step: 'login', ...(blueprint.login === true ? { username: 'admin' } diff --git a/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts b/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts index b17bdea7ad..71101455cd 100644 --- a/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts +++ b/packages/playground/website/src/lib/state/url/resolve-blueprint-from-url.ts @@ -215,37 +215,8 @@ function applyQueryOverridesToDeclaration( } } - const shouldSetLoginToTrue = () => { - /** - * Allow the Query API to explicitly set login - * if the login query param is provided. - */ - if (query.get('login') === 'no') { - return false; - } - if (query.get('login') === 'yes') { - return true; - } - - /** - * Set login to true by default in the Blueprint - * only if it doesn't already contain a login step or shorthand. - * Otherwise, the login provided by the blueprint would be overridden. - */ - if ( - blueprint.steps?.some( - (step) => - step && typeof step === 'object' && step?.step === 'login' - ) - ) { - return false; - } - if (blueprint.login !== undefined) { - return false; - } - return true; - }; - if (shouldSetLoginToTrue()) { + // Login + if (query.get('login') !== 'no') { blueprint.login = true; }