Skip to content

Commit f805210

Browse files
authored
Skip domain step if launch-site triggered from wp-admin (#103746)
* Skip the domains step from the launch-site flow if domain exists * Show the post-launch destination * Also show celebration modal if we only buy a domain * Address concerns in a code review and a cursor glitch
1 parent 80ed892 commit f805210

File tree

5 files changed

+134
-13
lines changed

5 files changed

+134
-13
lines changed

client/lib/signup/step-actions/index.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,11 +1065,12 @@ function shouldExcludeStep( stepName, fulfilledDependencies ) {
10651065
function excludeDomainStep( stepName, tracksEventValue, submitSignupStep ) {
10661066
let fulfilledDependencies = [];
10671067
const domainItem = undefined;
1068+
const domainCart = undefined;
10681069

1069-
submitSignupStep( { stepName, domainItem }, { domainItem } );
1070+
submitSignupStep( { stepName, domainItem }, { domainItem, domainCart } );
10701071
recordExcludeStepEvent( stepName, tracksEventValue );
10711072

1072-
fulfilledDependencies = [ 'domainItem', 'siteId', 'siteSlug', 'themeItem' ];
1073+
fulfilledDependencies = [ 'domainItem', 'domainCart', 'siteId', 'siteSlug', 'themeItem' ];
10731074

10741075
if ( shouldExcludeStep( stepName, fulfilledDependencies ) ) {
10751076
flows.excludeStep( stepName );

client/lib/signup/test/step-actions.js

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,17 +119,21 @@ describe( 'createSiteWithCart()', () => {
119119

120120
describe( 'isDomainFulfilled', () => {
121121
const submitSignupStep = jest.fn();
122-
const oneDomain = [ { domain: 'example.wordpress.com' } ];
123-
const twoDomains = [ { domain: 'example.wordpress.com' }, { domain: 'example.com' } ];
122+
const wpcomDomain = [ { domain: 'example.wordpress.com', isWPCOMDomain: true } ];
123+
const customDomain = { domain: 'example.com', isWPCOMDomain: false };
124+
const wpcomAndCustomDomains = [
125+
{ domain: 'example.wordpress.com', isWPCOMDomain: true },
126+
customDomain,
127+
];
124128

125129
beforeEach( () => {
126130
flows.excludeStep.mockClear();
127131
submitSignupStep.mockClear();
128132
} );
129133

130-
test( 'should call `submitSignupStep` with empty domainItem', () => {
134+
test( 'should call `submitSignupStep` with empty domainItem when site has custom domains', () => {
131135
const stepName = 'domains-launch';
132-
const nextProps = { siteDomains: twoDomains, submitSignupStep };
136+
const nextProps = { siteDomains: wpcomAndCustomDomains, submitSignupStep };
133137

134138
expect( submitSignupStep ).not.toHaveBeenCalled();
135139

@@ -141,9 +145,9 @@ describe( 'isDomainFulfilled', () => {
141145
);
142146
} );
143147

144-
test( 'should call `flows.excludeStep` with the stepName', () => {
148+
test( 'should call `flows.excludeStep` with the stepName when site has custom domains', () => {
145149
const stepName = 'domains-launch';
146-
const nextProps = { siteDomains: twoDomains, submitSignupStep };
150+
const nextProps = { siteDomains: wpcomAndCustomDomains, submitSignupStep };
147151

148152
expect( flows.excludeStep ).not.toHaveBeenCalled();
149153

@@ -152,9 +156,35 @@ describe( 'isDomainFulfilled', () => {
152156
expect( flows.excludeStep ).toHaveBeenCalledWith( stepName );
153157
} );
154158

155-
test( 'should not remove unfulfilled step', () => {
159+
test( 'should not remove step when site only has WordPress.com domains', () => {
160+
const stepName = 'domains-launch';
161+
const nextProps = { siteDomains: wpcomDomain, submitSignupStep };
162+
163+
expect( flows.excludeStep ).not.toHaveBeenCalled();
164+
expect( submitSignupStep ).not.toHaveBeenCalled();
165+
166+
isDomainFulfilled( stepName, undefined, nextProps );
167+
168+
expect( submitSignupStep ).not.toHaveBeenCalled();
169+
expect( flows.excludeStep ).not.toHaveBeenCalled();
170+
} );
171+
172+
test( 'should not remove step when domains are still loading (siteId exists but no siteDomains)', () => {
173+
const stepName = 'domains-launch';
174+
const nextProps = { siteId: 123, siteDomains: [], submitSignupStep };
175+
176+
expect( flows.excludeStep ).not.toHaveBeenCalled();
177+
expect( submitSignupStep ).not.toHaveBeenCalled();
178+
179+
isDomainFulfilled( stepName, undefined, nextProps );
180+
181+
expect( submitSignupStep ).not.toHaveBeenCalled();
182+
expect( flows.excludeStep ).not.toHaveBeenCalled();
183+
} );
184+
185+
test( 'should not remove step when domains are still loading (siteId exists but siteDomains is undefined)', () => {
156186
const stepName = 'domains-launch';
157-
const nextProps = { siteDomains: oneDomain, submitSignupStep };
187+
const nextProps = { siteId: 123, siteDomains: undefined, submitSignupStep };
158188

159189
expect( flows.excludeStep ).not.toHaveBeenCalled();
160190
expect( submitSignupStep ).not.toHaveBeenCalled();

client/signup/config/flows.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,19 @@ function getCheckoutUrl( dependencies, localeSlug, flowName, destination ) {
3232
? destination
3333
: pathToUrl( isDomainOnly ? `/start/${ flowName }/domain-only` : destination );
3434

35+
// Add celebrateLaunch=true for launch-site flow so the celebration modal shows after checkout
36+
const isLaunchSiteFlow = flowName === 'launch-site';
37+
const finalCheckoutBackUrl = isLaunchSiteFlow
38+
? addQueryArgs( { skippedCheckout: 1, celebrateLaunch: 'true' }, checkoutBackUrl )
39+
: addQueryArgs( { skippedCheckout: 1 }, checkoutBackUrl );
40+
3541
return addQueryArgs(
3642
{
3743
signup: 1,
3844
ref: getQueryArgs()?.ref,
3945
...( dependencies.coupon && { coupon: dependencies.coupon } ),
4046
...( isDomainOnly && { isDomainOnly: 1 } ),
41-
checkoutBackUrl: addQueryArgs( { skippedCheckout: 1 }, checkoutBackUrl ),
47+
checkoutBackUrl: finalCheckoutBackUrl,
4248
},
4349
checkoutURL
4450
);
@@ -90,7 +96,7 @@ function getSignupDestination( { domainItem, siteId, siteSlug, refParameter } )
9096
}
9197

9298
function getLaunchDestination( dependencies ) {
93-
return `/home/${ dependencies.siteSlug }`;
99+
return addQueryArgs( { celebrateLaunch: 'true' }, `/home/${ dependencies.siteSlug }` );
94100
}
95101

96102
function getDomainSignupFlowDestination( { domainItem, cartItem, siteId, designType, siteSlug } ) {

client/signup/main.jsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,8 @@ class Signup extends Component {
240240
}
241241

242242
componentDidUpdate( prevProps ) {
243-
const { flowName, stepName, sitePlanName, sitePlanSlug, signupDependencies } = this.props;
243+
const { flowName, stepName, sitePlanName, sitePlanSlug, signupDependencies, siteDomains } =
244+
this.props;
244245

245246
if (
246247
( flowName !== prevProps.flowName || stepName !== prevProps.stepName ) &&
@@ -278,6 +279,12 @@ class Signup extends Component {
278279
) {
279280
clearDomainsDependencies();
280281
}
282+
283+
// Re-check fulfilled steps when siteDomains data changes
284+
// This ensures that isDomainFulfilled is called again when domain data loads
285+
if ( flowName === 'launch-site' && siteDomains !== prevProps.siteDomains ) {
286+
this.removeFulfilledSteps( this.props );
287+
}
281288
}
282289

283290
getRecordPropsFromFlow = () => {

client/signup/test/flows.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
* @jest-environment jsdom
33
*/
44
import flows from 'calypso/signup/config/flows';
5+
import { generateFlows } from 'calypso/signup/config/flows-pure';
56
import mockedFlows from './fixtures/flows';
67

78
describe( 'Signup Flows Configuration', () => {
@@ -33,4 +34,80 @@ describe( 'Signup Flows Configuration', () => {
3334
expect( flows.getFlow( 'main', false ).steps ).toEqual( [ 'user' ] );
3435
} );
3536
} );
37+
38+
describe( 'getLaunchDestination', () => {
39+
test( 'should add celebrateLaunch=true query parameter to the destination URL', () => {
40+
const mockGetLaunchDestination = jest.fn( ( dependencies ) => {
41+
// Import the actual function from flows.js
42+
const { addQueryArgs } = require( 'calypso/lib/url' );
43+
return addQueryArgs( { celebrateLaunch: 'true' }, `/home/${ dependencies.siteSlug }` );
44+
} );
45+
46+
const testFlows = generateFlows( {
47+
getLaunchDestination: mockGetLaunchDestination,
48+
} );
49+
50+
const launchSiteFlow = testFlows[ 'launch-site' ];
51+
const dependencies = { siteSlug: 'test-site' };
52+
const destination = launchSiteFlow.destination( dependencies );
53+
54+
expect( destination ).toBe( '/home/test-site?celebrateLaunch=true' );
55+
} );
56+
} );
57+
58+
describe( 'filterDestination with checkout URLs', () => {
59+
// Mock the required modules
60+
beforeAll( () => {
61+
// Mock getQueryArgs to return empty object
62+
jest.doMock( 'calypso/lib/query-args', () => ( {
63+
getQueryArgs: () => ( {} ),
64+
} ) );
65+
66+
// Mock pathToUrl to return the path as-is
67+
jest.doMock( 'calypso/lib/url', () => ( {
68+
addQueryArgs: jest.requireActual( 'calypso/lib/url' ).addQueryArgs,
69+
pathToUrl: ( path ) => `https://wordpress.com${ path }`,
70+
} ) );
71+
} );
72+
73+
test( 'should add celebrateLaunch=true to checkout back URL when flow is launch-site', () => {
74+
// Import the actual filterDestination function
75+
const flowsModule = require( 'calypso/signup/config/flows' );
76+
const { filterDestination } = flowsModule.default;
77+
78+
const dependencies = {
79+
siteSlug: 'test-site',
80+
cartItem: 'premium_plan', // This will trigger checkout redirect
81+
};
82+
const destination = '/home/test-site';
83+
const flowName = 'launch-site';
84+
const localeSlug = 'en';
85+
86+
const result = filterDestination( destination, dependencies, flowName, localeSlug );
87+
88+
// The result should be a checkout URL with celebrateLaunch in the checkoutBackUrl
89+
expect( result ).toContain( '/checkout/test-site' );
90+
expect( result ).toContain( 'checkoutBackUrl=' );
91+
expect( result ).toContain( 'celebrateLaunch%3Dtrue' ); // URL encoded celebrateLaunch=true
92+
} );
93+
94+
test( 'should not add celebrateLaunch=true to non-launch-site flows', () => {
95+
const flowsModule = require( 'calypso/signup/config/flows' );
96+
const { filterDestination } = flowsModule.default;
97+
98+
const dependencies = {
99+
siteSlug: 'test-site',
100+
cartItem: 'premium_plan',
101+
};
102+
const destination = '/home/test-site';
103+
const flowName = 'onboarding';
104+
const localeSlug = 'en';
105+
106+
const result = filterDestination( destination, dependencies, flowName, localeSlug );
107+
108+
expect( result ).toContain( '/checkout/test-site' );
109+
expect( result ).toContain( 'checkoutBackUrl=' );
110+
expect( result ).not.toContain( 'celebrateLaunch%3Dtrue' );
111+
} );
112+
} );
36113
} );

0 commit comments

Comments
 (0)