public async Task IncludesProjecCreationWhenFilterTextMatchesASuggestion()
            {
                var workspaceId = 0;

                setupWorkspace(workspaceId, isEligibleForProjectCreation: true);
                var projectSuggestions    = getProjectSuggestions(10, workspaceId: 1);
                var suggestionsObservable = Observable.Return(projectSuggestions);
                var filterText            = projectSuggestions.First().ProjectName;

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(suggestionsObservable);
                var observer = TestScheduler.CreateObserver <IEnumerable <SectionModel <string, AutocompleteSuggestion> > >();

                ViewModel.Suggestions.Subscribe(observer);

                await ViewModel.Initialize();

                ViewModel.FilterText.OnNext(filterText);
                TestScheduler.Start();

                var latestSuggestions = observer.Messages.Last().Value.Value;

                latestSuggestions.Should().HaveCount(2);
                latestSuggestions.First().Header.Should().BeNull();
                latestSuggestions.First().Items.Should().HaveCount(1);
                var createEntitySuggestion = (CreateEntitySuggestion)latestSuggestions.First().Items.First();

                createEntitySuggestion.EntityName.Should().Be(filterText);
            }
            public async Task DoesNotContainASelectedProjectIfProjectIdIsNull()
            {
                var suggestions           = getProjectSuggestions(20, workspaceId: 10);
                var suggestionsObservable = Observable.Return(suggestions);

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(suggestionsObservable);
                var parameter = new SelectProjectParameter(null, null, 0);
                var observer  = TestScheduler.CreateObserver <IEnumerable <SectionModel <string, AutocompleteSuggestion> > >();

                ViewModel.Suggestions.Subscribe(observer);

                await ViewModel.Initialize(parameter);

                TestScheduler.Start();

                var latestSugestions = observer.Messages.Last().Value.Value;

                latestSugestions.Should().HaveCount(1);
                latestSugestions.First().Items
                .Cast <ProjectSuggestion>()
                .Should().OnlyContain(suggestion => !suggestion.Selected);
            }
            public async Task DoesNotPrependEmptyProjectToGroupsIfFilterIsUsed()
            {
                var suggestions = new List <ProjectSuggestion>();

                suggestions.AddRange(getProjectSuggestions(3, workspaceId: 0));
                suggestions.AddRange(getProjectSuggestions(4, workspaceId: 1));
                suggestions.AddRange(getProjectSuggestions(1, workspaceId: 10));
                suggestions.AddRange(getProjectSuggestions(10, workspaceId: 54));
                var suggestionsObservable = Observable.Return(suggestions);

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(suggestionsObservable);
                var observer = TestScheduler.CreateObserver <IEnumerable <SectionModel <string, AutocompleteSuggestion> > >();

                ViewModel.Suggestions.Subscribe(observer);

                await ViewModel.Initialize();

                ViewModel.FilterText.OnNext(suggestions.First().ProjectName);
                TestScheduler.Start();

                foreach (var section in observer.Messages.Last().Value.Value)
                {
                    section.Items.Cast <ProjectSuggestion>().First().ProjectName.Should().NotBe(Resources.NoProject);
                }
            }
            public async Task ContainsOnlyOneSelectedProjectIfProjectIdIsSet()
            {
                var suggestions           = getProjectSuggestions(20, workspaceId: 10);
                var suggestionsObservable = Observable.Return(suggestions);

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(suggestionsObservable);
                long selectedProjectId = 5;
                var  parameter         = SelectProjectParameter.WithIds(selectedProjectId, null, 0);
                var  observer          = TestScheduler.CreateObserver <IEnumerable <SectionModel <string, AutocompleteSuggestion> > >();

                ViewModel.Suggestions.Subscribe(observer);

                ViewModel.Prepare(parameter);
                await ViewModel.Initialize();

                TestScheduler.Start();

                var latestSuggestions = observer.Messages.Last().Value.Value;

                latestSuggestions.Should().HaveCount(1);
                latestSuggestions.First().Items.Should()
                .OnlyContain(suggestion => assertSuggestion(suggestion, selectedProjectId));
            }
            public async Task DoesNotIncludeProjectCreationRowWhenTheTextIsLongerThanTwoHundredAndFiftyCharacters()
            {
                var workspaceId = 0;

                setupWorkspace(workspaceId, isEligibleForProjectCreation: true);
                var projectSuggestions    = getProjectSuggestions(10, workspaceId: 0);
                var suggestionsObservable = Observable.Return(projectSuggestions);

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(suggestionsObservable);
                var observer = TestScheduler.CreateObserver <IEnumerable <SectionModel <string, AutocompleteSuggestion> > >();

                ViewModel.Suggestions.Subscribe(observer);

                await ViewModel.Initialize();

                ViewModel.FilterText.OnNext("Some absurdly long project name created solely for making sure that the SuggestCreation property returns false when the project name is longer than the previously specified threshold so that the mobile apps behave and avoid crashes in backend and even bigger problems.");
                TestScheduler.Start();

                var latestSuggestions = observer.Messages.Last().Value.Value;

                latestSuggestions.Should().HaveCount(1);
            }
            public async Task GroupsProjectsByWorkspace()
            {
                var suggestions  = new List <ProjectSuggestion>();
                var workspaceIds = new[] { 0, 1, 10, 54 };

                suggestions.AddRange(getProjectSuggestions(3, workspaceIds[0]));
                suggestions.AddRange(getProjectSuggestions(4, workspaceIds[1]));
                suggestions.AddRange(getProjectSuggestions(1, workspaceIds[2]));
                suggestions.AddRange(getProjectSuggestions(10, workspaceIds[3]));
                var suggestionsObservable = Observable.Return(suggestions);

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(suggestionsObservable);

                await ViewModel.Initialize();

                TestScheduler.Start();

                ViewModel.Suggestions.Should().HaveCount(4);
                foreach (var suggestionGroup in ViewModel.Suggestions)
                {
                    foreach (var suggestion in suggestionGroup.Cast <ProjectSuggestion>())
                    {
                        if (suggestion.ProjectName == Resources.NoProject)
                        {
                            continue;
                        }
                        suggestion.WorkspaceName.Should().Be(suggestionGroup.WorkspaceName);
                        suggestion.WorkspaceId.Should().Be(suggestionGroup.WorkspaceId);
                    }
                }
            }
            public async Task SortsTasksByName()
            {
                var suggestions = new List <ProjectSuggestion>();

                suggestions.Add(getProjectSuggestion(3, 0, new[]
                {
                    new MockTask {
                        Id = 2, WorkspaceId = 0, ProjectId = 3, Name = "Task2"
                    },
                    new MockTask {
                        Id = 1, WorkspaceId = 0, ProjectId = 3, Name = "Task1"
                    },
                    new MockTask {
                        Id = 3, WorkspaceId = 0, ProjectId = 3, Name = "Task3"
                    }
                }));
                var suggestionsObservable = Observable.Return(suggestions);

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(suggestionsObservable);

                await ViewModel.Initialize();

                TestScheduler.Start();

                ViewModel.ToggleTaskSuggestionsCommand.Execute((ProjectSuggestion)ViewModel.Suggestions[0][1]);

                ViewModel.Suggestions.Should().HaveCount(1);
                ViewModel.Suggestions[0].Should().HaveCount(5);
                tasksNames(ViewModel.Suggestions[0].Skip(2)).Should().BeInAscendingOrder();
            }
            public async Task DoesNotIncludeProjectCreationRowWhenNoWorkspaceIsEligible()
            {
                var workspaceId = 0;

                setupWorkspace(workspaceId, false);
                var projectSuggestions    = getProjectSuggestions(10, workspaceId: 1);
                var suggestionsObservable = Observable.Return(projectSuggestions);

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(suggestionsObservable);
                var observer = TestScheduler.CreateObserver <IEnumerable <SectionModel <string, AutocompleteSuggestion> > >();

                ViewModel.Suggestions.Subscribe(observer);

                await ViewModel.Initialize();

                ViewModel.FilterText.OnNext("This filter text should result in project creation");
                TestScheduler.Start();

                var latestSuggestions = observer.Messages.Last().Value.Value;

                latestSuggestions.Should().HaveCount(1);
            }
            public async Task SortsProjectsByName()
            {
                var suggestions = new List <ProjectSuggestion>();

                suggestions.Add(getProjectSuggestion(3, 0));
                suggestions.Add(getProjectSuggestion(4, 1));
                suggestions.Add(getProjectSuggestion(1, 0));
                suggestions.Add(getProjectSuggestion(33, 1));
                suggestions.Add(getProjectSuggestion(10, 1));
                var suggestionsObservable = Observable.Return(suggestions);

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(suggestionsObservable);

                await ViewModel.Initialize();

                ViewModel.Suggestions.Should().HaveCount(2);
                foreach (var suggestionGroup in ViewModel.Suggestions)
                {
                    string prevProjectName = "";
                    foreach (var suggestion in suggestionGroup.Cast <ProjectSuggestion>())
                    {
                        if (suggestion.ProjectName == Resources.NoProject)
                        {
                            continue;
                        }
                        bool correctOrder = string.Compare(prevProjectName, suggestion.ProjectName, true) < 0;
                        correctOrder.Should().BeTrue();
                        prevProjectName = suggestion.ProjectName;
                    }
                }
            }
            public async Task SortsProjectsByName()
            {
                var suggestions = new List <ProjectSuggestion>();

                suggestions.Add(getProjectSuggestion(3, 0));
                suggestions.Add(getProjectSuggestion(4, 1));
                suggestions.Add(getProjectSuggestion(1, 0));
                suggestions.Add(getProjectSuggestion(33, 1));
                suggestions.Add(getProjectSuggestion(10, 1));
                var suggestionsObservable = Observable.Return(suggestions);

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(suggestionsObservable);
                var observer = TestScheduler.CreateObserver <IEnumerable <SectionModel <string, AutocompleteSuggestion> > >();

                ViewModel.Suggestions.Subscribe(observer);

                await ViewModel.Initialize();

                TestScheduler.Start();

                var latestSuggestions = observer.Messages.Last().Value.Value;

                latestSuggestions.Should().HaveCount(2);
                foreach (var section in latestSuggestions)
                {
                    section.Items
                    .Cast <ProjectSuggestion>()
                    .Should()
                    .BeInAscendingOrder(projectSuggestion => projectSuggestion.ProjectName);
                }
            }
            public async Task IsPopulatedAfterInitialization()
            {
                var projectSuggestions    = getProjectSuggestions(10, 0);
                var suggestionsObservable = Observable.Return(projectSuggestions);

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(suggestionsObservable);

                await ViewModel.Initialize();

                ViewModel.Suggestions.Should().HaveCount(1);
                ViewModel.Suggestions.First().Should().HaveCount(11);
            }
            public TheSuggestCreationProperty()
            {
                var project = Substitute.For <IThreadSafeProject>();

                project.Name.Returns(name);
                var suggestion = new ProjectSuggestion(project);

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(Observable.Return(new List <ProjectSuggestion> {
                    suggestion
                }));

                ViewModel.Prepare();
            }
            private void prepareProjects()
            {
                var projects = Enumerable.Range(0, 30)
                               .Select(i =>
                {
                    var project = Substitute.For <IThreadSafeProject>();
                    project.Id.Returns(i);
                    project.Workspace.Name.Returns("Ws");
                    return(new ProjectSuggestion(project));
                });

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(Observable.Return(projects));
            }
            public async Task IsClearedWhenTextIsChanged()
            {
                var suggestions = getProjectSuggestions(1, 1);
                var queryText   = "Query text";

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(Observable.Return(suggestions));
                await ViewModel.Initialize();

                ViewModel.Text = queryText;

                ViewModel.Suggestions.Should().HaveCount(1);
                ViewModel.Suggestions.First().Should().HaveCount(1);
            }
            public async Task SortsTasksByName()
            {
                var suggestions = new List <ProjectSuggestion>
                {
                    getProjectSuggestion(3, 0, new[]
                    {
                        new MockTask {
                            Id = 1, WorkspaceId = 0, ProjectId = 3, Name = "Task1"
                        },
                        new MockTask {
                            Id = 2, WorkspaceId = 0, ProjectId = 3, Name = "Task2"
                        },
                        new MockTask {
                            Id = 3, WorkspaceId = 0, ProjectId = 3, Name = "Task3"
                        }
                    })
                };

                InteractorFactory.GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >()).Execute()
                .Returns(Observable.Return(suggestions));
                var observer = TestScheduler.CreateObserver <IEnumerable <SectionModel <string, AutocompleteSuggestion> > >();

                ViewModel.Suggestions.Subscribe(observer);

                await ViewModel.Initialize();

                TestScheduler.Start();

                ViewModel.ToggleTaskSuggestions.Execute(suggestions[0]);
                TestScheduler.Start();

                var latestSuggestions = observer.LastEmittedValue();

                latestSuggestions.Should().HaveCount(1);
                latestSuggestions.First().Items.Should().HaveCount(5);
                latestSuggestions.First().Items
                .Where(suggestion => suggestion is TaskSuggestion)
                .Cast <TaskSuggestion>()
                .Should()
                .BeInAscendingOrder(taskSuggestion => taskSuggestion.Name);
            }
            public async Task IsPopulatedAfterInitialization()
            {
                var workspaceId           = 0;
                var projectSuggestions    = getProjectSuggestions(10, workspaceId);
                var suggestionsObservable = Observable.Return(projectSuggestions);

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(suggestionsObservable);
                var observer = TestScheduler.CreateObserver <IEnumerable <SectionModel <string, AutocompleteSuggestion> > >();

                ViewModel.Suggestions.Subscribe(observer);

                await ViewModel.Initialize();

                TestScheduler.Start();

                observer.Messages.Should().HaveCount(2);
                observer.Messages[1].Value.Value.Should().HaveCount(1);
                observer.Messages[1].Value.Value.First().Items.Should().HaveCount(11);
            }
            public async Task PrependsEmptyProjectToEveryGroupIfFilterIsEmpty()
            {
                var suggestions = new List <ProjectSuggestion>();

                suggestions.AddRange(getProjectSuggestions(3, 0));
                suggestions.AddRange(getProjectSuggestions(4, 1));
                suggestions.AddRange(getProjectSuggestions(1, 10));
                suggestions.AddRange(getProjectSuggestions(10, 54));
                var suggestionsObservable = Observable.Return(suggestions);

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(suggestionsObservable);

                await ViewModel.Initialize();

                foreach (var group in ViewModel.Suggestions)
                {
                    group.Cast <ProjectSuggestion>().First().ProjectName.Should().Be(Resources.NoProject);
                }
            }
            public async Task DoesNotIncludeProjectCreationRowWhenTheTextIsEmpty()
            {
                var workspaceId = 0;

                setupWorkspace(workspaceId, isEligibleForProjectCreation: true);
                var projectSuggestions    = getProjectSuggestions(10, workspaceId: workspaceId);
                var suggestionsObservable = Observable.Return(projectSuggestions);

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(suggestionsObservable);
                var observer = TestScheduler.CreateObserver <IEnumerable <SectionModel <string, AutocompleteSuggestion> > >();

                ViewModel.Suggestions.Subscribe(observer);

                await ViewModel.Initialize(DefaultParameter);

                TestScheduler.Start();

                var latestSuggestions = observer.Messages.Last().Value.Value;

                latestSuggestions.Should().HaveCount(1);
            }
            public async Task GroupsProjectsByWorkspace()
            {
                var suggestions  = new List <ProjectSuggestion>();
                var workspaceIds = new[] { 0, 1, 10, 54 };

                suggestions.AddRange(getProjectSuggestions(3, workspaceId: workspaceIds[0]));
                suggestions.AddRange(getProjectSuggestions(4, workspaceId: workspaceIds[1]));
                suggestions.AddRange(getProjectSuggestions(1, workspaceId: workspaceIds[2]));
                suggestions.AddRange(getProjectSuggestions(10, workspaceId: workspaceIds[3]));
                var suggestionsObservable = Observable.Return(suggestions);

                InteractorFactory
                .GetProjectsAutocompleteSuggestions(Arg.Any <IList <string> >())
                .Execute()
                .Returns(suggestionsObservable);
                var observer = TestScheduler.CreateObserver <IEnumerable <SectionModel <string, AutocompleteSuggestion> > >();

                ViewModel.Suggestions.Subscribe(observer);

                await ViewModel.Initialize();

                TestScheduler.Start();

                var latestSuggestions = observer.Messages.Last().Value.Value.ToArray();

                latestSuggestions.Should().HaveCount(4);

                for (int i = 0; i < latestSuggestions.Length; i++)
                {
                    foreach (var suggestion in latestSuggestions[i].Items)
                    {
                        suggestion.WorkspaceName.Should().Be(latestSuggestions[i].Header);
                        suggestion.WorkspaceId.Should().Be(workspaceIds[i]);
                    }
                }
            }