assertSame('ABC-123-XYZ', economic_export_sanitizer::sanitizeTextLine('ABC/123/XYZ')); $this->assertSame('Order 1 - 2 - 3', economic_export_sanitizer::sanitizeTextLine('Order 1 / 2 / 3')); $this->assertSame('-leading and trailing-', economic_export_sanitizer::sanitizeTextLine('/leading and trailing/')); } public function testControlCharactersAreStripped(): void { $this->assertSame('hello', economic_export_sanitizer::sanitizeTextLine("hel\x00lo")); $this->assertSame('hello', economic_export_sanitizer::sanitizeTextLine("hel\x01lo")); $this->assertSame('hello', economic_export_sanitizer::sanitizeTextLine("hel\x1Flo")); $this->assertSame('hello', economic_export_sanitizer::sanitizeTextLine("hel\x7F\x7Flo")); } public function testTabIsReplacedWithSpace(): void { $this->assertSame('a b c', economic_export_sanitizer::sanitizeTextLine("a\tb\tc")); } public function testNewlinesCollapsedToSpace(): void { $this->assertSame('line1 line2 line3', economic_export_sanitizer::sanitizeTextLine("line1\nline2\nline3")); $this->assertSame('line1 line2', economic_export_sanitizer::sanitizeTextLine("line1\r\nline2")); $this->assertSame('line1 line2', economic_export_sanitizer::sanitizeTextLine("line1\n\n\nline2")); } public function testMultipleSpacesCollapsed(): void { $this->assertSame('a b c', economic_export_sanitizer::sanitizeTextLine('a b c')); } public function testTrimsLeadingAndTrailingWhitespace(): void { $this->assertSame('hello', economic_export_sanitizer::sanitizeTextLine(' hello ')); $this->assertSame('hello', economic_export_sanitizer::sanitizeTextLine("\n\thello\n\t")); } public function testTruncatesAtMaxLengthWithEllipsis(): void { $text = str_repeat('a', 300); $result = economic_export_sanitizer::sanitizeTextLine($text, 250); $this->assertSame(250, mb_strlen($result)); $this->assertStringEndsWith('...', $result); } public function testTruncatesAtMaxLengthWithoutEllipsisWhenTooShort(): void { // When maxLength is 3, no room for ellipsis $text = str_repeat('a', 100); $result = economic_export_sanitizer::sanitizeTextLine($text, 3); $this->assertSame(3, mb_strlen($result)); $this->assertSame('aaa', $result); } public function testDoesNotTruncateWhenShorterThanMaxLength(): void { $this->assertSame('short text', economic_export_sanitizer::sanitizeTextLine('short text', 250)); } public function testNullReturnsEmptyString(): void { $this->assertSame('', economic_export_sanitizer::sanitizeTextLine(null)); } public function testEmptyReturnsEmptyString(): void { $this->assertSame('', economic_export_sanitizer::sanitizeTextLine('')); } public function testWhitespaceOnlyReturnsEmptyString(): void { $this->assertSame('', economic_export_sanitizer::sanitizeTextLine(" \t\n ")); } public function testWhitespaceOnlyWithSlashesReturnsEmptyString(): void { // After all transformations, "///" becomes "---" // After trim of whitespace-only, " / " becomes "" (since / is replaced but space was there) // Actually let's see: " / " -> " " stays; " - " -> "-"; then trim -> "-" // So it doesn't become empty in this case. Let me re-test: $result = economic_export_sanitizer::sanitizeTextLine(' / '); $this->assertSame('-', $result); } public function testHandlesMultibyteChars(): void { $this->assertSame('æøå', economic_export_sanitizer::sanitizeTextLine('æøå')); $this->assertSame('中文', economic_export_sanitizer::sanitizeTextLine('中文')); $this->assertSame('🚗 car', economic_export_sanitizer::sanitizeTextLine('🚗 car')); } public function testTruncationRespectsMultibyteBoundaries(): void { $text = str_repeat('æ', 300); $result = economic_export_sanitizer::sanitizeTextLine($text, 10); $this->assertSame(10, mb_strlen($result)); $this->assertStringEndsWith('...', $result); } public function testHtmlTagsAreNotStripped(): void { // We don't strip HTML — that's a different concern (XSS). We just sanitize for e-conomic. // The "/" in gets replaced with "-" (per the rules). $this->assertSame('notags<-b>', economic_export_sanitizer::sanitizeTextLine('notags')); } public function testSlashesInTheMiddleOfValueAreReplaced(): void { $this->assertSame('foo-bar-baz', economic_export_sanitizer::sanitizeTextLine('foo/bar/baz')); } public function testMultipleProblemCharsCombined(): void { $input = "AB/\nC\t\rD\x00E "; $result = economic_export_sanitizer::sanitizeTextLine($input); // After: strip control -> "AB/\nC\tDE ", tab->space -> "AB/\nC DE ", // newline->space -> "AB/ C DE ", slash->dash -> "AB- C DE ", // collapse spaces -> "AB- C DE ", trim -> "AB- C DE" $this->assertSame('AB- C DE', $result); } public function testIntegerIsConvertedToString(): void { $this->assertSame('42', economic_export_sanitizer::sanitizeTextLine(42)); } public function testFloatIsConvertedToString(): void { $this->assertSame('3.14', economic_export_sanitizer::sanitizeTextLine(3.14)); } // ======================================================================== // sanitizeProductNumber // ======================================================================== public function testProductNumberRemovesPathSeparators(): void { $this->assertSame('ABCDEF', economic_export_sanitizer::sanitizeProductNumber('ABC/DEF')); $this->assertSame('ABCDEF', economic_export_sanitizer::sanitizeProductNumber('ABC\\DEF')); } public function testProductNumberRemovesForbiddenChars(): void { $input = "PROD:01?*<>|\""; $result = economic_export_sanitizer::sanitizeProductNumber($input); $this->assertSame('PROD01', $result); } public function testProductNumberTruncatesAt50Chars(): void { $text = str_repeat('a', 100); $result = economic_export_sanitizer::sanitizeProductNumber($text); $this->assertSame(50, mb_strlen($result)); } public function testProductNumberTrimsWhitespace(): void { $this->assertSame('PROD01', economic_export_sanitizer::sanitizeProductNumber(' PROD01 ')); } public function testProductNumberStripsControlChars(): void { $this->assertSame('PROD01', economic_export_sanitizer::sanitizeProductNumber("PROD\x0001")); } public function testProductNumberNullReturnsEmpty(): void { $this->assertSame('', economic_export_sanitizer::sanitizeProductNumber(null)); } public function testProductNumberAllForbiddenReturnsEmpty(): void { $this->assertSame('', economic_export_sanitizer::sanitizeProductNumber('///\\\\::')); } public function testProductNumberKeepsDotsAndDashes(): void { $this->assertSame('PROD-01.0', economic_export_sanitizer::sanitizeProductNumber('PROD-01.0')); } // ======================================================================== // sanitizeProductDescription // ======================================================================== public function testProductDescriptionTruncatesAt500(): void { $text = str_repeat('a', 1000); $result = economic_export_sanitizer::sanitizeProductDescription($text); $this->assertSame(500, mb_strlen($result)); } public function testProductDescriptionReplacesSlashes(): void { $this->assertSame('foo-bar-baz', economic_export_sanitizer::sanitizeProductDescription('foo/bar/baz')); } // ======================================================================== // sanitizeForEconApi // ======================================================================== public function testSanitizeForEconApiIsAliasForTextLine(): void { $this->assertSame( economic_export_sanitizer::sanitizeTextLine('foo/bar'), economic_export_sanitizer::sanitizeForEconApi('foo/bar') ); } }