Skip to content

Commit 41ab2cd

Browse files
committed
test: improve tests
1 parent 4af36da commit 41ab2cd

File tree

1 file changed

+35
-28
lines changed

1 file changed

+35
-28
lines changed

tests/ByteSync.Client.Tests/ViewModels/Sessions/Comparisons/Actions/TargetedActionGlobalViewModelTests.cs

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
using System.Reactive;
12
using System.Reactive.Linq;
23
using System.Reactive.Subjects;
4+
using System.Reflection;
35
using ByteSync.Business;
46
using ByteSync.Business.Actions.Local;
57
using ByteSync.Business.Comparisons;
@@ -10,6 +12,7 @@
1012
using ByteSync.Interfaces.Factories.ViewModels;
1113
using ByteSync.Interfaces.Services.Localizations;
1214
using ByteSync.Models.Comparisons.Result;
15+
using ByteSync.Tests.Helpers;
1316
using ByteSync.TestsCommon;
1417
using ByteSync.ViewModels.Sessions.Comparisons.Actions;
1518
using FluentAssertions;
@@ -48,7 +51,7 @@ public void SetUp()
4851
.Returns("The action cannot be applied to some items:");
4952
_mockLocalizationService.Setup(x => x["TargetedActionEditionGlobal_AffectedItemsTooltip"])
5053
.Returns("Affected items:");
51-
54+
5255
_mockFailureReasonService.Setup(x => x.GetLocalizedMessage(It.IsAny<AtomicActionValidationFailureReason>()))
5356
.Returns("Test failure message");
5457

@@ -71,6 +74,7 @@ private ComparisonItem CreateMockComparisonItem(FileSystemTypes fileSystemType)
7174
// Create a real ComparisonItem instance since it cannot be mocked (no parameterless constructor)
7275
var pathIdentity = new PathIdentity(fileSystemType, "test-file", "test-file", "test-file");
7376
var comparisonItem = new ComparisonItem(pathIdentity);
77+
7478
return comparisonItem;
7579
}
7680

@@ -93,7 +97,7 @@ public void Constructor_ShouldInitializeProperties()
9397
viewModel.ComparisonItems.Should().HaveCount(2);
9498
viewModel.FailureSummaries.Should().NotBeNull();
9599
viewModel.FailureSummaries.Should().BeEmpty();
96-
100+
97101
viewModel.AddActionCommand.Should().NotBeNull();
98102
viewModel.SaveCommand.Should().NotBeNull();
99103
viewModel.ResetCommand.Should().NotBeNull();
@@ -102,7 +106,7 @@ public void Constructor_ShouldInitializeProperties()
102106

103107
viewModel.ActionIssuesHeaderMessage.Should().Be("The action cannot be applied to some items:");
104108
viewModel.AffectedItemsTooltipHeader.Should().Be("Affected items:");
105-
109+
106110
viewModel.ShowWarning.Should().BeFalse();
107111
viewModel.AreMissingFields.Should().BeFalse();
108112
viewModel.IsInconsistentWithValidItems.Should().BeNull();
@@ -124,7 +128,7 @@ public void AddAction_ShouldCallActionEditViewModelFactory()
124128
);
125129

126130
// Act
127-
viewModel.AddActionCommand.Execute(System.Reactive.Unit.Default).Subscribe();
131+
viewModel.AddActionCommand.Execute(Unit.Default).Subscribe();
128132

129133
// Assert
130134
// The constructor calls the factory once during initialization, and AddActionCommand calls it again
@@ -133,7 +137,7 @@ public void AddAction_ShouldCallActionEditViewModelFactory()
133137
}
134138

