Skip to content

Commit

Permalink
Rewrite the tests to exactly match the tests in the spec
Browse files Browse the repository at this point in the history
Following the discussion at #2
  • Loading branch information
aradalvand committed Aug 7, 2023
1 parent 03d4107 commit 11d1cc4
Show file tree
Hide file tree
Showing 8 changed files with 397 additions and 310 deletions.
3 changes: 3 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"cSpell.words": ["sqids"]
}
93 changes: 36 additions & 57 deletions test/Sqids.Tests/AlphabetTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,85 +2,64 @@ namespace Sqids.Tests;

public class AlphabetTests
{
[Theory]
// NOTE: Too short
[InlineData("")]
[InlineData("a")]
[InlineData("1234")]
// NOTE: Repeated characters
[InlineData("aabcdefg")]
[InlineData("01234567789")]
public void Constructor_InvalidAlphabet_Throws(string alphabet)
[Fact]
public void Simple()
{
var act = () => new SqidsEncoder(new()
var sqids = new SqidsEncoder(new()
{
Alphabet = alphabet,
Alphabet = "0123456789abcdef",
});
act.Should().Throw<ArgumentException>();

var numbers = new[] { 1, 2, 3 };
var id = "4d9fd2";

sqids.Encode(numbers).Should().Be(id);
sqids.Decode(id).Should().BeEquivalentTo(numbers);
}

[Theory]
[InlineData("abcedfghijklmnop")]
[InlineData("0123456789")]
[InlineData("0123456789abcedfghijklmnop!@#$%^&*()")]
public void Constructor_ValidAlphabet_DoesNotThrow(string alphabet)
[Fact]
public void ShortAlphabet()
{
var act = () => new SqidsEncoder(new()
var sqids = new SqidsEncoder(new()
{
Alphabet = alphabet,
Alphabet = "abcde",
});
act.Should().NotThrow();

var numbers = new[] { 1, 2, 3 };

sqids.Decode(sqids.Encode(numbers)).Should().BeEquivalentTo(numbers);
}

[Theory]
[InlineData("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+|{}[];:\'\" /?.>,<`~", 420, "xP7")]
[InlineData("ABCDEFGHIJKLMNOP", 120, "EHB")]
[InlineData("abcde", 942, "dbbbcbcbbbc")]
public void Encode_WithCustomAlphabet_ReturnsRightId(
string alphabet,
int number,
string expected
)
[Fact]
public void LongAlphabet()
{
var encoder = new SqidsEncoder(new()
var sqids = new SqidsEncoder(new()
{
Alphabet = alphabet,
Alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+|{}[];:'\"/?.>,<`~",
});
var encoded = encoder.Encode(number);
encoded.Should().Be(expected); // todo: only check the characters?

var numbers = new[] { 1, 2, 3 };

sqids.Decode(sqids.Encode(numbers)).Should().BeEquivalentTo(numbers);
}

[Theory]
[InlineData("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_+|{}[];:\'\" /?.>,<`~", "xP7", 420)]
[InlineData("ABCDEFGHIJKLMNOP", "EHB", 120)]
[InlineData("abcde", "dbbbcbcbbbc", 942)]
public void Decode_WithCustomAlphabet_ReturnsRightId(
string alphabet,
string id,
int expected
)
[Fact]
public void RepeatedCharactersInAlphabet()
{
var encoder = new SqidsEncoder(new()
var act = () => new SqidsEncoder(new()
{
Alphabet = alphabet,
Alphabet = "aabcdefg",
});
var decoded = encoder.Decode(id);
decoded.Should().BeEquivalentTo(new[] { expected });
act.Should().Throw<ArgumentException>();
}

[Theory]
[InlineData("ABCDEFGHIJKLMNOP", "7dB")]
[InlineData("abcde", "98731232")]
public void Decode_InputWithCharactersNotInAlphabet_ReturnsRightId(
string alphabet,
string id
)
[Fact]
public void TooShortOfAnAlphabet()
{
var encoder = new SqidsEncoder(new()
var act = () => new SqidsEncoder(new()
{
Alphabet = alphabet,
Alphabet = "abcd",
});
var decoded = encoder.Decode(id);
decoded.Should().BeEmpty();
act.Should().Throw<ArgumentException>();
}
}
135 changes: 61 additions & 74 deletions test/Sqids.Tests/BlockListTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,113 +2,100 @@ namespace Sqids.Tests;

public class BlockListTests
{
[Theory]
[InlineData(200044, "sexy")] // NOTE: Without the blocklist, the number `200044` would yield `sexy` when encoded.
public void Encode_WithDefaultBlockList_BlocksDefaultBlockListWords(
int number,
string defaultBlockedEncoded
)
[Fact]
public void DefaultBlockListIfNoneSet()
{
var encoder = new SqidsEncoder();
var encoded = encoder.Encode(number);
encoded.Should().NotBe(defaultBlockedEncoded);
}
var sqids = new SqidsEncoder();

[Theory]
[InlineData("sexy", 200044)]
public void Decode_WithDefaultBlockList_StillDecodesBlockListWords(
string id,
int expected
)
{
var encoder = new SqidsEncoder();
var encoded = encoder.Decode(id);
encoded.Should().BeEquivalentTo(new[] { expected });
sqids.Decode("sexy").Should().BeEquivalentTo(new[] { 200044 });
sqids.Encode(200044).Should().Be("d171vI");
}

[Theory]
[InlineData(200044, "sexy")]
public void Encode_WithEmptyBlockList_DoesNotBlockAnything(
int number,
string expected
)
[Fact]
public void NoBlockListIfReset()
{
var encoder = new SqidsEncoder(new()
var sqids = new SqidsEncoder(new()
{
BlockList = new(),
});
var encoded = encoder.Encode(number);
encoded.Should().Be(expected);
}

[Theory]
[InlineData(2000, "srV")]
public void Encode_WithCustomBlockList_BlocksCustomBlockListWords(
int number,
string normalEncoded
)
{
var encoder = new SqidsEncoder(new()
{
BlockList = new() { normalEncoded },
});
var encoded = encoder.Encode(number);
encoded.Should().NotBe(normalEncoded);
sqids.Decode("sexy").Should().BeEquivalentTo(new[] { 200044 });
sqids.Encode(200044).Should().Be("sexy");
}

[Theory]
[InlineData(new[] { "foo" }, 200044, "sexy")]
public void Encode_WithCustomBlockList_DoesNotBlockDefaultBlockListWords(
string[] blocklist,
int number,
string byDefaultBlockedEncoded
)
[Fact]
public void OnlyCustomBlockListIfSet()
{
var encoder = new SqidsEncoder(new()
var sqids = new SqidsEncoder(new()
{
BlockList = new(blocklist),
BlockList = new()
{
"AvTg" // Originally encoded [100000]
},
});
var encoded = encoder.Encode(number);
encoded.Should().Be(byDefaultBlockedEncoded);

// Make sure the default blocklist isn't used
sqids.Decode("sexy").Should().BeEquivalentTo(new[] { 200044 });
sqids.Encode(200044).Should().Be("sexy");

// Make sure the passed blocklist IS used:
sqids.Decode("AvTg").Should().BeEquivalentTo(new[] { 100000 });
sqids.Encode(100000).Should().Be("7T1X8k");
sqids.Decode("7T1X8k").Should().BeEquivalentTo(new[] { 100000 });
}

[Theory]
[InlineData(982938132, "IrHOxXX")]
public void Encode_WithCustomBlockList_BlocksSubstring(
int number,
string normalEncoded
)
[Fact]
public void CustomBlockList()
{
var encoder = new SqidsEncoder(new()
var sqids = new SqidsEncoder(new()
{
BlockList = new()
{
normalEncoded[3..] // NOTE: First four characters
"8QRLaD", // normal result of 1st encoding, let's block that word on purpose
"7T1cd0dL", // result of 2nd encoding
"UeIe", // result of 3rd encoding is `RA8UeIe7`, let's block a substring
"imhw", // result of 4th encoding is `WM3Limhw`, let's block the postfix
"LfUQ", // result of 4th encoding is `LfUQh4HN`, let's block the prefix
},
});
var encoded = encoder.Encode(number);
encoded.Should().NotBe(normalEncoded);

sqids.Encode(1, 2, 3).Should().Be("TM0x1Mxz");
sqids.Decode("TM0x1Mxz").Should().BeEquivalentTo(new[] { 1, 2, 3 });
}

[Fact]
public void Encode_WithTooShortBlockListWords_DiscardsBlockList()
public void DecodingBlockedWordsShouldWork()
{
var encoder = new SqidsEncoder(new()
var sqids = new SqidsEncoder(new()
{
BlockList = new() { "U9" } // NOTE: `U9` is the normal encoding of `1`, and it's less than 3 characters, so its inclusion in the blocklist shouldn't not actually make a difference.
BlockList = new()
{
"8QRLaD",
"7T1cd0dL",
"RA8UeIe7",
"WM3Limhw",
"LfUQh4HN",
},
});
var encoded = encoder.Encode(1);
encoded.Should().Be("U9");

sqids.Decode("8QRLaD").Should().BeEquivalentTo(new[] { 1, 2, 3 });
sqids.Decode("7T1cd0dL").Should().BeEquivalentTo(new[] { 1, 2, 3 });
sqids.Decode("RA8UeIe7").Should().BeEquivalentTo(new[] { 1, 2, 3 });
sqids.Decode("WM3Limhw").Should().BeEquivalentTo(new[] { 1, 2, 3 });
sqids.Decode("LfUQh4HN").Should().BeEquivalentTo(new[] { 1, 2, 3 });
}

[Fact]
public void Encode_WithCustomBlockList_IgnoresCasing()
public void MatchAgainstShortBlockListWord()
{
var encoder = new SqidsEncoder(new()
var sqids = new SqidsEncoder(new()
{
BlockList = new() { "uAVP" } // `Uavp` is the normal encoding of `98765` — we block a different casing of it, and we expect it to be blocked, since the blocklist should work case-insensitively.
BlockList = new()
{
"pPQ",
},
});
var encoded = encoder.Encode(98765);
encoded.Should().NotBe("Uavp");

sqids.Decode(sqids.Encode(1000)).Should().BeEquivalentTo(new[] { 1000 });
}
}
Loading

0 comments on commit 11d1cc4

Please sign in to comment.