public void Command_with_invalid_CommunicationChannel_fails(CommunicationChannel communicationChannel)
        {
            // Arrange
            var id                   = EnrollmentAggregate.EnrollmentId.New;
            var enrollment           = new EnrollmentAggregate(id);
            var training             = CreateTrainingInFutureWithId(1);
            var recordingCoordinator = new Models.Users.ApplicationUser()
            {
                Id = Guid.NewGuid()
            };
            var command = new RecordAcceptedTrainingInvitation.Command()
            {
                EnrollmentId         = id.GetGuid(),
                CommunicationChannel = communicationChannel,
                SelectedTrainingID   = 1,
                AdditionalNotes      = "brak notatek"
            };

            // Act
            var result = enrollment.RecordCandidateAcceptedTrainingInvitation(command, recordingCoordinator, new[] { training }, NodaTime.SystemClock.Instance.GetCurrentInstant());

            // Assert
            Assert.False(result.IsSuccess);
            var error   = Assert.IsType <Error.ValidationFailed>(result.Error);
            var failure = Assert.Single(error.Failures);

            Assert.Equal(nameof(command.CommunicationChannel), failure.PropertyName);
            Assert.Single(failure.Errors);
        }
        private async Task Initialize(IServiceProvider services)
        {
            var userManager = services.GetRequiredService <UserManager <Models.Users.ApplicationUser> >();

            var admin = new Models.Users.ApplicationUser {
                UserName = "******", Email = "*****@*****.**", EmailConfirmed = true
            };

            AssertSuccess(await userManager.CreateAsync(admin, "test"));
            AssertSuccess(await userManager.AddToRoleAsync(admin, AuthorizationRoles.Admin));

            var coordinator1 = new Models.Users.ApplicationUser {
                UserName = "******", Email = "*****@*****.**", EmailConfirmed = true
            };

            AssertSuccess(await userManager.CreateAsync(coordinator1, "test"));
            AssertSuccess(await userManager.AddToRoleAsync(coordinator1, AuthorizationRoles.RegionalCoordinator));

            var coordinator2 = new Models.Users.ApplicationUser {
                UserName = "******", Email = "*****@*****.**", EmailConfirmed = true
            };

            AssertSuccess(await userManager.CreateAsync(coordinator2, "test"));
            AssertSuccess(await userManager.AddToRoleAsync(coordinator2, AuthorizationRoles.RegionalCoordinator));

            var regularUser = new Models.Users.ApplicationUser {
                UserName = "******", Email = "*****@*****.**", EmailConfirmed = true
            };

            AssertSuccess(await userManager.CreateAsync(regularUser, "test"));
        }
        public void Candidate_must_be_registered_to_accept_training_invitation()
        {
            // Arrange
            var id                   = EnrollmentAggregate.EnrollmentId.New;
            var enrollment           = new EnrollmentAggregate(id);
            var training             = CreateTrainingInFutureWithId(1);
            var recordingCoordinator = new Models.Users.ApplicationUser()
            {
                Id = Guid.NewGuid()
            };
            var command = new RecordAcceptedTrainingInvitation.Command()
            {
                EnrollmentId         = id.GetGuid(),
                CommunicationChannel = CommunicationChannel.OutgoingEmail,
                SelectedTrainingID   = 1,
                AdditionalNotes      = "brak notatek"
            };

            // Act
            var result = enrollment.RecordCandidateAcceptedTrainingInvitation(command, recordingCoordinator, new[] { training }, NodaTime.SystemClock.Instance.GetCurrentInstant());

            // Assert
            Assert.True(result.IsFailure);
            var error = Assert.IsType <Error.ResourceNotFound>(result.Error);

            Assert.Equal(CommonErrorMessages.CandidateNotFound, error.Message);
        }
        public void Candidate_must_be_registered_to_decline_training_invitation()
        {
            // Arrange
            var id                   = EnrollmentAggregate.EnrollmentId.New;
            var enrollment           = new EnrollmentAggregate(id);
            var recordingCoordinator = new Models.Users.ApplicationUser()
            {
                Id = Guid.NewGuid()
            };
            var command = new RecordRefusedTrainingInvitation.Command()
            {
                EnrollmentId         = id.GetGuid(),
                CommunicationChannel = CommunicationChannel.OutgoingPersonalContact,
                RefusalReason        = "brak powodu",
                AdditionalNotes      = "brak notatek"
            };

            // Act
            var result = enrollment.RecordCandidateRefusedTrainingInvitation(
                command,
                recordingCoordinator,
                Array.Empty <Training>(),
                SystemClock.Instance.GetCurrentInstant());

            // Assert
            Assert.True(result.IsFailure);
            var error = Assert.IsType <Szlem.Domain.Error.ResourceNotFound>(result.Error);

            Assert.Equal(CommonErrorMessages.CandidateNotFound, error.Message);
        }