135139
[Test]
136-
public async Task OnLocaleChanged_ShouldUpdateLocalizedMessages()
140+
public void OnLocaleChanged_ShouldUpdateLocalizedMessages()
137141
{
138142
// Arrange
139143
var viewModel = new TargetedActionGlobalViewModel(
@@ -157,13 +161,10 @@ public async Task OnLocaleChanged_ShouldUpdateLocalizedMessages()
157161

158162
// Act
159163
_cultureSubject.OnNext(new CultureDefinition { Code = "fr" });
160-
161-
// Allow time for the observable to process
162-
await Task.Delay(100);
163164

164165
// Assert
165-
viewModel.ActionIssuesHeaderMessage.Should().Be("Updated message");
166-
viewModel.AffectedItemsTooltipHeader.Should().Be("Updated tooltip");
166+
viewModel.ShouldEventuallyBe(vm => vm.ActionIssuesHeaderMessage, "Updated message");
167+
viewModel.ShouldEventuallyBe(vm => vm.AffectedItemsTooltipHeader, "Updated tooltip");
167168
}
168169

169170
[Test]
@@ -198,7 +199,7 @@ public async Task OnLocaleChanged_WithFailureSummaries_ShouldUpdateLocalizedMess
198199

199200
// Act
200201
_cultureSubject.OnNext(new CultureDefinition { Code = "fr" });
201-
202+
202203
// Allow time for the observable to process
203204
await Task.Delay(100);
204205

@@ -231,7 +232,7 @@ public void ResetWarning_ShouldClearAllWarningProperties()
231232

232233
// Use reflection or expose method for testing
233234
var resetWarningMethod = typeof(TargetedActionGlobalViewModel)
234-
.GetMethod("ResetWarning", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
235+
.GetMethod("ResetWarning", BindingFlags.NonPublic | BindingFlags.Instance);
235236

236237
// Act
237238
resetWarningMethod?.Invoke(viewModel, null);
@@ -243,7 +244,7 @@ public void ResetWarning_ShouldClearAllWarningProperties()
243244
viewModel.IsInconsistentWithNoValidItems.Should().BeFalse();
244245
}
245246

246-
[Test]
247+
[Test]
247248
public void ShowConsistencyWarning_WithValidAndInvalidItems_ShouldSetCorrectProperties()
248249
{
249250
// Arrange
@@ -260,11 +261,12 @@ public void ShowConsistencyWarning_WithValidAndInvalidItems_ShouldSetCorrectProp
260261
// Create real instance instead of mock
261262
var result = new AtomicActionConsistencyCheckCanAddResult(_comparisonItems);
262263
result.ValidationResults.Add(new ComparisonItemValidationResult(_comparisonItems[0], true)); // Valid
263-
result.ValidationResults.Add(new ComparisonItemValidationResult(_comparisonItems[1], AtomicActionValidationFailureReason.InvalidSourceCount)); // Invalid
264+
result.ValidationResults.Add(new ComparisonItemValidationResult(_comparisonItems[1],
265+
AtomicActionValidationFailureReason.InvalidSourceCount)); // Invalid
264266

265267
// Use reflection to access private method
266268
var showConsistencyWarningMethod = typeof(TargetedActionGlobalViewModel)
267-
.GetMethod("ShowConsistencyWarning", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
269+
.GetMethod("ShowConsistencyWarning", BindingFlags.NonPublic | BindingFlags.Instance);
268270

269271
// Act
270272
showConsistencyWarningMethod?.Invoke(viewModel, [result]);
@@ -300,12 +302,14 @@ public void ShowConsistencyWarning_WithNoValidItems_ShouldSetNoValidItemsFlag()
300302

301303
// Create real instance instead of mock - all items fail validation
302304
var result = new AtomicActionConsistencyCheckCanAddResult(_comparisonItems);
303-
result.ValidationResults.Add(new ComparisonItemValidationResult(_comparisonItems[0], AtomicActionValidationFailureReason.InvalidSourceCount)); // Invalid
304-
result.ValidationResults.Add(new ComparisonItemValidationResult(_comparisonItems[1], AtomicActionValidationFailureReason.InvalidSourceCount)); // Invalid
305+
result.ValidationResults.Add(new ComparisonItemValidationResult(_comparisonItems[0],
306+
AtomicActionValidationFailureReason.InvalidSourceCount)); // Invalid
307+
result.ValidationResults.Add(new ComparisonItemValidationResult(_comparisonItems[1],
308+
AtomicActionValidationFailureReason.InvalidSourceCount)); // Invalid
305309

306310
// Use reflection to access private method
307311
var showConsistencyWarningMethod = typeof(TargetedActionGlobalViewModel)
308-
.GetMethod("ShowConsistencyWarning", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
312+
.GetMethod("ShowConsistencyWarning", BindingFlags.NonPublic | BindingFlags.Instance);
309313

310314
// Act
311315
showConsistencyWarningMethod?.Invoke(viewModel, [result]);
@@ -334,27 +338,30 @@ public void ShowConsistencyWarning_WithMultipleFailureReasons_ShouldGroupByReaso
334338

335339
// Create real instance instead of mock with multiple failure reasons
336340
var result = new AtomicActionConsistencyCheckCanAddResult(_comparisonItems);
337-
result.ValidationResults.Add(new ComparisonItemValidationResult(_comparisonItems[0], AtomicActionValidationFailureReason.InvalidSourceCount)); // First InvalidSourceCount
338-
result.ValidationResults.Add(new ComparisonItemValidationResult(_comparisonItems[1], AtomicActionValidationFailureReason.CreateOperationOnFileNotAllowed)); // Different reason
339-
result.ValidationResults.Add(new ComparisonItemValidationResult(_comparisonItems[0], AtomicActionValidationFailureReason.InvalidSourceCount)); // Duplicate InvalidSourceCount
341+
result.ValidationResults.Add(new ComparisonItemValidationResult(_comparisonItems[0],
342+
AtomicActionValidationFailureReason.InvalidSourceCount)); // First InvalidSourceCount
343+
result.ValidationResults.Add(new ComparisonItemValidationResult(_comparisonItems[1],
344+
AtomicActionValidationFailureReason.CreateOperationOnFileNotAllowed)); // Different reason
345+
result.ValidationResults.Add(new ComparisonItemValidationResult(_comparisonItems[0],
346+
AtomicActionValidationFailureReason.InvalidSourceCount)); // Duplicate InvalidSourceCount
340347

341348
_mockFailureReasonService.Setup(x => x.GetLocalizedMessage(AtomicActionValidationFailureReason.CreateOperationOnFileNotAllowed))
342349
.Returns("Cannot create files");
343350

344351
// Use reflection to access private method
345352
var showConsistencyWarningMethod = typeof(TargetedActionGlobalViewModel)
346-
.GetMethod("ShowConsistencyWarning", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
353+
.GetMethod("ShowConsistencyWarning", BindingFlags.NonPublic | BindingFlags.Instance);
347354

348355
// Act
349356
showConsistencyWarningMethod?.Invoke(viewModel, [result]);
350357

351358
// Assert
352359
viewModel.FailureSummaries.Should().HaveCount(2);
353-
360+
354361
// Should be ordered by count (most frequent first)
355362
viewModel.FailureSummaries[0].Count.Should().Be(2); // InvalidSourceCount appears twice
356363
viewModel.FailureSummaries[0].Reason.Should().Be(AtomicActionValidationFailureReason.InvalidSourceCount);
357-
364+
358365
viewModel.FailureSummaries[1].Count.Should().Be(1); // CreateOperationOnFileNotAllowed appears once
359366
viewModel.FailureSummaries[1].Reason.Should().Be(AtomicActionValidationFailureReason.CreateOperationOnFileNotAllowed);
360367
viewModel.FailureSummaries[1].LocalizedMessage.Should().Be("Cannot create files");
@@ -384,7 +391,7 @@ public void ShowMissingFieldsWarning_ShouldClearFailureSummariesAndSetMissingFie
384391

385392
// Use reflection to access private method
386393
var showMissingFieldsWarningMethod = typeof(TargetedActionGlobalViewModel)
387-
.GetMethod("ShowMissingFieldsWarning", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
394+
.GetMethod("ShowMissingFieldsWarning", BindingFlags.NonPublic | BindingFlags.Instance);
388395

389396
// Act
390397
showMissingFieldsWarningMethod?.Invoke(viewModel, null);
@@ -411,7 +418,7 @@ public void Reset_ShouldCallActionEditViewModelFactory()
411418
);
412419

413420
// Act
414-
viewModel.ResetCommand.Execute(System.Reactive.Unit.Default).Subscribe();
421+
viewModel.ResetCommand.Execute(Unit.Default).Subscribe();
415422

416423
// Assert
417424
// Should call factory to create action edit view model (ResetToCreation behavior)
@@ -434,7 +441,7 @@ public void Cancel_ShouldCallActionEditViewModelFactory()
434441
);
435442

436443
// Act
437-
viewModel.CancelCommand.Execute(System.Reactive.Unit.Default).Subscribe();
444+
viewModel.CancelCommand.Execute(Unit.Default).Subscribe();
438445

439446
// Assert
440447
// Should call factory to create action edit view model (reset behavior)
@@ -519,4 +526,4 @@ public void ValidationFailureSummary_AffectedItemsTooltip_ShouldGenerateCorrectT
519526
// When FileName is null, it should use LinkingKeyValue
520527
tooltip.Should().Be("file1.txt\ndirectory1");
521528
}
522-
}
529+
}

0 commit comments

Comments
 (0)