Skip to content

Commit 3d9eb86

Browse files
committed
.
1 parent b795a1c commit 3d9eb86

6 files changed

+55
-26
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
RootProperty: RootValue
3+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
Property: Value
3+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Foo

src/Verify.Tests/Converters/ExtensionConverterTests.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,12 @@ public Task WithInfo_AndRecording()
210210
return Verify(new MemoryStream([1]), "WithInfo");
211211
}
212212

213+
// Test: Explicit root info + converter that returns its own info
214+
// Expected order: root info, converter info, converter text
215+
[Fact]
216+
public Task WithInfo_AndRootInfo() =>
217+
Verify(new MemoryStream([1]), "WithInfo", null, new { RootProperty = "RootValue" });
218+
213219
[ModuleInitializer]
214220
public static void WithInfoAndBinaryInit() =>
215221
VerifierSettings.RegisterStreamConverter(

src/Verify/Verifier/InnerVerifier_Inner.cs

Lines changed: 42 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,22 +39,15 @@ async Task<VerifyResult> VerifyInner(object? root, Func<Task>? cleanup, IEnumera
3939

4040
List<Target> list = [..targets, ..VerifierSettings.GetFileAppenders(settings)];
4141

42-
// Process root via TryGetRootTarget when root is NOT already in the targets list
43-
// This handles:
44-
// - VerifyStream with converter: root (info) is separate from targets → process both
45-
// - Verify(object, IEnumerable<Target>): root is separate from targets → process both
46-
// - Verify(): root is null, targets is empty → TryGetRootTarget handles null appropriately
47-
// Skip when:
48-
// - Verify(object): root is in targets list → avoid duplicate processing
42+
// Check if root is in targets list (to avoid duplicate processing)
4943
var rootInTargets = root != null && list.Any(t => ReferenceEquals(t.Data, root));
50-
if (!rootInTargets && TryGetRootTarget(root, ignoreNullRoot, out var rootTarget))
51-
{
52-
resultTargets.Add(rootTarget.Value);
53-
}
5444

45+
// Process extension conversions first (may produce converter info that becomes root)
46+
List<object>? converterInfos = null;
5547
if (doExtensionConversion)
5648
{
5749
var result = new List<Target>();
50+
converterInfos = [];
5851
foreach (var target in list)
5952
{
6053
if (!target.PerformConversion ||
@@ -69,21 +62,43 @@ target.Extension is null ||
6962
cleanup += itemCleanup;
7063
if (info != null)
7164
{
72-
result.Add(
73-
new(
74-
settings.TxtOrJson,
75-
JsonFormatter.AsJson(
76-
settings,
77-
counter,
78-
info)));
65+
converterInfos.Add(info);
7966
}
8067

8168
result.AddRange(converted);
8269
}
8370

71+
// If root is null and converters returned info, use converter info as root (for appenders)
72+
if (!rootInTargets && root == null && converterInfos.Count > 0)
73+
{
74+
root = converterInfos.Count == 1 ? converterInfos[0] : converterInfos;
75+
converterInfos = null; // Already used as root, don't add again
76+
}
77+
8478
list = result;
8579
}
8680

81+
// Process root via TryGetRootTarget (after extension conversion so converter info can become root)
82+
if (!rootInTargets && TryGetRootTarget(root, ignoreNullRoot, out var rootTarget))
83+
{
84+
resultTargets.Add(rootTarget.Value);
85+
}
86+
87+
// Add converter infos right after root (before other targets)
88+
if (converterInfos != null)
89+
{
90+
foreach (var info in converterInfos)
91+
{
92+
resultTargets.Add(
93+
new(
94+
settings.TxtOrJson,
95+
JsonFormatter.AsJson(
96+
settings,
97+
counter,
98+
info)));
99+
}
100+
}
101+
87102
// Resolve all targets (including objects) to ResolvedTargets
88103
var extraTargets = new List<ResolvedTarget>();
89104
var noScrubTargets = new List<ResolvedTarget>();
@@ -260,6 +275,15 @@ target.Extension is null ||
260275
JsonFormatter.AsJson(settings, counter, conversionResult.Info)));
261276
}
262277

278+
// Add appends as first target if present (typed converters don't include appends in their output)
279+
var converterAppends = VerifierSettings.GetJsonAppenders(settings);
280+
if (converterAppends.Count > 0)
281+
{
282+
results.Insert(0, new(
283+
settings.TxtOrJson,
284+
JsonFormatter.AsJson(settings, counter, new InfoBuilder(true, null, converterAppends))));
285+
}
286+
263287
return (results, cleanup, true);
264288
}
265289

src/Verify/Verifier/InnerVerifier_Stream.cs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,6 @@ public async Task<VerifyResult> VerifyStream(Stream? stream, string extension, o
8686

8787
stream.MoveToStart();
8888

89-
// Check for stream converter first - converter info should be root for appenders
90-
if (VerifierSettings.HasStreamConverter(extension))
91-
{
92-
var (newInfo, converted, cleanup) = await DoExtensionConversion(extension, stream, info, null);
93-
return await VerifyInner(newInfo, cleanup, converted, false, true);
94-
}
95-
96-
// No converter - create target directly
9789
Target target;
9890
if (FileExtensions.IsTextExtension(extension))
9991
{

0 commit comments

Comments
 (0)