dependabot-nuget 0.301.1 → 0.303.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/Directory.Packages.props +5 -5
  3. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.props +4 -1
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscovery.targets +19 -4
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencyDiscoveryTargetingPacks.props +10 -0
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +20 -17
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +179 -28
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +3 -0
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/FrameworkCompatibilityService.cs +15 -6
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/FrameworkChecker/SupportedFrameworks.cs +6 -4
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/NuGetUpdater.Core.csproj +1 -0
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +8 -0
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/BindingRedirectManager.cs +7 -4
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +2 -0
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +257 -37
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackagesConfigUpdater.cs +13 -4
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/{WebApplicationTargetsConditionPatcher.cs → SpecialImportsConditionPatcher.cs} +18 -11
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdateOperationBase.cs +209 -0
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdateOperationResult.cs +3 -0
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +79 -24
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/XmlFilePreAndPostProcessor.cs +26 -11
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +48 -22
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +54 -0
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.PackagesConfig.cs +68 -0
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +94 -0
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/FrameworkChecker/FrameworkCompatibilityServiceFacts.cs +1 -1
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/RunWorkerTests.cs +24 -6
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackageReferenceUpdaterTests.cs +177 -0
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/SpecialFilePatcherTests.cs +99 -0
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateOperationBaseTests.cs +130 -0
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTestBase.cs +5 -0
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.Mixed.cs +71 -5
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackageReference.cs +125 -3
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/UpdateWorkerTests.PackagesConfig.cs +23 -0
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +145 -147
  36. data/lib/dependabot/nuget/file_parser.rb +22 -19
  37. metadata +13 -8
