[CYS] Remove `Save` button from inside the different sections (#46526)

* Remove save button, rename done button and fix tests

* Add changefile(s) from automation for the following project(s): woocommerce

* Fix error

* Fix lint errors

* Fix more lint errors

* Fix done button tests

* Add missing awaits

---------

Co-authored-by: github-actions <github-actions@github.com>
This commit is contained in:
Alba Rincón 2024-04-22 14:26:57 +02:00 committed by GitHub
parent ecb48cc0fb
commit efbce912c5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 51 additions and 270 deletions

View File

@ -11,12 +11,11 @@ import {
useState, useState,
} from '@wordpress/element'; } from '@wordpress/element';
import { useQuery } from '@woocommerce/navigation'; import { useQuery } from '@woocommerce/navigation';
import { useSelect, useDispatch } from '@wordpress/data'; import { useDispatch } from '@wordpress/data';
import { import {
// @ts-ignore No types for this exist yet. // @ts-ignore No types for this exist yet.
__experimentalHStack as HStack, __experimentalHStack as HStack,
// @ts-ignore No types for this exist yet. // @ts-ignore No types for this exist yet.
__experimentalUseNavigator as useNavigator,
Button, Button,
Spinner, Spinner,
} from '@wordpress/components'; } from '@wordpress/components';
@ -37,7 +36,6 @@ import { useIsSiteEditorLoading } from '@wordpress/edit-site/build-module/compon
* Internal dependencies * Internal dependencies
*/ */
import { CustomizeStoreContext } from '../'; import { CustomizeStoreContext } from '../';
import { HighlightedBlockContext } from '../context/highlighted-block-context';
const PUBLISH_ON_SAVE_ENTITIES = [ const PUBLISH_ON_SAVE_ENTITIES = [
{ {
@ -51,10 +49,7 @@ export const SaveHub = () => {
const urlParams = useQuery(); const urlParams = useQuery();
const { sendEvent } = useContext( CustomizeStoreContext ); const { sendEvent } = useContext( CustomizeStoreContext );
const [ isResolving, setIsResolving ] = useState< boolean >( false ); const [ isResolving, setIsResolving ] = useState< boolean >( false );
const navigator = useNavigator();
const { resetHighlightedBlockClientId } = useContext(
HighlightedBlockContext
);
const isEditorLoading = useIsSiteEditorLoading(); const isEditorLoading = useIsSiteEditorLoading();
// @ts-ignore No types for this exist yet. // @ts-ignore No types for this exist yet.
const { __unstableMarkLastChangeAsPersistent } = const { __unstableMarkLastChangeAsPersistent } =
@ -78,22 +73,6 @@ export const SaveHub = () => {
isDirty: boolean; isDirty: boolean;
} = useIsDirty(); } = useIsDirty();
const { isSaving } = useSelect(
( select ) => {
return {
isSaving: dirtyEntityRecords.some( ( record ) =>
// @ts-ignore No types for this exist yet.
select( coreStore ).isSavingEntityRecord(
record.kind,
record.name,
record.key
)
),
};
},
[ dirtyEntityRecords ]
);
const { const {
// @ts-ignore No types for this exist yet. // @ts-ignore No types for this exist yet.
editEntityRecord, editEntityRecord,
@ -153,28 +132,6 @@ export const SaveHub = () => {
} }
}, [ isEditorLoading, isDirty, isMainScreen, save ] ); }, [ isEditorLoading, isDirty, isMainScreen, save ] );
const onClickSaveButton = async () => {
const source = `${ urlParams.path.replace(
'/customize-store/assembler-hub/',
''
) }`;
recordEvent( 'customize_your_store_assembler_hub_save_click', {
source,
} );
try {
await save();
resetHighlightedBlockClientId();
navigator.goToParent();
} catch ( error ) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore The types for this are incorrect.
createErrorNotice(
`${ __( 'Saving failed.', 'woocommerce' ) } ${ error }`
);
}
};
const onDone = async () => { const onDone = async () => {
recordEvent( 'customize_your_store_assembler_hub_done_click' ); recordEvent( 'customize_your_store_assembler_hub_done_click' );
setIsResolving( true ); setIsResolving( true );
@ -192,9 +149,13 @@ export const SaveHub = () => {
} }
}; };
const renderButton = () => { if ( isMainScreen ) {
if ( isMainScreen ) { return (
return ( <HStack
className="edit-site-save-hub"
alignment="right"
spacing={ 4 }
>
<Button <Button
variant="primary" variant="primary"
onClick={ onDone } onClick={ onDone }
@ -204,36 +165,11 @@ export const SaveHub = () => {
// @ts-ignore No types for this exist yet. // @ts-ignore No types for this exist yet.
__next40pxDefaultSize __next40pxDefaultSize
> >
{ isResolving ? <Spinner /> : __( 'Done', 'woocommerce' ) } { isResolving ? <Spinner /> : __( 'Save', 'woocommerce' ) }
</Button> </Button>
); </HStack>
}
// if we have only one unsaved change and it matches current context, we can show a more specific label
const label = isSaving
? __( 'Saving', 'woocommerce' )
: __( 'Save', 'woocommerce' );
const isDisabled = ! isDirty || isSaving;
return (
<Button
variant="primary"
onClick={ onClickSaveButton }
disabled={ isDisabled }
aria-disabled={ isDisabled }
className="edit-site-save-hub__button"
// @ts-ignore No types for this exist yet.
__next40pxDefaultSize
>
{ isSaving ? <Spinner /> : label }
</Button>
); );
}; }
return ( return null;
<HStack className="edit-site-save-hub" alignment="right" spacing={ 4 }>
{ renderButton() }
</HStack>
);
}; };

