Create APL template using ask-sdk-jsx-for-apl with TypeScript
Since AlexaLive 2020, we can create APL tempalte by using JSX. Let’s try it. Install We need to install […]
目次
Since AlexaLive 2020, we can create APL tempalte by using JSX.
Let’s try it.
Install
We need to install these require packages.
$ npm install -S ask-sdk-jsx-for-apl react react-dom
And install TypeScript helpers.
$ npm install -D @types/react @types/react-dom
Check and update tsconfig.json
We need to set these parameters into your tsconfig.json
compilerOptions.jsx = 'react'
compilerOptions.esModuleInterop = true
Here is a example of tsconfig.json
{
"compilerOptions": {
"module": "commonjs",
"target": "es6",
"noImplicitAny": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"outDir": "./dist",
"esModuleInterop": true,
"jsx": "react",
"allowJs": false
},
"include": [
"./src/**/*"
]
}
Create APL by React
Then, we can create APL template by using React JSX with TypeScript.
import React from 'react';
import { APL, MainTemplate, Container, Text } from 'ask-sdk-jsx-for-apl';
/**
* Class component
*/
export class LaunchAplDocument extends React.Component {
private readonly launchMessage = 'Welcome to my first JSX for APL skill!';
render() {
return (
<APL theme="dark">
<MainTemplate>
<Container
alignItems="center"
justifyContent="spaceAround">
<Text
text={this.launchMessage}
fontSize="50px"
color="rgb(251,184,41)" />
</Container>
</MainTemplate>
</APL>
);
}
}
/**
* Functional Component
*/
export const LaunchAplDocumentFC: React.FC = () => {
const launchMessage = 'Welcome to my first JSX for APL skill!';
return (
<APL theme="dark">
<MainTemplate>
<Container
alignItems="center"
justifyContent="spaceAround">
<Text
text={launchMessage}
fontSize="50px"
color="rgb(251,184,41)" />
</Container>
</MainTemplate>
</APL>
);
}
And use these component can be added by AplDocument class in your RequestHandler like the example.
import React from 'react'
import { RequestHandler } from 'ask-sdk-core';
import { AplDocument } from 'ask-sdk-jsx-for-apl';
import { LaunchAplDocument } from './LaunchRequest.apl';
export const LaunchRequestHandler: RequestHandler = {
async canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "LaunchRequest"
},
async handle(handlerInput) {
return handlerInput.responseBuilder
.speak("Hello! It's a nice development. How are you?")
.reprompt("How are you?")
.addDirective(
new AplDocument(
<LaunchAplDocument />
).getDirective()
)
.getResponse()
}
}
export default LaunchRequestHandler
Trouble shooting
Error: TS2352: Conversion of type ‘RegExp’ to type ‘LaunchAplDocument’ may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to ‘unknown’ first.
If you don’t using .tsx
suffix, you may get the error.
We have to replace your file from .ts
to .tsx
Error: TS2686: ‘React’ refers to a UMD global, but the current file is a module. Consider adding an import instead.
If we want to use JSX component, we must import React
in the file.
Test your APL Component by Jest
We can test your APL component by using jest.
import React from 'react';
import {
APL,
MainTemplate,
Container,
Text,
AplDocument
} from 'ask-sdk-jsx-for-apl'
const LaunchAplDocumentFC: React.FC = () => {
const launchMessage = 'Welcome to my first JSX for APL skill!';
return (
<APL theme="dark">
<MainTemplate>
<Container
alignItems="center"
justifyContent="spaceAround">
<Text
text={launchMessage}
fontSize="50px"
color="rgb(251,184,41)" />
</Container>
</MainTemplate>
</APL>
);
}
describe('AplDocument', () => {
const directive = new AplDocument(<LaunchAplDocumentFC />).getDirective()
it('should get RenderDocument Directive', () => {
expect(directive).toEqual({
"document": {
"import": [],
"mainTemplate": {
"items": [
{
"alignItems": "center",
"items": [
{
"color": "rgb(251,184,41)",
"fontSize": "50px",
"items": [],
"text": "Welcome to my first JSX for APL skill!",
"type": "Text"
}
],
"justifyContent": "spaceAround",
"type": "Container"
}
],
"parameters": []
},
"theme": "dark",
"type": "APL",
"version": "1.3"
},
"type": "Alexa.Presentation.APL.RenderDocument"
})
})
})
Use snapshot testing to check the component update
Jest provides a snapshot testing. We can detect the return value changes by the test.
We have to execute the test before update the component.
import React from 'react';
import {
APL,
MainTemplate,
Container,
Text,
AplDocument
} from 'ask-sdk-jsx-for-apl'
const LaunchAplDocumentFC: React.FC = () => {
const launchMessage = 'Welcome to my first JSX for APL skill!';
return (
<APL theme="dark">
<MainTemplate>
<Container
alignItems="center"
justifyContent="spaceAround">
<Text
text={launchMessage}
fontSize="50px"
color="rgb(251,184,41)" />
</Container>
</MainTemplate>
</APL>
);
}
describe('AplDocument', () => {
const directive = new AplDocument(<LaunchAplDocumentFC />).getDirective()
it('should match snapshot', () => {
expect(directive).toMatchSnapshot()
})
})
Then, if you update the Text color from rgb(251,184,41)
to rgb(255,184,41)
, jest will detect the change.
Snapshot name: `AplDocument should match snapshot 1`
- Snapshot - 1
+ Received + 1
@@ -14,11 +14,11 @@
"items": Array [
Object {
"alignItems": "center",
"items": Array [
Object {
- "color": "rgb(251,184,41)",
+ "color": "rgb(255,184,41)",
"fontSize": "50px",
"items": Array [],
"text": "Welcome to my first JSX for APL skill!",
"type": "Text",
},
29 | const directive = new AplDocument(<LaunchAplDocumentFC />).getDirective()
30 | it('should match snapshot', () => {
> 31 | expect(directive).toMatchSnapshot()
| ^
32 | })
33 | it('should get RenderDocument Directive', () => {
If the change is expected, we can update the snapshot by using -u
option to execute the jest test. If not, we need to fix it.