@@ -0,0 +1,177 @@
1
+ using System.Collections.Immutable;
2
+
3
+ using NuGet.Versioning;
4
+
5
+ using NuGetUpdater.Core.Test.Utilities;
6
+ using NuGetUpdater.Core.Updater;
7
+
8
+ using Xunit;
9
+
10
+ namespace NuGetUpdater.Core.Test.Update;
11
+
12
+ public class PackageReferenceUpdaterTests
13
+ {
14
+ [Theory]
15
+ [MemberData(nameof(ComputeUpdateOperationsTestData))]
16
+ public async Task ComputeUpdateOperations
17
+ (
18
+ ImmutableArray<Dependency> topLevelDependencies,
19
+ ImmutableArray<Dependency> requestedUpdates,
20
+ ImmutableArray<Dependency> resolvedDependencies,
21
+ ImmutableArray<UpdateOperationBase> expectedUpdateOperations
22
+ )
23
+ {
24
+ // arrange
25
+ using var repoRoot = await TemporaryDirectory.CreateWithContentsAsync(("project.csproj", "<Project Sdk=\"Microsoft.NET.Sdk\" />"));
26
+ var projectPath = Path.Combine(repoRoot.DirectoryPath, "project.csproj");
27
+ var experimentsManager = new ExperimentsManager() { UseDirectDiscovery = true };
28
+ await UpdateWorkerTestBase.MockNuGetPackagesInDirectory([
29
+ MockNuGetPackage.CreateSimplePackage("Parent.Package", "1.0.0", "net9.0", [(null, [("Transitive.Package", "1.0.0")])]),
30
+ MockNuGetPackage.CreateSimplePackage("Parent.Package", "2.0.0", "net9.0", [(null, [("Transitive.Package", "2.0.0")])]),
31
+ MockNuGetPackage.CreateSimplePackage("Transitive.Package", "1.0.0", "net9.0", [(null, [("Super.Transitive.Package", "1.0.0")])]),
32
+ MockNuGetPackage.CreateSimplePackage("Transitive.Package", "2.0.0", "net9.0", [(null, [("Super.Transitive.Package", "2.0.0")])]),
33
+ MockNuGetPackage.CreateSimplePackage("Super.Transitive.Package", "1.0.0", "net9.0"),
34
+ MockNuGetPackage.CreateSimplePackage("Super.Transitive.Package", "2.0.0", "net9.0")
35
+ ], repoRoot.DirectoryPath);
36
+
37
+ // act
38
+ var actualUpdateOperations = await PackageReferenceUpdater.ComputeUpdateOperations(
39
+ repoRoot.DirectoryPath,
40
+ projectPath,
41
+ "net9.0",
42
+ topLevelDependencies,
43
+ requestedUpdates,
44
+ resolvedDependencies,
45
+ experimentsManager,
46
+ new TestLogger());
47
+
48
+ // assert
49
+ AssertEx.Equal(expectedUpdateOperations, actualUpdateOperations);
50
+ }
51
+
52
+ public static IEnumerable<object[]> ComputeUpdateOperationsTestData()
53
+ {
54
+ // single dependency update
55
+ yield return
56
+ [
57
+ // topLevelDependencies
58
+ ImmutableArray.Create(
59
+ new Dependency("Some.Package", "1.0.0", DependencyType.PackageReference),
60
+ new Dependency("Unrelated.Package", "2.0.0", DependencyType.PackageReference)
61
+ ),
62
+
63
+ // requestedUpdates
64
+ ImmutableArray.Create(
65
+ new Dependency("Some.Package", "1.0.1", DependencyType.PackageReference)
66
+ ),
67
+
68
+ // resolvedDependencies
69
+ ImmutableArray.Create(
70
+ new Dependency("Some.Package", "1.0.1", DependencyType.PackageReference),
71
+ new Dependency("Unrelated.Package", "2.0.0", DependencyType.PackageReference)
72
+ ),
73
+
74
+ // expectedUpdateOperations
75
+ ImmutableArray.Create<UpdateOperationBase>(
76
+ new DirectUpdate()
77
+ {
78
+ DependencyName = "Some.Package",
79
+ NewVersion = NuGetVersion.Parse("1.0.1"),
80
+ UpdatedFiles = [],
81
+ }
82
+ )
83
+ ];
84
+
85
+ // dependency was updated by pinning
86
+ yield return
87
+ [
88
+ // topLevelDependencies
89
+ ImmutableArray.Create(
90
+ new Dependency("Top.Level.Package", "1.0.0", DependencyType.PackageReference)
91
+ ),
92
+
93
+ // requestedUpdates
94
+ ImmutableArray.Create(
95
+ new Dependency("Transitive.Package", "2.0.0", DependencyType.PackageReference)
96
+ ),
97
+
98
+ // resolvedDependencies
99
+ ImmutableArray.Create(
100
+ new Dependency("Top.Level.Package", "1.0.0", DependencyType.PackageReference),
101
+ new Dependency("Transitive.Package", "2.0.0", DependencyType.PackageReference)
102
+ ),
103
+
104
+ // expectedUpdateOperations
105
+ ImmutableArray.Create<UpdateOperationBase>(
106
+ new PinnedUpdate()
107
+ {
108
+ DependencyName = "Transitive.Package",
109
+ NewVersion = NuGetVersion.Parse("2.0.0"),
110
+ UpdatedFiles = [],
111
+ }
112
+ )
113
+ ];
114
+
115
+ // dependency was updated by updating parent 1 level up
116
+ yield return
117
+ [
118
+ // topLevelDependencies
119
+ ImmutableArray.Create(
120
+ new Dependency("Parent.Package", "1.0.0", DependencyType.PackageReference)
121
+ ),
122
+
123
+ // requestedUpdates
124
+ ImmutableArray.Create(
125
+ new Dependency("Transitive.Package", "2.0.0", DependencyType.PackageReference)
126
+ ),
127
+
128
+ // resolvedDependencies
129
+ ImmutableArray.Create(
130
+ new Dependency("Parent.Package", "2.0.0", DependencyType.PackageReference)
131
+ ),
132
+
133
+ // expectedUpdateOperations
134
+ ImmutableArray.Create<UpdateOperationBase>(
135
+ new ParentUpdate()
136
+ {
137
+ DependencyName = "Transitive.Package",
138
+ NewVersion = NuGetVersion.Parse("2.0.0"),
139
+ UpdatedFiles = [],
140
+ ParentDependencyName = "Parent.Package",
141
+ ParentNewVersion = NuGetVersion.Parse("2.0.0"),
142
+ }
143
+ )
144
+ ];
145
+
146
+ // dependency was updated by updating parent 2 levels up
147
+ yield return
148
+ [
149
+ // topLevelDependencies
150
+ ImmutableArray.Create(
151
+ new Dependency("Parent.Package", "1.0.0", DependencyType.PackageReference)
152
+ ),
153
+
154
+ // requestedUpdates
155
+ ImmutableArray.Create(
156
+ new Dependency("Super.Transitive.Package", "2.0.0", DependencyType.PackageReference)
157
+ ),
158
+
159
+ // resolvedDependencies
160
+ ImmutableArray.Create(
161
+ new Dependency("Parent.Package", "2.0.0", DependencyType.PackageReference)
162
+ ),
163
+
164
+ // expectedUpdateOperations
165
+ ImmutableArray.Create<UpdateOperationBase>(
166
+ new ParentUpdate()
167
+ {
168
+ DependencyName = "Super.Transitive.Package",
169
+ NewVersion = NuGetVersion.Parse("2.0.0"),
170
+ UpdatedFiles = [],
171
+ ParentDependencyName = "Parent.Package",
172
+ ParentNewVersion = NuGetVersion.Parse("2.0.0"),
173
+ }
174
+ )
175
+ ];
176
+ }
177
+ }
@@ -0,0 +1,99 @@
1
+ using NuGetUpdater.Core.Updater;
2
+
3
+ using Xunit;
4
+
5
+ namespace NuGetUpdater.Core.Test.Update;
6
+
7
+ public class SpecialFilePatcherTests
8
+ {
9
+ [Theory]
10
+ [MemberData(nameof(SpecialImportsConditionPatcherTestData))]
11
+ public async Task SpecialImportsConditionPatcher(string fileContent, string expectedPatchedContent)
12
+ {
13
+ // arrange
14
+ var projectFileName = "project.csproj";
15
+ using var tempDir = await TemporaryDirectory.CreateWithContentsAsync((projectFileName, fileContent));
16
+ var projectPath = Path.Join(tempDir.DirectoryPath, projectFileName);
17
+
18
+ // act
19
+ using (var patcher = new SpecialImportsConditionPatcher(projectPath))
20
+ {
21
+ var actualPatchedContent = await File.ReadAllTextAsync(projectPath);
22
+
23
+ // assert
24
+ Assert.Equal(expectedPatchedContent.Replace("\r", ""), actualPatchedContent.Replace("\r", ""));
25
+ }
26
+
27
+ // assert again
28
+ var restoredContent = await File.ReadAllTextAsync(projectPath);
29
+ Assert.Equal(restoredContent.Replace("\r", ""), fileContent.Replace("\r", ""));
30
+ }
31
+
32
+ public static IEnumerable<object[]> SpecialImportsConditionPatcherTestData()
33
+ {
34
+ // one-off test to verify namespaces don't interfere
35
+ yield return
36
+ [
37
+ // fileContent
38
+ """
39
+ <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
40
+ <Import Project="Unrelated.One.targets" />
41
+ <Import Project="Some\Path\Microsoft.WebApplication.targets" />
42
+ <Import Project="Unrelated.Two.targets" />
43
+ </Project>
44
+ """,
45
+ // expectedPatchedContent
46
+ """
47
+ <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
48
+ <Import Project="Unrelated.One.targets" />
49
+ <Import Project="Some\Path\Microsoft.WebApplication.targets" Condition="false" />
50
+ <Import Project="Unrelated.Two.targets" />
51
+ </Project>
52
+ """
53
+ ];
54
+
55
+ // one-off test to verify existing conditions are restored
56
+ yield return
57
+ [
58
+ // fileContent
59
+ """
60
+ <Project>
61
+ <Import Project="Unrelated.One.targets" />
62
+ <Import Project="Some\Path\Microsoft.WebApplication.targets" Condition="existing condition" />
63
+ <Import Project="Unrelated.Two.targets" />
64
+ </Project>
65
+ """,
66
+ // expectedPatchedContent
67
+ """
68
+ <Project>
69
+ <Import Project="Unrelated.One.targets" />
70
+ <Import Project="Some\Path\Microsoft.WebApplication.targets" Condition="false" />
71
+ <Import Project="Unrelated.Two.targets" />
72
+ </Project>
73
+ """
74
+ ];
75
+
76
+ // all file variations - by its nature, also verifies that multiple replacements can occur
77
+ yield return
78
+ [
79
+ // fileContent
80
+ """
81
+ <Project>
82
+ <Import Project="Unrelated.One.targets" />
83
+ <Import Project="Some\Path\Microsoft.TextTemplating.targets" />
84
+ <Import Project="Some\Path\Microsoft.WebApplication.targets" />
85
+ <Import Project="Unrelated.Two.targets" />
86
+ </Project>
87
+ """,
88
+ // expectedPatchedContent
89
+ """
90
+ <Project>
91
+ <Import Project="Unrelated.One.targets" />
92
+ <Import Project="Some\Path\Microsoft.TextTemplating.targets" Condition="false" />
93
+ <Import Project="Some\Path\Microsoft.WebApplication.targets" Condition="false" />
94
+ <Import Project="Unrelated.Two.targets" />
95
+ </Project>
96
+ """
97
+ ];
98
+ }
99
+ }
@@ -0,0 +1,130 @@
1
+ using NuGet.Versioning;
2
+
3
+ using NuGetUpdater.Core.Test.Utilities;
4
+ using NuGetUpdater.Core.Updater;
5
+
6
+ using Xunit;
7
+
8
+ namespace NuGetUpdater.Core.Test.Update;
9
+
10
+ public class UpdateOperationBaseTests
11
+ {
12
+ [Fact]
13
+ public void GetReport()
14
+ {
15
+ // arrange
16
+ var updateOperations = new UpdateOperationBase[]
17
+ {
18
+ new DirectUpdate()
19
+ {
20
+ DependencyName = "Package.A",
21
+ NewVersion = NuGetVersion.Parse("1.0.0"),
22
+ UpdatedFiles = ["file/a.txt"]
23
+ },
24
+ new PinnedUpdate()
25
+ {
26
+ DependencyName = "Package.B",
27
+ NewVersion = NuGetVersion.Parse("2.0.0"),
28
+ UpdatedFiles = ["file/b.txt"]
29
+ },
30
+ new ParentUpdate()
31
+ {
32
+ DependencyName = "Package.C",
33
+ NewVersion = NuGetVersion.Parse("3.0.0"),
34
+ UpdatedFiles = ["file/c.txt"],
35
+ ParentDependencyName = "Package.D",
36
+ ParentNewVersion = NuGetVersion.Parse("4.0.0"),
37
+ },
38
+ };
39
+
40
+ // act
41
+ var actualReport = UpdateOperationBase.GenerateUpdateOperationReport(updateOperations);
42
+
43
+ // assert
44
+ var expectedReport = """
45
+ Performed the following updates:
46
+ - Updated Package.A to 1.0.0 in file/a.txt
47
+ - Pinned Package.B at 2.0.0 in file/b.txt
48
+ - Updated Package.C to 3.0.0 indirectly via Package.D/4.0.0 in file/c.txt
49
+ """.Replace("\r", "");
50
+ Assert.Equal(expectedReport, actualReport);
51
+ }
52
+
53
+ [Fact]
54
+ public void NormalizeUpdateOperationCollection_SortAndDistinct()
55
+ {
56
+ // arrange
57
+ var repoRootPath = "/repo/root";
58
+ var updateOperations = new UpdateOperationBase[]
59
+ {
60
+ new DirectUpdate()
61
+ {
62
+ DependencyName = "Dependency.Direct",
63
+ NewVersion = NuGetVersion.Parse("1.0.0"),
64
+ UpdatedFiles = ["/repo/root/file/a.txt"]
65
+ },
66
+ new PinnedUpdate()
67
+ {
68
+ DependencyName = "Dependency.Pinned",
69
+ NewVersion = NuGetVersion.Parse("2.0.0"),
70
+ UpdatedFiles = ["/repo/root/file/b.txt"]
71
+ },
72
+ // this is the same as the first item and will be removed
73
+ new DirectUpdate()
74
+ {
75
+ DependencyName = "Dependency.Direct",
76
+ NewVersion = NuGetVersion.Parse("1.0.0"),
77
+ UpdatedFiles = ["/repo/root/file/a.txt"]
78
+ },
79
+ new ParentUpdate()
80
+ {
81
+ DependencyName = "Dependency.Parent",
82
+ NewVersion = NuGetVersion.Parse("3.0.0"),
83
+ UpdatedFiles = ["/repo/root/file/c.txt"],
84
+ ParentDependencyName = "Dependency.Root",
85
+ ParentNewVersion = NuGetVersion.Parse("4.0.0"),
86
+ },
87
+ };
88
+
89
+ // act
90
+ var normalizedOperations = UpdateOperationBase.NormalizeUpdateOperationCollection(repoRootPath, updateOperations);
91
+ var normalizedDependencyNames = string.Join(", ", normalizedOperations.Select(o => o.DependencyName));
92
+
93
+ // assert
94
+ var expectedDependencyNames = "Dependency.Direct, Dependency.Parent, Dependency.Pinned";
95
+ Assert.Equal(expectedDependencyNames, normalizedDependencyNames);
96
+ }
97
+
98
+ [Fact]
99
+ public void NormalizeUpdateOperationCollection_CombinedOnTypeAndDependency()
100
+ {
101
+ // arrange
102
+ var repoRootPath = "/repo/root";
103
+ var updateOperations = new UpdateOperationBase[]
104
+ {
105
+ // both operations are the same type, same dependency, same version => files are combined
106
+ new DirectUpdate()
107
+ {
108
+ DependencyName = "Dependency.Direct",
109
+ NewVersion = NuGetVersion.Parse("1.0.0"),
110
+ UpdatedFiles = ["/repo/root/file/b.txt"]
111
+ },
112
+ new DirectUpdate()
113
+ {
114
+ DependencyName = "Dependency.Direct",
115
+ NewVersion = NuGetVersion.Parse("1.0.0"),
116
+ UpdatedFiles = ["/repo/root/file/a.txt"]
117
+ },
118
+ };
119
+
120
+ // act
121
+ var normalizedOperations = UpdateOperationBase.NormalizeUpdateOperationCollection(repoRootPath, updateOperations);
122
+
123
+ // assert
124
+ var singleUpdate = Assert.Single(normalizedOperations);
125
+ var directUpdate = Assert.IsType<DirectUpdate>(singleUpdate);
126
+ Assert.Equal("Dependency.Direct", directUpdate.DependencyName);
127
+ Assert.Equal(NuGetVersion.Parse("1.0.0"), directUpdate.NewVersion);
128
+ AssertEx.Equal(["/file/a.txt", "/file/b.txt"], directUpdate.UpdatedFiles);
129
+ }
130
+ }
@@ -3,6 +3,7 @@ using System.Text.Json;
3
3
  using NuGetUpdater.Core.Run;