View File

@ -195,7 +195,7 @@ const getTourConfig = ( {
* *
* @filter experimental_woocommerce_admin_product_tour_steps * @filter experimental_woocommerce_admin_product_tour_steps
* @param {Object} WooStep Array of Woo tour guide steps. * @param {Object} WooStep Array of Woo tour guide steps.
* @param string tutorialType The type of tutorial to display. * @param string tutorialType The type of tutorial to display.
*/ */
const steps: TourKitTypes.WooStep[] = applyFilters( const steps: TourKitTypes.WooStep[] = applyFilters(
'experimental_woocommerce_admin_product_tour_steps', 'experimental_woocommerce_admin_product_tour_steps',

View File

@ -0,0 +1,4 @@
Significance: minor
Type: update
[CYS] Remove the "Save" button from inside the different sections.

View File

@ -16,7 +16,7 @@ export class AssemblerPage {
'.cys-fullscreen-iframe[style="opacity: 1;"]' '.cys-fullscreen-iframe[style="opacity: 1;"]'
); );
await frame.getByRole( 'button', { name: 'Done' } ).waitFor(); await frame.getByRole( 'button', { name: 'Save' } ).waitFor();
} }
/** /**

View File

@ -298,6 +298,8 @@ test.describe( 'Assembler -> Color Pickers', () => {
await colorPicker.click(); await colorPicker.click();
await assembler.locator( '[aria-label="Back"]' ).click();
const saveButton = assembler.getByText( 'Save' ); const saveButton = assembler.getByText( 'Save' );
const waitResponse = page.waitForResponse( const waitResponse = page.waitForResponse(
@ -382,51 +384,6 @@ test.describe( 'Assembler -> Color Pickers', () => {
await expect( colorPicker ).toHaveClass( /is-active/ ); await expect( colorPicker ).toHaveClass( /is-active/ );
} ); } );
test( 'Picking a color should activate the save button', async ( {
assemblerPageObject,
} ) => {
const assembler = await assemblerPageObject.getAssembler();
const colorPicker = assembler
.locator(
'.woocommerce-customize-store_global-styles-variations_item'
)
.nth( 2 );
await colorPicker.click();
const saveButton = assembler.getByText( 'Save' );
await expect( saveButton ).toBeEnabled();
} );
test( 'The Done button should be visible after clicking save', async ( {
assemblerPageObject,
page,
} ) => {
const assembler = await assemblerPageObject.getAssembler();
const colorPicker = assembler
.locator(
'.woocommerce-customize-store_global-styles-variations_item'
)
.nth( 2 );
await colorPicker.click();
const saveButton = assembler.getByText( 'Save' );
const waitResponse = page.waitForResponse(
( response ) =>
response.url().includes( 'wp-json/wp/v2/global-styles' ) &&
response.status() === 200
);
await saveButton.click();
await waitResponse;
await expect( assembler.getByText( 'Done' ) ).toBeEnabled();
} );
test( 'Selected color palette should be applied on the frontend', async ( { test( 'Selected color palette should be applied on the frontend', async ( {
assemblerPageObject, assemblerPageObject,
page, page,
@ -442,6 +399,8 @@ test.describe( 'Assembler -> Color Pickers', () => {
await colorPicker.click(); await colorPicker.click();
await assembler.locator( '[aria-label="Back"]' ).click();
const saveButton = assembler.getByText( 'Save' ); const saveButton = assembler.getByText( 'Save' );
const waitResponse = page.waitForResponse( const waitResponse = page.waitForResponse(

View File

@ -154,47 +154,6 @@ test.describe( 'Assembler -> Font Picker', () => {
await expect( fontPicker ).toHaveClass( /is-active/ ); await expect( fontPicker ).toHaveClass( /is-active/ );
} ); } );
test( 'Picking a font should activate the save button', async ( {
pageObject,
} ) => {
const assembler = await pageObject.getAssembler();
const fontPicker = assembler.locator(
'.woocommerce-customize-store_global-styles-variations_item:not(.is-active)'
);
await fontPicker.click();
const saveButton = assembler.getByText( 'Save' );
await expect( saveButton ).toBeEnabled();
} );
test( 'The Done button should be visible after clicking save', async ( {
pageObject,
page,
} ) => {
const assembler = await pageObject.getAssembler();
const fontPicker = assembler.locator(
'.woocommerce-customize-store_global-styles-variations_item:not(.is-active)'
);
await fontPicker.click();
const saveButton = assembler.getByText( 'Save' );
const waitResponse = page.waitForResponse(
( response ) =>
response.url().includes( 'wp-json/wp/v2/global-styles' ) &&
response.status() === 200
);
await saveButton.click();
await waitResponse;
await expect( assembler.getByText( 'Done' ) ).toBeEnabled();
} );
test( 'Selected font palette should be applied on the frontend', async ( { test( 'Selected font palette should be applied on the frontend', async ( {
pageObject, pageObject,
page, page,
@ -216,6 +175,8 @@ test.describe( 'Assembler -> Font Picker', () => {
.split( '+' ) .split( '+' )
.map( ( e ) => e.trim() ); .map( ( e ) => e.trim() );
await assembler.locator( '[aria-label="Back"]' ).click();
const saveButton = assembler.getByText( 'Save' ); const saveButton = assembler.getByText( 'Save' );
const waitResponse = page.waitForResponse( const waitResponse = page.waitForResponse(

View File

@ -3,6 +3,14 @@ const { AssemblerPage } = require( './assembler.page' );
const { activateTheme, DEFAULT_THEME } = require( '../../../utils/themes' ); const { activateTheme, DEFAULT_THEME } = require( '../../../utils/themes' );
const { setOption } = require( '../../../utils/options' ); const { setOption } = require( '../../../utils/options' );
const extractFooterClass = ( footerPickerClass ) => {
const regex = /\bwc-blocks-pattern-footer\S*/;
const match = footerPickerClass.match( regex );
return match ? match[ 0 ] : null;
};
const test = base.extend( { const test = base.extend( {
assemblerPage: async ( { page }, use ) => { assemblerPage: async ( { page }, use ) => {
const assemblerPage = new AssemblerPage( { page } ); const assemblerPage = new AssemblerPage( { page } );
@ -80,31 +88,6 @@ test.describe( 'Assembler -> Footers', () => {
await expect( footer ).toHaveClass( /is-selected/ ); await expect( footer ).toHaveClass( /is-selected/ );
} ); } );
test( 'The Done button should be visible after clicking save', async ( {
assemblerPage,
page,
} ) => {
const assembler = await assemblerPage.getAssembler();
const footer = assembler
.locator( '.block-editor-block-patterns-list__item' )
.nth( 2 );
await footer.click();
const saveButton = assembler.getByText( 'Save' );
const waitResponse = page.waitForResponse(
( response ) =>
response.url().includes( 'wp-json/wp/v2/template-parts' ) &&
response.status() === 200
);
await saveButton.click();
await waitResponse;
await expect( assembler.getByText( 'Done' ) ).toBeEnabled();
} );
test( 'The selected footer should be applied on the frontend', async ( { test( 'The selected footer should be applied on the frontend', async ( {
assemblerPage, assemblerPage,
page, page,
@ -123,6 +106,8 @@ test.describe( 'Assembler -> Footers', () => {
await footer.click(); await footer.click();
await assembler.locator( '[aria-label="Back"]' ).click();
const saveButton = assembler.getByText( 'Save' ); const saveButton = assembler.getByText( 'Save' );
const waitResponse = page.waitForResponse( const waitResponse = page.waitForResponse(
@ -160,7 +145,6 @@ test.describe( 'Assembler -> Footers', () => {
.locator( '.block-editor-block-patterns-list__list-item' ) .locator( '.block-editor-block-patterns-list__list-item' )
.all(); .all();
let index = 0;
for ( const footerPicker of footerPickers ) { for ( const footerPicker of footerPickers ) {
await footerPicker.waitFor(); await footerPicker.waitFor();
await footerPicker.click(); await footerPicker.click();
@ -179,16 +163,6 @@ test.describe( 'Assembler -> Footers', () => {
await expect( await expect(
await footerPattern.getAttribute( 'class' ) await footerPattern.getAttribute( 'class' )
).toContain( expectedFooterClass ); ).toContain( expectedFooterClass );
index++;
} }
} ); } );
} ); } );
const extractFooterClass = ( footerPickerClass ) => {
const regex = /\bwc-blocks-pattern-footer\S*/;
const match = footerPickerClass.match( regex );
return match ? match[ 0 ] : null;
};

View File

@ -3,6 +3,14 @@ const { AssemblerPage } = require( './assembler.page' );
const { activateTheme, DEFAULT_THEME } = require( '../../../utils/themes' ); const { activateTheme, DEFAULT_THEME } = require( '../../../utils/themes' );
const { setOption } = require( '../../../utils/options' ); const { setOption } = require( '../../../utils/options' );
const extractHeaderClass = ( headerPickerClass ) => {
const regex = /\bwc-blocks-pattern-header\S*/;
const match = headerPickerClass.match( regex );
return match ? match[ 0 ] : null;
};
const test = base.extend( { const test = base.extend( {
assemblerPage: async ( { page }, use ) => { assemblerPage: async ( { page }, use ) => {
const assemblerPage = new AssemblerPage( { page } ); const assemblerPage = new AssemblerPage( { page } );
@ -80,31 +88,6 @@ test.describe( 'Assembler -> headers', () => {
await expect( header ).toHaveClass( /is-selected/ ); await expect( header ).toHaveClass( /is-selected/ );
} ); } );
test( 'The Done button should be visible after clicking save', async ( {
assemblerPage,
page,
} ) => {
const assembler = await assemblerPage.getAssembler();
const header = assembler
.locator( '.block-editor-block-patterns-list__item' )
.nth( 2 );
await header.click();
const saveButton = assembler.getByText( 'Save' );
const waitResponse = page.waitForResponse(
( response ) =>
response.url().includes( 'wp-json/wp/v2/template-parts' ) &&
response.status() === 200
);
await saveButton.click();
await waitResponse;
await expect( assembler.getByText( 'Done' ) ).toBeEnabled();
} );
test( 'The selected header should be applied on the frontend', async ( { test( 'The selected header should be applied on the frontend', async ( {
assemblerPage, assemblerPage,
page, page,
@ -123,6 +106,8 @@ test.describe( 'Assembler -> headers', () => {
await header.click(); await header.click();
await assembler.locator( '[aria-label="Back"]' ).click();
const saveButton = assembler.getByText( 'Save' ); const saveButton = assembler.getByText( 'Save' );
const waitResponse = page.waitForResponse( const waitResponse = page.waitForResponse(
@ -159,7 +144,6 @@ test.describe( 'Assembler -> headers', () => {
.locator( '.block-editor-block-patterns-list__list-item' ) .locator( '.block-editor-block-patterns-list__list-item' )
.all(); .all();
let index = 0;
for ( const headerPicker of headerPickers ) { for ( const headerPicker of headerPickers ) {
await headerPicker.waitFor(); await headerPicker.waitFor();
await headerPicker.click(); await headerPicker.click();
@ -178,16 +162,6 @@ test.describe( 'Assembler -> headers', () => {
await expect( await expect(
await headerPattern.getAttribute( 'class' ) await headerPattern.getAttribute( 'class' )
).toContain( expectedHeaderClass ); ).toContain( expectedHeaderClass );
index++;
} }
} ); } );
} ); } );
const extractHeaderClass = ( headerPickerClass ) => {
const regex = /\bwc-blocks-pattern-header\S*/;
const match = headerPickerClass.match( regex );
return match ? match[ 0 ] : null;
};

View File

@ -121,34 +121,6 @@ test.describe( 'Assembler -> Homepage', () => {
} }
} ); } );
test( 'The Done button should be visible after clicking save', async ( {
pageObject,
page,
} ) => {
const assembler = await pageObject.getAssembler();
const homepage = assembler
.locator( '.block-editor-block-patterns-list__item' )
.nth( 2 );
await homepage.click();
const saveButton = assembler.getByText( 'Save' );
const waitResponse = page.waitForResponse(
( response ) =>
response
.url()
.includes(
'wp-json/wp/v2/templates/twentytwentyfour//home'
) && response.status() === 200
);
await saveButton.click();
await waitResponse;
await expect( assembler.getByText( 'Done' ) ).toBeEnabled();
} );
test( 'Selected homepage should be applied on the frontend', async ( { test( 'Selected homepage should be applied on the frontend', async ( {
pageObject, pageObject,
page, page,
@ -162,6 +134,8 @@ test.describe( 'Assembler -> Homepage', () => {
await homepage.click(); await homepage.click();
await assembler.locator( '[aria-label="Back"]' ).click();
const saveButton = assembler.getByText( 'Save' ); const saveButton = assembler.getByText( 'Save' );
const waitResponse = page.waitForResponse( const waitResponse = page.waitForResponse(

View File

@ -67,6 +67,7 @@ export class LogoPickerPage {
} }
async saveLogoSettings( assemblerLocator ) { async saveLogoSettings( assemblerLocator ) {
await assemblerLocator.locator( '[aria-label="Back"]' ).click();
await assemblerLocator.getByText( 'Save' ).click(); await assemblerLocator.getByText( 'Save' ).click();
const waitForLogoResponse = this.page.waitForResponse( const waitForLogoResponse = this.page.waitForResponse(
( response ) => ( response ) =>

View File

@ -120,12 +120,10 @@ test.describe( 'Assembler -> Logo Picker', () => {
await expect( await expect(
logoPickerPageObject.getLogoLocator( editor ) logoPickerPageObject.getLogoLocator( editor )
).toBeVisible(); ).toBeVisible();
await expect( assembler.getByText( 'Save' ) ).toBeEnabled();
await expect( imageWidth ).toBeVisible(); await expect( imageWidth ).toBeVisible();
await expect( linkLogoToHomepage ).toBeVisible(); await expect( linkLogoToHomepage ).toBeVisible();
await expect( useAsSiteIcon ).toBeVisible(); await expect( useAsSiteIcon ).toBeVisible();
await assembler.getByText( 'Save' ).click();
} ); } );
test( 'Changing the image width should update the site preview and the frontend', async ( { test( 'Changing the image width should update the site preview and the frontend', async ( {

View File

@ -123,7 +123,7 @@ test.describe( 'Assembler - Loading Page', () => {
await pageObject.waitForLoadingScreenFinish(); await pageObject.waitForLoadingScreenFinish();
const assembler = await pageObject.getAssembler(); const assembler = await pageObject.getAssembler();
await assembler.getByRole( 'button', { name: 'Done' } ).click(); await assembler.getByRole( 'button', { name: 'Save' } ).click();
await pageObject.setupSite( baseURL ); await pageObject.setupSite( baseURL );
const requestToSetupStore = createRequestsToSetupStoreDictionary(); const requestToSetupStore = createRequestsToSetupStoreDictionary();

View File

@ -69,7 +69,7 @@ test.describe( 'Store owner can view the Transitional page', () => {
await expect( page.url() ).toBe( `${ baseURL }${ INTRO_URL }` ); await expect( page.url() ).toBe( `${ baseURL }${ INTRO_URL }` );
} ); } );
test( 'Clicking on "Done" in the assembler should go to the transitional page', async ( { test( 'Clicking on "Save" in the assembler should go to the transitional page', async ( {
pageObject, pageObject,
baseURL, baseURL,
} ) => { } ) => {
@ -77,7 +77,7 @@ test.describe( 'Store owner can view the Transitional page', () => {
await pageObject.waitForLoadingScreenFinish(); await pageObject.waitForLoadingScreenFinish();
const assembler = await pageObject.getAssembler(); const assembler = await pageObject.getAssembler();
await assembler.getByRole( 'button', { name: 'Done' } ).click(); await assembler.getByRole( 'button', { name: 'Save' } ).click();
await expect( await expect(
assembler.locator( 'text=Your store looks great!' ) assembler.locator( 'text=Your store looks great!' )