public async Task Send_farfare_notice_when_user_has_fanfare_and_is_arriving(bool hasFanfare, int timesSent)
        {
            // arrange
            var username        = "******";
            var expectedFanfare = new FanfareInfo
            {
                Message          = "message " + Guid.NewGuid(),
                Timeout          = 12312,
                YouTubeCode      = "ytcode" + Guid.NewGuid(),
                YouTubeStartTime = 111,
                YouTubeEndTime   = 222
            };
            var twitchLibMessage = TwitchLibMessageBuilder.Create().WithUsername(username).Build();
            var chatMessage      = ChatMessageBuilder.Create().WithTwitchLibMessage(twitchLibMessage).Build();
            var request          = new UserHasArrived(chatMessage);

            MockCollection.Setup(x => x.ExistsAsync($"{username}::arrived_recently", null))
            .ReturnsAsync(new FakeExistsResult(false));
            MockCollection.Setup(x => x.GetAsync(It.IsAny <string>(), null))
            .ReturnsAsync(new FakeGetResult(new TwitcherProfile {
                HasFanfare = hasFanfare, Fanfare = expectedFanfare
            }));

            // act
            await _handler.Handle(request, CancellationToken.None);

            // assert
            _mockTwitchHub.Verify(x => x.ReceiveFanfare(expectedFanfare), Times.Exactly(timesSent));
        }
        public async Task Create_recent_activity_marker_document_if_necessary()
        {
            // arrange
            var username = "******";

            MockCollection.Setup(x => x.ExistsAsync($"{username}::arrived_recently", null))
            .ReturnsAsync(new FakeExistsResult(false));
            var twitchLibMessage = TwitchLibMessageBuilder.Create().WithUsername(username).Build();
            var chatMessage      = ChatMessageBuilder.Create().WithTwitchLibMessage(twitchLibMessage).Build();
            var request          = new UserHasArrived(chatMessage);

            MockCollection.Setup(x => x.GetAsync(It.IsAny <string>(), null))
            .ReturnsAsync(new FakeGetResult(new TwitcherProfile()));
            _mockTwitchHub.Setup(x => x.ReceiveFanfare(It.IsAny <FanfareInfo>()));

            // act
            await _handler.Handle(request, CancellationToken.None);

            // assert
            MockCollection.Verify(x => x.UpsertAsync(
                                      It.Is <string>(k => k == $"{username}::arrived_recently"),
                                      It.IsAny <UserHasArrivedMarker>(),
                                      It.IsAny <UpsertOptions>()), Times.Once);
            MockCollection.Verify(x => x.UpsertAsync(
                                      It.IsAny <string>(),
                                      It.IsAny <UserHasArrivedMarker>(),
                                      It.Is <UpsertOptions>(u =>
                                                            (u.GetInternalPropertyValue <TimeSpan, UpsertOptions>("ExpiryValue")).Hours == 12)),
                                  Times.Once);
        }
        [TestCase(true, 0)]         // if marker document does exist, don't create/update it
        public async Task Create_recent_activity_marker_document_if_necessary(bool documentAlreadyExists, int timesCalled)
        {
            // arrange
            var username = "******";

            _mockBucket.Setup(x => x.ExistsAsync($"{username}::arrived_recently"))
            .ReturnsAsync(documentAlreadyExists);
            var twitchLibMessage = TwitchLibMessageBuilder.Create().WithUsername(username).Build();
            var chatMessage      = ChatMessageBuilder.Create().WithTwitchLibMessage(twitchLibMessage).Build();
            var request          = new UserHasArrived(chatMessage);

            _mockBucket.Setup(x => x.GetAsync <TwitcherProfile>(It.IsAny <string>()))
            .ReturnsAsync(new FakeOperationResult <TwitcherProfile> {
                Value = new TwitcherProfile()
            });
            _mockTwitchHub.Setup(x => x.ReceiveFanfare(It.IsAny <FanfareInfo>()));

            // act
            await _handler.Handle(request, CancellationToken.None);

            // assert
            _mockBucket.Verify(x => x.UpsertAsync(

                                   It.Is <Document <dynamic> >(x =>
                                                               x.Id == $"{username}::arrived_recently" &&
                                                               x.Expiry == 12 * 60 * 60 * 1000 // 12 hours
                                                               )

                                   ), Times.Exactly(timesCalled));
        }
        public async Task No_fanfare_if_there_is_no_user_profile()
        {
            // arrange
            var username         = "******";
            var twitchLibMessage = TwitchLibMessageBuilder.Create().WithUsername(username).Build();
            var chatMessage      = ChatMessageBuilder.Create().WithTwitchLibMessage(twitchLibMessage).Build();
            var request          = new UserHasArrived(chatMessage);

            // setup: user has NOT arrive recently
            _mockBucket.Setup(m => m.ExistsAsync($"{username}::arrived_recently"))
            .ReturnsAsync(false);
            // setup: don't care about the arrive_recently document being added
            _mockBucket.Setup(m => m.UpsertAsync(It.IsAny <Document <dynamic> >()));
            // setup: user does NOT have a profile
            _mockBucket.Setup(m => m.GetAsync <TwitcherProfile>(username.ToLower()))
            .ReturnsAsync(new FakeOperationResult <TwitcherProfile> {
                Value = null
            });

            // act
            await _handler.Handle(request, CancellationToken.None);

            // assert
            _mockTwitchHub.Verify(m => m.ReceiveFanfare(It.IsAny <FanfareInfo>()), Times.Never);
        }
        public async Task No_fanfare_if_there_is_no_user_profile()
        {
            // arrange
            var username         = "******";
            var twitchLibMessage = TwitchLibMessageBuilder.Create().WithUsername(username).Build();
            var chatMessage      = ChatMessageBuilder.Create().WithTwitchLibMessage(twitchLibMessage).Build();
            var request          = new UserHasArrived(chatMessage);

            // setup: user has NOT arrive recently
            MockCollection.Setup(m => m.ExistsAsync($"{username}::arrived_recently", null))
            .ReturnsAsync(new FakeExistsResult(false));
            // setup: don't care about the arrive_recently document being added
            MockCollection.Setup(m => m.UpsertAsync(It.IsAny <string>(), It.IsAny <UserHasArrivedMarker>(), null));
            // setup: user does NOT have a profile
            MockCollection.Setup(m => m.GetAsync(username.ToLower(), null))
            .ReturnsAsync(new FakeGetResult(null));

            // act
            await _handler.Handle(request, CancellationToken.None);

            // assert
            _mockTwitchHub.Verify(m => m.ReceiveFanfare(It.IsAny <FanfareInfo>()), Times.Never);
        }