4
4
  using NuGetUpdater.Core.Run.ApiModel;
5
5
  using NuGetUpdater.Core.Test.Updater;
6
+ using NuGetUpdater.Core.Test.Utilities;
6
7
  using NuGetUpdater.Core.Updater;
7
8
 
8
9
  using Xunit;
@@ -191,6 +192,10 @@ public abstract class UpdateWorkerTestBase : TestBase
191
192
  else
192
193
  {
193
194
  Assert.Null(actualResult.Error);
195
+ if (expectedResult is not null)
196
+ {
197
+ AssertEx.Equal(expectedResult.UpdateOperations, actualResult.UpdateOperations, UpdateOperationBaseComparer.Instance);
198
+ }
194
199
  }
195
200
  }
196
201
 
@@ -1,5 +1,7 @@
1
1
  using System.Text.Json;
2
2
 
3
+ using NuGet.Versioning;
4
+
3
5
  using NuGetUpdater.Core.Run.ApiModel;
4
6
  using NuGetUpdater.Core.Updater;
5
7
 
@@ -12,16 +14,14 @@ public partial class UpdateWorkerTests
12
14
  public class Mixed : UpdateWorkerTestBase
13
15
  {
14
16
  [Fact]
15
- public async Task ResultFileHasCorrectShapeForAuthenticationFailure()
17
+ public void ResultFileHasCorrectShapeForAuthenticationFailure()
16
18
  {
17
- using var temporaryDirectory = await TemporaryDirectory.CreateWithContentsAsync([]);
18
19
  var result = new UpdateOperationResult()
19
20
  {
20
21
  Error = new PrivateSourceAuthenticationFailure(["<some package feed>"]),
22
+ UpdateOperations = [],
21
23
  };
22
- var resultFilePath = Path.Combine(temporaryDirectory.DirectoryPath, "update-result.json");
23
- await UpdaterWorker.WriteResultFile(result, resultFilePath, new TestLogger());
24
- var resultContent = await File.ReadAllTextAsync(resultFilePath);
24
+ var resultContent = UpdaterWorker.Serialize(result);
25
25
 
26
26
  // raw result file should look like this:
27
27
  // {
@@ -44,6 +44,72 @@ public partial class UpdateWorkerTests
44
44
  Assert.Equal("(<some package feed>)", source.GetString());
45
45
  }
46
46
 
47
+ [Fact]
48
+ public void ResultFileListsUpdateOperations()
49
+ {
50
+ var result = new UpdateOperationResult()
51
+ {
52
+ Error = null,
53
+ UpdateOperations = [
54
+ new DirectUpdate()
55
+ {
56
+ DependencyName = "Package.A",
57
+ NewVersion = NuGetVersion.Parse("1.0.0"),
58
+ UpdatedFiles = ["a.txt"]
59
+ },
60
+ new PinnedUpdate()
61
+ {
62
+ DependencyName = "Package.B",
63
+ NewVersion = NuGetVersion.Parse("2.0.0"),
64
+ UpdatedFiles = ["b.txt"]
65
+ },
66
+ new ParentUpdate()
67
+ {
68
+ DependencyName = "Package.C",
69
+ NewVersion = NuGetVersion.Parse("3.0.0"),
70
+ UpdatedFiles = ["c.txt"],
71
+ ParentDependencyName = "Package.D",
72
+ ParentNewVersion = NuGetVersion.Parse("4.0.0"),
73
+ }
74
+ ]
75
+ };
76
+ var actualJson = UpdaterWorker.Serialize(result).Replace("\r", "");
77
+ var expectedJson = """
78
+ {
79
+ "UpdateOperations": [
80
+ {
81
+ "Type": "DirectUpdate",
82
+ "DependencyName": "Package.A",
83
+ "NewVersion": "1.0.0",
84
+ "UpdatedFiles": [
85
+ "a.txt"
86
+ ]
87
+ },
88
+ {
89
+ "Type": "PinnedUpdate",
90
+ "DependencyName": "Package.B",
91
+ "NewVersion": "2.0.0",
92
+ "UpdatedFiles": [
93
+ "b.txt"
94
+ ]
95
+ },
96
+ {
97
+ "Type": "ParentUpdate",
98
+ "ParentDependencyName": "Package.D",
99
+ "ParentNewVersion": "4.0.0",
100
+ "DependencyName": "Package.C",
101
+ "NewVersion": "3.0.0",
102
+ "UpdatedFiles": [
103
+ "c.txt"
104
+ ]
105
+ }
106
+ ],
107
+ "Error": null
108
+ }
109
+ """.Replace("\r", "");
110
+ Assert.Equal(expectedJson, actualJson);
111
+ }
112
+
47
113
  [Fact]
48
114
  public async Task ForPackagesProject_UpdatePackageReference_InBuildProps()
49
115
  {