Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions client/signup/config/flows-pure.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,9 @@ export function generateFlows( {
showRecaptcha: true,
providesDependenciesInQuery: [ 'plugin', 'billing_period', 'intervalType' ],
optionalDependenciesInQuery: [ 'intervalType' ],
// Persist domains data so re-entering via browser back from checkout skips the domains
// step and reuses the created site instead of making a duplicate.
persistsDomainsOnReEntry: true,
hideProgressIndicator: true,
},
{
Expand All @@ -141,6 +144,7 @@ export function generateFlows( {
showRecaptcha: true,
providesDependenciesInQuery: [ 'coupon' ],
optionalDependenciesInQuery: [ 'coupon' ],
persistsDomainsOnReEntry: true,
hideProgressIndicator: true,
},
{
Expand Down
10 changes: 6 additions & 4 deletions client/signup/config/flows.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,19 @@ function getCheckoutUrl( dependencies, localeSlug, flowName, destination ) {
const queryArgs = getQueryArgs() ?? {};

// with-plugin: point "back" at the plans grid (params from the dependency store — the URL query
// is empty by now), not the post-purchase destination which can't render pre-purchase. Known
// tradeoff: this re-enters signup and recreates the site; kept over a blank page for now.
// is empty by now), not the post-purchase destination which can't render pre-purchase. The flow
// skips the domains step on this re-entry (see controller.js) so it reuses the created site.
let backDestination = destination;
if ( flowName === 'with-plugin' ) {
const { pluginParameter, pluginBillingPeriod } = dependencies;
backDestination = addQueryArgs(
{
...( pluginParameter && { plugin: pluginParameter } ),
// billing_period is a required query dependency of this flow, so always include it
// (empty for free plugins) — otherwise the flow controller rejects the URL.
billing_period: pluginBillingPeriod ?? '',
// Default the grid to the plugin's billing interval.
...( pluginBillingPeriod && {
billing_period: pluginBillingPeriod,
// Default the grid to the plugin's billing interval.
intervalType: pluginBillingPeriod === 'MONTHLY' ? 'monthly' : 'yearly',
} ),
},
Expand Down
12 changes: 5 additions & 7 deletions client/signup/controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,8 @@ export default {
const flowName = getFlowName( context.params, userLoggedIn );
const stepName = getStepName( context.params );
const stepSectionName = getStepSectionName( context.params );
const { providesDependenciesInQuery, excludeFromManageSiteFlows } = flows.getFlow(
flowName,
userLoggedIn
);
const { providesDependenciesInQuery, excludeFromManageSiteFlows, persistsDomainsOnReEntry } =
flows.getFlow( flowName, userLoggedIn );

// Update initialContext to help woocommerce-install support site switching.
if ( 'woocommerce-install' === flowName ) {
Expand Down Expand Up @@ -249,13 +247,13 @@ export default {
const isManageSiteFlow =
! excludeFromManageSiteFlows && ! isAddNewSiteFlow && isReEnteringSignupViaBrowserBack;

// Hydrate the store with domains dependencies from session storage,
// only in the onboarding flow.
// Hydrate the store with domains dependencies from session storage so re-entering via
// browser back from checkout skips the domains step instead of recreating the site.
const domainsDependencies = getDomainsDependencies();
if (
domainsDependencies &&
isManageSiteFlow &&
flowName === 'onboarding' &&
persistsDomainsOnReEntry &&
stepName !== 'domains'
) {
const { step, dependencies } = JSON.parse( domainsDependencies );
Expand Down
5 changes: 3 additions & 2 deletions client/signup/main.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -451,8 +451,9 @@ class Signup extends Component {
setSignupCompleteFlowName( this.props.flowName );
}

// Persist current domains data in the onboarding flow.
if ( this.props.flowName === 'onboarding' ) {
// Persist current domains data so re-entering via browser back from checkout can skip the
// domains step instead of recreating the site.
if ( flows.getFlow( this.props.flowName, this.props.isLoggedIn ).persistsDomainsOnReEntry ) {
const { domainItem, siteUrl, domainCart } = dependencies;
const { stepSectionName } = this.props;

Expand Down
21 changes: 21 additions & 0 deletions client/signup/test/flows.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,5 +131,26 @@ describe( 'Signup Flows Configuration', () => {
expect( result ).toContain( 'billing_period%3DANNUALLY' );
expect( result ).toContain( 'intervalType%3Dyearly' );
} );

test( 'should still include an empty billing_period for a free plugin', () => {
// A free plugin has no billing period, but billing_period is a required query dependency,
// so the back URL must still carry it (empty) or the flow controller rejects the URL.
const flowsModule = require( 'calypso/signup/config/flows' );
const { filterDestination } = flowsModule.default;

const dependencies = {
siteSlug: 'test-site',
cartItem: 'personal_plan',
pluginParameter: 'mailpoet',
};
const destination = '/marketplace/plugin/mailpoet/install/test-site';

const result = filterDestination( destination, dependencies, 'with-plugin', 'en' );

expect( result ).toContain( 'plans-with-plugin' );
expect( result ).toContain( 'plugin%3Dmailpoet' );
expect( result ).toContain( 'billing_period%3D' );
expect( result ).not.toContain( 'intervalType' );
} );
} );
} );
1 change: 1 addition & 0 deletions client/signup/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface Flow {
disallowResume?: boolean;
showRecaptcha?: boolean;
enableBranchSteps?: boolean;
persistsDomainsOnReEntry?: boolean;
hideProgressIndicator?: boolean;
helpCenterButtonText?: string;
enableHotjar?: boolean;
Expand Down
Loading