Commit f9c8782ab4d for woocommerce

commit f9c8782ab4d63fa0d9076dc8af88d928723d5958
Author: Copilot <198982749+Copilot@users.noreply.github.com>
Date:   Wed Jul 1 08:00:27 2026 +0200

    Fix: Disable "Continue" button on product CSV import until a file is selected (#66009)

    * Initial plan

    * fix: disable Continue button on product import page until file is selected

    * update E2E test

    * use const instead of var

    * fix lint error

    ---------

    Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
    Co-authored-by: Luigi Teschio <gigitux@gmail.com>

diff --git a/plugins/woocommerce/changelog/fix-30454-disable-continue-button-no-file b/plugins/woocommerce/changelog/fix-30454-disable-continue-button-no-file
new file mode 100644
index 00000000000..f18845ffbe9
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-30454-disable-continue-button-no-file
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Disable the "Continue" button on the product CSV import page until a file is selected or a server path is entered.
diff --git a/plugins/woocommerce/includes/admin/importers/views/html-product-csv-import-form.php b/plugins/woocommerce/includes/admin/importers/views/html-product-csv-import-form.php
index 2740d4da118..a3af9e8e45f 100644
--- a/plugins/woocommerce/includes/admin/importers/views/html-product-csv-import-form.php
+++ b/plugins/woocommerce/includes/admin/importers/views/html-product-csv-import-form.php
@@ -108,11 +108,26 @@ if ( ! defined( 'ABSPATH' ) ) {
 				}
 				return false;
 			} );
+
+			const uploadInput  = jQuery( '#upload' );
+			const fileUrlInput = jQuery( '#woocommerce-importer-file-url' );
+			const submitButton = jQuery( '.woocommerce-importer .button-next' );
+
+			function updateSubmitButton() {
+				const hasFile    = uploadInput.length && uploadInput.val().trim().length > 0;
+				const hasFileUrl = fileUrlInput.length && fileUrlInput.val().trim().length > 0;
+				submitButton.prop( 'disabled', ! hasFile && ! hasFileUrl );
+			}
+
+			uploadInput.on( 'change', updateSubmitButton );
+			fileUrlInput.on( 'input', updateSubmitButton );
+
+			updateSubmitButton();
 		});
 	</script>
 	<div class="wc-actions">
 		<a href="#" class="woocommerce-importer-toggle-advanced-options" data-hidetext="<?php esc_attr_e( 'Hide advanced options', 'woocommerce' ); ?>" data-showtext="<?php esc_attr_e( 'Show advanced options', 'woocommerce' ); ?>"><?php esc_html_e( 'Show advanced options', 'woocommerce' ); ?></a>
-		<button type="submit" class="button button-primary button-next" value="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>" name="save_step"><?php esc_html_e( 'Continue', 'woocommerce' ); ?></button>
+		<button type="submit" class="button button-primary button-next" value="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>" name="save_step" disabled><?php esc_html_e( 'Continue', 'woocommerce' ); ?></button>
 		<?php wp_nonce_field( 'woocommerce-csv-importer' ); ?>
 	</div>
 </form>
diff --git a/plugins/woocommerce/tests/e2e/tests/product/product-import-csv.spec.ts b/plugins/woocommerce/tests/e2e/tests/product/product-import-csv.spec.ts
index 58bc5d771db..d4d1f6587e4 100644
--- a/plugins/woocommerce/tests/e2e/tests/product/product-import-csv.spec.ts
+++ b/plugins/woocommerce/tests/e2e/tests/product/product-import-csv.spec.ts
@@ -98,8 +98,6 @@ const productCategories = [
 ];
 const productAttributes = [ 'Color', 'Size' ];

-const errorMessage = 'File is empty. Please upload something more substantial.';
-
 test.describe( 'Import Products from a CSV file', () => {
 	test.use( { storageState: ADMIN_STATE_PATH } );

@@ -165,18 +163,16 @@ test.describe( 'Import Products from a CSV file', () => {
 	} );

 	test(
-		'should show error message if you go without providing CSV file',
+		'should button disabled if no CSV file is provided',
 		{ tag: [ tags.NOT_E2E, tags.NON_CRITICAL ] },
 		async ( { page } ) => {
 			await page.goto(
 				'wp-admin/edit.php?post_type=product&page=product_importer'
 			);

-			// verify the error message if you go without providing CSV file
-			await page.locator( 'button[value="Continue"]' ).click();
-			await expect( page.locator( 'div.error.inline' ) ).toContainText(
-				errorMessage
-			);
+			await expect(
+				page.locator( 'button[value="Continue"]' )
+			).toBeDisabled();
 		}
 	);