├── .ask └── config ├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── LICENSE ├── NOTICE ├── README.md ├── assets ├── aws-stack.json ├── launch.json └── vui.png ├── js ├── assets.js ├── constants.js ├── index.js ├── package.json ├── serverless.yml └── stateHandlers.js ├── labs ├── img │ ├── lab02-screen01.png │ ├── lab02-screen02.png │ ├── lab03-screen01.png │ ├── lab03-screen02.png │ ├── lab04-screen01.png │ ├── lab04-screen02.png │ ├── lab04-screen03.png │ ├── lab04-screen04.png │ ├── lab04-screen05.png │ ├── lab04-screen06.png │ ├── lab04-screen07.png │ ├── lab08-screen01.png │ ├── lab08-screen02.png │ ├── lab08-screen03.png │ └── lab08-screen04.png ├── lab01.md ├── lab02.md ├── lab03.md ├── lab04.md ├── lab04_hw.md ├── lab05.md ├── lab06.md ├── lab07.md └── lab08.md ├── models └── en-US.json ├── scripts ├── lab04.yml ├── lab05.yml ├── lab06.yml ├── lab07-extended.yml ├── lab07-final.yml └── lab07.yml └── skill.json /.ask/config: -------------------------------------------------------------------------------- 1 | { 2 | "deploy_settings": { 3 | "default": { 4 | "skill_id": "", 5 | "was_cloned": false 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | *Issue #, if available:* 2 | 3 | *Description of changes:* 4 | 5 | 6 | By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (http://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # Typescript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Amazon Software License 1.0 2 | 3 | This Amazon Software License ("License") governs your use, reproduction, and 4 | distribution of the accompanying software as specified below. 5 | 6 | 1. Definitions 7 | 8 | "Licensor" means any person or entity that distributes its Work. 9 | 10 | "Software" means the original work of authorship made available under this 11 | License. 12 | 13 | "Work" means the Software and any additions to or derivative works of the 14 | Software that are made available under this License. 15 | 16 | The terms "reproduce," "reproduction," "derivative works," and 17 | "distribution" have the meaning as provided under U.S. copyright law; 18 | provided, however, that for the purposes of this License, derivative works 19 | shall not include works that remain separable from, or merely link (or bind 20 | by name) to the interfaces of, the Work. 21 | 22 | Works, including the Software, are "made available" under this License by 23 | including in or with the Work either (a) a copyright notice referencing the 24 | applicability of this License to the Work, or (b) a copy of this License. 25 | 26 | 2. License Grants 27 | 28 | 2.1 Copyright Grant. Subject to the terms and conditions of this License, 29 | each Licensor grants to you a perpetual, worldwide, non-exclusive, 30 | royalty-free, copyright license to reproduce, prepare derivative works of, 31 | publicly display, publicly perform, sublicense and distribute its Work and 32 | any resulting derivative works in any form. 33 | 34 | 2.2 Patent Grant. Subject to the terms and conditions of this License, each 35 | Licensor grants to you a perpetual, worldwide, non-exclusive, royalty-free 36 | patent license to make, have made, use, sell, offer for sale, import, and 37 | otherwise transfer its Work, in whole or in part. The foregoing license 38 | applies only to the patent claims licensable by Licensor that would be 39 | infringed by Licensor's Work (or portion thereof) individually and 40 | excluding any combinations with any other materials or technology. 41 | 42 | 3. Limitations 43 | 44 | 3.1 Redistribution. You may reproduce or distribute the Work only if 45 | (a) you do so under this License, (b) you include a complete copy of this 46 | License with your distribution, and (c) you retain without modification 47 | any copyright, patent, trademark, or attribution notices that are present 48 | in the Work. 49 | 50 | 3.2 Derivative Works. You may specify that additional or different terms 51 | apply to the use, reproduction, and distribution of your derivative works 52 | of the Work ("Your Terms") only if (a) Your Terms provide that the use 53 | limitation in Section 3.3 applies to your derivative works, and (b) you 54 | identify the specific derivative works that are subject to Your Terms. 55 | Notwithstanding Your Terms, this License (including the redistribution 56 | requirements in Section 3.1) will continue to apply to the Work itself. 57 | 58 | 3.3 Use Limitation. The Work and any derivative works thereof only may be 59 | used or intended for use with the web services, computing platforms or 60 | applications provided by Amazon.com, Inc. or its affiliates, including 61 | Amazon Web Services, Inc. 62 | 63 | 3.4 Patent Claims. If you bring or threaten to bring a patent claim against 64 | any Licensor (including any claim, cross-claim or counterclaim in a 65 | lawsuit) to enforce any patents that you allege are infringed by any Work, 66 | then your rights under this License from such Licensor (including the 67 | grants in Sections 2.1 and 2.2) will terminate immediately. 68 | 69 | 3.5 Trademarks. This License does not grant any rights to use any 70 | Licensor's or its affiliates' names, logos, or trademarks, except as 71 | necessary to reproduce the notices described in this License. 72 | 73 | 3.6 Termination. If you violate any term of this License, then your rights 74 | under this License (including the grants in Sections 2.1 and 2.2) will 75 | terminate immediately. 76 | 77 | 4. Disclaimer of Warranty. 78 | 79 | THE WORK IS PROVIDED "AS IS" WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, 80 | EITHER EXPRESS OR IMPLIED, INCLUDING WARRANTIES OR CONDITIONS OF 81 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE OR 82 | NON-INFRINGEMENT. YOU BEAR THE RISK OF UNDERTAKING ANY ACTIVITIES UNDER 83 | THIS LICENSE. SOME STATES' CONSUMER LAWS DO NOT ALLOW EXCLUSION OF AN 84 | IMPLIED WARRANTY, SO THIS DISCLAIMER MAY NOT APPLY TO YOU. 85 | 86 | 5. Limitation of Liability. 87 | 88 | EXCEPT AS PROHIBITED BY APPLICABLE LAW, IN NO EVENT AND UNDER NO LEGAL 89 | THEORY, WHETHER IN TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE 90 | SHALL ANY LICENSOR BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY DIRECT, 91 | INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR 92 | RELATED TO THIS LICENSE, THE USE OR INABILITY TO USE THE WORK (INCLUDING 93 | BUT NOT LIMITED TO LOSS OF GOODWILL, BUSINESS INTERRUPTION, LOST PROFITS 94 | OR DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY OTHER COMM ERCIAL DAMAGES 95 | OR LOSSES), EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF 96 | SUCH DAMAGES. 97 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Alexa Skill Sample: Node.js test automation 2 | Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Test Automation for Alexa Skills 2 | 3 | # ** This repository has been archived ** 4 | This repository is still available as a point-in-time reference, but no further updates or support will be prioritized. 5 | 6 | ## **Related Resources** 7 | 8 | View [re:Invent workshop slides](https://www.slideshare.net/AmazonWebServices/alx315test-automation-for-alexa-skills) and check out the [Test SDK open-source project](https://github.com/KayLerch/alexa-skills-kit-tester-java) 9 | 10 | ## **Prerequisites** 11 | 12 | - **Amazon Developer Account** Go to the [Amazon developer console](https://developer.amazon.com/) to sign up for free in case you don't have an account yet. 13 | 14 | - **AWS Developer Account** Go to the [AWS Signup pages](https://portal.aws.amazon.com/billing/signup#/) to create an account in case you don't already have it. You need a valid credit card and access to your mobile phone. 15 | 16 | - **Node.js** is running on your system. If _$ node -v_ does not return a version number 17 | go to [Node.js downloads page](https://nodejs.org/en/download/) and install it. 18 | 19 | - **Alexa Skills Kit Commandline Interface** (ask-cli) is installed on your host. If _$ ask -v_ does not return a version number in your console, install it with _$ npm install -g ask-cli_. If you are using Linux, the installation may require _sudo_. More details can be found in the ask-cli [quickstart guide](https://developer.amazon.com/docs/smapi/quick-start-alexa-skills-kit-command-line-interface.html) 20 | 21 | ## **Getting Started** 22 | 23 | - Clone this Github repository on your local system. 24 | 25 | ```bash 26 | $ git clone https://github.com/alexa/skill-sample-nodejs-test-automation 27 | $ cd skill-sample-nodejs-test-automation 28 | ``` 29 | 30 | or [download](https://github.com/alexa/skill-sample-nodejs-test-automation/archive/master.zip) and unzip it 31 | 32 | ## **Lab guides** 33 | 34 | - [Lab01](labs/lab01.md): SMAPI and ASK CLI 35 | - [Lab02](labs/lab02.md): Service Simulator 36 | - [Lab03](labs/lab03.md): Skill Invocation API and Simulation API 37 | - [Lab04](labs/lab04.md): Set up the Test SDK and Client 38 | - [Lab05](labs/lab05.md): Single-turn conversations 39 | - [Lab06](labs/lab06.md): Multi-turn conversations 40 | - [Lab07](labs/lab07.md): Multi-path conversations 41 | - [Lab08](labs/lab08.md): Proactive Skill Monitoring 42 | 43 | ## **The Number Guessing Game skill** 44 | 45 | You will work with an already implemented skill. It's a simple but fun number guessing game. 46 | 47 | ![](assets/vui.png) -------------------------------------------------------------------------------- /assets/aws-stack.json: -------------------------------------------------------------------------------- 1 | { 2 | "AWSTemplateFormatVersion": "2010-09-09", 3 | "Description": "Stack creates an S3 Bucket for test scripts and a Lambda function with the Skill test client.", 4 | "Parameters": { 5 | "lwaClientId": { 6 | "Description": "Login With Amazon - Client Id // don't change it", 7 | "Default" : "amzn1.application-oa2-client.aad322b5faab44b980c8f87f94fbac56", 8 | "Type": "String", 9 | "MinLength": "1", 10 | "ConstraintDescription": "must contain a valid client id." 11 | }, 12 | "lwaClientSecret": { 13 | "Description": "Login With Amazon - Client Secret // don't change it", 14 | "Default" : "1642d8869b829dda3311d6c6539f3ead55192e3fc767b9071c888e60ef151cf9", 15 | "Type": "String", 16 | "MinLength": "1", 17 | "ConstraintDescription": "must contain a valid client secret." 18 | }, 19 | "lwaRefreshToken": { 20 | "Description": "Login With Amazon - Refresh token // get it from ~/.ask/cli_config on your machine", 21 | "Type": "String", 22 | "MinLength": "1", 23 | "ConstraintDescription": "must contain a valid refresh token." 24 | }, 25 | "skillId": { 26 | "Description": "The skill id of your number guessing game skill // get it from the Amazon developer portal", 27 | "Type": "String", 28 | "MinLength": "1", 29 | "ConstraintDescription": "must contain a valid refresh token." 30 | } 31 | }, 32 | "Resources": { 33 | "TestScriptBucket" : { 34 | "Type" : "AWS::S3::Bucket", 35 | "Properties" : { 36 | } 37 | }, 38 | "TestClientLambda": { 39 | "Type": "AWS::Lambda::Function", 40 | "Properties": { 41 | "Code": { 42 | "S3Bucket": "io.klerch.alexa.test", 43 | "S3Key": "alexa-skills-kit-tester-java-1.0.0.jar" 44 | }, 45 | "Environment" : { 46 | "Variables" : { 47 | "s3Bucket" : { "Ref" : "TestScriptBucket" }, 48 | "s3Path" : "", 49 | "skillId" : { "Ref" : "skillId" }, 50 | "lwaClientId" : { "Ref" : "lwaClientId" }, 51 | "lwaClientSecret" : { "Ref" : "lwaClientSecret" }, 52 | "lwaRefreshToken" : { "Ref" : "lwaRefreshToken" } 53 | } 54 | }, 55 | "FunctionName": "reinvent-alx315-test-client", 56 | "Handler": "io.klerch.alexa.test.Lambda", 57 | "MemorySize": "1024", 58 | "Role": { "Fn::GetAtt": [ "TestClientExecutionRole", "Arn" ] }, 59 | "Runtime": "java8", 60 | "Timeout": "300" 61 | } 62 | }, 63 | "TestClientExecutionRole": { 64 | "Type": "AWS::IAM::Role", 65 | "Properties": { 66 | "AssumeRolePolicyDocument": { 67 | "Version": "2012-10-17", 68 | "Statement": [ 69 | { 70 | "Effect": "Allow", 71 | "Principal": { 72 | "Service": [ "lambda.amazonaws.com" ] 73 | }, 74 | "Action": [ "sts:AssumeRole" ] 75 | } 76 | ] 77 | }, 78 | "Policies": [ 79 | { 80 | "PolicyName": "reinvent-alx315-test-client-s3-policy", 81 | "PolicyDocument": { 82 | "Version": "2012-10-17", 83 | "Statement": [ 84 | { 85 | "Effect": "Allow", 86 | "Action": [ 87 | "s3:ListBucket", 88 | "s3:ListObjects" 89 | ], 90 | "Resource": { "Fn::GetAtt": [ "TestScriptBucket", "Arn" ] } 91 | }, 92 | { 93 | "Effect": "Allow", 94 | "Action": [ 95 | "s3:GetObject" 96 | ], 97 | "Resource": { "Fn::Join" : [ "/", [ { "Fn::GetAtt": [ "TestScriptBucket", "Arn" ] }, "*" ] ] } 98 | }, 99 | { 100 | "Effect": "Allow", 101 | "Action": [ 102 | "logs:CreateLogGroup", 103 | "logs:CreateLogStream", 104 | "logs:PutLogEvents" 105 | ], 106 | "Resource": "*" 107 | } 108 | ] 109 | } 110 | } 111 | ] 112 | } 113 | } 114 | }, 115 | "Outputs": { 116 | "LambdaName": { 117 | "Value": { "Ref": "TestClientLambda" }, 118 | "Description": "The Lambda function" 119 | }, 120 | "S3Bucket": { 121 | "Value": { "Ref": "TestScriptBucket" }, 122 | "Description": "Upload your YAML script files into this S3 bucket. All scripts in this bucket will be executed by the Lambda function." 123 | } 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /assets/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "session": { 3 | "new": true, 4 | "sessionId": "SessionId.68be57e6-41d2-4dcb-817c-19fd970f15c0", 5 | "application": { 6 | "applicationId": "amzn1.ask.skill.3c38a39f-3da9-4cd1-803d-9056c724d4af" 7 | }, 8 | "attributes": {}, 9 | "user": { 10 | "userId": "amzn1.ask.account.AFJPCFRBCDLWOLW2672HS7PA7JH6DCCUFMPA25SBKFAJUJP7ESNCQRXE6YTTSEDOFLQFXPVEBRPAIZENOUVZKRVRMHWICU4QJB2ZAP6N2OCGGEA7WGV4QRXZNJ5GTSOJG7VENYFFRGNEWM3A3IMXH5H4UT2KTCHHEEOH6S3L3ASYBBS3H3SYP7QV7P7VADLMDT7XUO4ETPFBVQY" 11 | } 12 | }, 13 | "request": { 14 | "type": "LaunchRequest", 15 | "requestId": "EdwRequestId.6fad3ef2-b3fd-45fa-86b1-933606456109", 16 | "locale": "en-US", 17 | "timestamp": "2017-11-28T04:08:12Z" 18 | }, 19 | "context": { 20 | "AudioPlayer": { 21 | "playerActivity": "IDLE" 22 | }, 23 | "System": { 24 | "application": { 25 | "applicationId": "amzn1.ask.skill.3c38a39f-3da9-4cd1-803d-9056c724d4af" 26 | }, 27 | "user": { 28 | "userId": "amzn1.ask.account.AFJPCFRBCDLWOLW2672HS7PA7JH6DCCUFMPA25SBKFAJUJP7ESNCQRXE6YTTSEDOFLQFXPVEBRPAIZENOUVZKRVRMHWICU4QJB2ZAP6N2OCGGEA7WGV4QRXZNJ5GTSOJG7VENYFFRGNEWM3A3IMXH5H4UT2KTCHHEEOH6S3L3ASYBBS3H3SYP7QV7P7VADLMDT7XUO4ETPFBVQY" 29 | }, 30 | "device": { 31 | "supportedInterfaces": {} 32 | } 33 | } 34 | }, 35 | "version": "1.0" 36 | } -------------------------------------------------------------------------------- /assets/vui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/assets/vui.png -------------------------------------------------------------------------------- /js/assets.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2017 Amazon.com, Inc. and its affiliates. All Rights Reserved. 3 | Licensed under the Amazon Software License (the "License"). 4 | You may not use this file except in compliance with the License. 5 | A copy of the License is located at 6 | http://aws.amazon.com/asl/ 7 | or in the "license" file accompanying this file. This file is distributed 8 | on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express 9 | or implied. See the License for the specific language governing 10 | permissions and limitations under the License. 11 | 12 | This skill demonstrates how to automate testing an Alexa skill. 13 | **/ 14 | 15 | "use strict"; 16 | 17 | module.exports = Object.freeze({ 18 | numberLimit : 10, 19 | welcome : 'welcome to the number guessing skill.', 20 | welcomeBack : 'welcome back to the number guessing skill.', 21 | help : 'this skill is your game master for a simple number guessing game. Do you want to start a game now?', 22 | helpReprompt : 'do you want to start a game now?', 23 | guess : 'I am thinking of a number between one and 10. What is your guess?', 24 | correct : 'Great. That’s it. You want more?', 25 | incorrect: 'Sorry. That’s not correct.', 26 | numberNotSaid: 'Sorry, I was not able to get the number you said. Please answer with a number.', 27 | numberIsLower: 'My number is lower than', 28 | numberIsHigher: 'My number is higher than', 29 | sorry : 'sorry, something went wrong. say start a quiz or stop to exit.', 30 | goodBye : 'Good bye.' 31 | }); -------------------------------------------------------------------------------- /js/constants.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2017 Amazon.com, Inc. and its affiliates. All Rights Reserved. 3 | Licensed under the Amazon Software License (the "License"). 4 | You may not use this file except in compliance with the License. 5 | A copy of the License is located at 6 | http://aws.amazon.com/asl/ 7 | or in the "license" file accompanying this file. This file is distributed 8 | on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express 9 | or implied. See the License for the specific language governing 10 | permissions and limitations under the License. 11 | 12 | This skill demonstrates how to automate testing an Alexa skill. 13 | **/ 14 | 15 | "use strict"; 16 | 17 | module.exports = Object.freeze({ 18 | // enter your skill-id here 19 | appId : '', 20 | // enter the name for a Dynamo table that is created on first execution 21 | dynamoDBTableName : 'io.klerch.alexa.numberguess' 22 | }); 23 | -------------------------------------------------------------------------------- /js/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2017 Amazon.com, Inc. and its affiliates. All Rights Reserved. 3 | Licensed under the Amazon Software License (the "License"). 4 | You may not use this file except in compliance with the License. 5 | A copy of the License is located at 6 | http://aws.amazon.com/asl/ 7 | or in the "license" file accompanying this file. This file is distributed 8 | on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express 9 | or implied. See the License for the specific language governing 10 | permissions and limitations under the License. 11 | 12 | This skill demonstrates how to automate testing an Alexa skill. 13 | **/ 14 | 15 | 'use strict'; 16 | 17 | var Alexa = require('alexa-sdk'); 18 | var constants = require('./constants'); 19 | var stateHandlers = require('./stateHandlers'); 20 | 21 | exports.handler = function(event, context, callback) { 22 | var alexa = Alexa.handler(event, context, callback); 23 | //alexa.appId = constants.appId; 24 | alexa.dynamoDBTableName = constants.dynamoDBTableName; 25 | alexa.registerHandlers(stateHandlers); 26 | alexa.execute(); 27 | }; 28 | -------------------------------------------------------------------------------- /js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "io-klerch-alexa-number-guessing", 3 | "version": "1.0.0", 4 | "description": "Guess the number Alexa thinks of.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [ 10 | "alexa", 11 | "number guessing", 12 | "demo" 13 | ], 14 | "author": "Kay Lerch", 15 | "license": "See license in ../LICENSE.txt", 16 | "dependencies": { 17 | "alexa-sdk": "^1.0.14" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "https://github.com/KayLerch/io-klerch-alexa-number-guessing" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /js/serverless.yml: -------------------------------------------------------------------------------- 1 | service: io-klerch-alexa-numberguess 2 | 3 | provider: 4 | name: aws 5 | stage: prod 6 | runtime: nodejs6.10 7 | region: us-east-1 8 | memorySize: 1024 9 | timeout: 8 10 | versionFunctions: false 11 | iamRoleStatements: 12 | - Effect: Allow 13 | Action: 14 | - dynamodb:DescribeTable 15 | - dynamodb:Query 16 | - dynamodb:GetItem 17 | - dynamodb:PutItem 18 | - dynamodb:UpdateItem 19 | - dynamodb:DeleteItem 20 | - dynamodb:CreateTable 21 | Resource: "arn:aws:dynamodb:us-east-1:*:table/io.klerch.alexa.numberguess" 22 | 23 | functions: 24 | skill: 25 | name: ${self:service}-skill 26 | handler: index.handler 27 | events: 28 | - alexaSkill -------------------------------------------------------------------------------- /js/stateHandlers.js: -------------------------------------------------------------------------------- 1 | /** 2 | Copyright 2017 Amazon.com, Inc. and its affiliates. All Rights Reserved. 3 | Licensed under the Amazon Software License (the "License"). 4 | You may not use this file except in compliance with the License. 5 | A copy of the License is located at 6 | http://aws.amazon.com/asl/ 7 | or in the "license" file accompanying this file. This file is distributed 8 | on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, express 9 | or implied. See the License for the specific language governing 10 | permissions and limitations under the License. 11 | 12 | This skill demonstrates how to automate testing an Alexa skill. 13 | **/ 14 | 15 | 'use strict'; 16 | 17 | var Alexa = require('alexa-sdk'); 18 | var constants = require('./constants'); 19 | var assets = require('./assets'); 20 | 21 | var welcomeSpeech = ''; 22 | 23 | var stateHandlers = { 24 | 'LaunchRequest': function () { 25 | welcomeSpeech = (this.attributes['hasAlreadyBeenHere']) ? assets.welcomeBack : assets.welcome; 26 | this.emit('StartQuiz'); 27 | }, 28 | 'StartQuiz': function () { 29 | if (this.attributes['number']) { 30 | this.emit(':ask', assets.numberNotSaid); 31 | } 32 | if (!this.attributes['hasAlreadyBeenHere']) { 33 | this.attributes['hasAlreadyBeenHere'] = 1; 34 | } 35 | this.attributes['number'] = (Math.floor(Math.random() * (assets.numberLimit - 1))) + 1; 36 | this.response.speak(welcomeSpeech + ' ' + assets.guess).listen(assets.guess); 37 | this.emit(':responseReady'); 38 | }, 39 | 'GuessNumber': function () { 40 | var targetNum = (this.attributes['number'] || -1); 41 | 42 | var guessNumber = parseInt(this.event.request.intent.slots.number.value); 43 | 44 | if (targetNum === guessNumber) { 45 | // reset number 46 | this.attributes['number'] = null; 47 | this.emit(':ask', assets.correct); 48 | } else { 49 | var outputSpeech = assets.incorrect + ' ' + (targetNum > guessNumber ? assets.numberIsHigher : assets.numberIsLower) + ' ' + guessNumber + '

' + assets.guess + '

'; 50 | this.emit(':ask', outputSpeech); 51 | } 52 | }, 53 | 'AMAZON.YesIntent': function () { 54 | this.emit('StartQuiz'); 55 | }, 56 | 'AMAZON.NoIntent': function () { 57 | this.emit('AMAZON.StopIntent'); 58 | }, 59 | 'AMAZON.HelpIntent': function () { 60 | this.response.speak(assets.help).listen(assets.helpReprompt); 61 | this.emit(':responseReady'); 62 | }, 63 | 'AMAZON.CancelIntent': function () { 64 | this.emit('AMAZON.StopIntent'); 65 | }, 66 | 'AMAZON.StopIntent': function () { 67 | this.attributes['number'] = null; 68 | this.response.speak(assets.goodBye); 69 | this.emit(':responseReady'); 70 | }, 71 | 'SessionEndedRequest': function () { 72 | }, 73 | 'Unhandled': function() { 74 | this.response.speak(assets.sorry).listen(assets.sorry); 75 | this.emit(':responseReady'); 76 | } 77 | }; 78 | 79 | module.exports = stateHandlers; -------------------------------------------------------------------------------- /labs/img/lab02-screen01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/labs/img/lab02-screen01.png -------------------------------------------------------------------------------- /labs/img/lab02-screen02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/labs/img/lab02-screen02.png -------------------------------------------------------------------------------- /labs/img/lab03-screen01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/labs/img/lab03-screen01.png -------------------------------------------------------------------------------- /labs/img/lab03-screen02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/labs/img/lab03-screen02.png -------------------------------------------------------------------------------- /labs/img/lab04-screen01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/labs/img/lab04-screen01.png -------------------------------------------------------------------------------- /labs/img/lab04-screen02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/labs/img/lab04-screen02.png -------------------------------------------------------------------------------- /labs/img/lab04-screen03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/labs/img/lab04-screen03.png -------------------------------------------------------------------------------- /labs/img/lab04-screen04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/labs/img/lab04-screen04.png -------------------------------------------------------------------------------- /labs/img/lab04-screen05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/labs/img/lab04-screen05.png -------------------------------------------------------------------------------- /labs/img/lab04-screen06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/labs/img/lab04-screen06.png -------------------------------------------------------------------------------- /labs/img/lab04-screen07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/labs/img/lab04-screen07.png -------------------------------------------------------------------------------- /labs/img/lab08-screen01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/labs/img/lab08-screen01.png -------------------------------------------------------------------------------- /labs/img/lab08-screen02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/labs/img/lab08-screen02.png -------------------------------------------------------------------------------- /labs/img/lab08-screen03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/labs/img/lab08-screen03.png -------------------------------------------------------------------------------- /labs/img/lab08-screen04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/alexa-samples/skill-sample-nodejs-test-automation/865231f299701b72839e5916f640c218a175fa0d/labs/img/lab08-screen04.png -------------------------------------------------------------------------------- /labs/lab01.md: -------------------------------------------------------------------------------- 1 | [<< Home](../README.md) | **Lab 1** | [Lab 2 >>](lab02.md) 2 | 3 | # Lab Guide 1 - SMAPI and ASK CLI 4 | 5 | ## **What you will do in this lab** 6 | 7 | Work with Alexa Skills Kit Commandline Interface (ask-cli) tool to set up a Custom Alexa skill with the Skill Management API (SMAPI). 8 | 9 | ## **What you will get at the end of this lab** 10 | 11 | You have learned how to set up a new skill with ask-cli in an automated fashion. 12 | 13 | ## **Instructions** 14 | 15 | ### **1.1.) Initialize ask-cli** 16 | 17 | If you never used ask-cli before, you need to initialize it and authorize this tool for your Amazon developer account 18 | 19 | ```bash 20 | $ ask configure 21 | ``` 22 | 23 | and select **Create new Profile**. Skip the input of a profile name by hitting Enter. Also, **skip AWS credential for ask-cli** as we don't need it. A browser window opens. Follow the login procedure by using your Amazon developer account credentials and grant this tool permission to create and update Alexa skills. 24 | 25 | **Side note:** We won't deploy the skill backend (Lambda function) which you can find in the [./js](../js)-folder. It is already hosted for you in another AWS account and your skill will just point to it and use it. That is why we skipped authorization for AWS in the initialization step. See the homework instructions below in case you would like to deploy the code as part of the skill creation / update procedure via ask-cli. 26 | 27 | ### **1.2.) Familiarize with the skill** 28 | 29 | Navigate to the folder where you cloned this Github repo. 30 | 31 | The [skill.json](../skill.json) file contains metadata used to create the skill. It also has a reference to an existing Lambda function as the skill backend is already implemented and hosted for you. If you're interested in the source code you can look into the [js](../js)-folder 32 | 33 | The [./models/en-US.json](../models/en-US.json) in this repo contains the interaction model of the skill. Leave it as is. It is all set for you. However, it's worth having a quick look into it in order to understand what the skill expects its users to say. 34 | 35 | ### **1.3.) Deploy the skill** 36 | 37 | Now that you got a basic idea of what this skill will look like you can deploy it to your Amazon developer account with one single command. Run the below from within the root folder of this repo on your local drive. 38 | 39 | ```bash 40 | $ ask deploy 41 | ``` 42 | 43 | This execution may take 2-3 minutes to complete. Ignore the _[Warning]: Lambda deployment skipped, since AWS credentialsfor profile: [default] is missing._ you will get at the end. 44 | 45 | Once the deployment is finished double-check if the skill has been created in your Amazon developer account by running the following command. 46 | 47 | ```bash 48 | $ ask api list-skills 49 | ``` 50 | 51 | Do you see a skill entry called _Number guessing game_? Great! 52 | 53 | ### **Just in case you got some time ...** 54 | 55 | Already done? You can dive deeper into ask-cli [here](https://developer.amazon.com/docs/smapi/ask-cli-command-reference.html) and try out a few other commands if you like. You could also dig into the [skill code](../js) to learn how it is implemented. 56 | 57 | ### **Homework** 58 | 59 | When you were initializing ask-cli in the first step of this lab you skipped authorizing with your AWS credentials. You didn't need it at this point as you were creating a skill using an already existing Lambda function. At home you might want to upload and host the code of this skill in your own AWS account. 60 | 61 | 1. Follow the ask-cli [quickstart guide](https://developer.amazon.com/docs/smapi/quick-start-alexa-skills-kit-command-line-interface.html) and give this tool access to your AWS account. 62 | 63 | 2. Next, you should go to the [skill.json](../skill.json) file in order to change the endpoint configuration which is part of the _apis_ element node. Replace the _uri_ parameter beneath _endpoint_ with _"sourceDir": "./js/."_ and _ask deploy_ your skill again. For more information go to [ask-cli reference](https://developer.amazon.com/docs/smapi/ask-cli-command-reference.html#deploy-command) in the developer documentation. 64 | 65 | [<< Home](../README.md) | **Lab 1** | [Lab 2 >>](lab02.md) 66 | -------------------------------------------------------------------------------- /labs/lab02.md: -------------------------------------------------------------------------------- 1 | [<< Lab 1](lab01.md) | **Lab 2** | [Lab 3 >>](lab03.md) 2 | 3 | # Lab Guide 2 - Service Simulator 4 | 5 | ## **What you will do in this lab** 6 | Work with the Service Simulator tool in the [Amazon developer console](https://developer.amazon.com/) to manually test your freshly created Alexa skill. 7 | 8 | ## **What you will get at the end of this lab** 9 | You have learned how to send utterances to your skill and how to examine the resulting request and response payloads send to and received from your skill Lambda endpoint. 10 | 11 | ## **Prerequisites** 12 | 13 | - **Skill** which has been deployed to your Amazon developer account in [Lab 1](lab01.md). 14 | 15 | ## **Instructions** 16 | 17 | ### **2.1.) Play with Service Simulator** 18 | 19 | **2.1.1.** Go to the [Amazon developer console](https://developer.amazon.com/) and sign in. Select __Developer Console__ in the header section and navigate to __Alexa__. Click on __Alexa Skills Kit__. You should see the list of your skills - with _Number guessing game_ being one of them. 20 | Click on the skill name __Number guessing game__ and go to the __Test__ section in the left menu. 21 | 22 | **2.1.2.** Enable testing for this skill for your developer account just in case it is not already showing up as _Enabled_. 23 | 24 | ![](img/lab02-screen02.png) 25 | 26 | **2.1.3.** You can now _Enter an Utterance_ and click on _Ask number guessing game_ to send the entered utterance to the skill endpoint. 27 | 28 | ![](img/lab02-screen01.png) 29 | 30 | In the underneath section you can examine the request and response payloads sent to and returned from the skill. Continue the dialog and interact with the skill by following the instructions returned by the skill (outputspeech portion in the response contains what Alexa would say to the user). The below Voice User Interface Diagram of the skill will help you. 31 | 32 | __Side note: Numbers in utterances__: The Service Simulator does not resolve numbers in utterances when written as integers (e.g. "the number is 10"). Instead, you should always use numerals (e.g. "the number is **ten**"). 33 | 34 | **2.1.4.** Extra points: Go to [Echosim.io](https://echosim.io) and test this skill with your voice. Once you 35 | logged in with your Amazon developer credentials you can hold down the space bar and start speaking - release the space bar when you'd like to finish your voice input. Start with _'open number guessing'_. 36 | 37 | ![](../assets/vui.png) 38 | 39 | [<< Lab 1](lab01.md) | **Lab 2** | [Lab 3 >>](lab03.md) -------------------------------------------------------------------------------- /labs/lab03.md: -------------------------------------------------------------------------------- 1 | [<< Lab 2](lab02.md) | **Lab 3** | [Lab 4 >>](lab04.md) 2 | 3 | # Lab Guide 3 - Skill Invocation API and Simulation API 4 | 5 | ## **What you will do in this lab** 6 | Use the Skill Invocation API and Skill Simulation API - part of SMAPI - to test an Alexa skill by using ask-cli 7 | 8 | ## **What you will get at the end of this lab** 9 | You have learned how to fire requests at your skill by using the ask-cli. 10 | 11 | ## **Prerequisites** 12 | 13 | - **Number guessing skill** which has been deployed to your Amazon developer account in [Lab 1](lab01.md). 14 | 15 | - **Testing is enabled** for the _number guessing game_ skill. You should be fine if you followed step 2 in [Lab 2](lab02.md) 16 | 17 | ## **Instructions** 18 | 19 | ### **3.1.) Invoke a skill with ask-cli** 20 | 21 | **3.1.1.** Go back to the Service Simulator of the _number guessing game_ skill in your [Amazon developer console](https://developer.amazon.com/). Again, enter _"start number guessing"_ and hit the _Ask ..._ button. 22 | 23 | ![](img/lab02-screen01.png) 24 | 25 | **3.1.2.** Copy the request payload from the left textbox and paste it into the existing but empty [./assets/launch.json](../assets/launch.json) file and save your changes. 26 | 27 | **3.1.3.** Next you go to the commandline and use ask-cli to fire the same request at your skill using the Invocation API. Run the following command from within the root folder of this repository. 28 | 29 | ```bash 30 | $ ask api invoke-skill -e NA -s {skillId} -f assets/launch.json 31 | ``` 32 | - where _{skillId}_ needs to be replaced with the id of your skill you can find in the Amazon developer console (see screenshot below) or in the request payload you just copied (referred to as _applicationId_). 33 | 34 | ![](img/lab03-screen01.png) 35 | 36 | An example: 37 | ```bash 38 | $ ask api invoke-skill -e NA -s amzn1.ask.skill.b440f3d5-2a08-47ab-xxxx-495abbfxxxxd -f assets/launch.json 39 | ``` 40 | 41 | **3.1.4.** Inspect the returned response payload printed out in the console and try answer the following questions. 42 | 43 | __Q3.1.5__: Is the status of the request SUCCESSFUL? 44 | 45 | __Q3.1.6__: Is the skill session left open? 46 | 47 | __Q3.1.7__: Can you spot the number Alexa thinks of in the current skill session? Prove it by typing in the correct answer in the Service Simulator where you just copied the request payload. 48 | 49 | ### **3.2.) Simulate user interaction** 50 | 51 | Instead of sending an entire payload to the skill endpoint, you will now just give it a written utterance as you would it give it to your skill via voice. 52 | 53 | __Please note__: Simulation API currently does not support multi-turn dialogs. That being said you can only test modal invocations (e.g. _"ask number guessing"_) or one-shot invocations (e.g. _"ask number guessing for help"_). 54 | 55 | **3.2.1.** Run the following command in your commandline tool: 56 | 57 | ```bash 58 | $ ask api simulate-skill -l en-US -s {skillId} -t '{utteranceText}' 59 | ``` 60 | - where _{skillId}_ needs to be replaced with the id of your skill 61 | - where _{utteranceText}_ needs to be replaced by the text you'd like to send to the skill. It needs to be a valid modal or one-shot invocation starting with _"{ ask | open | start } number guessing ..."_. 62 | 63 | An example: 64 | ```bash 65 | $ ask api simulate-skill -l en-US -s amzn1.ask.skill.b440f3d5-2a08-47ab-xxxx-495abbfxxxxd -t 'start number guessing' 66 | ``` 67 | 68 | ![](img/lab03-screen02.png) 69 | 70 | **3.2.2.** Simulation API processes requests asynchronously. The response you get from above command contains an _id_ you can use to retrieve the actual response from the skill: 71 | 72 | ```bash 73 | $ ask api get-simulation -s {skillId} -i {simulationId} 74 | ``` 75 | - where _{skillId}_ needs to be replaced with the id of your skill 76 | - where _{simulationId}_ needs to be replaced by the id returned by a _simulate-skill_ call (see screenshot) 77 | 78 | An example: 79 | ```bash 80 | $ ask api get-simulation -s amzn1.ask.skill.b440f3d5-2a08-47ab-xxxx-495abbfxxxxd -i d41b28a2-61f8-4fc3-a366-da49029cxxxx 81 | ``` 82 | 83 | **3.2.3.** Inspect the returned payload. It should look familiar to you as it is almost the same as returned by the Invocation API. 84 | 85 | ### **3.3.) Extended testing** 86 | 87 | **3.3.1.** try to ask this skill for help by using the Invocation API 88 | 89 | **3.3.2.** try to ask this skill for help by using the Simulation API 90 | 91 | **3.3.3.** try to bypass the welcome speech by using the Invocation API 92 | 93 | **3.3.4.** try to bypass the welcome speech by using the Simulation API 94 | 95 | ![](../assets/vui.png) 96 | 97 | [<< Lab 2](lab02.md) | **Lab 3** | [Lab 4 >>](lab04.md) -------------------------------------------------------------------------------- /labs/lab04.md: -------------------------------------------------------------------------------- 1 | [<< Lab 3](lab03.md) | **Lab 4** | [Lab 5 >>](lab05.md) 2 | 3 | # Lab Guide 4 - Set up the Test SDK and Client 4 | 5 | ## **What you will do in this lab** 6 | The [Test SDK](https://github.com/KayLerch/alexa-skills-kit-tester-java) is an opensource project on Github which uses SMAPI in a similar way ask-cli does. It keeps track of session state and supports multi-turn dialogs. You'll configure the client tool in this lab to get started for the next labs. 7 | 8 | ## **What you will get at the end of this lab** 9 | You have learned how to configure the Test SDK tool and fire a request at the skill that has been defined in a YAML script file. 10 | 11 | ## **Instructions** 12 | 13 | We will use generic Login With Amazon _clientId_ and _clientSecret_ and use the _refreshToken_ generated by 14 | ask-cli in the previous lab. This is just to make the process of setting things up in this workshop easier. 15 | When you're back home, you should set up your _clientId_ and _clientSecret_ and generate your own _refreshToken_. There's a [homework lab](lab04_hw.md) prepared for you with detailled instructions. 16 | 17 | ### **4.1) Deploy the test environment in AWS** 18 | 19 | You will use a CloudFormation template to create an S3 bucket and a Lambda function which hosts the test client tool written in Java. 20 | 21 | **4.1.1.** Go to the [AWS management console](https://console.aws.amazon.com/console/home) and log in with your AWS credentials. 22 | 23 | **4.1.2.** Go to _Services_ -> _CloudFormation_ and click on __Create Stack__. 24 | 25 | **4.1.3.** Select __Upload a template to Amazon S3__ and __Choose file__. Navigate to [./assets/aws-stack.json](../assets/aws-stack.json) in this repo. Click __Next__. 26 | 27 | **4.1.4.** Set the following 28 | - __Stack name:__ reinvent-alx315 29 | - __lwaClientId, lwaClientSecret__ are already set for you. Those are generic credentials ask-cli used to generate your _refreshToken_. 30 | - __lwaRefreshToken:__ on your local machine, navigate to your home folder (_$ cd ~_) and open the _.ask/cli_config_ file. ask-cli created it to store your settings when you initialized the tool in the first lab. Copy the _refreshToken_ you find in this file and paste it into the CloudFormation setup page. Please note, if you're not seeing the _.ask_ folder in your home directory, tell your file explorer to also show hidden objects. 31 | - __skillId:__ Here goes the skill-Id of your _number guessing game_ skill. Return to the Amazon developer portal to get it. 32 | 33 | ![](img/lab04-screen06.png) 34 | 35 | Click on __Next__. 36 | 37 | **4.1.5.** Click on __Next__. 38 | 39 | **4.1.6.** Confirm __I acknowledge that AWS CloudFormation might create IAM resources.__ and click on __Create__. 40 | 41 | The stack creates an S3 bucket and a Lambda function which hosts the test client. When the status indicates _CREATE_COMPLETE_ go to the _Resources_ tab at the bottom of this page. 42 | 43 | ![](img/lab04-screen07.png) 44 | 45 | **4.1.7.** In the _Resources_ tab you should see three resources which have been created in your AWS account. Follow the links to the _TestClientLambda_ and _TestScriptBucket_ resource. Each of them will open in up in a new browser tab. Leave them open until the end of this workshop as you will return to your S3 bucket and Lambda function in the upcoming labs. 46 | 47 | ### **4.2) Run your first test script** 48 | 49 | We recommend you to use an advanced text editor or IDE. You could also use an [Online YAML editor](https://codebeautify.org/yaml-validator) if you want. 50 | 51 | **4.2.1.** Navigate to the [./scripts/lab04.yml](../scripts/lab04.yml) in this repo. This is your first conversation test script. Look at it and familiarize with its content. 52 | 53 | **4.2.2.** Return to the S3 bucket windows in your browser. The bucket should have a name similar to _reinvent-alx315-testscriptbucket-xxxxxxxxxx_. 54 | 55 | **4.2.3.** __Upload__ the [./scripts/lab04.yml](../scripts/lab04.yml) from your local drive into this bucket. 56 | 57 | **4.2.4.** Switch to the browser tab of your _reinvent-alx315-test-client_ Lambda function. Look at the environment variables already set for you. This Lambda function will access the referenced skill by using your Login With Amazon token. 58 | 59 | **4.2.5.** Hit __Test__ to execute the Lambda function. You might have to configure a test event first. Choose the _Hello World_ example event as the Lambda function does not expect anything specific as an input. 60 | 61 | **4.2.6.** Look at the _log output_ once the Lambda execution is finished. 62 | 63 | __Q4.2.7__: From what is in the [./scripts/lab04.yml](../scripts/lab04.yml) and in the Lambda _log output_, can you describe what just happened? 64 | 65 | Congratulations. You ran your first automated test. 66 | 67 | [<< Lab 3](lab03.md) | **Lab 4** | [Lab 5 >>](lab05.md) -------------------------------------------------------------------------------- /labs/lab04_hw.md: -------------------------------------------------------------------------------- 1 | [<< Lab 4](lab04.md) | **Lab 4 Homework** | [Lab 5 >>](lab05.md) 2 | 3 | # Lab Guide 4 Homework - Create Login With Amazon credentials 4 | 5 | In this workshop we used generic Login With Amazon _clientId_ and _clientSecret_. However, we recommend 6 | you to create your own credentials in the Amazon developer portal. Follow the below instructions to create 7 | a security profile and generate a refresh token for the test client to access your skills. 8 | 9 | __Side Note:__ When you're working with your own _clientId_ and _clientSecret_ you cannot reuse the _refreshToken_ generated and stored in ~/ask/cli_config_ by ask-cli. You really need to generate your own 10 | by using your _clientId_ and _clientSecret_ as described below. 11 | 12 | ## **Instructions** 13 | 14 | ### **4.1) Set up Login With Amazon (LWA) credentials** 15 | 16 | LWA credentials are required by the test client to get access to your skill. You need three things: a _client-id_, a _client-secret_ and _refresh-token_ from LWA. 17 | 18 | **4.1.1.** Go to the [Amazon developer console](https://developer.amazon.com/), click on _Developer Console_ in the header section and navigate to _Apps & Services_ 19 | 20 | **4.1.2.** Click on _Login With Amazon_ and _Create A New Security Profile_ 21 | 22 | ![](img/lab04-screen01.png) 23 | 24 | **4.1.3.** Give it a name, description and policy-url _https://example.com_ as suggested below and hit _Save_. 25 | 26 | ![](img/lab04-screen02.png) 27 | 28 | **4.1.4.** Click on _Show ClientID and Secret_. Copy the client-id and client-secret. 29 | 30 | **4.1.5.** Back in the browser, go to _Manage_ -> _Web Settings_ and click on _Edit_. Set _https://example.com_ as the _Allowed Return Url_. 31 | 32 | **4.1.6.** Browse to 33 | 34 | https://www.amazon.com/ap/oa?client_id=__{clientId}__&scope=alexa::ask:skills:test&response_type=code&redirect_uri=https://example.com 35 | 36 | after you replaced __{clientId}__ with your clientId you pasted into the lab04.yml file 37 | 38 | **4.1.7.** Follow the authentication and authorization procedure. You end up being redirected to example.com. Look at the URL in the address line of your browser. It should contain an authorization _code_. 39 | 40 | **4.1.8.** Take the code you retrieved in the previous step and use it in the following HTTP POST request command in your local shell. 41 | 42 | ```bash 43 | curl -d "client_id={clientId}&client_secret={secret}&code={code}&grant_type=authorization_code&redirect_uri=https://example.com" -H "Content-Type: application/x-www-form-urlencoded" -X POST https://api.amazon.com/auth/o2/token 44 | ``` 45 | - where _{clientId}_ needs to be replaced by the clientId you got in step 4.1.4. 46 | - where _{secret}_ needs to be replaced by the clientSecret you got in step 4.1.4. 47 | - where _{code}_ needs to be replaced by the authorization code you received in step 4.1.7. 48 | 49 | This curl command returns a JSON payload that contains the refresh token you need. Copy it. 50 | 51 | **Side note** If you made a mistake in step 4.1.8. and retrieve an error it is necessary to return to step 4.1.6. as the authorization code is only valid for one request. 52 | 53 | [<< Lab 4](lab04.md) | **Lab 4 Homework** | [Lab 5 >>](lab05.md) -------------------------------------------------------------------------------- /labs/lab05.md: -------------------------------------------------------------------------------- 1 | [<< Lab 4](lab04.md) | **Lab 5** | [Lab 6 >>](lab06.md) 2 | 3 | # Lab Guide 5 - Single-turn conversations 4 | 5 | ## **What you will do in this lab** 6 | You will set up a single-turn conversation with the skill and make a few assertions on the expected response by using the Test SDK tool. 7 | 8 | ## **What you will get at the end of this lab** 9 | You have learned how to define assertions on returned skill responses in a YAML script file and know how to execute the script with help of a Lambda function. 10 | 11 | ## **Prerequisites** 12 | 13 | - **Test Lambda function** you deployed in [Lab 4](lab04.md) 14 | - **S3 Test script bucket** that was created in [Lab 4](lab04.md) 15 | - **Number guessing skill** that was deployed to your Amazon developer account in [Lab 1](lab01.md) 16 | 17 | We recommend you to use an advanced text editor or IDE. You could also use an [Online YAML editor](https://codebeautify.org/yaml-validator) if you want. 18 | 19 | ## **Instructions** 20 | 21 | ### **5.1.) Single-turn conversation with Invocation API** 22 | 23 | **5.1.1.** Open [./scripts/lab05.yml](../scripts/lab05.yml). 24 | 25 | __Side note:__ The hash (#)-sign in front of a line indicates a commentary in YAML. It will be ignored by the test client and is just to help you with some extra information. 26 | 27 | **5.1.2.** The _Launch_ node is the entry point for the test client. If neither an _intent_ nor an _utterance_ is provided (both are currently commented out), it fires a _LaunchRequest_ at your skill. That's what already happened in Lab 4. There's already one assertion made for the resulting response of the _LaunchRequest_. 28 | 29 | **Q5.1.3.** What does the assertion in [lab05.yml](../scripts/lab05.yml) mean? 30 | 31 | You will now make some changes to the script file and run it with help of the Test Lambda function. Whenever you would like to run it, follow these steps: 32 | - save your changes made in the YAML file 33 | - upload the respective YAML file to the S3 bucket like you did in [Lab 4](lab04.md) 34 | - go to the Test Lambda function in the AWS developer console and execute it like you did in [Lab 4](lab04.md) 35 | 36 | __Side note__: The Lambda function will execute all YAML scripts it finds in the S3 bucket one by one unless you remove them from the bucket. 37 | 38 | Now it's your turn. Try the following and upload and run the script as described above after each change. 39 | 40 | **5.1.4** Uncomment line 8 of [lab05.yml](../scripts/lab05.yml) and run it. What happens and why does it fail? 41 | 42 | **5.1.5** Try to fix the script by changing the assertion and upload the file again. When running the Lambda function, the response should be "Ok" again. 43 | 44 | **5.1.6.** Comment out line 8 again - we'd like to proceed with _LaunchRequest_ (don't forget to negate the assertion again). Now write at least three more assertions on the response returned by the skill. What might help you: 45 | - Use the Service Simulator in the developer console if you want to inspect the response payload of a _LaunchRequest_. 46 | - The [lab05.yml](../scripts/lab05.yml) file contains a few suggestions of what expressions are supported. Assertions are written in simplified [JSONPath](http://goessner.net/articles/JsonPath/) syntax and support all operators valid in JSONPath. 47 | - Look into the [JSON schema](https://developer.amazon.com/docs/custom-skills/request-and-response-json-reference.html#response-body-syntax) for response bodies of custom skills to use correct path expressions for assertions 48 | 49 | ### **5.2.) Single-turn conversation with Simulation API** 50 | 51 | You can reuse the [lab05.yml](../scripts/lab05.yml) file that you used. Change the following things: 52 | 53 | **5.2.1.** uncomment line 9. 54 | 55 | **5.2.2.** in the configuration section at the very top of the file, change the endpoint type from _InvocationApi_ to _SimulationApi_ 56 | 57 | Rerun the script by uploading it to S3 and execute the Test Lambda function. 58 | 59 | **Q5.2.3.** In the log output, can you spot what's different now compared to the previous tests against the InvocationApi? 60 | 61 | [<< Lab 4](lab04.md) | **Lab 5** | [Lab 6 >>](lab06.md) -------------------------------------------------------------------------------- /labs/lab06.md: -------------------------------------------------------------------------------- 1 | [<< Lab 5](lab05.md) | **Lab 6** | [Lab 7 >>](lab07.md) 2 | 3 | # Lab Guide 6 - Multi-turn conversations 4 | 5 | ## **What you will do in this lab** 6 | You set up a multi-turn conversation with the skill and make a few assertions on the expected response by using the Test SDK tool. 7 | 8 | ## **What you will get at the end of this lab** 9 | You have learned how to chain multiple requests to simulate multi-turn conversations with your skill in one user session. 10 | 11 | ## **Prerequisites** 12 | - **Test Lambda function** you deployed in [Lab 4](lab04.md) 13 | - **S3 Test-Script bucket** that was created in [Lab 4](lab04.md) 14 | - **Number guessing skill** that was deployed to your Amazon developer account in [Lab 1](lab01.md) 15 | 16 | We recommend you to use an advanced text editor or IDE. You could also use an [Online YAML editor](https://codebeautify.org/yaml-validator) if you want. 17 | 18 | ## **Instructions** 19 | 20 | ### **6.1.) Multi-turn conversation with Invocation API** 21 | 22 | **6.1.1.** Open [./scripts/lab06.yml](../scripts/lab06.yml). 23 | 24 | The _Launch_ node is still the entry point for the test client but it is not the only node anymore. A second top-level node called _GuessFive_ has been added. The Launch node is referencing to it via a YAML anchor. 25 | 26 | __Side note:__ Anchors in YAML are defined as a value to parent nodes and start with an ampersand (e.g. _&GuessFive_). Referencing to it goes with a star followed by the anchor name (e.g. _*GuessFive_). An anchor definition always comes before its references. Learn more about [YAML anchors](http://blog.daemonl.com/2016/02/yaml.html) 27 | 28 | **6.1.2.** In line 8 there's an intent name missing. Please set it correctly according to what makes sense in this case. Looking at the interaction model of the skill might help you get the correct name. 29 | 30 | **6.1.3.** Upload the [lab06.yml](../scripts/lab06.yml) file to S3 and again run the Test Lambda function. Look into the log output. 31 | 32 | **6.1.4.** Change the script in a way it is guessing a 6. Upload the file an run the Test Lambda. 33 | 34 | **6.1.5.** Change the script in a way it is guessing a 5 and then a 6. Upload the file an run the Test Lambda. 35 | 36 | **6.1.6.** Change the script in a way it is guessing a 5 and then a 6 and then exits (stop) the session. Upload the file an run the Test Lambda. The intent for stopping a session is named _AMAZON.StopIntent_ 37 | 38 | [<< Lab 5](lab05.md) | **Lab 6** | [Lab 7 >>](lab07.md) -------------------------------------------------------------------------------- /labs/lab07.md: -------------------------------------------------------------------------------- 1 | [<< Lab 6](lab06.md) | **Lab 7** | [Lab 8 >>](lab08.md) 2 | 3 | # Lab Guide 7 - Multi-path conversations 4 | 5 | ## **What you will do in this lab** 6 | You set up a multi-turn conversation with the skill and make a few assertions on the expected response by using the Test SDK tool. In addition to that we introduce conditional paths entered when certain conditions are met. 7 | 8 | ## **What you will get at the end of this lab** 9 | You have learned how to create branches run tests dynamically depedant on the skills response. 10 | 11 | ## **Prerequisites** 12 | - **Test Lambda function** you deployed in [Lab 4](lab04.md) 13 | - **S3 Test-Script bucket** that was created in [Lab 4](lab04.md) 14 | - **Number guessing skill** that was deployed to your Amazon developer account in [Lab 1](lab01.md) 15 | 16 | We recommend you to use an advanced text editor or IDE. You could also use an [Online YAML editor](https://codebeautify.org/yaml-validator) if you want. 17 | 18 | ## **Instructions** 19 | 20 | ### **7.1.) Multi-path conversation with Invocation API** 21 | 22 | **7.1.1.** Open [./scripts/lab07.yml](../scripts/lab07.yml). 23 | 24 | Aside from the assertions you're already familiar with some of those elements now have a value (an anchor link to another conversation step) assigned to it. 25 | 26 | __Side note:__ Assertions that have an anchor link assigned as a value turn into _conditions_. The main difference is that the Test client won't throw an exception in case it is not true. The client rather just evaluates the condition statement and follows the anchor reference (conversation path) in case it is true. If it's false it steps over it. 27 | 28 | **7.1.2.** In line 25 to 27 of [lab07.yml](../scripts/lab07.yml) file there are some values missing. Please set it correctly according to what makes sense in this case. 29 | 30 | **7.1.3.** When you are done, upload the [lab07.yml](../scripts/lab07.yml) file to S3 and again run the Test Lambda function. 31 | 32 | **7.1.4.** Extend the script so it is going down from 4 to 1 and going up from 6 to 10 when looking for the number the skill thinks of. 33 | 34 | The [./scripts/lab07-final.yml](../scripts/lab07-final.yml) file gives you the right solution. Extra points: try not to look into it ;) 35 | 36 | __Q7.1.5.__ Also look into [./scripts/lab07-extended.yml](../scripts/lab07-extended.yml) file as it provides more configuration options. Can you guess what these new properties stand for and what are use cases to set things like a fixed timestamp or user-id? 37 | 38 | [<< Lab 6](lab06.md) | **Lab 7** | [Lab 8 >>](lab08.md) -------------------------------------------------------------------------------- /labs/lab08.md: -------------------------------------------------------------------------------- 1 | [<< Lab 7](lab07.md) | **Lab 8** 2 | 3 | # Lab Guide 8 - Proactive Skill Monitoring 4 | 5 | ## **What you will do in this lab** 6 | You will schedule periodical test executions for your skill and set up an alarm in case tests fail. 7 | 8 | ## **What you will get at the end of this lab** 9 | You have learned how to set up proactive monitoring for your skill. 10 | 11 | ## **Prerequisites** 12 | - **Test Lambda function** you deployed in [Lab 4](lab04.md) 13 | - **S3 Test-Script bucket** that was created in [Lab 4](lab04.md) 14 | - **Number guessing skill** that was deployed to your Amazon developer account in [Lab 1](lab01.md) 15 | 16 | ## **Instructions** 17 | 18 | ![](img/lab08-screen01.png) 19 | 20 | ### **8.1.) Schedule periodical executions** 21 | 22 | **8.1.1.** In the [AWS Developer console](https://console.aws.amazon.com/console/home) go to _Services_ -> _CloudWatch_ and navigate to _Rules_ in the left menu. Click on __Create Rule__. 23 | 24 | **8.1.2.** Select _Schedule_ and set the fixed rate to 3 minutes. 25 | 26 | **8.1.3.** In the right hand side click on __Add target__ and point to the _reinvent-alx315-test-client_ Test Lambda function. 27 | 28 | ![](img/lab08-screen02.png) 29 | 30 | Confirm with pressing the __Configure details__ button. 31 | 32 | **8.1.4.** Set the name to _test-client-run-schedule_ and hit __Create rule__ (PLEASE DON'T FORGET TO DISABLE OR REMOVE 33 | THIS RULE AFTER THE LAB AS IT MIGHT GENERATE COSTS ON YOUR END) 34 | 35 | The Test Lambda function will now execute every 3 minutes and simulates conversations like they are scripted in the YAML files stored in S3. 36 | 37 | **8.1.5.** Go back to _Services_ -> _Lambda_, navigate to the Test Lambda function and wait for a few minutes. In the _Monitoring_ tab on the Lambda detail page you should notice automatic executions. The logs but also the _Invocation errors_ dashboard tell you if the skill responses align with the assertions made in the YAML scripts. Remember, the Test Lambda function throws an error if one of those assertions is not met. 38 | 39 | ### **8.2.) Set alarming on test failures** 40 | 41 | As you don't want to manually look at CloudWatch metrics in order to see if your tests run smoothly, you would like to get notified instead. 42 | 43 | **8.2.1.** In the [AWS Developer console](https://console.aws.amazon.com/console/home) go to _Services_ -> _CloudWatch_ and navigate to _Alarms_. Click on __Create Alarm__. 44 | 45 | **8.2.2.** Click on _Lambda Metrics_. In the search field type _reinvent_ to better find the Test Lambda function metrics. You're looking for the _Errors_ metric of the Lambda function _reinvent-alx315-test-client_. 46 | 47 | ![](img/lab08-screen03.png) 48 | 49 | Select it and click __Next__. 50 | 51 | **8.2.3.** On the next page set this alarm's name to _test-client-alarm_. Set the threshold to _Whenever Error is >= 1 for 1 consecutive periods_. 52 | 53 | **8.2.4.** In the _Actions_ section click on the _New list_ link. Set the _topic name_ to _test-client-alarm-notifications_ and enter your e-mail address in the _E-mail list_. You should have access to your mailbox in order to check if the alarm is sending out notifications. 54 | 55 | ![](img/lab08-screen04.png) 56 | 57 | Confirm with hitting __Create Alarm__ 58 | 59 | **8.2.5.** CloudWatch sends a confirmation to your mail and waits for your approval on sending out notifications to your mailbox. Click on the confirmation link in the mail and return to CloudWatch. 60 | 61 | **8.2.6.** The last exercise is to break something. If the scripts you created during the last labs all work fine, it is now time to let a test run fail. Make an assertion in one of the YAML-files you know will go wrong, upload this file to the S3 bucket and wait for up to 3 minutes. In CloudWatch you can check if the alarm got triggered. Once this has happened, you should receive an e-mail. 62 | 63 | ### **8.3.) IMPORTANT! Clean up** 64 | 65 | Please don't forget to: 66 | - remove or disbale the CloudWatch rule you created. 67 | - remove or disable the CloudWatch alarm you created. 68 | 69 | If you'd like to remove all AWS resources created in the previous labs you could also roll back and delete the CloudFormation stack. Just make sure you empty the S3 bucket before rolling it back as otherwise it will fail. 70 | 71 | [<< Lab 7](lab07.md) | **Lab 8** -------------------------------------------------------------------------------- /models/en-US.json: -------------------------------------------------------------------------------- 1 | { 2 | "interactionModel" : { 3 | "languageModel" : { 4 | "intents" : [ { 5 | "name" : "AMAZON.CancelIntent", 6 | "samples" : [ ], 7 | "slots" : [ ] 8 | }, { 9 | "name" : "AMAZON.HelpIntent", 10 | "samples" : [ ], 11 | "slots" : [ ] 12 | }, { 13 | "name" : "AMAZON.NoIntent", 14 | "samples" : [ ], 15 | "slots" : [ ] 16 | }, { 17 | "name" : "AMAZON.StopIntent", 18 | "samples" : [ ], 19 | "slots" : [ ] 20 | }, { 21 | "name" : "AMAZON.YesIntent", 22 | "samples" : [ ], 23 | "slots" : [ ] 24 | }, { 25 | "name" : "GuessNumber", 26 | "samples" : [ "and {number}", "could be {number}", "i guess it is {number}", "i guess {number}", "i think it is {number}", "i think {number}", "is it {number}", "it is {number}", "may be {number}", "might be {number}", "probably {number}", "should be {number}", "we guess it is {number}", "we guess {number}", "we think it is {number}", "we think {number}", "what about {number}", "{number}" ], 27 | "slots" : [ { 28 | "name" : "number", 29 | "type" : "AMAZON.NUMBER", 30 | "samples" : [ ] 31 | } ] 32 | }, { 33 | "name" : "StartQuiz", 34 | "samples" : [ "a game", "a game please", "a guessing game", "a guessing game please", "a new game", "a new game please", "a new guessing game", "a new guessing game please", "a new number game", "a new number game please", "a new number guessing game", "a new number guessing game please", "a new number quiz game", "a new number quiz game please", "a new quiz", "a new quiz game", "a new quiz game please", "a new quiz please", "a next game", "a next game please", "a next guessing game", "a next guessing game please", "a next number game", "a next number game please", "a next number guessing game", "a next number guessing game please", "a next number quiz game", "a next number quiz game please", "a next quiz", "a next quiz game", "a next quiz game please", "a next quiz please", "a number game", "a number game please", "a number guessing game", "a number guessing game please", "a number quiz game", "a number quiz game please", "a quiz", "a quiz game", "a quiz game please", "a quiz please", "begin a game", "begin a game please", "begin a guessing game", "begin a guessing game please", "begin a new game", "begin a new game please", "begin a new guessing game", "begin a new guessing game please", "begin a new number game", "begin a new number game please", "begin a new number guessing game", "begin a new number guessing game please", "begin a new number quiz game", "begin a new number quiz game please", "begin a new quiz", "begin a new quiz game", "begin a new quiz game please", "begin a new quiz please", "begin a next game", "begin a next game please", "begin a next guessing game", "begin a next guessing game please", "begin a next number game", "begin a next number game please", "begin a next number guessing game", "begin a next number guessing game please", "begin a next number quiz game", "begin a next number quiz game please", "begin a next quiz", "begin a next quiz game", "begin a next quiz game please", "begin a next quiz please", "begin a number game", "begin a number game please", "begin a number guessing game", "begin a number guessing game please", "begin a number quiz game", "begin a number quiz game please", "begin a quiz", "begin a quiz game", "begin a quiz game please", "begin a quiz please", "begin game", "begin game please", "begin guessing game", "begin guessing game please", "begin new game", "begin new game please", "begin new guessing game", "begin new guessing game please", "begin new number game", "begin new number game please", "begin new number guessing game", "begin new number guessing game please", "begin new number quiz game", "begin new number quiz game please", "begin new quiz", "begin new quiz game", "begin new quiz game please", "begin new quiz please", "begin next game", "begin next game please", "begin next guessing game", "begin next guessing game please", "begin next number game", "begin next number game please", "begin next number guessing game", "begin next number guessing game please", "begin next number quiz game", "begin next number quiz game please", "begin next quiz", "begin next quiz game", "begin next quiz game please", "begin next quiz please", "begin number game", "begin number game please", "begin number guessing game", "begin number guessing game please", "begin number quiz game", "begin number quiz game please", "begin quiz", "begin quiz game", "begin quiz game please", "begin quiz please", "begin the game", "begin the game please", "begin the guessing game", "begin the guessing game please", "begin the new game", "begin the new game please", "begin the new guessing game", "begin the new guessing game please", "begin the new number game", "begin the new number game please", "begin the new number guessing game", "begin the new number guessing game please", "begin the new number quiz game", "begin the new number quiz game please", "begin the new quiz", "begin the new quiz game", "begin the new quiz game please", "begin the new quiz please", "begin the next game", "begin the next game please", "begin the next guessing game", "begin the next guessing game please", "begin the next number game", "begin the next number game please", "begin the next number guessing game", "begin the next number guessing game please", "begin the next number quiz game", "begin the next number quiz game please", "begin the next quiz", "begin the next quiz game", "begin the next quiz game please", "begin the next quiz please", "begin the number game", "begin the number game please", "begin the number guessing game", "begin the number guessing game please", "begin the number quiz game", "begin the number quiz game please", "begin the quiz", "begin the quiz game", "begin the quiz game please", "begin the quiz please", "game", "game please", "guessing game", "guessing game please", "new game", "new game please", "new guessing game", "new guessing game please", "new number game", "new number game please", "new number guessing game", "new number guessing game please", "new number quiz game", "new number quiz game please", "new quiz", "new quiz game", "new quiz game please", "new quiz please", "next game", "next game please", "next guessing game", "next guessing game please", "next number game", "next number game please", "next number guessing game", "next number guessing game please", "next number quiz game", "next number quiz game please", "next quiz", "next quiz game", "next quiz game please", "next quiz please", "number game", "number game please", "number guessing game", "number guessing game please", "number quiz game", "number quiz game please", "quiz", "quiz game", "quiz game please", "quiz please", "run a game", "run a game please", "run a guessing game", "run a guessing game please", "run a new game", "run a new game please", "run a new guessing game", "run a new guessing game please", "run a new number game", "run a new number game please", "run a new number guessing game", "run a new number guessing game please", "run a new number quiz game", "run a new number quiz game please", "run a new quiz", "run a new quiz game", "run a new quiz game please", "run a new quiz please", "run a next game", "run a next game please", "run a next guessing game", "run a next guessing game please", "run a next number game", "run a next number game please", "run a next number guessing game", "run a next number guessing game please", "run a next number quiz game", "run a next number quiz game please", "run a next quiz", "run a next quiz game", "run a next quiz game please", "run a next quiz please", "run a number game", "run a number game please", "run a number guessing game", "run a number guessing game please", "run a number quiz game", "run a number quiz game please", "run a quiz", "run a quiz game", "run a quiz game please", "run a quiz please", "run game", "run game please", "run guessing game", "run guessing game please", "run new game", "run new game please", "run new guessing game", "run new guessing game please", "run new number game", "run new number game please", "run new number guessing game", "run new number guessing game please", "run new number quiz game", "run new number quiz game please", "run new quiz", "run new quiz game", "run new quiz game please", "run new quiz please", "run next game", "run next game please", "run next guessing game", "run next guessing game please", "run next number game", "run next number game please", "run next number guessing game", "run next number guessing game please", "run next number quiz game", "run next number quiz game please", "run next quiz", "run next quiz game", "run next quiz game please", "run next quiz please", "run number game", "run number game please", "run number guessing game", "run number guessing game please", "run number quiz game", "run number quiz game please", "run quiz", "run quiz game", "run quiz game please", "run quiz please", "run the game", "run the game please", "run the guessing game", "run the guessing game please", "run the new game", "run the new game please", "run the new guessing game", "run the new guessing game please", "run the new number game", "run the new number game please", "run the new number guessing game", "run the new number guessing game please", "run the new number quiz game", "run the new number quiz game please", "run the new quiz", "run the new quiz game", "run the new quiz game please", "run the new quiz please", "run the next game", "run the next game please", "run the next guessing game", "run the next guessing game please", "run the next number game", "run the next number game please", "run the next number guessing game", "run the next number guessing game please", "run the next number quiz game", "run the next number quiz game please", "run the next quiz", "run the next quiz game", "run the next quiz game please", "run the next quiz please", "run the number game", "run the number game please", "run the number guessing game", "run the number guessing game please", "run the number quiz game", "run the number quiz game please", "run the quiz", "run the quiz game", "run the quiz game please", "run the quiz please", "start a game", "start a game please", "start a guessing game", "start a guessing game please", "start a new game", "start a new game please", "start a new guessing game", "start a new guessing game please", "start a new number game", "start a new number game please", "start a new number guessing game", "start a new number guessing game please", "start a new number quiz game", "start a new number quiz game please", "start a new quiz", "start a new quiz game", "start a new quiz game please", "start a new quiz please", "start a next game", "start a next game please", "start a next guessing game", "start a next guessing game please", "start a next number game", "start a next number game please", "start a next number guessing game", "start a next number guessing game please", "start a next number quiz game", "start a next number quiz game please", "start a next quiz", "start a next quiz game", "start a next quiz game please", "start a next quiz please", "start a number game", "start a number game please", "start a number guessing game", "start a number guessing game please", "start a number quiz game", "start a number quiz game please", "start a quiz", "start a quiz game", "start a quiz game please", "start a quiz please", "start game", "start game please", "start guessing game", "start guessing game please", "start new game", "start new game please", "start new guessing game", "start new guessing game please", "start new number game", "start new number game please", "start new number guessing game", "start new number guessing game please", "start new number quiz game", "start new number quiz game please", "start new quiz", "start new quiz game", "start new quiz game please", "start new quiz please", "start next game", "start next game please", "start next guessing game", "start next guessing game please", "start next number game", "start next number game please", "start next number guessing game", "start next number guessing game please", "start next number quiz game", "start next number quiz game please", "start next quiz", "start next quiz game", "start next quiz game please", "start next quiz please", "start number game", "start number game please", "start number guessing game", "start number guessing game please", "start number quiz game", "start number quiz game please", "start quiz", "start quiz game", "start quiz game please", "start quiz please", "start the game", "start the game please", "start the guessing game", "start the guessing game please", "start the new game", "start the new game please", "start the new guessing game", "start the new guessing game please", "start the new number game", "start the new number game please", "start the new number guessing game", "start the new number guessing game please", "start the new number quiz game", "start the new number quiz game please", "start the new quiz", "start the new quiz game", "start the new quiz game please", "start the new quiz please", "start the next game", "start the next game please", "start the next guessing game", "start the next guessing game please", "start the next number game", "start the next number game please", "start the next number guessing game", "start the next number guessing game please", "start the next number quiz game", "start the next number quiz game please", "start the next quiz", "start the next quiz game", "start the next quiz game please", "start the next quiz please", "start the number game", "start the number game please", "start the number guessing game", "start the number guessing game please", "start the number quiz game", "start the number quiz game please", "start the quiz", "start the quiz game", "start the quiz game please", "start the quiz please", "the game", "the game please", "the guessing game", "the guessing game please", "the new game", "the new game please", "the new guessing game", "the new guessing game please", "the new number game", "the new number game please", "the new number guessing game", "the new number guessing game please", "the new number quiz game", "the new number quiz game please", "the new quiz", "the new quiz game", "the new quiz game please", "the new quiz please", "the next game", "the next game please", "the next guessing game", "the next guessing game please", "the next number game", "the next number game please", "the next number guessing game", "the next number guessing game please", "the next number quiz game", "the next number quiz game please", "the next quiz", "the next quiz game", "the next quiz game please", "the next quiz please", "the number game", "the number game please", "the number guessing game", "the number guessing game please", "the number quiz game", "the number quiz game please", "the quiz", "the quiz game", "the quiz game please", "the quiz please" ], 35 | "slots" : [ ] 36 | } ], 37 | "types" : [ ], 38 | "invocationName" : "number guessing" 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /scripts/lab04.yml: -------------------------------------------------------------------------------- 1 | configuration: 2 | endpoint: 3 | type: InvocationApi 4 | region: NA 5 | locale: en-US 6 | 7 | Launch: 8 | - response.shouldEndSession == false -------------------------------------------------------------------------------- /scripts/lab05.yml: -------------------------------------------------------------------------------- 1 | configuration: 2 | endpoint: 3 | type: InvocationApi 4 | region: NA 5 | locale: en-US 6 | 7 | Launch: 8 | - intent: AMAZON.StopIntent 9 | #- utterance: 'ask number guessing for help' 10 | - response.shouldEndSession == false 11 | 12 | 13 | # Session still open / closed 14 | # response.shouldEndSession == false (session is still open) 15 | # response.shouldEndSession == true (session is closed) 16 | 17 | # Asset (not) exists 18 | # response.outputSpeech.ssml (ssml exists) 19 | # response.reprompt.outputSpeech.text (plain reprompt text exists) 20 | # response.card (card exists) 21 | # response.card.image (card contains an image) 22 | # sessionAttributes.key (session attribute named key exists) 23 | 24 | # Asset has specific value 25 | # response.outputSpeech.ssml =~ /.*test.*/i (ssml outputspeech contains "test") 26 | # sessionAttributes.key != 1 (session attribute named key has value not equal to 1 27 | # sessionAttributes.key >= 10 (session attribute named key has value >= 10 28 | # sessionAttributes.key >= 10 (session attribute named key has value >= 10 29 | -------------------------------------------------------------------------------- /scripts/lab06.yml: -------------------------------------------------------------------------------- 1 | configuration: 2 | endpoint: 3 | type: InvocationApi 4 | region: NA 5 | locale: en-US 6 | 7 | GuessFive: &GuessFive 8 | - intent: <> 9 | - number: 5 10 | - response.shouldEndSession == false 11 | - response.outputSpeech.ssml 12 | 13 | Launch: 14 | - response.shouldEndSession == false 15 | - *GuessFive 16 | 17 | 18 | # Session still open / closed 19 | # response.shouldEndSession == false (session is still open) 20 | # response.shouldEndSession == true (session is closed) 21 | 22 | # Asset (not) exists 23 | # response.outputSpeech.ssml (ssml exists) 24 | # response.reprompt.outputSpeech.text (plain reprompt text exists) 25 | # response.card (card exists) 26 | # response.card.image (card contains an image) 27 | # sessionAttributes.key (session attribute named key exists) 28 | 29 | # Asset has specific value 30 | # response.outputSpeech.ssml =~ /.*test.*/i (ssml outputspeech contains "test") 31 | # sessionAttributes.key != 1 (session attribute named key has value not equal to 1 32 | # sessionAttributes.key >= 10 (session attribute named key has value >= 10 33 | # sessionAttributes.key >= 10 (session attribute named key has value >= 10 -------------------------------------------------------------------------------- /scripts/lab07-extended.yml: -------------------------------------------------------------------------------- 1 | configuration: 2 | endpoint: 3 | type: InvocationApi | SimulationApi 4 | skillId: mySkillId 5 | region: NA | EU 6 | locale: en-US | en-GB | de-DE | en-IN | en-CA 7 | lwa: 8 | clientId: myClientId 9 | clientSecret: myClientSecret 10 | refreshToken: myRefreshToken 11 | device: 12 | id: myDeviceId 13 | supportedInterfaces: 14 | - AudioPlayer 15 | - Display 16 | user: 17 | id: myUserId 18 | accessToken: myToken 19 | debugFlagSessionAttributeName: myDebugFlag 20 | timestamp: 2010-09-30T11:11:11Z 21 | 22 | StopIt: &Exit 23 | - intent: AMAZON.StopIntent 24 | - response.shouldEndSession == true 25 | 26 | GuessOne: &GuessOne 27 | - intent: GuessNumber 28 | - number: 1 29 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i 30 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 31 | 32 | GuessTwo: &GuessTwo 33 | - intent: GuessNumber 34 | - number: 2 35 | - response.outputSpeech.ssml =~ /.*My number is lower.*/i : *GuessOne 36 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 37 | 38 | GuessThree: &GuessThree 39 | - intent: GuessNumber 40 | - number: 3 41 | - response.outputSpeech.ssml =~ /.*My number is lower.*/i : *GuessTwo 42 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 43 | 44 | GuessFour: &GuessFour 45 | - intent: GuessNumber 46 | - number: 4 47 | - response.outputSpeech.ssml =~ /.*My number is lower.*/i : *GuessThree 48 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 49 | 50 | GuessTen: &GuessTen 51 | - intent: GuessNumber 52 | - number: 10 53 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i 54 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 55 | 56 | GuessNine: &GuessNine 57 | - intent: GuessNumber 58 | - number: 9 59 | - response.outputSpeech.ssml =~ /.*My number is higher.*/i : *GuessTen 60 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 61 | 62 | GuessEight: &GuessEight 63 | - intent: GuessNumber 64 | - number: 8 65 | - response.outputSpeech.ssml =~ /.*My number is higher.*/i : *GuessNine 66 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 67 | 68 | GuessSeven: &GuessSeven 69 | - intent: GuessNumber 70 | - number: 7 71 | - response.outputSpeech.ssml =~ /.*My number is higher.*/i : *GuessEight 72 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 73 | 74 | GuessSix: &GuessSix 75 | - intent: GuessNumber 76 | - number: 6 77 | - response.outputSpeech.ssml =~ /.*My number is higher.*/i : *GuessSeven 78 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 79 | 80 | GuessFive: &GuessFive 81 | - intent: GuessNumber 82 | - number: 5 83 | - response.outputSpeech.ssml =~ /.*My number is higher.*/i : *GuessSix 84 | - response.outputSpeech.ssml =~ /.*My number is lower.*/i : *GuessFour 85 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 86 | 87 | Launch: 88 | - response.shouldEndSession == false 89 | - *GuessFive 90 | 91 | 92 | # Session still open / closed 93 | # response.shouldEndSession == false (session is still open) 94 | # response.shouldEndSession == true (session is closed) 95 | 96 | # Asset (not) exists 97 | # response.outputSpeech.ssml (ssml exists) 98 | # response.reprompt.outputSpeech.text (plain reprompt text exists) 99 | # response.card (card exists) 100 | # response.card.image (card contains an image) 101 | # sessionAttributes.key (session attribute named key exists) 102 | 103 | # Asset has specific value 104 | # response.outputSpeech.ssml =~ /.*test.*/i (ssml outputspeech contains "test") 105 | # sessionAttributes.key != 1 (session attribute named key has value not equal to 1 106 | # sessionAttributes.key >= 10 (session attribute named key has value >= 10 107 | # sessionAttributes.key >= 10 (session attribute named key has value >= 10 -------------------------------------------------------------------------------- /scripts/lab07-final.yml: -------------------------------------------------------------------------------- 1 | configuration: 2 | endpoint: 3 | type: InvocationApi 4 | region: NA 5 | locale: en-US 6 | 7 | StopIt: &Exit 8 | - intent: AMAZON.StopIntent 9 | - response.shouldEndSession == true 10 | 11 | GuessOne: &GuessOne 12 | - intent: GuessNumber 13 | - number: 1 14 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i 15 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 16 | 17 | GuessTwo: &GuessTwo 18 | - intent: GuessNumber 19 | - number: 2 20 | - response.outputSpeech.ssml =~ /.*My number is lower.*/i : *GuessOne 21 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 22 | 23 | GuessThree: &GuessThree 24 | - intent: GuessNumber 25 | - number: 3 26 | - response.outputSpeech.ssml =~ /.*My number is lower.*/i : *GuessTwo 27 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 28 | 29 | GuessFour: &GuessFour 30 | - intent: GuessNumber 31 | - number: 4 32 | - response.outputSpeech.ssml =~ /.*My number is lower.*/i : *GuessThree 33 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 34 | 35 | GuessTen: &GuessTen 36 | - intent: GuessNumber 37 | - number: 10 38 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i 39 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 40 | 41 | GuessNine: &GuessNine 42 | - intent: GuessNumber 43 | - number: 9 44 | - response.outputSpeech.ssml =~ /.*My number is higher.*/i : *GuessTen 45 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 46 | 47 | GuessEight: &GuessEight 48 | - intent: GuessNumber 49 | - number: 8 50 | - response.outputSpeech.ssml =~ /.*My number is higher.*/i : *GuessNine 51 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 52 | 53 | GuessSeven: &GuessSeven 54 | - intent: GuessNumber 55 | - number: 7 56 | - response.outputSpeech.ssml =~ /.*My number is higher.*/i : *GuessEight 57 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 58 | 59 | GuessSix: &GuessSix 60 | - intent: GuessNumber 61 | - number: 6 62 | - response.outputSpeech.ssml =~ /.*My number is higher.*/i : *GuessSeven 63 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 64 | 65 | GuessFive: &GuessFive 66 | - intent: GuessNumber 67 | - number: 5 68 | - response.outputSpeech.ssml =~ /.*My number is higher.*/i : *GuessSix 69 | - response.outputSpeech.ssml =~ /.*My number is lower.*/i : *GuessFour 70 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 71 | 72 | Launch: 73 | - response.shouldEndSession == false 74 | - *GuessFive 75 | 76 | 77 | # Session still open / closed 78 | # response.shouldEndSession == false (session is still open) 79 | # response.shouldEndSession == true (session is closed) 80 | 81 | # Asset (not) exists 82 | # response.outputSpeech.ssml (ssml exists) 83 | # response.reprompt.outputSpeech.text (plain reprompt text exists) 84 | # response.card (card exists) 85 | # response.card.image (card contains an image) 86 | # sessionAttributes.key (session attribute named key exists) 87 | 88 | # Asset has specific value 89 | # response.outputSpeech.ssml =~ /.*test.*/i (ssml outputspeech contains "test") 90 | # sessionAttributes.key != 1 (session attribute named key has value not equal to 1 91 | # sessionAttributes.key >= 10 (session attribute named key has value >= 10 92 | # sessionAttributes.key >= 10 (session attribute named key has value >= 10 -------------------------------------------------------------------------------- /scripts/lab07.yml: -------------------------------------------------------------------------------- 1 | configuration: 2 | endpoint: 3 | type: InvocationApi 4 | region: NA 5 | locale: en-US 6 | 7 | StopIt: &Exit 8 | - intent: AMAZON.StopIntent 9 | - response.shouldEndSession == true 10 | 11 | GuessFour: &GuessFour 12 | - intent: GuessNumber 13 | - number: 4 14 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 15 | 16 | GuessSix: &GuessSix 17 | - intent: GuessNumber 18 | - number: 6 19 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : *Exit 20 | 21 | GuessFive: &GuessFive 22 | - intent: GuessNumber 23 | - number: 5 24 | - response.shouldEndSession == false 25 | - response.outputSpeech.ssml =~ /.*My number is higher.*/i : <> 26 | - response.outputSpeech.ssml =~ /.*My number is lower.*/i : <> 27 | - response.outputSpeech.ssml =~ /.*Great. That’s it.*/i : <> 28 | 29 | Launch: 30 | - response.shouldEndSession == false 31 | - *GuessFive 32 | 33 | 34 | # Session still open / closed 35 | # response.shouldEndSession == false (session is still open) 36 | # response.shouldEndSession == true (session is closed) 37 | 38 | # Asset (not) exists 39 | # response.outputSpeech.ssml (ssml exists) 40 | # response.reprompt.outputSpeech.text (plain reprompt text exists) 41 | # response.card (card exists) 42 | # response.card.image (card contains an image) 43 | # sessionAttributes.key (session attribute named key exists) 44 | 45 | # Asset has specific value 46 | # response.outputSpeech.ssml =~ /.*test.*/i (ssml outputspeech contains "test") 47 | # sessionAttributes.key != 1 (session attribute named key has value not equal to 1 48 | # sessionAttributes.key >= 10 (session attribute named key has value >= 10 49 | # sessionAttributes.key >= 10 (session attribute named key has value >= 10 -------------------------------------------------------------------------------- /skill.json: -------------------------------------------------------------------------------- 1 | { 2 | "skillManifest": { 3 | "publishingInformation": { 4 | "locales": { 5 | "en-US": { 6 | "summary": "Yet another number guessing game.", 7 | "examplePhrases": [ 8 | "Alexa, open number guessing", 9 | "Alexa, ask number guessing for a quiz", 10 | "Alexa, ask number guessing for help" 11 | ], 12 | "name": "Number guessing game", 13 | "description": "Guess the number Alexa thinks of." 14 | } 15 | }, 16 | "isAvailableWorldwide": true, 17 | "testingInstructions": "", 18 | "category": "EDUCATION_AND_REFERENCE", 19 | "distributionCountries": [] 20 | }, 21 | "apis": { 22 | "custom": { 23 | "endpoint": { 24 | "uri": "arn:aws:lambda:us-east-1:661661179496:function:io-klerch-alexa-numberguess-skill" 25 | }, 26 | "regions": { 27 | "NA": { 28 | "endpoint": { 29 | "uri": "arn:aws:lambda:us-east-1:661661179496:function:io-klerch-alexa-numberguess-skill" 30 | } 31 | } 32 | } 33 | } 34 | }, 35 | "manifestVersion": "1.0" 36 | } 37 | } --------------------------------------------------------------------------------