浏览代码

Added testing modules

pull/2/head
BinHong Lee 7 年前
父节点
当前提交
31e7057144
共有 6 个文件被更改,包括 328 次插入8 次删除
  1. +14
    -0
      .travis.yml
  2. +8
    -6
      README.md
  3. +7
    -1
      package.json
  4. +2
    -1
      src/index.js
  5. +7
    -0
      test/dialogs/default.txt
  6. +290
    -0
      test/testflow.js

+ 14
- 0
.travis.yml 查看文件

@@ -0,0 +1,14 @@
language: node_js
node_js:
- "node"
- "7"
- "6"
- "5"
- "4"
- "lts/*"
before_script:
- npm install
- npm install-test
script: npm test
env:
CODECLIMATE_REPO_TOKEN: a174b03227cdc953c831f45bebcf0af357ec1b8a4b8477f36444c16f084a409f

+ 8
- 6
README.md 查看文件

@@ -1,14 +1,16 @@
# Dota 2 Random - Alexa Skill

Skill is now available from the [Alexa Skill Store](https://www.amazon.com/binhonglee-Dota2-Random/dp/B073W4GDLS)!
[![Build Status](https://travis-ci.org/binhonglee/dota2-random.svg?branch=master)](https://travis-ci.org/binhonglee/dota2-random) [![Test Coverage](https://codeclimate.com/github/binhonglee/dota2-random/badges/coverage.svg)](https://codeclimate.com/github/binhonglee/dota2-random/coverage) [![Dependency Status](https://gemnasium.com/badges/github.com/binhonglee/dota2-random.svg)](https://gemnasium.com/github.com/binhonglee/dota2-random)

#### Dependency
- alexa-sdk
## Skill is now available from the [Alexa Skill Store](https://www.amazon.com/binhonglee-Dota2-Random/dp/B073W4GDLS)!

### Dependency
- node.js
- alexa-sdk

## Documentations
### Documentations

### Intents
#### Intents

| Intents | Description |
|:---------|:------------|
@@ -20,7 +22,7 @@ Skill is now available from the [Alexa Skill Store](https://www.amazon.com/binho
| `AMAZON.HelpIntent` | Provide examples on how to use the skill |
| `Stop` | Stop the skill |

### ROLE_TYPES (Custom slot)
#### ROLE_TYPES (Custom slot)
- melee
- ranged
- carry


+ 7
- 1
package.json 查看文件

@@ -6,6 +6,11 @@
"dependencies": {
"alexa-sdk": "^1.0.7"
},
"scripts": {
"install-test": "npm install -g standard",
"test": "standard && node test/testflow.js",
"remove-test": "npm uninstall -g standard"
},
"author": "binhonglee",
"license": "MIT",
"repository": {
@@ -15,5 +20,6 @@
"bugs": {
"url": "https://github.com/binhonglee/dota2-alexa-skill/issues"
},
"homepage": "https://github.com/binhonglee/dota2-alexa-skill#readme"
"homepage": "https://github.com/binhonglee/dota2-alexa-skill#readme",
"devDependencies": {}
}

+ 2
- 1
src/index.js 查看文件

@@ -81,7 +81,8 @@ function randomHero (categories, callback) {
}

if (!possible) {
callback('Random failed')
var errorMessage = 'Random failed'
callback(errorMessage)
return
}



+ 7
- 0
test/dialogs/default.txt 查看文件

@@ -0,0 +1,7 @@
LaunchRequest
AMAZON.HelpIntent
AnyRequest
RequestIntent Role=agility
RequestTwoIntent RoleOne=melee RoleTwo=ranged
RequestThreeIntent RoleOne=melee RoleTwo=intelligence RoleThree=support
Stop

+ 290
- 0
test/testflow.js 查看文件

@@ -0,0 +1,290 @@
// Test Flow - a multiple intent test script for Alexa Lambda code
// Launch from a Terminal Prompt. Examples:
// node testflow
// node testflow staterequest.txt

// Originally taken from https://github.com/alexa/alexa-cookbook/blob/master/testing/TestFlow/testflow.js

// Toggle on or off various debugging outputs
const options = {
speechOutput: true,
slots: true,
stdout: false, // standard output / console.log() in your code
requestEvent: false, // show the full request JSON sent to your code
reprompt: false,
delay: 1.0 // seconds between requests
}

var locale = 'en-US'

var fs = require('fs')
var MyLambdaFunction = require('../src/index.js') // Your Lambda source with exports.handler

var MyDialog = './test/dialogs/default.txt'
var appId = '' // 'amzn1.ask.skill.d60ceb98-befe-4f49-a627-1f20f6e98d94'
var slotArray = []

if (process.argv[2]) {
MyDialog = './dialogs/' + process.argv[2]
}

console.log()
console.log('================================================================================')
console.log('Running test sequence from dialog file : ', MyDialog)
console.log()

const OriginalConsoleLog = console.log

var slotname = ''
var slotvalue = ''
var sa = {}
var currentLine = 1
var lineArray = []
var Intent = ''
var prompt = false

var context = {
'succeed': function (data) {
if (data.response.shouldEndSession) {
sa = {}
} else {
sa = data.sessionAttributes
}

console.log = OriginalConsoleLog
var textToSay = data.response.outputSpeech.ssml

if (options.speechOutput) {
console.log('\n\x1b[36m%s\x1b[0m', textToSay)
}

if (data.response.reprompt && data.response.reprompt.outputSpeech && data.response.reprompt.outputSpeech.ssml) {
var textReprompt = data.response.reprompt.outputSpeech.ssml
if (options.reprompt) {
// console.log('%s \x1b[33m\x1b[1m%s\x1b[0m \x1b[2m%s\x1b[0m', currentLine+1, Intent, sdkState)
console.log('\x1b[36m \x1b[2m%s\x1b[0m ', textReprompt)
}
}

if (data.response.shouldEndSession) {
console.log('\n================= Session Ended =================')
}

if (currentLine < lineArray.length) {
console.log()
runSingleTest(lineArray, currentLine++, sa)
} else {
console.log('')
process.exit()
}
},
'fail': function (err) {
console.log('context.fail occurred')
console.log(JSON.stringify(err, null, '\t'))
}
}

fs.readFile(MyDialog, function (err, data) { // open dialog sequence file and read Intents
// var newSession = true
if (err) {}
lineArray = cleanArray(data.toString().split('\n')) // remove empty or comment lines (# or //)
runSingleTest(lineArray, 0, {})
})

function runSingleTest (myLineArray, currentLine, sa) {
// console.log('--------------------------------------------------------------------------------')
// console.log('testing line ', currentLine)
// console.log('testing line values ', myLineArray[currentLine])
prompt = false
var newSession = true
if (currentLine > 0) {
newSession = false
}

var tokenArray = myLineArray[currentLine].split(' ')

if (tokenArray[0].replace('\r', '') === '?') { // pause and prompt the user to confirm
prompt = true
// console.log(' ----------------- > prompt')
tokenArray.shift() // removes first item
}

var requestType = tokenArray[0].replace('\r', '')
tokenArray.shift()

if (requestType === 'stop') {
console.log('')
process.exit()
}

Intent = requestType
// slotArray = []

var sdkState = ''
if (sa['STATE']) {
sdkState = sa['STATE']
}

console.log('%s \x1b[33m\x1b[1m%s\x1b[0m \x1b[2m%s\x1b[0m', currentLine + 1, Intent, sdkState)
processArray(tokenArray, function (request) {
prepareTestRequest(sa, newSession, request)
})
}

function processArray (arr, cb) {
if (arr.length > 0) {
var equalsPosition = arr[0].indexOf('=')
slotname = arr[0].substr(0, equalsPosition)
slotvalue = decodeURI(arr[0].substr(equalsPosition + 1, 300)).replace('\r', '')

promptForSlot(prompt, slotname, slotvalue, (newValue) => {
// console.log('slotname, slotvalue, newValue')
// console.log(slotname, slotvalue, newValue)

var answer = newValue.toString().trim()

// console.log('answer = ' + answer)

if (answer === '') {
answer = slotvalue
}

if (answer !== '') {
slotArray.push('"' + slotname + '": {"name":"' + slotname + '","value":"' + answer + '"}')
}

arr.shift()
processArray(arr, cb) // RECURSION
})
} else { // nothing left in slot array
var slotArrayString = '{' + slotArray.toString() + '}'

var slotObj = JSON.parse(slotArrayString)

var req = {
'type': 'IntentRequest',
'intent': {
'name': Intent,
'slots': slotObj
},
'locale': locale
}
cb(req)
// process.exit()
}
}

function prepareTestRequest (sa, newSession, request) {
var eventJSON = {
'session': {
'sessionId': 'SessionId.f9e6dcbb-b7da-4b47-905c.etc.etc',
'application': {
'applicationId': appId
},
'attributes': sa,
'user': {
'userId': 'amzn1.ask.account.VO3PVTGF563MOPBY.etc.etc'
},
'new': newSession
},
request,
'version': '1.0'
}

if (options.requestEvent) {
console.log(JSON.stringify(request, null, 2))
}

// blocking pause
var waitTill = new Date(new Date().getTime() + options.delay * 1000)
while (waitTill > new Date()) {}

// call the function
if (options.stdout) {
MyLambdaFunction['handler'](eventJSON, context, callback)
} else {
// console.log('setting log to {}')
console.log = function () {}
// console.log('set log to {}')

MyLambdaFunction['handler'](eventJSON, context, callback)
console.log = OriginalConsoleLog
}
}

function promptForSlot (prompt, slotname, slotvalue, callback) {
if (prompt) {
process.stdout.write('\x1b[34m' + slotname + ' \x1b[0m\x1b[32m [' + slotvalue + ']\x1b[0m: ')

// console.log('\x1b[34m%s :\x1b[0m\x1b[32m %s\x1b[0m ', slotname, slotvalue )

process.stdin.once('data', function (data) {
var answer = data.toString().trim()
// console.log(answer)
if (answer === '') {
if (slotvalue === '') {
// no default, user must type something
console.error('Error: No default slot value defined, user must type a slot value.')
process.exit()
} else {
answer = slotvalue
}
}

callback(answer)
})
} else {
if (options.slots) {
console.log('\x1b[34m%s :\x1b[0m\x1b[32m %s\x1b[0m ', slotname, slotvalue)
}

callback(slotvalue)
}
}

function callback (error, data) {
if (error) {
console.log('error: ' + error)
} else {
console.log(data)
}
}

function cleanArray (myArray) {
var cleanedArray = []

for (var i = 0; i < myArray.length; i++) {
if (myArray[i] !== '' && myArray[i].substring(0, 1) !== '#' && myArray[i].substring(0, 2) !== '//') {
cleanedArray.push(myArray[i])
}
}
return cleanedArray
}
//
// const fontcolor = {
// Reset = '\x1b[0m',
// Bright = '\x1b[1m',
// Dim = '\x1b[2m',
// Underscore = '\x1b[4m',
// Blink = '\x1b[5m',
// Reverse = '\x1b[7m',
// Hidden = '\x1b[8m',
//
// FgBlack = '\x1b[30m',
// FgRed = '\x1b[31m',
// FgGreen = '\x1b[32m',
// FgYellow = '\x1b[33m',
// FgBlue = '\x1b[34m',
// FgMagenta = '\x1b[35m',
// FgCyan = '\x1b[36m',
// FgWhite = '\x1b[37m',
//
// BgBlack = '\x1b[40m',
// BgRed = '\x1b[41m',
// BgGreen = '\x1b[42m',
// BgYellow = '\x1b[43m',
// BgBlue = '\x1b[44m',
// BgMagenta = '\x1b[45m',
// BgCyan = '\x1b[46m',
// BgWhite = '\x1b[47m'
// }

正在加载...
取消
保存