Commit 8c00ce17a3c for woocommerce
commit 8c00ce17a3ce217b82cde19b158c83919e1b085e
Author: Noruzzaman <noruzzamanrubel@gmail.com>
Date: Mon Sep 14 01:24:54 2026 +0600
Add unit tests for CSVUploadHelper (#68636)
* Add unit tests for CSVUploadHelper (#68635)
* Assert directory is absent before and after get_import_dir(false)
* Update assertions for non-HTML MIME check in CSVUploadHelperTest
diff --git a/plugins/woocommerce/changelog/test-add-csv-upload-helper-unit-tests b/plugins/woocommerce/changelog/test-add-csv-upload-helper-unit-tests
new file mode 100644
index 00000000000..b2df7330baf
--- /dev/null
+++ b/plugins/woocommerce/changelog/test-add-csv-upload-helper-unit-tests
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Add unit tests for CSVUploadHelper.
diff --git a/plugins/woocommerce/tests/php/src/Internal/Admin/ImportExport/CSVUploadHelperTest.php b/plugins/woocommerce/tests/php/src/Internal/Admin/ImportExport/CSVUploadHelperTest.php
new file mode 100644
index 00000000000..3332f06f047
--- /dev/null
+++ b/plugins/woocommerce/tests/php/src/Internal/Admin/ImportExport/CSVUploadHelperTest.php
@@ -0,0 +1,192 @@
+<?php
+declare( strict_types = 1 );
+
+namespace Automattic\WooCommerce\Tests\Internal\Admin\ImportExport;
+
+use Automattic\WooCommerce\Internal\Admin\ImportExport\CSVUploadHelper;
+use WC_Unit_Test_Case;
+
+/**
+ * Tests for the CSVUploadHelper class.
+ */
+class CSVUploadHelperTest extends WC_Unit_Test_Case {
+
+ /**
+ * The System Under Test.
+ *
+ * @var CSVUploadHelper
+ */
+ private $sut;
+
+ /**
+ * Set up test fixtures.
+ */
+ public function setUp(): void {
+ parent::setUp();
+ $this->sut = new CSVUploadHelper();
+ }
+
+ /**
+ * Tear down test fixtures.
+ */
+ public function tearDown(): void {
+ $import_dir = $this->sut->get_import_dir( false );
+ if ( is_dir( $import_dir ) ) {
+ \Automattic\WooCommerce\Internal\Utilities\FilesystemUtil::get_wp_filesystem_direct()->delete( $import_dir, true );
+ }
+
+ parent::tearDown();
+ }
+
+ /**
+ * @testdox Should return the expected import directory path and create the directory when create is true.
+ */
+ public function test_get_import_dir_returns_path_and_creates_directory(): void {
+ $wp_upload_dir = wp_upload_dir();
+ $expected_dir = trailingslashit( $wp_upload_dir['basedir'] ) . 'wc-imports';
+
+ $actual_dir = $this->sut->get_import_dir( true );
+
+ $this->assertSame( $expected_dir, $actual_dir, 'get_import_dir should return path ending in wc-imports' );
+ $this->assertDirectoryExists( $actual_dir, 'get_import_dir(true) should ensure directory exists on disk' );
+ }
+
+ /**
+ * @testdox Should return the expected import directory path without creating it when create is false.
+ */
+ public function test_get_import_dir_returns_path_without_creation_when_false(): void {
+ $wp_upload_dir = wp_upload_dir();
+ $expected_dir = trailingslashit( $wp_upload_dir['basedir'] ) . 'wc-imports';
+
+ $this->assertDirectoryDoesNotExist( $expected_dir, 'wc-imports directory should not exist prior to invocation' );
+
+ $actual_dir = $this->sut->get_import_dir( false );
+
+ $this->assertSame( $expected_dir, $actual_dir, 'get_import_dir should match expected upload subdirectory path' );
+ $this->assertDirectoryDoesNotExist( $actual_dir, 'get_import_dir(false) should not create directory on disk' );
+ }
+
+ /**
+ * @testdox Should modify path, url, and subdir in upload_dir array to use wc-imports.
+ */
+ public function test_override_upload_dir_modifies_path_url_and_subdir(): void {
+ $uploads = array(
+ 'path' => '/var/www/uploads/2026/09',
+ 'url' => 'https://example.com/wp-content/uploads/2026/09',
+ 'subdir' => '/2026/09',
+ 'basedir' => '/var/www/uploads',
+ 'baseurl' => 'https://example.com/wp-content/uploads',
+ 'error' => false,
+ );
+
+ $result = $this->sut->override_upload_dir( $uploads );
+
+ $this->assertSame( '/var/www/uploads/wc-imports', $result['path'], 'Upload path should point to wc-imports' );
+ $this->assertSame( 'https://example.com/wp-content/uploads/wc-imports', $result['url'], 'Upload URL should point to wc-imports' );
+ $this->assertSame( '/wc-imports', $result['subdir'], 'Upload subdir should be /wc-imports' );
+ }
+
+ /**
+ * @testdox Should append a unique random suffix before the file extension.
+ */
+ public function test_override_unique_filename_appends_random_suffix(): void {
+ $filename = 'sample.csv';
+ $ext = '.csv';
+
+ $unique_filename1 = $this->sut->override_unique_filename( $filename, $ext );
+ $unique_filename2 = $this->sut->override_unique_filename( $filename, $ext );
+
+ $this->assertStringStartsWith( 'sample-', $unique_filename1, 'Filename should start with original base name followed by hyphen' );
+ $this->assertStringEndsWith( '.csv', $unique_filename1, 'Filename should retain original extension' );
+ $this->assertNotSame( $unique_filename1, $unique_filename2, 'Two consecutive calls should generate distinct randomized filenames' );
+ }
+
+ /**
+ * @testdox Should strip trailing .txt extension added by WordPress import upload handler.
+ */
+ public function test_remove_txt_from_uploaded_file_strips_txt_extension(): void {
+ $file = array(
+ 'name' => 'products-export.csv.txt',
+ 'type' => 'text/plain',
+ 'tmp_name' => '/tmp/php123456',
+ 'error' => 0,
+ 'size' => 1024,
+ );
+
+ $result = $this->sut->remove_txt_from_uploaded_file( $file );
+
+ $this->assertSame( 'products-export.csv', $result['name'], 'remove_txt_from_uploaded_file should strip .txt from file name' );
+ }
+
+ /**
+ * @testdox Should correct filetype and extension to csv when PHP misidentifies a CSV as text/html.
+ */
+ public function test_filter_woocommerce_check_filetype_for_csv_corrects_misidentified_html(): void {
+ $data = array(
+ 'ext' => 'txt',
+ 'type' => 'text/plain',
+ 'proper_filename' => false,
+ );
+ $mimes = array(
+ 'csv' => 'text/csv',
+ );
+
+ $filtered = $this->sut->filter_woocommerce_check_filetype_for_csv(
+ $data,
+ '/tmp/test.csv',
+ 'test.csv',
+ $mimes,
+ 'text/html'
+ );
+
+ $this->assertSame( 'csv', $filtered['ext'], 'Extension should be corrected to csv' );
+ $this->assertSame( 'text/csv', $filtered['type'], 'MIME type should be corrected to text/csv' );
+ }
+
+ /**
+ * @testdox Should not modify filetype data when real mime is not text/html.
+ */
+ public function test_filter_woocommerce_check_filetype_for_csv_ignores_non_html_mime(): void {
+ $data = array(
+ 'ext' => false,
+ 'type' => false,
+ 'proper_filename' => false,
+ );
+ $mimes = array(
+ 'csv' => 'text/csv',
+ );
+
+ $filtered = $this->sut->filter_woocommerce_check_filetype_for_csv(
+ $data,
+ '/tmp/test.csv',
+ 'test.csv',
+ $mimes,
+ 'text/plain'
+ );
+
+ $this->assertFalse( $filtered['ext'], 'Extension should remain unchanged' );
+ $this->assertFalse( $filtered['type'], 'MIME type should remain unchanged' );
+ }
+
+ /**
+ * @testdox Should throw an exception when import_type is empty or invalid.
+ */
+ public function test_handle_csv_upload_throws_exception_for_invalid_import_type(): void {
+ $this->expectException( \Exception::class );
+ $this->expectExceptionMessage( 'Import type is invalid.' );
+
+ $this->sut->handle_csv_upload( ' ' );
+ }
+
+ /**
+ * @testdox Should throw an exception when the upload file entry is missing from $_FILES.
+ */
+ public function test_handle_csv_upload_throws_exception_for_missing_file(): void {
+ unset( $_FILES['import'] );
+
+ $this->expectException( \Exception::class );
+ $this->expectExceptionMessage( 'File is empty.' );
+
+ $this->sut->handle_csv_upload( 'products', 'import' );
+ }
+}