Skip to content

Commit 29454f5

Browse files
authored
E2E: use-my-domain transfer-or-connect regression tests (#113269)
* E2E: add use-my-domain transfer-or-connect regression tests Adds Playwright specs verifying that entering an owned domain on the "use my domain" step lands on the transfer-or-connect screen instead of bouncing back to the domains step, across the onboarding, newsletter, reblogging, and domain-and-plan flows. Each test authenticates and stops at the chooser screen, so no site is created. Adds NewsletterSetupPage and NewsletterGoalsPage page objects for the newsletter preamble steps. Covers the regression fixed in #113224 and #113225. * E2E: use dev-testing.com as the owned domain for use-my-domain tests * E2E: match both use-my-domain CTA variants in DomainSearchComponent * E2E: scope use-my-domain transfer-or-connect tests to desktop only
1 parent 37235ee commit 29454f5

5 files changed

Lines changed: 213 additions & 2 deletions

File tree

packages/calypso-e2e/src/lib/components/domain-search-component.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,17 @@ export class DomainSearchComponent {
171171
}
172172

173173
/**
174-
* Clicks on the button to use a domain I already own
174+
* Clicks on the button to use a domain I already own.
175+
*
176+
* The CTA has two copy variants depending on state: the top-bar "Use a domain I own"
177+
* link (shown once a search has been performed, or on mobile) and the empty-state card
178+
* "Already have a domain? Bring it over to WordPress.com." Match either.
175179
*/
176180
async clickUseADomainIAlreadyOwn(): Promise< void > {
177-
await this.page.getByRole( 'button', { name: 'Use a domain I own' } ).click();
181+
await this.page
182+
.getByRole( 'button', { name: /Use a domain I own|Already have a domain/ } )
183+
.first()
184+
.click();
178185
}
179186

180187
/**

packages/calypso-e2e/src/lib/pages/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ export * from './login-page';
2626
export * from './marketing-page';
2727
export * from './media-page';
2828
export * from './my-home-page';
29+
export * from './newsletter-goals-page';
30+
export * from './newsletter-setup-page';
2931
export * from './p2-page';
3032
export * from './pages-page';
3133
export * from './people-page';
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { Page } from 'playwright';
2+
3+
const selectors = {
4+
// Each goal is a `FlowCard`, rendered as a clickable `.flow-question` card containing its title.
5+
optionCard: ( title: string ) => `.flow-question:has-text("${ title }")`,
6+
};
7+
8+
/**
9+
* Represents the "goals" step (Free / Paid / Import) of the Stepper newsletter flow.
10+
*/
11+
export class NewsletterGoalsPage {
12+
private page: Page;
13+
14+
/**
15+
* Constructs an instance of the component.
16+
*
17+
* @param {Page} page The underlying page.
18+
*/
19+
constructor( page: Page ) {
20+
this.page = page;
21+
}
22+
23+
/**
24+
* Selects the "Free newsletter" option, advancing to the domains step.
25+
*/
26+
async selectFreeNewsletter(): Promise< void > {
27+
await this.page.click( selectors.optionCard( 'Free newsletter' ) );
28+
}
29+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { Page } from 'playwright';
2+
3+
const selectors = {
4+
nameInput: '#setup-form-input-name',
5+
continueButton: '.setup-form__submit',
6+
};
7+
8+
/**
9+
* Represents the "setup" step (newsletter name + description) of the Stepper newsletter flow.
10+
*/
11+
export class NewsletterSetupPage {
12+
private page: Page;
13+
14+
/**
15+
* Constructs an instance of the component.
16+
*
17+
* @param {Page} page The underlying page.
18+
*/
19+
constructor( page: Page ) {
20+
this.page = page;
21+
}
22+
23+
/**
24+
* Enters the newsletter name and submits the step, advancing to the goals step.
25+
*
26+
* @param {string} name The newsletter name.
27+
*/
28+
async enterNameAndContinue( name: string ): Promise< void > {
29+
await this.page.fill( selectors.nameInput, name );
30+
await this.page.click( selectors.continueButton );
31+
}
32+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import {
2+
DataHelper,
3+
DomainSearchComponent,
4+
NewsletterGoalsPage,
5+
NewsletterSetupPage,
6+
UseADomainIOwnPage,
7+
} from '@automattic/calypso-e2e';
8+
import { Page } from 'playwright';
9+
import { tags, test, expect } from '../../lib/pw-base';
10+
11+
/**
12+
* A domain that is already registered (i.e. not available for purchase) so that submitting
13+
* it on the "use my domain" step routes to the transfer-or-connect chooser.
14+
*
15+
* NOTE: verify this is a suitable owned/registered domain for the test environment before
16+
* relying on it — the step hits the real domain-availability API.
17+
*/
18+
const OWNED_DOMAIN = 'dev-testing.com';
19+
20+
/**
21+
* Shared assertion: from a flow's domain search step, choose "Already have a domain?",
22+
* enter an owned domain, and confirm we land on the transfer-or-connect screen.
23+
*
24+
* This is the exact segment that regressed: a leading slash in the flow's redirect made
25+
* the router bounce the user back to the `domains` step instead of `use-my-domain`.
26+
*/
27+
async function assertLandsOnTransferOrConnect(
28+
page: Page,
29+
componentDomainSearch: DomainSearchComponent,
30+
pageUseADomainIAlreadyOwn: UseADomainIOwnPage,
31+
ownedDomain: string
32+
): Promise< void > {
33+
await test.step( 'When I choose "Already have a domain?" and submit an owned domain', async () => {
34+
await componentDomainSearch.clickUseADomainIAlreadyOwn();
35+
await pageUseADomainIAlreadyOwn.fillUseDomainIOwnInput( ownedDomain );
36+
} );
37+
38+
await test.step( 'Then I land on the transfer-or-connect screen (not bounced back to domains)', async () => {
39+
// Regression guard: the bug changed this URL to `.../domains?step=transfer-or-connect`.
40+
await expect( page ).toHaveURL( /\/use-my-domain\?.*step=transfer-or-connect/ );
41+
await pageUseADomainIAlreadyOwn.validateButtonToTransferDomain();
42+
await pageUseADomainIAlreadyOwn.validateButtonToConnectDomain();
43+
} );
44+
}
45+
46+
test.describe(
47+
DataHelper.createSuiteTitle( 'Use My Domain: transfer-or-connect renders across flows' ),
48+
{ tag: [ tags.CALYPSO_PR, tags.DESKTOP_ONLY ] },
49+
() => {
50+
test( 'Onboarding flow shows transfer-or-connect after entering an owned domain', async ( {
51+
page,
52+
accountDefaultUser,
53+
componentDomainSearch,
54+
pageUseADomainIAlreadyOwn,
55+
} ) => {
56+
await test.step( 'Given I am authenticated', async () => {
57+
await accountDefaultUser.authenticate( page );
58+
} );
59+
60+
await test.step( 'And I am on the onboarding domains step', async () => {
61+
await page.goto( DataHelper.getCalypsoURL( '/setup/onboarding/domains' ) );
62+
} );
63+
64+
await assertLandsOnTransferOrConnect(
65+
page,
66+
componentDomainSearch,
67+
pageUseADomainIAlreadyOwn,
68+
OWNED_DOMAIN
69+
);
70+
} );
71+
72+
test( 'Newsletter flow shows transfer-or-connect after entering an owned domain', async ( {
73+
page,
74+
accountDefaultUser,
75+
componentDomainSearch,
76+
pageUseADomainIAlreadyOwn,
77+
} ) => {
78+
await test.step( 'Given I am authenticated', async () => {
79+
await accountDefaultUser.authenticate( page );
80+
} );
81+
82+
await test.step( 'And I walk the newsletter preamble to the domains step', async () => {
83+
await page.goto( DataHelper.getCalypsoURL( '/setup/newsletter' ) );
84+
await new NewsletterSetupPage( page ).enterNameAndContinue( DataHelper.getBlogName() );
85+
await new NewsletterGoalsPage( page ).selectFreeNewsletter();
86+
} );
87+
88+
await assertLandsOnTransferOrConnect(
89+
page,
90+
componentDomainSearch,
91+
pageUseADomainIAlreadyOwn,
92+
OWNED_DOMAIN
93+
);
94+
} );
95+
96+
test( 'Reblogging flow shows transfer-or-connect after entering an owned domain', async ( {
97+
page,
98+
accountDefaultUser,
99+
componentDomainSearch,
100+
pageUseADomainIAlreadyOwn,
101+
} ) => {
102+
await test.step( 'Given I am authenticated', async () => {
103+
await accountDefaultUser.authenticate( page );
104+
} );
105+
106+
await test.step( 'And I am on the reblogging domains step', async () => {
107+
await page.goto( DataHelper.getCalypsoURL( '/setup/reblogging' ) );
108+
} );
109+
110+
await assertLandsOnTransferOrConnect(
111+
page,
112+
componentDomainSearch,
113+
pageUseADomainIAlreadyOwn,
114+
OWNED_DOMAIN
115+
);
116+
} );
117+
118+
test( 'Domain-and-plan flow shows transfer-or-connect after entering an owned domain', async ( {
119+
page,
120+
accountAtomic,
121+
componentDomainSearch,
122+
pageUseADomainIAlreadyOwn,
123+
} ) => {
124+
await test.step( 'Given I am authenticated with a site', async () => {
125+
await accountAtomic.authenticate( page );
126+
} );
127+
128+
await test.step( 'And I am on the domain-and-plan domains step', async () => {
129+
const siteSlug = accountAtomic.getSiteURL( { protocol: false } );
130+
await page.goto( DataHelper.getCalypsoURL( '/setup/domain-and-plan', { siteSlug } ) );
131+
} );
132+
133+
await assertLandsOnTransferOrConnect(
134+
page,
135+
componentDomainSearch,
136+
pageUseADomainIAlreadyOwn,
137+
OWNED_DOMAIN
138+
);
139+
} );
140+
}
141+
);

0 commit comments

Comments
 (0)