Skip to content

Commit

Permalink
Merge pull request #23 from alexa/release-2024.1
Browse files Browse the repository at this point in the history
Mar 2024 Release of APL Suggester 2024.1
  • Loading branch information
jamescryptoji committed Mar 11, 2024
2 parents fc0b3b7 + d8fb6b4 commit 8071682
Show file tree
Hide file tree
Showing 37 changed files with 979 additions and 5,688 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Alexa APL Suggester

## Overview
This package is developed for providing suggestions and validations on APL (Alexa Presentation Language) templates. Currently it performs static instead of runtime checks. The output warnings are aimed for suggesting best practice of writing APL templates but don't indicate that the template can't be rendered.
This package aims at enhancing APL (Alexa Presentation Language) authoring experience with accurate linting results. With the suggestions and validations provided by APL Suggester, developers can write quality APL templates more easily. The output warnings are suggestions on syntactical validity and best practices, but they don't necessarily indicate that the template can't be rendered.

For more information of how to build APL templates, please visit https://developer.amazon.com/en-US/docs/alexa/alexa-presentation-language/understand-apl.html

Expand All @@ -11,9 +11,9 @@ The easiest way to use apl-suggester is to install it from npm and build it into
npm install apl-suggester --save
```

Since November 27 2023, APL Suggester's latest version is `2023.3.0`, following APL 2023.3 release. Existing users please make sure to pull the latest and update your `package.json`:
Since March 11 2024, APL Suggester's latest version is `2024.1.0`, following APL 2024.1 release. Existing users please make sure to pull the latest and update your `package.json`:
```
npm install apl-suggester@2023 --save
npm install apl-suggester@2024 --save
```

Then use it in your app:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "apl-suggester",
"version": "2023.3.0",
"version": "2024.1.0",
"description": "This Package is developed for providing suggestions and validations on APL templates.",
"engines": {
"node": ">=12.0.0"
Expand Down
4 changes: 3 additions & 1 deletion src/CommandSchemaValidator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import * as SelectCommandJSONSchema from './assets/commands/SelectCommand';
import * as ReinflateCommandJSONSchema from './assets/commands/ReinflateCommand';
import * as InsertItemCommandJSONSchema from './assets/commands/InsertItemCommand';
import * as RemoveItemCommandJSONSchema from './assets/commands/RemoveItemCommand';
import * as LogCommandJSONSchema from './assets/commands/LogCommand';

/**
* Entrance to validate commands.
Expand Down Expand Up @@ -103,7 +104,8 @@ export class CommandSchemaValidator {
['Select', SelectCommandJSONSchema.JSON_SCHEMA],
['Reinflate', ReinflateCommandJSONSchema.JSON_SCHEMA],
['InsertItem', InsertItemCommandJSONSchema.JSON_SCHEMA],
['RemoveItem', RemoveItemCommandJSONSchema.JSON_SCHEMA]
['RemoveItem', RemoveItemCommandJSONSchema.JSON_SCHEMA],
['Log', LogCommandJSONSchema.JSON_SCHEMA]
]);

/**
Expand Down
38 changes: 38 additions & 0 deletions src/__tests__/CommandSchemaValidator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,44 @@ describe('CommandSchemaValidator.', () => {
expect(result[0].level).to.equal(NotificationLevel.WARN);
});

it('should allow all levels in Log command.', async () => {
const data = fs.readFileSync(`src/__tests__/commands/Log_allLevels.json`, 'utf8');
const testCases = JSON.parse(data);
let result;
let total = 0;
testCases.forEach((obj) => {
result = commandSchemaValidator.validateCommand(obj, 'Log');
total += result.length;
});
expect(total).to.be.equal(0);
});

it('should allow array of anything in Log command.', async () => {
const data = fs.readFileSync(`src/__tests__/commands/Log_differentArguments.json`, 'utf8');
const testCases = JSON.parse(data);
let result;
let total = 0;
testCases.forEach((obj) => {
result = commandSchemaValidator.validateCommand(obj, 'Log');
total += result.length;
});
expect(total).to.be.equal(0);
});

it('should see 3 errors in Log command.', async () => {
const data = fs.readFileSync(`src/__tests__/commands/Log_errorCases.json`, 'utf8');
const testCases = JSON.parse(data);
let result = [];
testCases.forEach((obj) => {
result = result.concat(commandSchemaValidator.validateCommand(obj, 'Log'));
});
expect(result.length).to.be.equal(4);
expect(result[0].path).to.equal('/type');
expect(result[1].path).to.equal('/arguments');
expect(result[2].path).to.equal('/level');
expect(result[3].path).to.equal('/level');
});

async function verifyCommand(fileName : string, type : string) {
const data = fs.readFileSync(`src/__tests__/commands/${fileName}`, 'utf8');
const result = commandSchemaValidator.validateCommand(JSON.parse(data), type);
Expand Down
28 changes: 18 additions & 10 deletions src/__tests__/ComponentSchemaController.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,10 @@ describe('ComponentSchemaController.', () => {
await verifyComponent('Frame.json', 'Frame');
});

it('should validate Frame component.', async () => {
await verifyComponent('FrameWithGradient.json', 'Frame');
});

it('should validate Image component.', async () => {
// TODO add it back to Image.json when mixin is implemented. "position": "absolute",
await verifyComponent('Image.json', 'Image');
Expand Down Expand Up @@ -99,21 +103,21 @@ describe('ComponentSchemaController.', () => {
expect(result.length).to.be.equal(8);
expect(result[0].path).to.be.equal('/');
expect(result[0].level).to.be.equal(NotificationLevel.WARN);
expect(result[0].errorMessage.indexOf('position') > 0).to.be.equal(true);
expect(result[0].errorMessage).to.include('position');
expect(result[1].path).to.be.equal('/');
expect(result[1].level).to.be.equal(NotificationLevel.WARN);
expect(result[1].errorMessage.indexOf('scrim') > 0).to.be.equal(true);
expect(result[2].path).to.be.equal('/layoutDirection');
expect(result[1].errorMessage).to.include('scrim');
expect(result[2].path).to.be.equal('/actions/0');
expect(result[2].errorMessage).to.include('name');
expect(result[2].level).to.be.equal(NotificationLevel.WARN);
expect(result[3].path).to.be.equal('/width');
expect(result[3].path).to.be.equal('/actions/1/enabled');
expect(result[3].errorMessage).to.include('boolean');
expect(result[3].level).to.be.equal(NotificationLevel.WARN);
expect(result[4].path).to.be.equal('/actions/0');
expect(result[4].errorMessage.indexOf('name') > 0).to.be.equal(true);
expect(result[4].path).to.be.equal('/layoutDirection');
expect(result[4].level).to.be.equal(NotificationLevel.WARN);
expect(result[5].path).to.be.equal('/actions/1/enabled');
expect(result[5].errorMessage.indexOf('boolean') > 0).to.be.equal(true);
expect(result[5].path).to.be.equal('/role');
expect(result[5].level).to.be.equal(NotificationLevel.WARN);
expect(result[6].path).to.be.equal('/role');
expect(result[6].path).to.be.equal('/width');
expect(result[6].level).to.be.equal(NotificationLevel.WARN);
expect(result[7].path).to.be.equal('/filters/0/kind');
expect(result[7].level).to.be.equal(NotificationLevel.WARN);
Expand Down Expand Up @@ -190,12 +194,16 @@ describe('ComponentSchemaController.', () => {
const result = await validate('VideoTextTracksError.json', 'Video');
expect(result.length).to.equal(3);
expect(result[0].errorMessage).to.equal('should have required property \'type\'');
// From 2023.2, "type" enum expects to include "subtitle" and maybe more
expect(result[1].errorMessage).to.equal('should be equal to one of the allowed values : caption');
expect(result[2].errorMessage).to.equal('should NOT be valid');
});
it('should validate Extension component', async () => {
await verifyComponent('ExtensionComponent.json', 'ExtensionComponent');
});

it('should find 1 error in handleVisibilityChange.', async () => {
const result = await validate('VisibilityChangeHandler.json', 'Text');
expect(result.length).to.be.equal(1);
expect(result[0].path).to.be.equal('/handleVisibilityChange/0/when');
});
});
4 changes: 2 additions & 2 deletions src/__tests__/GraphicSchemaValidator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ describe('GraphicSchemaValidator.', () => {
expect(result.length).to.be.equal(10);
expect(result[0].path).to.be.equal('/');
expect(result[0].level).to.be.equal(NotificationLevel.WARN);
expect(result[0].errorMessage.indexOf('pathData') > 0).to.be.equal(true);
expect(result[0].errorMessage).to.include('pathData');
expect(result[1].path).to.be.equal('/');
expect(result[1].level).to.be.equal(NotificationLevel.WARN);
expect(result[2].path).to.be.equal('/');
expect(result[2].level).to.be.equal(NotificationLevel.WARN);
expect(result[3].path).to.be.equal('/bind/0');
expect(result[3].level).to.be.equal(NotificationLevel.WARN);
expect(result[3].errorMessage.indexOf('value') > 0).to.be.equal(true);
expect(result[3].errorMessage).to.include('value');
expect(result[4].path).to.be.equal('/filters/0/type');
expect(result[4].level).to.be.equal(NotificationLevel.WARN);
expect(result[5].path).to.be.equal('/filters/0/horizontalOffset');
Expand Down
13 changes: 13 additions & 0 deletions src/__tests__/StaticAplTemplateValidator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,19 @@ describe('Integration Test to verify the JSON schema.', () => {
expect(result[2].path).to.equal('/extensions/2/required');
});

it('should allow valid settings section', async () => {
await readSchemaAndPassAllValidations('allowedSettings.json');
});

it('should validate settings section and yield 2 errors', async () => {
const result = await verifyTemplate('errorSettings.json');
expect(result.length).to.be.equal(2);
expect(result[0].path).to.equal('/settings/supportsResizing');
expect(result[0].errorMessage).to.equal('should be boolean');
expect(result[1].path).to.equal('/settings/pseudoLocalization');
expect(result[1].errorMessage).to.equal('should NOT have unevaluated properties');
});

async function readSchemaAndPassAllValidations(fileName : string) {
const result = await verifyTemplate(fileName);
expect(result).to.have.lengthOf(0);
Expand Down
36 changes: 36 additions & 0 deletions src/__tests__/commands/Log_allLevels.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[
{
"type":"Log",
"level":"info",
"message":"printing info log",
"arguments":[ "this is info log for you"
]
},
{
"type":"Log",
"level":"warn",
"message":"printing warning log",
"arguments":["this is info warning for you"
]
},
{
"type":"Log",
"level":"error",
"message":"printing error log",
"arguments":["this is error log for you"
]
},
{
"type":"Log",
"level":"critical",
"message":"printing critical log",
"arguments":["this is critical log for you"]
},
{
"type":"Log",
"level":"debug",
"message":"printing debug log",
"arguments":["this is debug log for you"
]
}
]
49 changes: 49 additions & 0 deletions src/__tests__/commands/Log_differentArguments.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
[
{
"type":"Log",
"level":"info",
"message":"printing info log with argument value as NULL",
"arguments":[]
},
{
"type":"Log",
"level":"warn",
"message":"printing warning log with argument value as STRING",
"arguments":[
"String 1",
"String 2",
"String 3"
]
},
{
"type":"Log",
"level":"error",
"message":"printing error log with argument value as NUMBERS",
"arguments":[
1,
2,
3
]
},
{
"type":"Log",
"level":"critical",
"message":"printing critical log with argument value as ARRAY",
"arguments":[
[1, "array1", 2, "array2"]
]
},
{
"type":"Log",
"level":"debug",
"message":"printing debug log with argument value as NESTED OBJECT",
"arguments":[
1,
2,
{
"nested1":"object1",
"nested2":"object2"
}
]
}
]
32 changes: 32 additions & 0 deletions src/__tests__/commands/Log_errorCases.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[
{
"type":"LOG",
"level":"critical",
"message":"type is a const: Log",
"arguments":[]
},
{
"type":"Log",
"level":"warn",
"message":"",
"arguments":"cannot be string"
},
{
"type":"Log",
"level":1,
"message":"NULL log level",
"arguments":[
1,
2,
3
]
},
{
"type":"Log",
"level":"karthik",
"message":"incorrect log level",
"arguments":[
[1, "array1", 2, "array2"]
]
}
]
12 changes: 10 additions & 2 deletions src/__tests__/components/Container.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,20 @@
{
"name": "booleanValueAsNumber",
"type": "boolean",
"value": 1
"value": 1,
"onChange": [
{
"type": "SetValue",
"property": "opacity",
"value": 1
}
]
},
{
"name": "booleanValueAsNull",
"type": "boolean",
"value": null
"value": null,
"onChange": []
}
],
"handleTick": [
Expand Down
12 changes: 7 additions & 5 deletions src/__tests__/components/ExtensionComponent.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
"screenMode": "${environment.screenMode}",
"width": "50vw",
"height": "100vh",
"onMount": {
"type": "Fish:AutoCycleHealthMonitors",
"seconds": 30
},
"onMount": [
{
"type": "Fish:AutoCycleHealthMonitors",
"seconds": 30
}
],
"monitors": {
"Temperature": {
"low": 78,
Expand All @@ -28,4 +30,4 @@
"phone": "${tankOwner.mobile}",
"text": "Tank alarm ${event.monitorName} current value is ${event.monitorValue}"
}
}
}
7 changes: 7 additions & 0 deletions src/__tests__/components/Frame.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@
]
}
],
"handleVisibilityChange": [
{
"description": "test visibility change handler",
"when": true,
"commands": []
}
],
"width": 10,
"bind": [
{
Expand Down
6 changes: 6 additions & 0 deletions src/__tests__/components/FrameWithGradient.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"type": "Frame",
"background": {
"colorRange": ["black", "white"]
}
}
7 changes: 7 additions & 0 deletions src/__tests__/components/Image.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@
]
}
],
"handleVisibilityChange": [
{
"description": "test visibility change handler",
"when": true,
"commands": []
}
],
"actions": [
{
"name": "activate",
Expand Down

0 comments on commit 8071682

Please sign in to comment.