Exemple #5
0
        private async Task Initialize(IServiceProvider serviceProvider)
        {
            var user = new Models.Users.ApplicationUser {
                UserName = "******", Email = "*****@*****.**", EmailConfirmed = true
            };
            var userManager = serviceProvider.GetRequiredService <Microsoft.AspNetCore.Identity.UserManager <Models.Users.ApplicationUser> >();
            await userManager.CreateAsync(user, "test");

            await userManager.AddToRoleAsync(user, SharedKernel.AuthorizationRoles.Admin);
        }
        public void Cannot_accept_invitation_to_training_not_selected_as_preferred_training()
        {
            // Arrange
            var id     = EnrollmentAggregate.EnrollmentId.New;
            var event1 = new DomainEvent <EnrollmentAggregate, EnrollmentAggregate.EnrollmentId, RecruitmentFormSubmitted>(
                new RecruitmentFormSubmitted(
                    NodaTime.SystemClock.Instance.GetCurrentInstant(),
                    "Andrzej", "Strzelba",
                    EmailAddress.Parse("*****@*****.**"), Consts.FakePhoneNumber,
                    "ala ma kota", 1, "małopolskie", new[] { "Wadowice" }, new[] { 1 }, true),
                new Metadata(),
                DateTimeOffset.Now,
                id,
                1);
            var enrollment = new EnrollmentAggregate(id);

            enrollment.ApplyEvents(new[] { event1 });

            var training1            = CreateTrainingInFutureWithId(1);
            var training2            = CreateTrainingInFutureWithId(2);
            var recordingCoordinator = new Models.Users.ApplicationUser()
            {
                Id = Guid.NewGuid()
            };

            var command = new RecordAcceptedTrainingInvitation.Command()
            {
                EnrollmentId         = id.GetGuid(),
                CommunicationChannel = CommunicationChannel.OutgoingEmail,
                SelectedTrainingID   = 2,
                AdditionalNotes      = "brak notatek"
            };

            // Act
            var result = enrollment.RecordCandidateAcceptedTrainingInvitation(command, recordingCoordinator, new[] { training1, training2 }, NodaTime.SystemClock.Instance.GetCurrentInstant());

            // Assert
            Assert.False(result.IsSuccess);
            var error   = Assert.IsType <Error.ValidationFailed>(result.Error);
            var failure = Assert.Single(error.Failures);

            Assert.Equal(nameof(command.SelectedTrainingID), failure.PropertyName);
            var errorMessage = Assert.Single(failure.Errors);

            Assert.Equal(RecordAcceptedTrainingInvitation_ErrorMessages.TrainingWasNotSpecifiedAsPreferred, errorMessage);
        }
        public void Cannot_accept_invitation_to_training_earlier_than_submission_date()
        {
            // Arrange
            var id     = EnrollmentAggregate.EnrollmentId.New;
            var event1 = new DomainEvent <EnrollmentAggregate, EnrollmentAggregate.EnrollmentId, RecruitmentFormSubmitted>(
                new RecruitmentFormSubmitted(
                    SystemClock.Instance.GetCurrentInstant(),
                    "Andrzej", "Strzelba",
                    EmailAddress.Parse("*****@*****.**"), Consts.FakePhoneNumber,
                    "ala ma kota", 1, "małopolskie", new[] { "Wadowice" }, new[] { 1 }, true),
                new Metadata(),
                DateTimeOffset.Now,
                id,
                1);
            var enrollment = new EnrollmentAggregate(id);

            enrollment.ApplyEvents(new[] { event1 });

            var training = new Training(
                "Papieska 12/37", "Wadowice",
                SystemClock.Instance.GetOffsetDateTime().Minus(Duration.FromDays(7)),
                SystemClock.Instance.GetOffsetDateTime().Minus(Duration.FromDays(6)),
                Guid.NewGuid());

            training.GetType().GetProperty(nameof(training.ID)).SetValue(training, 1);
            var recordingCoordinator = new Models.Users.ApplicationUser()
            {
                Id = Guid.NewGuid()
            };
            var command = new RecordAcceptedTrainingInvitation.Command()
            {
                EnrollmentId         = id.GetGuid(),
                CommunicationChannel = CommunicationChannel.OutgoingEmail,
                SelectedTrainingID   = 1,
                AdditionalNotes      = "brak notatek"
            };

            // Act
            var result = enrollment.RecordCandidateAcceptedTrainingInvitation(command, recordingCoordinator, new[] { training }, NodaTime.SystemClock.Instance.GetCurrentInstant());

            // Assert
            Assert.False(result.IsSuccess);
            var error = Assert.IsType <Error.DomainError>(result.Error);

            Assert.Equal(RecordAcceptedTrainingInvitation_ErrorMessages.TrainingTimeAlreadyPassed, error.Message);
        }
        // PhoneNumber.Parse() takes ~1 second, WHY? because initial call to PhoneNumbers.PhoneNumberUtil.Parse() loads entire XML dictionary
        public void Registered_candidate_can_decline_training_invitation()
        {
            // Arrange
            var id     = EnrollmentAggregate.EnrollmentId.New;
            var event1 = new DomainEvent <EnrollmentAggregate, EnrollmentAggregate.EnrollmentId, RecruitmentFormSubmitted>(
                new RecruitmentFormSubmitted(
                    SystemClock.Instance.GetCurrentInstant(),
                    "Andrzej", "Strzelba",
                    EmailAddress.Parse("*****@*****.**"), Consts.FakePhoneNumber,
                    "ala ma kota", 1, "Wolne Miasto Gdańsk", new[] { "Wadowice" }, new[] { 1 }, true),
                new Metadata(),
                DateTimeOffset.Now,
                id,
                1);

            var enrollment = new EnrollmentAggregate(id);

            enrollment.ApplyEvents(new[] { event1 });

            var recordingCoordinator = new Models.Users.ApplicationUser()
            {
                Id = Guid.NewGuid()
            };
            var training = CreateTrainingWithIdAndDaysOffset(1, 1);

            // Act
            var command = new RecordRefusedTrainingInvitation.Command()
            {
                EnrollmentId         = id.GetGuid(),
                CommunicationChannel = CommunicationChannel.OutgoingPersonalContact,
                RefusalReason        = "brak powodu",
                AdditionalNotes      = "brak notatek"
            };
            var result = enrollment.RecordCandidateRefusedTrainingInvitation(command, recordingCoordinator, new[] { training }, SystemClock.Instance.GetCurrentInstant());

            // Assert
            Assert.True(result.IsSuccess);
            var e      = Assert.Single(enrollment.UncommittedEvents);
            var @event = Assert.IsType <CandidateRefusedTrainingInvitation>(e.AggregateEvent);

            Assert.Equal(recordingCoordinator.Id, @event.RecordingCoordinatorID);
            Assert.Equal(CommunicationChannel.OutgoingPersonalContact, @event.CommunicationChannel);
            Assert.Equal("brak powodu", @event.RefusalReason);
            Assert.Equal("brak notatek", @event.AdditionalNotes);
        }
        public void Registered_candidate_can_accept_training_invitation()
        {
            // Arrange
            var id     = EnrollmentAggregate.EnrollmentId.New;
            var event1 = new DomainEvent <EnrollmentAggregate, EnrollmentAggregate.EnrollmentId, RecruitmentFormSubmitted>(
                new RecruitmentFormSubmitted(
                    NodaTime.SystemClock.Instance.GetCurrentInstant(),
                    "Andrzej", "Strzelba",
                    EmailAddress.Parse("*****@*****.**"), Consts.FakePhoneNumber,
                    "ala ma kota", 1, "małopolskie", new[] { "Wadowice" }, new[] { 1 }, true),
                new Metadata(),
                DateTimeOffset.Now,
                id,
                1);
            var enrollment = new EnrollmentAggregate(id);

            enrollment.ApplyEvents(new[] { event1 });

            var training = CreateTrainingInFutureWithId(1);
            var command  = new RecordAcceptedTrainingInvitation.Command()
            {
                EnrollmentId         = id.GetGuid(),
                CommunicationChannel = CommunicationChannel.OutgoingEmail,
                SelectedTrainingID   = 1,
                AdditionalNotes      = "brak notatek"
            };
            var recordingCoordinator = new Models.Users.ApplicationUser()
            {
                Id = Guid.NewGuid()
            };

            // Act
            var result = enrollment.RecordCandidateAcceptedTrainingInvitation(command, recordingCoordinator, new[] { training }, NodaTime.SystemClock.Instance.GetCurrentInstant());

            // Assert
            Assert.True(result.IsSuccess);
            var uncommittedEvent = Assert.Single(enrollment.UncommittedEvents);
            var @event           = Assert.IsType <CandidateAcceptedTrainingInvitation>(uncommittedEvent.AggregateEvent);

            Assert.Equal(recordingCoordinator.Id, @event.RecordingCoordinatorID);
            Assert.Equal(CommunicationChannel.OutgoingEmail, @event.CommunicationChannel);
            Assert.Equal(1, @event.SelectedTrainingID);
            Assert.Equal("brak notatek", @event.AdditionalNotes);
        }
        public void If_training_was_selected_cannot_refuse_training_invitation_after_that_training_has_started()
        {
            // Arrange
            var id     = EnrollmentAggregate.EnrollmentId.New;
            var event1 = new DomainEvent <EnrollmentAggregate, EnrollmentAggregate.EnrollmentId, RecruitmentFormSubmitted>(
                new RecruitmentFormSubmitted(
                    SystemClock.Instance.GetCurrentInstant(),
                    "Andrzej", "Strzelba",
                    EmailAddress.Parse("*****@*****.**"), Consts.FakePhoneNumber,
                    "ala ma kota", 1, "Wolne Miasto Gdańsk", new[] { "Wadowice" }, new[] { 1, 2 }, true),
                new Metadata(), DateTimeOffset.Now, id, 1
                );
            var event2 = new DomainEvent <EnrollmentAggregate, EnrollmentAggregate.EnrollmentId, CandidateAcceptedTrainingInvitation>(
                new CandidateAcceptedTrainingInvitation(Guid.NewGuid(), CommunicationChannel.OutgoingEmail, 1, string.Empty),
                new Metadata(), DateTimeOffset.Now, id, 2
                );
            var enrollment = new EnrollmentAggregate(id);

            enrollment.ApplyEvents(new IDomainEvent[] { event1, event2 });
            var recordingCoordinator = new Models.Users.ApplicationUser()
            {
                Id = Guid.NewGuid()
            };
            var training1 = CreateTrainingWithIdAndDaysOffset(1, -1);
            var training2 = CreateTrainingWithIdAndDaysOffset(2, -2);

            // Act
            var result = enrollment.RecordCandidateRefusedTrainingInvitation(
                new RecordRefusedTrainingInvitation.Command()
            {
                EnrollmentId         = enrollment.Id.GetGuid(),
                CommunicationChannel = CommunicationChannel.OutgoingPersonalContact,
                AdditionalNotes      = "brak notatek"
            },
                recordingCoordinator,
                new[] { training1, training2 },
                SystemClock.Instance.GetCurrentInstant());

            // Assert
            Assert.False(result.IsSuccess);
            var error = Assert.IsType <Error.DomainError>(result.Error);

            Assert.Equal(RecordRefusedTrainingInvitation_ErrorMessages.SelectedTrainingHasAlreadyPassed, error.Message);
        }
        public void After_accepting_invitation__HasSignedUpForTraining_is_true()
        {
            // Arrange
            var id     = EnrollmentAggregate.EnrollmentId.New;
            var event1 = new DomainEvent <EnrollmentAggregate, EnrollmentAggregate.EnrollmentId, RecruitmentFormSubmitted>(
                new RecruitmentFormSubmitted(
                    NodaTime.SystemClock.Instance.GetCurrentInstant(),
                    "Andrzej", "Strzelba",
                    EmailAddress.Parse("*****@*****.**"), Consts.FakePhoneNumber,
                    "ala ma kota", 1, "małopolskie", new[] { "Wadowice" }, new[] { 1 }, true),
                new Metadata(), DateTimeOffset.Now, id, 1
                );
            var event2 = new DomainEvent <EnrollmentAggregate, EnrollmentAggregate.EnrollmentId, CandidateRefusedTrainingInvitation>(
                new CandidateRefusedTrainingInvitation(Guid.NewGuid(), CommunicationChannel.OutgoingEmail, "kandydat nie ma czasu", string.Empty),
                new Metadata(), DateTimeOffset.Now, id, 2
                );
            var training   = CreateTrainingInFutureWithId(1);
            var enrollment = new EnrollmentAggregate(id);

            enrollment.ApplyEvents(new IDomainEvent[] { event1, event2 });
            var recordingCoordinator = new Models.Users.ApplicationUser()
            {
                Id = Guid.NewGuid()
            };

            // Act
            var result = enrollment.RecordCandidateAcceptedTrainingInvitation(
                new RecordAcceptedTrainingInvitation.Command()
            {
                EnrollmentId         = enrollment.Id.GetGuid(),
                CommunicationChannel = CommunicationChannel.OutgoingPersonalContact,
                AdditionalNotes      = "brak notatek",
                SelectedTrainingID   = training.ID
            },
                recordingCoordinator,
                new[] { training },
                NodaTime.SystemClock.Instance.GetCurrentInstant());

            // Assert
            Assert.True(result.IsSuccess);
            Assert.True(enrollment.HasSignedUpForTraining(training));
        }
        private async Task Initialize(IServiceProvider services)
        {
            var userManager = services.GetRequiredService <UserManager <Models.Users.ApplicationUser> >();

            var admin = new Models.Users.ApplicationUser {
                UserName = "******", Email = "*****@*****.**", EmailConfirmed = true
            };

            AssertSuccess(await userManager.CreateAsync(admin, "test"));
            AssertSuccess(await userManager.AddToRoleAsync(admin, AuthorizationRoles.Admin));
            _adminName = admin.DisplayName;

            var coordinator = new Models.Users.ApplicationUser {
                UserName = "******", Email = "*****@*****.**", EmailConfirmed = true
            };

            AssertSuccess(await userManager.CreateAsync(coordinator, "test"));
            AssertSuccess(await userManager.AddToRoleAsync(coordinator, AuthorizationRoles.RegionalCoordinator));
            _coordinatorName = coordinator.DisplayName;
        }
        public void Command_with_mismatched_EnrollmentID_fails()
        {
            // Arrange
            var id                   = EnrollmentAggregate.EnrollmentId.New;
            var enrollment           = new EnrollmentAggregate(id);
            var training             = CreateTrainingInFutureWithId(1);
            var recordingCoordinator = new Models.Users.ApplicationUser()
            {
                Id = Guid.NewGuid()
            };
            var command = new RecordAcceptedTrainingInvitation.Command()
            {
                CommunicationChannel = CommunicationChannel.OutgoingEmail,
                SelectedTrainingID   = 1,
                AdditionalNotes      = "brak notatek"
            };

            // Act & Assert
            var ex = Assert.Throws <AggregateMismatchException>(() => enrollment.RecordCandidateAcceptedTrainingInvitation(command, recordingCoordinator, new[] { training }, NodaTime.SystemClock.Instance.GetCurrentInstant()));
        }
        public void Command_without_EnrollmentID_fails()
        {
            // Arrange
            var id                   = EnrollmentAggregate.EnrollmentId.New;
            var enrollment           = new EnrollmentAggregate(id);
            var recordingCoordinator = new Models.Users.ApplicationUser()
            {
                Id = Guid.NewGuid()
            };
            var training = CreateTrainingWithIdAndDaysOffset(1, 1);
            var command  = new RecordRefusedTrainingInvitation.Command()
            {
                CommunicationChannel = CommunicationChannel.OutgoingEmail
            };

            // Act & Assert
            var ex = Assert.Throws <AggregateMismatchException>(() =>
                                                                enrollment.RecordCandidateRefusedTrainingInvitation(
                                                                    command, recordingCoordinator, new[] { training }, SystemClock.Instance.GetCurrentInstant()));
        }
        public void Cannot_accept_training_invitation_after_training_start_datetime()
        {
            // Arrange
            var id     = EnrollmentAggregate.EnrollmentId.New;
            var event1 = new DomainEvent <EnrollmentAggregate, EnrollmentAggregate.EnrollmentId, RecruitmentFormSubmitted>(
                new RecruitmentFormSubmitted(
                    NodaTime.SystemClock.Instance.GetCurrentInstant(),
                    "Andrzej", "Strzelba",
                    EmailAddress.Parse("*****@*****.**"), Consts.FakePhoneNumber,
                    "ala ma kota", 1, "małopolskie", new[] { "Wadowice" }, new[] { 1 }, true),
                new Metadata(), DateTimeOffset.Now, id, 1
                );
            var enrollment = new EnrollmentAggregate(id);

            enrollment.ApplyEvents(new IDomainEvent[] { event1 });
            var recordingCoordinator = new Models.Users.ApplicationUser()
            {
                Id = Guid.NewGuid()
            };
            var training = CreateTrainingWithIdAndOffset(1, Duration.FromHours(-1));

            // Act
            var result = enrollment.RecordCandidateAcceptedTrainingInvitation(
                new RecordAcceptedTrainingInvitation.Command()
            {
                EnrollmentId         = enrollment.Id.GetGuid(),
                CommunicationChannel = CommunicationChannel.OutgoingPersonalContact,
                AdditionalNotes      = "brak notatek",
                SelectedTrainingID   = 1
            },
                recordingCoordinator,
                new[] { training },
                NodaTime.SystemClock.Instance.GetCurrentInstant());

            // Assert
            Assert.False(result.IsSuccess);
            var error = Assert.IsType <Error.DomainError>(result.Error);

            Assert.Equal(RecordAcceptedTrainingInvitation_ErrorMessages.TrainingTimeAlreadyPassed, error.Message);
        }
        public void After_refusing_invitation__candidate_is_not_signed_up_for_training()
        {
            // Arrange
            var id     = EnrollmentAggregate.EnrollmentId.New;
            var event1 = new DomainEvent <EnrollmentAggregate, EnrollmentAggregate.EnrollmentId, RecruitmentFormSubmitted>(
                new RecruitmentFormSubmitted(
                    SystemClock.Instance.GetCurrentInstant(),
                    "Andrzej", "Strzelba",
                    EmailAddress.Parse("*****@*****.**"), Consts.FakePhoneNumber,
                    "ala ma kota", 1, "Wolne Miasto Gdańsk", new[] { "Wadowice" }, new[] { 1 }, true),
                new Metadata(), DateTimeOffset.Now, id, 1
                );
            var event2 = new DomainEvent <EnrollmentAggregate, EnrollmentAggregate.EnrollmentId, CandidateAcceptedTrainingInvitation>(
                new CandidateAcceptedTrainingInvitation(Guid.NewGuid(), CommunicationChannel.OutgoingEmail, 1, string.Empty),
                new Metadata(), DateTimeOffset.Now, id, 2
                );
            var enrollment = new EnrollmentAggregate(id);

            enrollment.ApplyEvents(new IDomainEvent[] { event1, event2 });
            var recordingCoordinator = new Models.Users.ApplicationUser()
            {
                Id = Guid.NewGuid()
            };
            var training = CreateTrainingWithIdAndDaysOffset(1, 1);

            // Act
            var command = new RecordRefusedTrainingInvitation.Command()
            {
                EnrollmentId         = enrollment.Id.GetGuid(),
                CommunicationChannel = CommunicationChannel.OutgoingPersonalContact,
                RefusalReason        = "brak powodu",
                AdditionalNotes      = "brak notatek"
            };
            var result = enrollment.RecordCandidateRefusedTrainingInvitation(command, recordingCoordinator, new[] { training }, SystemClock.Instance.GetCurrentInstant());

            // Assert
            Assert.True(result.IsSuccess);
            enrollment.HasSignedUpForTraining(training).Should().BeFalse();
        }