public void parse_returns_an_appropriate_exercise_programs_instance(string input, string[] expectedProgramNames) { var result = ExercisePrograms.Parse( input, new AudioServiceMock(MockBehavior.Loose), new DelayServiceMock(MockBehavior.Loose), new SpeechServiceMock(MockBehavior.Loose)); Assert.NotNull(result); Assert.True(result.Programs.Select(x => x.Name).SequenceEqual(expectedProgramNames)); }
public ExerciseProgramsViewModel( IAudioService audioService, IDelayService delayService, IExerciseDocumentService exerciseDocumentService, ILoggerService loggerService, ISchedulerService schedulerService, ISpeechService speechService, IStateService stateService, IScreen hostScreen, ExerciseProgramViewModelFactory exerciseProgramViewModelFactory) { audioService.AssertNotNull(nameof(audioService)); delayService.AssertNotNull(nameof(delayService)); exerciseDocumentService.AssertNotNull(nameof(exerciseDocumentService)); loggerService.AssertNotNull(nameof(loggerService)); schedulerService.AssertNotNull(nameof(schedulerService)); speechService.AssertNotNull(nameof(speechService)); stateService.AssertNotNull(nameof(stateService)); hostScreen.AssertNotNull(nameof(hostScreen)); exerciseProgramViewModelFactory.AssertNotNull(nameof(exerciseProgramViewModelFactory)); this.exerciseDocumentService = exerciseDocumentService; this.stateService = stateService; this.logger = loggerService.GetLogger(this.GetType()); this.hostScreen = hostScreen; this.disposables = new CompositeDisposable(); var documentsFromCache = this .stateService .GetAsync <string>(exerciseProgramsCacheKey) .Where(x => x != null) .Select(x => new DocumentSourceWith <string>(DocumentSource.Cache, x)); var documentsFromService = this .exerciseDocumentService .ExerciseDocument .Where(x => x != null) .Select(x => new DocumentSourceWith <string>(DocumentSource.Service, x)); var documents = documentsFromCache .Catch((Exception ex) => Observable.Empty <DocumentSourceWith <string> >()) .Concat(documentsFromService) .Do(x => this.logger.Debug("Received document from {0}.", x.Source)) .Publish(); var safeDocuments = documents .Catch((Exception ex) => Observable.Empty <DocumentSourceWith <string> >()); var results = documents .ObserveOn(schedulerService.TaskPoolScheduler) .Select( x => { IResult <ExercisePrograms> parsedExercisePrograms; using (this.logger.Perf("Parsing exercise programs from {0}.", x.Source)) { parsedExercisePrograms = ExercisePrograms.TryParse(x.Item, audioService, delayService, loggerService, speechService); } return(new DocumentSourceWith <IResult <ExercisePrograms> >(x.Source, parsedExercisePrograms)); }) .Publish(); var safeResults = results .Catch((Exception ex) => Observable.Empty <DocumentSourceWith <IResult <ExercisePrograms> > >()); safeResults .Select(x => x.Item.WasSuccessful ? null : x.Item.ToString()) .ObserveOn(schedulerService.MainScheduler) .Subscribe(x => this.ParseErrorMessage = x) .AddTo(this.disposables); results .Select(x => !x.Item.WasSuccessful ? ExerciseProgramsViewModelStatus.ParseFailed : x.Source == DocumentSource.Cache ? ExerciseProgramsViewModelStatus.LoadedFromCache : ExerciseProgramsViewModelStatus.LoadedFromService) .Catch((Exception ex) => Observable.Return(ExerciseProgramsViewModelStatus.LoadFailed)) .ObserveOn(schedulerService.MainScheduler) .Subscribe(x => this.Status = x) .AddTo(this.disposables); safeResults .Select(x => x.Item.WasSuccessful ? x.Item.Value : null) .ObserveOn(schedulerService.MainScheduler) .Subscribe(x => this.Model = x) .AddTo(this.disposables); this.WhenAnyValue(x => x.Model) .Select(x => x == null ? null : x.Programs.CreateDerivedCollection(y => exerciseProgramViewModelFactory(y))) .ObserveOn(schedulerService.MainScheduler) .Subscribe(x => this.Programs = x) .AddTo(this.disposables); safeDocuments .Where(x => x.Source == DocumentSource.Service) .SelectMany(x => this.stateService.SetAsync(exerciseProgramsCacheKey, x.Item)) .Subscribe() .AddTo(this.disposables); results .Connect() .AddTo(this.disposables); documents .Connect() .AddTo(this.disposables); this .WhenAnyValue(x => x.SelectedProgram) .Where(x => x != null) .Subscribe(x => this.hostScreen.Router.Navigate.Execute(x)) .AddTo(this.disposables); this .hostScreen .Router .CurrentViewModel .OfType <ExerciseProgramsViewModel>() .Subscribe(x => x.SelectedProgram = null) .AddTo(this.disposables); }
public void parse_throws_if_speech_service_is_null() { Assert.Throws <ArgumentNullException>(() => ExercisePrograms.Parse("input", new AudioServiceMock(), new DelayServiceMock(), new LoggerServiceMock(), null)); }
public void try_parse_throws_if_input_is_null() { Assert.Throws <ArgumentNullException>(() => ExercisePrograms.TryParse(null, new AudioServiceMock(), new DelayServiceMock(), new LoggerServiceMock(), new SpeechServiceMock())); }
public ExerciseProgramsViewModel( IAudioService audioService, IDelayService delayService, IExerciseDocumentService exerciseDocumentService, IScheduler mainScheduler, IScheduler backgroundScheduler, ISpeechService speechService, IStateService stateService, IScreen hostScreen, ExerciseProgramViewModelFactory exerciseProgramViewModelFactory) { Ensure.ArgumentNotNull(audioService, nameof(audioService)); Ensure.ArgumentNotNull(delayService, nameof(delayService)); Ensure.ArgumentNotNull(exerciseDocumentService, nameof(exerciseDocumentService)); Ensure.ArgumentNotNull(mainScheduler, nameof(mainScheduler)); Ensure.ArgumentNotNull(backgroundScheduler, nameof(backgroundScheduler)); Ensure.ArgumentNotNull(speechService, nameof(speechService)); Ensure.ArgumentNotNull(stateService, nameof(stateService)); Ensure.ArgumentNotNull(hostScreen, nameof(hostScreen)); Ensure.ArgumentNotNull(exerciseProgramViewModelFactory, nameof(exerciseProgramViewModelFactory)); this.logger = LoggerService.GetLogger(this.GetType()); using (this.logger.Perf("Construction")) { this.activator = new ViewModelActivator(); this.exerciseDocumentService = exerciseDocumentService; this.stateService = stateService; this.hostScreen = hostScreen; this .WhenAnyValue(x => x.SelectedProgram) .Where(x => x != null) .SelectMany(x => this.hostScreen.Router.Navigate.Execute(x)) .SubscribeSafe(); var isActivated = this .GetIsActivated() .Publish() .RefCount(); var documentsFromCache = this .stateService .Get <string>(exerciseProgramsCacheKey) .Where(x => x != null) .Select(x => new DocumentSourceWith <string>(DocumentSource.Cache, x)); var documentsFromService = this .exerciseDocumentService .ExerciseDocument .Where(x => x != null) .Select(x => new DocumentSourceWith <string>(DocumentSource.Service, x)); var documents = isActivated .Select( activated => { if (activated) { return(documentsFromCache .Catch((Exception ex) => Observable <DocumentSourceWith <string> > .Empty) .Concat(documentsFromService) .Do(x => this.logger.Debug("Received document from {0}.", x.Source))); } else { return(Observable <DocumentSourceWith <string> > .Empty); } }) .Switch() .Publish(); var results = documents .ObserveOn(backgroundScheduler) .Select( x => { IResult <ExercisePrograms> parsedExercisePrograms; using (this.logger.Perf("Parsing exercise programs from {0}.", x.Source)) { parsedExercisePrograms = ExercisePrograms.TryParse(x.Item, audioService, delayService, speechService); } return(new DocumentSourceWith <IResult <ExercisePrograms> >(x.Source, parsedExercisePrograms)); }) .Publish(); var safeResults = results .Catch((Exception ex) => Observable <DocumentSourceWith <IResult <ExercisePrograms> > > .Empty); this.parseErrorMessage = safeResults .Select(x => x.Item.WasSuccessful ? null : x.Item.ToString()) .ToProperty(this, x => x.ParseErrorMessage, scheduler: mainScheduler); this.status = results .Select(x => !x.Item.WasSuccessful ? ExerciseProgramsViewModelStatus.ParseFailed : x.Source == DocumentSource.Cache ? ExerciseProgramsViewModelStatus.LoadedFromCache : ExerciseProgramsViewModelStatus.LoadedFromService) .Catch((Exception ex) => Observable.Return(ExerciseProgramsViewModelStatus.LoadFailed)) .ObserveOn(mainScheduler) .ToProperty(this, x => x.Status); this.model = safeResults .Select(x => x.Item.WasSuccessful ? x.Item.Value : null) .ToProperty(this, x => x.Model, scheduler: mainScheduler); this.programs = this .WhenAnyValue(x => x.Model) .Select(x => x == null ? null : x.Programs.Select(program => exerciseProgramViewModelFactory(program)).ToImmutableList()) .ObserveOn(mainScheduler) .ToProperty(this, x => x.Programs); var safeDocuments = documents .Catch((Exception ex) => Observable <DocumentSourceWith <string> > .Empty); safeDocuments .Where(x => x.Source == DocumentSource.Service) .SelectMany(x => this.stateService.Set(exerciseProgramsCacheKey, x.Item)) .SubscribeSafe(); results .Connect(); documents .Connect(); this .WhenActivated( disposables => { using (this.logger.Perf("Activation")) { this .hostScreen .Router .CurrentViewModel .OfType <ExerciseProgramsViewModel>() .SubscribeSafe(x => x.SelectedProgram = null) .AddTo(disposables); } }); } }