public async Task Can_Invoke_Function_When_The_Skill_Is_Not_Linked() { // Arrange AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentRequestWithToken(accessToken: null); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert ResponseBody response = AssertResponse(actual); response.Card.ShouldNotBeNull(); response.Card.ShouldBeOfType <LinkAccountCard>(); response.Reprompt.ShouldBeNull(); response.OutputSpeech.ShouldNotBeNull(); response.OutputSpeech.Type.ShouldBe("SSML"); var ssml = response.OutputSpeech.ShouldBeOfType <SsmlOutputSpeech>(); ssml.Ssml.ShouldBe("<speak>You need to link your account to be able to ask me about your commute.</speak>"); }
public async Task Can_Invoke_Function_For_Invalid_Line(string id) { // Arrange AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentForLine(id); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert ResponseBody response = AssertResponse(actual); response.Card.ShouldBeNull(); response.OutputSpeech.ShouldNotBeNull(); response.Reprompt.ShouldNotBeNull(); var speeches = new[] { response.OutputSpeech, response.Reprompt.OutputSpeech }; foreach (var speech in speeches) { speech.Type.ShouldBe("SSML"); var ssml = speech.ShouldBeOfType <SsmlOutputSpeech>(); ssml.Ssml.ShouldBe("<speak>Sorry, I am not sure what line you said. You can ask about the status of any tube line, London Overground, the D.L.R. or T.F.L. Rail.</speak>"); } }
public async Task Can_Invoke_Function_For_Elizabeth_Line(string id) { // Arrange AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentForLine(id); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert ResponseBody response = AssertResponse(actual); response.Card.ShouldBeNull(); response.OutputSpeech.ShouldNotBeNull(); response.Reprompt.ShouldNotBeNull(); var speeches = new[] { response.OutputSpeech, response.Reprompt.OutputSpeech }; foreach (var speech in speeches) { speech.Type.ShouldBe("SSML"); var ssml = speech.ShouldBeOfType <SsmlOutputSpeech>(); ssml.Ssml.ShouldBe("<speak>Sorry, I cannot tell you about the status of the Elizabeth Line yet.</speak>"); } }
public async Task Can_Invoke_Function_When_The_Skill_Token_Is_Invalid() { // Arrange Interceptor.RegisterBundle(Path.Combine("Bundles", "skill-api-invalid-token.json")); AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentRequestWithToken(accessToken: "invalid-access-token"); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert ResponseBody response = AssertResponse(actual); response.Card.ShouldNotBeNull(); response.Card.ShouldBeOfType <LinkAccountCard>(); response.Reprompt.ShouldBeNull(); response.OutputSpeech.ShouldNotBeNull(); response.OutputSpeech.Type.ShouldBe("SSML"); var ssml = response.OutputSpeech.ShouldBeOfType <SsmlOutputSpeech>(); ssml.Ssml.ShouldBe("<speak>It looks like you've disabled account linking. You need to re-link your account to be able to ask me about your commute.</speak>"); }
public async Task Can_Invoke_Function() { // Arrange var function = new AlexaFunction(); await function.InitializeAsync(); SkillRequest request = CreateIntentRequest("FooIntent"); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert ResponseBody response = AssertResponse(actual); response.Card.ShouldBeNull(); response.Reprompt.ShouldBeNull(); response.OutputSpeech.ShouldNotBeNull(); response.OutputSpeech.Type.ShouldBe("SSML"); var ssml = response.OutputSpeech.ShouldBeOfType <SsmlOutputSpeech>(); ssml.Ssml.ShouldBe("<speak>Sorry, I don't understand how to do that.</speak>"); }
public async Task Can_Invoke_Function() { // Arrange AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateRequest <UnknownRequest>(); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert AssertResponse(actual); }
/// <summary> /// Runs the function using a custom runtime as an asynchronous operation. /// </summary> /// <param name="httpClient">The optional HTTP client to use.</param> /// <param name="cancellationToken">The optional cancellation token to use.</param> /// <returns> /// A <see cref="Task"/> representing the asynchronous operation to run the function. /// </returns> public static async Task RunAsync( HttpClient httpClient = null, CancellationToken cancellationToken = default) { var serializer = new JsonSerializer(); var function = new AlexaFunction(); #pragma warning disable CA2000 using var handlerWrapper = HandlerWrapper.GetHandlerWrapper <SkillRequest, SkillResponse>(function.HandlerAsync, serializer); using var bootstrap = new LambdaBootstrap(httpClient ?? new HttpClient(), handlerWrapper, function.InitializeAsync); #pragma warning restore CA2000 await bootstrap.RunAsync(cancellationToken); }
public async Task Can_Invoke_Function_For_Valid_Line(string id) { // Arrange Interceptor.RegisterBundle(Path.Combine("Bundles", "tfl-line-statuses.json")); AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentForLine(id); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert AssertLineResponse(actual); }
public async Task Cannot_Invoke_Function_If_Application_Id_Incorrect() { // Arrange AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentRequest("AMAZON.HelpIntent"); request.Session.Application.ApplicationId = "not-my-skill-id"; ILambdaContext context = CreateContext(); // Act InvalidOperationException exception = await Assert.ThrowsAsync <InvalidOperationException>( async() => await function.HandlerAsync(request, context)); // Assert exception.Message.ShouldBe("Request application Id 'not-my-skill-id' and configured skill Id 'my-skill-id' mismatch."); }
public async Task Can_Invoke_Function_For_Different_Severities( string id, string expected) { // Arrange Interceptor.RegisterBundle(Path.Combine("Bundles", "tfl-line-severities.json")); AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentForLine(id); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert AssertLineResponse(actual, expectedSsml: "<speak>" + expected + "</speak>"); }
public async Task Can_Invoke_Function() { // Arrange AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentRequest("AMAZON.CancelIntent"); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert ResponseBody response = AssertResponse(actual); response.Card.ShouldBeNull(); response.OutputSpeech.ShouldBeNull(); response.Reprompt.ShouldBeNull(); }
public async Task Can_Invoke_Function_When_There_Is_One_Disruption() { // Arrange Interceptor.RegisterBundle(Path.Combine("Bundles", "tfl-one-disruption.json")); AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentRequest(); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert AssertResponse( actual, "<speak><p>There are severe delays on the District Line.</p><p>There is a good service on all other lines.</p></speak>", "There are severe delays on the District Line."); }
public async Task Can_Invoke_Function_When_There_Are_No_Disruptions() { // Arrange Interceptor.RegisterBundle(Path.Combine("Bundles", "tfl-no-disruptions.json")); AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentRequest(); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert AssertResponse( actual, "<speak>There is currently no disruption on the tube, London Overground, the D.L.R. or T.F.L. Rail.</speak>", "There is currently no disruption on the tube, London Overground, the DLR or TfL Rail."); }
public async Task Can_Invoke_Function_When_There_Are_Multiple_Disruptions() { // Arrange Interceptor.RegisterBundle(Path.Combine("Bundles", "tfl-multiple-disruptions.json")); AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentRequest(); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert AssertResponse( actual, "<speak><p>Circle Line: There are minor delays on the Circle Line.</p><p>District Line: There are severe delays on the District Line.</p><p>Hammersmith and City Line: There are minor delays on the Hammersmith and City Line.</p><p>There is a good service on all other lines.</p></speak>", "Circle Line: There are minor delays on the Circle Line.\nDistrict Line: There are severe delays on the District Line.\nHammersmith & City Line: There are minor delays on the Hammersmith & City Line."); }
public async Task Can_Invoke_Function_When_The_Skill_Is_Linked_And_Has_One_Favorite_Line() { // Arrange Interceptor.RegisterBundle(Path.Combine("Bundles", "skill-api-one-favorite.json")); Interceptor.RegisterBundle(Path.Combine("Bundles", "tfl-line-statuses.json")); AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentRequestWithToken(accessToken: "token-for-one-favorite"); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert AssertResponse( actual, "<speak>Saturday 19 and Sunday 20 October, no service between Hammersmith / Wimbledon / Kensington Olympia and South Kensington / Edgware Road. Replacement buses operate.</speak>", "Saturday 19 and Sunday 20 October, no service between Hammersmith / Wimbledon / Kensington Olympia and South Kensington / Edgware Road. Replacement buses operate."); }
public async Task Can_Invoke_Function_When_The_Skill_Is_Linked_And_Has_Two_Favorite_Lines() { // Arrange Interceptor.RegisterBundle(Path.Combine("Bundles", "skill-api-two-favorites.json")); Interceptor.RegisterBundle(Path.Combine("Bundles", "tfl-line-statuses.json")); AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentRequestWithToken(accessToken: "token-for-two-favorites"); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert AssertResponse( actual, "<speak><p>Northern Line: There is a good service on the Northern line.</p><p>Victoria Line: There is a good service on the Victoria line.</p></speak>", "Northern Line: There is a good service on the Northern line.\nVictoria Line: There is a good service on the Victoria line."); }
public async Task Can_Invoke_Function_When_The_Skill_Is_Linked_And_Only_The_Elizabeth_Line_Is_A_Favorite() { // Arrange Interceptor.RegisterBundle(Path.Combine("Bundles", "skill-api-elizabeth.json")); Interceptor.RegisterBundle(Path.Combine("Bundles", "tfl-line-statuses.json")); AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentRequestWithToken(accessToken: "token-for-only-elizabeth-line"); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert AssertResponse( actual, "<speak>You have not selected any favourite lines yet. Visit the London Travel website to set your preferences.</speak>", "You have not selected any favourite lines yet. Visit the London Travel website to set your preferences."); }
public async Task Can_Invoke_Function_If_Locale_Is_Invalid(string locale) { // Arrange AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentRequest("AMAZON.HelpIntent"); request.Request.Locale = locale; ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert ResponseBody response = AssertResponse(actual, shouldEndSession: false); response.OutputSpeech.ShouldNotBeNull(); response.OutputSpeech.Type.ShouldBe("SSML"); }
public async Task Cannot_Invoke_Function_With_System_Failure() { // Arrange AlexaFunction function = await CreateFunctionAsync(); ILambdaContext context = CreateContext(); var error = new SystemExceptionRequest() { Error = new Error() { Message = "Internal error.", Type = ErrorType.InternalError, }, ErrorCause = new ErrorCause() { requestId = "my-request-id", }, }; var request = CreateRequest(error); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert ResponseBody response = AssertResponse(actual); response.Card.ShouldBeNull(); response.Reprompt.ShouldBeNull(); response.OutputSpeech.ShouldNotBeNull(); response.OutputSpeech.Type.ShouldBe("SSML"); var ssml = response.OutputSpeech.ShouldBeOfType <SsmlOutputSpeech>(); ssml.Ssml.ShouldBe("<speak>Sorry, something went wrong.</speak>"); }
public async Task Can_Invoke_Function() { // Arrange AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateRequest <LaunchRequest>(); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert ResponseBody response = AssertResponse(actual, shouldEndSession: false); response.Card.ShouldBeNull(); response.Reprompt.ShouldBeNull(); response.OutputSpeech.ShouldNotBeNull(); response.OutputSpeech.Type.ShouldBe("SSML"); var ssml = response.OutputSpeech.ShouldBeOfType <SsmlOutputSpeech>(); ssml.Ssml.ShouldBe("<speak>Welcome to London Travel. You can ask me about disruption or for the status of any tube line, London Overground, the D.L.R. or T.F.L. Rail.</speak>"); }
public async Task Can_Invoke_Function_When_The_Skill_Api_Fails() { // Arrange AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentRequestWithToken(accessToken: "random-access-token"); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert ResponseBody response = AssertResponse(actual); response.Card.ShouldBeNull(); response.Reprompt.ShouldBeNull(); response.OutputSpeech.ShouldNotBeNull(); response.OutputSpeech.Type.ShouldBe("SSML"); var ssml = response.OutputSpeech.ShouldBeOfType <SsmlOutputSpeech>(); ssml.Ssml.ShouldBe("<speak>Sorry, something went wrong.</speak>"); }
public async Task Can_Invoke_Function() { // Arrange AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateRequest <SessionEndedRequest>(); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert ResponseBody response = AssertResponse(actual); response.Card.ShouldBeNull(); response.Reprompt.ShouldBeNull(); response.OutputSpeech.ShouldNotBeNull(); response.OutputSpeech.Type.ShouldBe("SSML"); var ssml = response.OutputSpeech.ShouldBeOfType <SsmlOutputSpeech>(); ssml.Ssml.ShouldBe("<speak>Goodbye.</speak>"); }
public async Task Can_Invoke_Function() { // Arrange AlexaFunction function = await CreateFunctionAsync(); SkillRequest request = CreateIntentRequest("AMAZON.HelpIntent"); ILambdaContext context = CreateContext(); // Act SkillResponse actual = await function.HandlerAsync(request, context); // Assert ResponseBody response = AssertResponse(actual, shouldEndSession: false); response.Card.ShouldBeNull(); response.Reprompt.ShouldBeNull(); response.OutputSpeech.ShouldNotBeNull(); response.OutputSpeech.Type.ShouldBe("SSML"); var ssml = response.OutputSpeech.ShouldBeOfType <SsmlOutputSpeech>(); ssml.Ssml.ShouldBe("<speak><p>This skill allows you to check for the status of a specific line, or for disruption in general. You can ask about any London Underground line, London Overground, the Docklands Light Railway or T.F.L. Rail.</p><p>Asking about disruption in general provides information about any lines that are currently experiencing issues, such as any delays or planned closures.</p><p>Asking for the status for a specific line provides a summary of the current service, such as whether there is a good service or if there are any delays.</p><p>If you link your account and setup your preferences in the London Travel website, you can ask about your commute to quickly find out the status of the lines you frequently use.</p></speak>"); }