public async Task It_can_surface_code_submission_errors() { var command = new SubmitCode(@"var a = 12"); command.SetToken("abc"); await _standardIOKernelServer.WriteAsync(command); _kernelEvents .Should() .ContainSingle <KernelEventEnvelope <IncompleteCodeSubmissionReceived> >(e => e.Event.Command.GetToken() == "abc"); }
public async Task It_indicates_when_a_code_submission_is_incomplete() { var command = new SubmitCode(@"var a = 12"); command.SetToken("abc"); await _kernelServer.WriteAsync(command); _kernelEvents .Should() .ContainSingle <KernelEventEnvelope <IncompleteCodeSubmissionReceived> >(e => e.Event.Command.GetToken() == "abc"); }
public async Task Kernel_can_pound_r_nuget_using_kernel_client() { var command = new SubmitCode(@"#r ""nuget:Microsoft.Spark, 0.4.0"""); command.SetToken("abc"); await _standardIOKernelServer.WriteAsync(command); _kernelEvents .Should() .ContainSingle <KernelEventEnvelope <PackageAdded> >( where : e => e.Event.Command.GetToken() == "abc" && e.Event.PackageReference.PackageName == "Microsoft.Spark"); }
public void Command_tokens_cannot_be_changed() { var command = new SubmitCode("123"); command.SetToken("once"); command.Invoking(c => c.SetToken("again")) .Should() .Throw <InvalidOperationException>() .Which .Message .Should() .Be("Command token cannot be changed."); }
public void Command_tokens_are_reproducible_given_the_same_seed() { var command1 = new SubmitCode("123"); command1.SetToken("the-token"); string token1 = command1.GetToken(); var command2 = new SubmitCode("123"); command2.SetToken("the-token"); string token2 = command2.GetToken(); token2.Should().Be(token1); }
public async Task It_produces_a_unique_CommandHandled_for_root_command() { var command = new SubmitCode("#!time\ndisplay(1543); display(4567);"); command.SetToken("abc"); await _standardIOKernelServer.WriteAsync(command); _kernelEvents .Should() .ContainSingle <KernelEventEnvelope <CommandHandled> >() .Which .Event .Command .GetToken() .Should() .Be("abc"); }
public async Task It_does_not_indicate_compilation_errors_as_exceptions() { var command = new SubmitCode("DOES NOT COMPILE"); command.SetToken("abc"); await _standardIOKernelServer.WriteAsync(command); _kernelEvents .Should() .ContainSingle <KernelEventEnvelope <CommandFailed> >() .Which .Event .Message .ToLowerInvariant() .Should() .NotContain("exception"); }
public void When_resent_then_child_commands_having_the_same_parent_have_repeatable_tokens() { var parentCommand = new SubmitCode("123"); parentCommand.SetToken("the-token"); string token1 = null; string token2 = null; using (KernelInvocationContext.Establish(parentCommand)) { token1 = new SubmitCode("456").GetToken(); } using (KernelInvocationContext.Establish(parentCommand)) { token2 = new SubmitCode("456").GetToken(); } token1.Should().Be(token2); }
#pragma warning disable CS1998 protected override async Task OnMessageActivityAsync(ITurnContext <IMessageActivity> turnContext, CancellationToken cancellationToken) { var value = turnContext.Activity; var attachments = turnContext.Activity.Attachments; if (turnContext.Activity.Value == null) // someone typed in something, it isn't a card { var content = turnContext.Activity.Text; var code = CheckForCode(content); var conversationReference = turnContext.Activity.GetConversationReference(); var mention = new Mention { Mentioned = turnContext.Activity.From, Text = $"<at>{turnContext.Activity.From.Name}</at>", }; if (!string.IsNullOrEmpty(code)) { if (DotNetInteractiveProcessRunner.Instance.CanExecuteCode) { var submissionToken = Guid.NewGuid().ToString("N"); var messageText = string.Empty; var user = UserGame.GetOrCreateUser(mention, turnContext.Activity.From); if (UserGame.CurrentChatUser?.Id != user.Id) { UserGame.CurrentChatUser = user; messageText = $"Hey {mention.Text} It looks like you're typing some code. Let me run it for you! 😊"; } else { messageText = UserGame.GetMessageForUser(mention); } await turnContext.Adapter.ContinueConversationAsync(_botId, conversationReference, async (context, token) => { var message = MessageFactory.Text(messageText); if (messageText.Contains(mention.Text)) { message.Entities.Add(mention); } await context.SendActivityAsync(message, token); }, cancellationToken); // build the envelope var submitCode = new SubmitCode(code); submitCode.SetToken(submissionToken); var envelope = KernelCommandEnvelope.Create(submitCode); var channel = ContentSubjectHelper.GetOrCreateChannel(submissionToken); EnvelopeHelper.StoreEnvelope(submissionToken, envelope); var cardSent = false; channel .Timeout(DateTimeOffset.UtcNow.Add(TimeSpan.FromMinutes(1))) .Buffer(TimeSpan.FromSeconds(1)) .Subscribe( onNext: async formattedValues => { turnContext.Adapter.ContinueConversationAsync(_botId, conversationReference, (context, token) => { if (formattedValues.Count > 0) { var hasHtml = formattedValues.Any(f => f.MimeType == HtmlFormatter.MimeType); if (hasHtml) { if (!cardSent) { cardSent = true; var card = new HeroCard { Title = "Your output is too awesome 😎", Subtitle = "Use the viewer to see it.", Buttons = new List <CardAction> { new TaskModuleAction("Open Viewer", new { data = submissionToken }) }, }.ToAttachment(); var message = MessageFactory.Attachment(card); context.SendActivityAsync(message, token).Wait(); } } else { var content = string.Join("\n", formattedValues.Select(f => f.Value)); var message = MessageFactory.Text($"```\n{content.HtmlEncode()}"); context.SendActivityAsync(message, token).Wait(); } } return(Task.CompletedTask); }, cancellationToken).Wait(); }, onCompleted: async() => { await turnContext.Adapter.ContinueConversationAsync(_botId, conversationReference, async(context, token) => { await Task.Delay(1000); var message = MessageFactory.Text($"{mention.Text} all done here 👍"); message.Entities.Add(mention); await context.SendActivityAsync(message, token); }, cancellationToken); }, onError: async error => { await turnContext.Adapter.ContinueConversationAsync(_botId, conversationReference, async(context, token) => { await Task.Delay(1000); var message = MessageFactory.Text($@"{mention.Text} there were some issues 👎 :\n {error.Message}"); message.Entities.Add(mention); await context.SendActivityAsync(message, token); }, cancellationToken); }); user.IncrementCodeSubmissionCount(); await DotNetInteractiveProcessRunner.Instance.ExecuteEnvelope(submissionToken); } else { await turnContext.Adapter.ContinueConversationAsync(_botId, conversationReference, async (context, token) => { var message = MessageFactory.Text($"Sorry {mention.Text} cannot execute your code now. 😓"); message.Entities.Add(mention); await context.SendActivityAsync(message, token); }, cancellationToken); } } else if (string.IsNullOrWhiteSpace(DotNetInteractiveProcessRunner.Instance.SessionLanguage)) { var card = CardUtilities.CreateAdaptiveCardAttachment(CardJsonFiles.SelectLanguage); var attach = MessageFactory.Attachment(card); await turnContext.SendActivityAsync(attach, cancellationToken); } else if (content.Contains("👊")) { var mentioned = turnContext.Activity.GetMentions()?.FirstOrDefault(m => m.Mentioned.Id.EndsWith(_botId)); if (mentioned != null) { await turnContext.Adapter.ContinueConversationAsync(_botId, conversationReference, async (context, token) => { var message = MessageFactory.Text($"{mention.Text} back at you my friend! 👊"); message.Entities.Add(mention); await context.SendActivityAsync(message, token); }, cancellationToken); } } } else { var userAction = turnContext.Activity.Value; if (((JObject)userAction).Value <string>("userAction").Equals("SelectLanguage")) { if (string.IsNullOrWhiteSpace(DotNetInteractiveProcessRunner.Instance.SessionLanguage)) { var language = ((JObject)userAction).Value <string>("language"); DotNetInteractiveProcessRunner.Instance.SessionLanguage = language; var languageLabel = ((JObject)userAction).Value <string>("languageLabel"); var message = MessageFactory.Text($"All set. Let's write some {DotNetInteractiveProcessRunner.Instance.SessionLanguage} code together! 🤘🏻"); await turnContext.SendActivityAsync(message, cancellationToken); } } } }