Files
Umbraco-CMS/tests/Umbraco.Tests.UnitTests/Umbraco.Core/ShortStringHelper/StringExtensionsTests.cs

399 lines
14 KiB
C#
Raw Normal View History

// Copyright (c) Umbraco.
// See LICENSE for more details.
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
2019-02-21 09:35:38 +01:00
using System.Text;
using NUnit.Framework;
using Umbraco.Cms.Core.Strings;
using Umbraco.Extensions;
namespace Umbraco.Cms.Tests.UnitTests.Umbraco.Core.ShortStringHelper;
[TestFixture]
public class StringExtensionsTests
{
private readonly IShortStringHelper _mockShortStringHelper = new MockShortStringHelper();
[TestCase("hello-world.png", "Hello World")]
[TestCase("hello-world .png", "Hello World")]
[TestCase("_hello-world __1.png", "Hello World 1")]
public void To_Friendly_Name(string first, string second) => Assert.AreEqual(first.ToFriendlyName(), second);
[TestCase("hello", "world", false)]
[TestCase("hello", "hello", true)]
[TestCase("hellohellohellohellohellohellohello", "hellohellohellohellohellohellohelloo", false)]
[TestCase(
"hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello",
"hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohelloo",
false)]
[TestCase(
"hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello",
"hellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohellohello",
true)]
public void String_To_Guid(string first, string second, bool result)
{
Debug.Print("First: " + first.ToGuid());
Debug.Print("Second: " + second.ToGuid());
Assert.AreEqual(result, first.ToGuid() == second.ToGuid());
}
[TestCase("hello.txt", "hello")]
[TestCase("this.is.a.Txt", "this.is.a")]
[TestCase("this.is.not.a. Txt", "this.is.not.a. Txt")]
[TestCase("not a file", "not a file")]
public void Strip_File_Extension(string input, string result)
{
var stripped = input.StripFileExtension();
Assert.AreEqual(stripped, result);
}
[TestCase("../wtf.js?x=wtf", ".js")]
[TestCase(".htaccess", ".htaccess")]
[TestCase("path/to/file/image.png", ".png")]
[TestCase("c:\\abc\\def\\ghi.jkl", ".jkl")]
[TestCase("/root/folder.name/file.ext", ".ext")]
[TestCase("http://www.domain.com/folder/name/file.txt", ".txt")]
[TestCase("i/don't\\have\\an/extension", "")]
[TestCase("https://some.where/path/to/file.ext?query=this&more=that", ".ext")]
[TestCase("double_query.string/file.ext?query=abc?something.else", ".ext")]
[TestCase("test.tar.gz", ".gz")]
[TestCase("wierd.file,but._legal", "._legal")]
[TestCase("one_char.x", ".x")]
public void Get_File_Extension(string input, string result)
{
var extension = input.GetFileExtension();
Assert.AreEqual(result, extension);
}
2019-02-21 09:35:38 +01:00
[TestCase("'+alert(1234)+'", "+alert1234+")]
[TestCase("'+alert(56+78)+'", "+alert56+78+")]
[TestCase("{{file}}", "file")]
[TestCase("'+alert('hello')+'", "+alerthello+")]
[TestCase("Test", "Test")]
public void Clean_From_XSS(string input, string result)
{
var cleaned = input.CleanForXss();
Assert.AreEqual(cleaned, result);
}
[TestCase("Hello this is my string", " string", "Hello this is my")]
[TestCase("Hello this is my string strung", " string", "Hello this is my string strung")]
[TestCase("Hello this is my string string", " string", "Hello this is my")]
[TestCase("Hello this is my string string", "g", "Hello this is my string strin")]
[TestCase("Hello this is my string string", "ello this is my string string", "H")]
[TestCase("Hello this is my string string", "Hello this is my string string", "")]
public void TrimEnd(string input, string forTrimming, string shouldBe)
{
2024-11-13 09:27:29 +01:00
var trimmed = input.TrimEnd(forTrimming);
Assert.AreEqual(shouldBe, trimmed);
}
[TestCase("Hello this is my string", "hello", " this is my string")]
[TestCase("Hello this is my string", "Hello this", " is my string")]
[TestCase("Hello this is my string", "Hello this is my ", "string")]
[TestCase("Hello this is my string", "Hello this is my string", "")]
public void TrimStart(string input, string forTrimming, string shouldBe)
{
2024-11-13 09:27:29 +01:00
var trimmed = input.TrimStart(forTrimming);
Assert.AreEqual(shouldBe, trimmed);
}
[TestCase(
"Hello this is my string",
"hello",
"replaced",
"replaced this is my string",
StringComparison.CurrentCultureIgnoreCase)]
[TestCase(
"Hello this is hello my string",
"hello",
"replaced",
"replaced this is replaced my string",
StringComparison.CurrentCultureIgnoreCase)]
[TestCase(
"Hello this is my string",
"nonexistent",
"replaced",
"Hello this is my string",
StringComparison.CurrentCultureIgnoreCase)]
[TestCase(
"Hellohello this is my string",
"hello",
"replaced",
"replacedreplaced this is my string",
StringComparison.CurrentCultureIgnoreCase)]
// Ensure replacing with the same string doesn't cause infinite loop.
[TestCase(
"Hello this is my string",
"hello",
"hello",
"hello this is my string",
StringComparison.CurrentCultureIgnoreCase)]
public void ReplaceWithStringComparison(
string input,
string oldString,
string newString,
string shouldBe,
StringComparison stringComparison)
{
var replaced = input.Replace(oldString, newString, stringComparison);
Assert.AreEqual(shouldBe, replaced);
}
[TestCase(null, null)]
[TestCase("", "")]
[TestCase("x", "X")]
[TestCase("xyzT", "XyzT")]
[TestCase("XyzT", "XyzT")]
public void ToFirstUpper(string input, string expected)
{
var output = input.ToFirstUpper();
Assert.AreEqual(expected, output);
}
[TestCase(null, null)]
[TestCase("", "")]
[TestCase("X", "x")]
[TestCase("XyZ", "xyZ")]
[TestCase("xyZ", "xyZ")]
public void ToFirstLower(string input, string expected)
{
var output = input.ToFirstLower();
Assert.AreEqual(expected, output);
}
[TestCase("pineapple", new[] { "banana", "apple", "blueberry", "strawberry" }, StringComparison.CurrentCulture, true)]
[TestCase("PINEAPPLE", new[] { "banana", "apple", "blueberry", "strawberry" }, StringComparison.CurrentCulture, false)]
[TestCase("pineapple", new[] { "banana", "Apple", "blueberry", "strawberry" }, StringComparison.CurrentCulture, false)]
[TestCase("pineapple", new[] { "banana", "Apple", "blueberry", "strawberry" }, StringComparison.OrdinalIgnoreCase, true)]
[TestCase("pineapple", new[] { "banana", "blueberry", "strawberry" }, StringComparison.OrdinalIgnoreCase, false)]
[TestCase("Strawberry unicorn pie", new[] { "Berry" }, StringComparison.OrdinalIgnoreCase, true)]
[TestCase("empty pie", new string[0], StringComparison.OrdinalIgnoreCase, false)]
public void ContainsAny(string haystack, IEnumerable<string> needles, StringComparison comparison, bool expected)
{
var output = haystack.ContainsAny(needles, comparison);
Assert.AreEqual(expected, output);
}
[TestCase("", true)]
[TestCase(" ", true)]
[TestCase("\r\n\r\n", true)]
[TestCase("\r\n", true)]
[TestCase(
@"
Hello
",
false)]
[TestCase(null, true)]
[TestCase("a", false)]
[TestCase("abc", false)]
[TestCase("abc ", false)]
[TestCase(" abc", false)]
[TestCase(" abc ", false)]
public void IsNullOrWhiteSpace(string value, bool expected)
{
// Act
var result = value.IsNullOrWhiteSpace();
// Assert
Assert.AreEqual(expected, result);
}
[TestCase("hello", "aGVsbG8")]
[TestCase("tad", "dGFk")]
[TestCase("AmqGr+Fd!~ééé", "QW1xR3IrRmQhfsOpw6nDqQ")]
public void UrlTokenEncoding(string value, string expected)
{
var bytes = Encoding.UTF8.GetBytes(value);
Console.WriteLine("base64: " + Convert.ToBase64String(bytes));
var encoded = bytes.UrlTokenEncode();
Assert.AreEqual(expected, encoded);
var backBytes = encoded.UrlTokenDecode();
var backString = Encoding.UTF8.GetString(backBytes);
Assert.AreEqual(value, backString);
}
// FORMAT STRINGS
// note: here we just ensure that the proper helper gets called properly
// but the "legacy" tests have moved to the legacy helper tests
[Test]
public void ToUrlAlias()
{
var output = "JUST-ANYTHING".ToUrlSegment(_mockShortStringHelper);
Assert.AreEqual("URL-SEGMENT::JUST-ANYTHING", output);
}
[Test]
public void FormatUrl()
{
var output = "JUST-ANYTHING".ToUrlSegment(_mockShortStringHelper);
Assert.AreEqual("URL-SEGMENT::JUST-ANYTHING", output);
}
[Test]
public void ToUmbracoAlias()
{
var output = "JUST-ANYTHING".ToSafeAlias(_mockShortStringHelper);
Assert.AreEqual("SAFE-ALIAS::JUST-ANYTHING", output);
}
[Test]
public void ToSafeAlias()
{
var output = "JUST-ANYTHING".ToSafeAlias(_mockShortStringHelper);
Assert.AreEqual("SAFE-ALIAS::JUST-ANYTHING", output);
}
[Test]
public void ToSafeAliasWithCulture()
{
var output = "JUST-ANYTHING".ToSafeAlias(_mockShortStringHelper, null);
Assert.AreEqual("SAFE-ALIAS-CULTURE::JUST-ANYTHING", output);
}
[Test]
public void ToUrlSegment()
{
var output = "JUST-ANYTHING".ToUrlSegment(_mockShortStringHelper);
Assert.AreEqual("URL-SEGMENT::JUST-ANYTHING", output);
}
[Test]
public void ToUrlSegmentWithCulture()
{
var output = "JUST-ANYTHING".ToUrlSegment(_mockShortStringHelper, null);
Assert.AreEqual("URL-SEGMENT-CULTURE::JUST-ANYTHING", output);
}
[Test]
public void ToSafeFileName()
{
var output = "JUST-ANYTHING".ToSafeFileName(_mockShortStringHelper);
Assert.AreEqual("SAFE-FILE-NAME::JUST-ANYTHING", output);
}
[Test]
public void ToSafeFileNameWithCulture()
{
var output = "JUST-ANYTHING".ToSafeFileName(_mockShortStringHelper, null);
Assert.AreEqual("SAFE-FILE-NAME-CULTURE::JUST-ANYTHING", output);
}
[Test]
public void ConvertCase()
{
var output = "JUST-ANYTHING".ToCleanString(_mockShortStringHelper, CleanStringType.Unchanged);
Assert.AreEqual("CLEAN-STRING-A::JUST-ANYTHING", output);
}
[Test]
public void SplitPascalCasing()
{
var output = "JUST-ANYTHING".SplitPascalCasing(_mockShortStringHelper);
Assert.AreEqual("SPLIT-PASCAL-CASING::JUST-ANYTHING", output);
}
[Test] // can't do cases with an IDictionary
public void ReplaceManyWithCharMap()
{
const string input = "télévisiön tzvâr ßup &nbsp; pof";
const string expected = "television tzvar ssup pof";
IDictionary<string, string> replacements = new Dictionary<string, string>
{
{ "é", "e" },
{ "ö", "o" },
{ "â", "a" },
{ "ß", "ss" },
{ "&nbsp;", " " },
};
var output = input.ReplaceMany(replacements);
Assert.AreEqual(expected, output);
}
[TestCase("val$id!ate|this|str'ing", "$!'", '-', "val-id-ate|this|str-ing")]
[TestCase("val$id!ate|this|str'ing", "$!'", '*', "val*id*ate|this|str*ing")]
public void ReplaceManyByOneChar(string input, string toReplace, char replacement, string expected)
{
var output = input.ReplaceMany(toReplace.ToArray(), replacement);
Assert.AreEqual(expected, output);
}
[TestCase("test to test", "test", "release", "release to test")]
[TestCase("nothing to do", "test", "release", "nothing to do")]
public void ReplaceFirst(string input, string search, string replacement, string expected)
{
var output = input.ReplaceFirst(search, replacement);
Assert.AreEqual(expected, output);
}
[Test]
public void IsFullPath()
{
bool isWindows = System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
// These are full paths on Windows, but not on Linux
TryIsFullPath(@"C:\dir\file.ext", isWindows);
TryIsFullPath(@"C:\dir\", isWindows);
TryIsFullPath(@"C:\dir", isWindows);
TryIsFullPath(@"C:\", isWindows);
TryIsFullPath(@"\\unc\share\dir\file.ext", isWindows);
TryIsFullPath(@"\\unc\share", isWindows);
// These are full paths on Linux, but not on Windows
TryIsFullPath(@"/some/file", !isWindows);
TryIsFullPath(@"/dir", !isWindows);
TryIsFullPath(@"/", !isWindows);
// Not full paths on either Windows or Linux
TryIsFullPath(@"file.ext", false);
TryIsFullPath(@"dir\file.ext", false);
TryIsFullPath(@"\dir\file.ext", false);
TryIsFullPath(@"C:", false);
TryIsFullPath(@"C:dir\file.ext", false);
TryIsFullPath(@"\dir", false); // An "absolute", but not "full" path
// Invalid on both Windows and Linux
Resolved more warnings, and marked more warning types as errors (#16991) * Fix warnings SA1111, SA1028, SA1500, IDE1270 in Umbraco.Web.Website, and updated rules. * Remove warnings: IDE0270: Null check can be simplified * More SqlServer project warnings resolved * CS0105 namespace appeared already * Suppress warning until implementation: #pragma warning disable CS0162 // Unreachable code detected #pragma warning disable CS0618 // Type or member is obsolete CS0162 remove unreachable code SA1028 remove trailing whitespace SA1106 no empty statements CS1570 malformed XML CS1572 corrected xml parameter CS1573 param tag added IDE0007 var not explicit IDE0008 explicit not var IDE0057 simplify substring IDE0074 compound assignment CA1825 array.empty Down to 3479 warnings * - SA1116, SA117 params on same line - IDE0057 substring simplified Specific warnings for Umbraco.Tests.Benchmarks * Fixed IDE0074 compound assignment and added specific warnings for Umbraco.Tests.Common * Specific warnings for Umbraco.Tests.Integration and Umbraco.Tests.Common Fixed: - SA1111, SA1116, SA117 params and line formatting (not all as there are many) - SA1122 string.Empty - IDE0057 simplify substring - IDE0044,IDE0044 make field readonly - IDE1006 naming rule violation (add _) - SA1111 closing parenthesis on line of last parameter - SA1649 filename match type name - SA1312,SA1306 lowercase variable and field names * Fixed various warnings where they are more straight-forward, including: - SA1649 file name match type name - SA111 parenthesis on line of last parameter - IDE0028 simplify collection initializer - SA1306 lower-case letter field - IDE044 readonly field - SA1122 string.Empty - SA1116 params same line - IDE1006 upper casing - IDE0041 simplify null check Updated the following projects to only list their remaining specific warning codes: - Umbraco.Tests.UnitTests Typo in `Umbraco.Web.Website` project * Reverted test change * Now 1556 warnings. Fixed various warnings where they are more straight-forward, including: - SA1111/SA1116/SA1119 parenthesis - SA1117 params - SA1312 lowercase variable - SA1121 built-in type - SA1500/SA1513/SA1503 formatting braces - SA1400 declare access modifier - SA1122 string.Empty - SA1310 no underscore - IDE0049 name simplified - IDE0057 simplify substring - IDE0074 compound assignment - IDE0032 use auto-property - IDE0037 simplify member name - IDE0008 explicit type not var - IDE0016/IDE0270/IDE0041 simplify null checks - IDE0048/SA1407 clarity in arithmetic - IDE1006 correct param names - IDE0042 deconstruct variable - IDE0044 readonly - IDE0018 inline variable declarations - IDE0074/IDE0054 compound assignment - IDE1006 naming - CS1573 param XML - CS0168 unused variable Comment formatting in project files for consistency. Updated all projects to only list remaining specific warning codes as warnings instead of errors (errors is now default). * Type not var, and more warning exceptions * Tweaked merge issue, readded comment about rollback * Readded comment re rollback. * Readded comments * Comment tweak * Comment tweak
2024-09-24 12:56:28 +01:00
TryIsFullPath(string.Empty, false, false);
TryIsFullPath(" ", false, false); // technically, a valid filename on Linux
}
[TestCase("test@test.com", true)]
[TestCase("test@test", true)]
[TestCase("testtest.com", false)]
[TestCase("test@test.dk", true)]
[TestCase("test@test.se", true)]
[TestCase(null, false)]
[TestCase("", false)]
[TestCase(" ", false)]
public void IsEmail(string? email, bool isEmail) => Assert.AreEqual(isEmail, email.IsEmail());
private static void TryIsFullPath(string path, bool expectedIsFull, bool expectedIsValid = true)
{
Assert.AreEqual(expectedIsFull, path.IsFullPath(), "IsFullPath('" + path + "')");
if (expectedIsFull)
{
Assert.AreEqual(path, Path.GetFullPath(path));
}
else if (expectedIsValid)
{
Assert.AreNotEqual(path, Path.GetFullPath(path));
}
}
[TestCase("1,2,3,4,5", "5,4,3,2,1")]
[TestCase("1,2,x,4,5", "5,4,2,1")]
public void GetIdsFromPathReversed(string input, string expected)
{
var ids = input.GetIdsFromPathReversed();
Assert.AreEqual(expected, string.Join(",", ids));
}
}