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

    Left: LaunchRequest.ts (get Error)
    Right: LaunchRequest.tsx (No Error)

    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.

    Left: import React (No Error)
    Right:nothing (Get Error)

    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.

    広告ここから
    広告ここまで

    Random posts

    Home
    Search
    Bookmark