您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

testflow.js 7.6 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. // Test Flow - a multiple intent test script for Alexa Lambda code
  2. // Launch from a Terminal Prompt. Examples:
  3. // node testflow
  4. // node testflow staterequest.txt
  5. // Originally taken from https://github.com/alexa/alexa-cookbook/blob/master/testing/TestFlow/testflow.js
  6. // Toggle on or off various debugging outputs
  7. const options = {
  8. speechOutput: true,
  9. slots: true,
  10. stdout: false, // standard output / console.log() in your code
  11. requestEvent: false, // show the full request JSON sent to your code
  12. reprompt: false,
  13. delay: 1.0 // seconds between requests
  14. }
  15. var locale = 'en-US'
  16. var fs = require('fs')
  17. var MyLambdaFunction = require('../src/index.js') // Your Lambda source with exports.handler
  18. var MyDialog = './test/dialogs/default.txt'
  19. var appId = '' // 'amzn1.ask.skill.d60ceb98-befe-4f49-a627-1f20f6e98d94'
  20. var slotArray = []
  21. if (process.argv[2]) {
  22. MyDialog = './dialogs/' + process.argv[2]
  23. }
  24. console.log()
  25. console.log('================================================================================')
  26. console.log('Running test sequence from dialog file : ', MyDialog)
  27. console.log()
  28. const OriginalConsoleLog = console.log
  29. var slotname = ''
  30. var slotvalue = ''
  31. var sa = {}
  32. var currentLine = 1
  33. var lineArray = []
  34. var Intent = ''
  35. var prompt = false
  36. var context = {
  37. 'succeed': function (data) {
  38. if (data.response.shouldEndSession) {
  39. sa = {}
  40. } else {
  41. sa = data.sessionAttributes
  42. }
  43. console.log = OriginalConsoleLog
  44. var textToSay = data.response.outputSpeech.ssml
  45. if (options.speechOutput) {
  46. console.log('\n\x1b[36m%s\x1b[0m', textToSay)
  47. }
  48. if (data.response.reprompt && data.response.reprompt.outputSpeech && data.response.reprompt.outputSpeech.ssml) {
  49. var textReprompt = data.response.reprompt.outputSpeech.ssml
  50. if (options.reprompt) {
  51. // console.log('%s \x1b[33m\x1b[1m%s\x1b[0m \x1b[2m%s\x1b[0m', currentLine+1, Intent, sdkState)
  52. console.log('\x1b[36m \x1b[2m%s\x1b[0m ', textReprompt)
  53. }
  54. }
  55. if (data.response.shouldEndSession) {
  56. console.log('\n================= Session Ended =================')
  57. }
  58. if (currentLine < lineArray.length) {
  59. console.log()
  60. runSingleTest(lineArray, currentLine++, sa)
  61. } else {
  62. console.log('')
  63. process.exit()
  64. }
  65. },
  66. 'fail': function (err) {
  67. console.log('context.fail occurred')
  68. console.log(JSON.stringify(err, null, '\t'))
  69. }
  70. }
  71. fs.readFile(MyDialog, function (err, data) { // open dialog sequence file and read Intents
  72. // var newSession = true
  73. if (err) {}
  74. lineArray = cleanArray(data.toString().split('\n')) // remove empty or comment lines (# or //)
  75. runSingleTest(lineArray, 0, {})
  76. })
  77. function runSingleTest (myLineArray, currentLine, sa) {
  78. // console.log('--------------------------------------------------------------------------------')
  79. // console.log('testing line ', currentLine)
  80. // console.log('testing line values ', myLineArray[currentLine])
  81. prompt = false
  82. var newSession = true
  83. if (currentLine > 0) {
  84. newSession = false
  85. }
  86. var tokenArray = myLineArray[currentLine].split(' ')
  87. if (tokenArray[0].replace('\r', '') === '?') { // pause and prompt the user to confirm
  88. prompt = true
  89. // console.log(' ----------------- > prompt')
  90. tokenArray.shift() // removes first item
  91. }
  92. var requestType = tokenArray[0].replace('\r', '')
  93. tokenArray.shift()
  94. if (requestType === 'stop') {
  95. console.log('')
  96. process.exit()
  97. }
  98. Intent = requestType
  99. // slotArray = []
  100. var sdkState = ''
  101. if (sa['STATE']) {
  102. sdkState = sa['STATE']
  103. }
  104. console.log('%s \x1b[33m\x1b[1m%s\x1b[0m \x1b[2m%s\x1b[0m', currentLine + 1, Intent, sdkState)
  105. processArray(tokenArray, function (request) {
  106. prepareTestRequest(sa, newSession, request)
  107. })
  108. }
  109. function processArray (arr, cb) {
  110. if (arr.length > 0) {
  111. var equalsPosition = arr[0].indexOf('=')
  112. slotname = arr[0].substr(0, equalsPosition)
  113. slotvalue = decodeURI(arr[0].substr(equalsPosition + 1, 300)).replace('\r', '')
  114. promptForSlot(prompt, slotname, slotvalue, (newValue) => {
  115. // console.log('slotname, slotvalue, newValue')
  116. // console.log(slotname, slotvalue, newValue)
  117. var answer = newValue.toString().trim()
  118. // console.log('answer = ' + answer)
  119. if (answer === '') {
  120. answer = slotvalue
  121. }
  122. if (answer !== '') {
  123. slotArray.push('"' + slotname + '": {"name":"' + slotname + '","value":"' + answer + '"}')
  124. }
  125. arr.shift()
  126. processArray(arr, cb) // RECURSION
  127. })
  128. } else { // nothing left in slot array
  129. var slotArrayString = '{' + slotArray.toString() + '}'
  130. var slotObj = JSON.parse(slotArrayString)
  131. var req = {
  132. 'type': 'IntentRequest',
  133. 'intent': {
  134. 'name': Intent,
  135. 'slots': slotObj
  136. },
  137. 'locale': locale
  138. }
  139. cb(req)
  140. // process.exit()
  141. }
  142. }
  143. function prepareTestRequest (sa, newSession, request) {
  144. var eventJSON = {
  145. 'session': {
  146. 'sessionId': 'SessionId.f9e6dcbb-b7da-4b47-905c.etc.etc',
  147. 'application': {
  148. 'applicationId': appId
  149. },
  150. 'attributes': sa,
  151. 'user': {
  152. 'userId': 'amzn1.ask.account.VO3PVTGF563MOPBY.etc.etc'
  153. },
  154. 'new': newSession
  155. },
  156. request,
  157. 'version': '1.0'
  158. }
  159. if (options.requestEvent) {
  160. console.log(JSON.stringify(request, null, 2))
  161. }
  162. // blocking pause
  163. var waitTill = new Date(new Date().getTime() + options.delay * 1000)
  164. while (waitTill > new Date()) {}
  165. // call the function
  166. if (options.stdout) {
  167. MyLambdaFunction['handler'](eventJSON, context, callback)
  168. } else {
  169. // console.log('setting log to {}')
  170. console.log = function () {}
  171. // console.log('set log to {}')
  172. MyLambdaFunction['handler'](eventJSON, context, callback)
  173. console.log = OriginalConsoleLog
  174. }
  175. }
  176. function promptForSlot (prompt, slotname, slotvalue, callback) {
  177. if (prompt) {
  178. process.stdout.write('\x1b[34m' + slotname + ' \x1b[0m\x1b[32m [' + slotvalue + ']\x1b[0m: ')
  179. // console.log('\x1b[34m%s :\x1b[0m\x1b[32m %s\x1b[0m ', slotname, slotvalue )
  180. process.stdin.once('data', function (data) {
  181. var answer = data.toString().trim()
  182. // console.log(answer)
  183. if (answer === '') {
  184. if (slotvalue === '') {
  185. // no default, user must type something
  186. console.error('Error: No default slot value defined, user must type a slot value.')
  187. process.exit()
  188. } else {
  189. answer = slotvalue
  190. }
  191. }
  192. callback(answer)
  193. })
  194. } else {
  195. if (options.slots) {
  196. console.log('\x1b[34m%s :\x1b[0m\x1b[32m %s\x1b[0m ', slotname, slotvalue)
  197. }
  198. callback(slotvalue)
  199. }
  200. }
  201. function callback (error, data) {
  202. if (error) {
  203. console.log('error: ' + error)
  204. } else {
  205. console.log(data)
  206. }
  207. }
  208. function cleanArray (myArray) {
  209. var cleanedArray = []
  210. for (var i = 0; i < myArray.length; i++) {
  211. if (myArray[i] !== '' && myArray[i].substring(0, 1) !== '#' && myArray[i].substring(0, 2) !== '//') {
  212. cleanedArray.push(myArray[i])
  213. }
  214. }
  215. return cleanedArray
  216. }
  217. //
  218. // const fontcolor = {
  219. // Reset = '\x1b[0m',
  220. // Bright = '\x1b[1m',
  221. // Dim = '\x1b[2m',
  222. // Underscore = '\x1b[4m',
  223. // Blink = '\x1b[5m',
  224. // Reverse = '\x1b[7m',
  225. // Hidden = '\x1b[8m',
  226. //
  227. // FgBlack = '\x1b[30m',
  228. // FgRed = '\x1b[31m',
  229. // FgGreen = '\x1b[32m',
  230. // FgYellow = '\x1b[33m',
  231. // FgBlue = '\x1b[34m',
  232. // FgMagenta = '\x1b[35m',
  233. // FgCyan = '\x1b[36m',
  234. // FgWhite = '\x1b[37m',
  235. //
  236. // BgBlack = '\x1b[40m',
  237. // BgRed = '\x1b[41m',
  238. // BgGreen = '\x1b[42m',
  239. // BgYellow = '\x1b[43m',
  240. // BgBlue = '\x1b[44m',
  241. // BgMagenta = '\x1b[45m',
  242. // BgCyan = '\x1b[46m',
  243. // BgWhite = '\x1b[47m'
  244. // }