Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e40d131
:sparkles: add DecodeKind enum to distinguish key and value decoding …
techouse Aug 21, 2025
2c7102e
:bug: fix dot decoding in keys with context-aware decoder and improve…
techouse Aug 21, 2025
0284a30
:refactor: replace GetDecoder with DecodeKey and DecodeValue for impr…
techouse Aug 21, 2025
c77f29f
:white_check_mark: add DecodeOptions tests for dot handling, decoder …
techouse Aug 21, 2025
3669f46
:white_check_mark: add tests for encoded dot handling in keys with Al…
techouse Aug 21, 2025
9605513
:fire: remove obsolete GetDecoder method in favor of context-aware de…
techouse Aug 21, 2025
69d17ab
:bulb: clarify AllowDots behavior when DecodeDotInKeys is enabled
techouse Aug 21, 2025
cf37563
:white_check_mark: update DecodeOptions test to use flexible exceptio…
techouse Aug 21, 2025
b91d0ad
:bug: ensure DecodeKey returns string or null, throw if decoder retur…
techouse Aug 21, 2025
a2afb17
:bulb: document implied AllowDots behavior when DecodeDotInKeys is en…
techouse Aug 21, 2025
a80c88a
:bug: handle incomplete percent escapes in decoder and clarify AllowD…
techouse Aug 21, 2025
bfc18ce
:white_check_mark: add tests to verify encoded dots inside brackets a…
techouse Aug 21, 2025
261a530
:bug: correctly track bracket depth in DecodeKey when brackets are pe…
techouse Aug 22, 2025
8840f4f
:bug: optimize DecodeKey to skip scanning when no encoded dots or bra…
techouse Aug 22, 2025
e7e8cb1
:bug: simplify DefaultDecode logic for key decoding; add XML docs to …
techouse Aug 22, 2025
32b069d
:bug: decode keys identically to values in DefaultDecode; fix bracket…
techouse Aug 22, 2025
e64ac82
:bug: correctly handle nested brackets when splitting key segments in…
techouse Aug 22, 2025
1741cb5
:bug: convert top-level dots in keys to bracket segments; preserve do…
techouse Aug 22, 2025
8d1f0cb
:white_check_mark: update tests to expect decoded dot-encoded keys as…
techouse Aug 22, 2025
b999e5d
:white_check_mark: add tests for percent-decoding of dots in keys; ve…
techouse Aug 22, 2025
80df68d
:white_check_mark: move percent-decoding and dot-encoded key tests fr…
techouse Aug 22, 2025
0d90d6c
:white_check_mark: add tests for handling percent-encoded dots in key…
techouse Aug 22, 2025
db08a58
:recycle: make DefaultDecode static to ensure consistent decoding beh…
techouse Aug 22, 2025
8adf5cb
:recycle: simplify DefaultDecode by removing unused DecodeKind parame…
techouse Aug 22, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions QsNet.Tests/DecodeOptionsTests.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System;
using System.Collections.Generic;
using System.Text;
using FluentAssertions;
using QsNet.Enums;
Expand Down Expand Up @@ -108,4 +110,111 @@ public void CopyWith_WithModifications_ShouldReturnModifiedOptions()
newOptions.ParseLists.Should().BeTrue();
newOptions.StrictNullHandling.Should().BeFalse();
}

[Fact]
public void DecodeKey_ShouldThrow_When_DecodeDotInKeysTrue_And_AllowDotsFalse()
{
var options = new DecodeOptions
{
AllowDots = false,
DecodeDotInKeys = true
};

Action act = () => options.DecodeKey("a%2Eb", Encoding.UTF8);
act.Should().Throw<ArgumentException>()
.Where(e => e.Message.Contains("decodeDotInKeys", StringComparison.OrdinalIgnoreCase)
&& e.Message.Contains("allowDots", StringComparison.OrdinalIgnoreCase));
}

[Fact]
public void DecodeKey_DecodesPercentSequences_LikeValues()
{
var options = new DecodeOptions
{
AllowDots = true,
DecodeDotInKeys = false
};

options.DecodeKey("a%2Eb", Encoding.UTF8).Should().Be("a.b");
options.DecodeKey("a%2eb", Encoding.UTF8).Should().Be("a.b");
}

[Fact]
public void DecodeValue_DecodesPercentSequences_Normally()
{
var options = new DecodeOptions();
options.DecodeValue("%2E", Encoding.UTF8).Should().Be(".");
}

[Fact]
public void DecoderWithKind_IsUsed_For_Key_And_Value()
{
var calls = new List<(string? s, DecodeKind kind)>();
var options = new DecodeOptions
{
DecoderWithKind = (s, enc, kind) =>
{
calls.Add((s, kind));
return s;
}
};

options.DecodeKey("x", Encoding.UTF8).Should().Be("x");
options.DecodeValue("y", Encoding.UTF8).Should().Be("y");

calls.Should().HaveCount(2);
calls[0].kind.Should().Be(DecodeKind.Key);
calls[0].s.Should().Be("x");
calls[1].kind.Should().Be(DecodeKind.Value);
calls[1].s.Should().Be("y");
}

[Fact]
public void DecoderWithKind_NullReturn_IsHonored_NoFallback()
{
var options = new DecodeOptions
{
DecoderWithKind = (s, enc, kind) => null
};

options.DecodeValue("foo", Encoding.UTF8).Should().BeNull();
options.DecodeKey("bar", Encoding.UTF8).Should().BeNull();
}

[Fact]
public void LegacyDecoder_IsUsed_When_NoKindAwareDecoder_IsProvided()
{
var options = new DecodeOptions
{
Decoder = (s, enc) => s is null ? null : s.ToUpperInvariant()
};

options.DecodeValue("abc", Encoding.UTF8).Should().Be("ABC");
// For keys, legacy decoder is also used when no kind-aware decoder is set
options.DecodeKey("a%2Eb", Encoding.UTF8).Should().Be("A%2EB");
}

[Fact]
public void CopyWith_PreservesAndOverrides_Decoders()
{
var original = new DecodeOptions
{
Decoder = (s, enc) => s == null ? null : $"L:{s}",
DecoderWithKind = (s, enc, k) => s == null ? null : $"K:{k}:{s}"
};

// Copy without overrides preserves both decoders
var copy = original.CopyWith();
copy.DecodeValue("v", Encoding.UTF8).Should().Be("K:Value:v");
copy.DecodeKey("k", Encoding.UTF8).Should().Be("K:Key:k");

// Override only the legacy decoder; kind-aware remains
var copy2 = original.CopyWith(decoder: (s, enc) => s == null ? null : $"L2:{s}");
copy2.DecodeValue("v", Encoding.UTF8).Should().Be("K:Value:v"); // still kind-aware takes precedence

// Override kind-aware decoder
var copy3 = original.CopyWith(decoderWithKind: (s, enc, k) => s == null ? null : $"K2:{k}:{s}");
copy3.DecodeValue("v", Encoding.UTF8).Should().Be("K2:Value:v");
copy3.DecodeKey("k", Encoding.UTF8).Should().Be("K2:Key:k");
}
}
Loading
Loading