public async Task Counts_Conflict()
    {
        var model = CreateDefaultSettingModel();

        await model.LoadFileElements();

        var fileElementVMs = new FileElementsGridViewModel(model);
        await Task.Delay(10);

        fileElementVMs.IsAnyFiles.Value
        .Should().BeTrue("ファイル読込後なので、ファイルはあるはず");

        ListCollectionView cViewFileElementVMs = (ListCollectionView)fileElementVMs.CViewFileElementVMs;

        //ステージ 衝突する置換後
        const string conflictText = "A";

        model.Setting.ReplaceTexts.Add(new("B", conflictText));
        model.Setting.ReplaceTexts.Add(new("C", conflictText));

        await model.Replace();

        await model.WaitIdleUI().Timeout(3000);

        await fileElementVMs.CountReplaced
        .WaitShouldBe(2, 3000d, "B→A・C→Aの2つの置換する設定があるので");

        await fileElementVMs.CountConflicted
        .WaitShouldBe(3, 3000d, "元々A・B→A・C→Aの3つが衝突するので");

        fileElementVMs.IsReplacedAny.Value
        .Should().BeTrue("置換する設定があるので");
        fileElementVMs.IsNotConflictedAny.Value
        .Should().BeFalse("衝突するので");

        foreach (FileElementViewModel vm in cViewFileElementVMs)
        {
            (vm.PathModel.OutputFileName.Contains(conflictText) == vm.IsConflicted.Value)
            .Should().BeTrue("Aを含んだファイル名は衝突しているはず");
        }

        //ステージ 衝突ファイルのみ表示にした後
        fileElementVMs.IsVisibleConflictedOnly.Value = true;

        await cViewFileElementVMs.ObserveProperty(x => x.Count)
        .WaitShouldBe(3, 3000d, "元々A・B→A・C→Aの3つのファイルにフィルタ後は絞られたはず");

        //ステージ 衝突&置換ファイルのみ表示にした後
        fileElementVMs.IsVisibleReplacedOnly.Value = true;

        await cViewFileElementVMs.ObserveProperty(x => x.Count)
        .WaitShouldBe(2, 3000d, "B→A・C→Aの2つのファイルにフィルタ後は絞られたはず");

        //ステージ すべてのファイル表示にした後
        fileElementVMs.IsVisibleConflictedOnly.Value = false;
        fileElementVMs.IsVisibleReplacedOnly.Value   = false;

        await cViewFileElementVMs.ObserveProperty(x => x.Count)
        .WaitShouldBe(6, 3000d, "フィルタ削除後はすべてのファイルがあるはず");
    }
    public async Task AddTargetFiles_RemoveFile()
    {
        MockFileSystem fileSystem    = CreateMockFileSystem();
        var            syncScheduler = new SynchronizationContextScheduler(SynchronizationContext.Current !);

        var model = new MainModel(fileSystem, syncScheduler);

        model.Initialize();

        var fileElementVMs = new FileElementsGridViewModel(model);

        await model.WaitIdleUI().Timeout(3000);

        //ステージ ファイル追加後
        fileElementVMs.AddTargetFilesCommand.Execute(new[] { filePathA, filePathG });
        await model.WaitIdleUI().Timeout(3000);

        await Task.Delay(100);

        fileElementVMs.IsAnyFiles.Value
        .Should().BeTrue("ファイル読込後なので、ファイルはあるはず");

        //なぜかReactiveCollectionをつかったテストは複数のテストをまとめて実行するとエラーする
        //var cViewFileElementVMs = (ListCollectionView)fileElementVMs.CViewFileElementVMs;
        //await cViewFileElementVMs.ObserveProperty(x => x.Count)
        //    .WaitShouldBe(1, 3000d, "ファイル読込後なので、ファイルはあるはず");

        model.FileElementModels
        .Should().HaveCount(2, "ファイル読込後なので、ファイルはあるはず");
        fileElementVMs.fileElementVMs
        .Should().HaveCount(2, "ファイル読込後なので、ファイルはあるはず");
        fileElementVMs.CountFiles.Value
        .Should().Be(2, "ファイル読込後なので、ファイルはあるはず");

        await Task.Delay(100);

        //ステージ ファイル削除後
        var removedVM = fileElementVMs.fileElementVMs
                        .First(x => x.PathModel.InputFilePath == filePathA);

        fileElementVMs.RemoveItemCommand.Execute(removedVM);
        await Task.Delay(100);

        model.FileElementModels.Count
        .Should().Be(1, "ファイル削除後なので、ファイルは減ったはず");

        await Task.Delay(100);

        //ステージ ファイルクリア後
        fileElementVMs.ClearFileElementsCommand.Execute();
        await Task.Delay(100);

        model.FileElementModels.Count
        .Should().Be(0, "ファイルはなくなったはず");
    }
    public async Task Counts_NotConflict()
    {
        var model = CreateDefaultSettingModel();

        await model.LoadFileElements();

        var fileElementVMs = new FileElementsGridViewModel(model);

        var cViewFileElementVMs = (ListCollectionView)fileElementVMs.CViewFileElementVMs;

        model.Setting.ReplaceTexts.Add(new("B", "BBB"));
        model.Setting.ReplaceTexts.Add(new("C", "CCC"));

        //ステージ 衝突はしない置換後
        await model.Replace();

        await model.WaitIdleUI().Timeout(3000);

        await fileElementVMs.CountReplaced
        .WaitShouldBe(2, 3000d, "B→BBB・C→CCCの置換する設定があるので");

        await fileElementVMs.CountConflicted
        .WaitShouldBe(0, 3000d, "衝突はしないので");

        fileElementVMs.IsReplacedAny.Value
        .Should().BeTrue("置換する設定があるので");
        fileElementVMs.IsNotConflictedAny.Value
        .Should().BeTrue("衝突はしないので");

        //ステージ 置換ファイルのみ表示にした後
        fileElementVMs.IsVisibleReplacedOnly.Value = true;

        await cViewFileElementVMs.ObserveProperty(x => x.Count)
        .WaitShouldBe(2, 3000d, "フィルタ後は絞られたはず");

        //ステージ すべてのファイル表示にした後
        fileElementVMs.IsVisibleConflictedOnly.Value = false;
        fileElementVMs.IsVisibleReplacedOnly.Value   = false;

        await cViewFileElementVMs.ObserveProperty(x => x.Count)
        .WaitShouldBe(6, 3000d, "フィルタ削除後はすべてのファイルがあるはず");
    }
    public async Task Counts_NoFile()
    {
        ReactivePropertyScheduler.SetDefault(new ReactivePropertyWpfScheduler(Dispatcher.CurrentDispatcher));
        var model = CreateDefaultSettingModel();

        await model.LoadFileElements();

        var fileElementVMs = new FileElementsGridViewModel(model);

        //ステージ 置換前
        fileElementVMs.IsAnyFiles.Value
        .Should().BeTrue("ファイル読込後なので、ファイルはあるはず");

        var cViewFileElementVMs = (ListCollectionView)fileElementVMs.CViewFileElementVMs;

        cViewFileElementVMs.IsEmpty
        .Should().BeFalse("ファイル読込後なので、ファイルはあるはず");
        cViewFileElementVMs.Count
        .Should().Be(6, "ファイル読込後なので、ファイルはあるはず");

        fileElementVMs.CountReplaced.Value
        .Should().Be(0, "置換前はまだ0のはず");

        fileElementVMs.CountConflicted.Value
        .Should().Be(0, "置換前はまだ0のはず");

        //ステージ なにも置換しない置換後
        await model.Replace();

        await model.WaitIdleUI().Timeout(3000);

        fileElementVMs.CountReplaced.Value
        .Should().Be(0, "置換する設定がないので、0のはず");
        fileElementVMs.CountConflicted.Value
        .Should().Be(0, "置換する設定がないので、0のはず");

        fileElementVMs.IsReplacedAny.Value
        .Should().BeFalse("置換する設定がないので、0のはず");
        fileElementVMs.IsNotConflictedAny.Value
        .Should().BeTrue("置換する設定がないので、0のはず");
    }