Skip to content

Commit

Permalink
feat: Add support for CanFulfillIntentRequest
Browse files Browse the repository at this point in the history
  • Loading branch information
Shulou authored and Shreyas-vgr committed Aug 20, 2021
1 parent b611476 commit 7587a46
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 2 deletions.
14 changes: 14 additions & 0 deletions src/systemActs/ContentActs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
ValueClearedPayload,
ValueRemovedPayload,
ValueSetPayload,
CanFulfillIntentPayload,
} from './PayloadTypes';
import { SystemAct } from './SystemAct';

Expand Down Expand Up @@ -410,3 +411,16 @@ export class InvalidRemoveValueAct<T> extends ContentAct {
);
}
}

export class CanFulfillIntentAct extends ContentAct {
payload: CanFulfillIntentPayload;

constructor(control: Control, payload: CanFulfillIntentPayload) {
super(control);
this.payload = payload;
}

render(input: ControlInput, controlResponseBuilder: ControlResponseBuilder): void {
controlResponseBuilder.withCanFulfillIntent(this.payload.intent);
}
}
8 changes: 8 additions & 0 deletions src/systemActs/PayloadTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
import { canfulfill } from 'ask-sdk-model';

/**
* Payload for ValueSetAct
Expand Down Expand Up @@ -184,3 +185,10 @@ export interface LiteralContentPayload {
promptFragment: string;
repromptFragment?: string;
}

/**
* Payload for CanFulfillIntentAct
*/
export interface CanFulfillIntentPayload {
intent: canfulfill.CanFulfillIntent;
}
33 changes: 31 additions & 2 deletions src/utils/testSupport/TestingUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@ import {
ResponseFactory,
Skill,
} from 'ask-sdk-core';
import { Intent, IntentRequest, interfaces, LaunchRequest, Request, RequestEnvelope } from 'ask-sdk-model';
import {
Intent,
IntentRequest,
interfaces,
LaunchRequest,
Request,
RequestEnvelope,
canfulfill,
} from 'ask-sdk-model';
import { expect } from 'chai';
import _ from 'lodash';
import { Control } from '../../controls/Control';
Expand Down Expand Up @@ -185,7 +193,10 @@ export async function testTurn(
} else {
const expectedPrompt: string =
typeof expectedResponse === 'string' ? expectedResponse : expectedResponse.prompt;
if (!expectedPrompt.toLowerCase().startsWith('a:')) {
if (
!expectedPrompt.toLowerCase().startsWith('a:') &&
input.handlerInput.requestEnvelope.request.type !== 'CanFulfillIntentRequest'
) {
throw new Error(
`test configuration error: Alexa prompt should start with A: -->${expectedResponse}`,
);
Expand Down Expand Up @@ -285,6 +296,24 @@ export class TestInput {

return dummyControlInput(userEvent);
}

public static canFulfillIntentRequest(
nameOrIntent: string | Intent,
slotValues?: { [k: string]: any },
): ControlInput {
const intent =
typeof nameOrIntent === 'string' ? IntentBuilder.of(nameOrIntent, slotValues) : nameOrIntent;
const canFulfillIntentRequest: canfulfill.CanFulfillIntentRequest = {
type: 'CanFulfillIntentRequest',
requestId: makeRequestId(),
timestamp: '2020-10-19T18:46:20Z',
locale: 'en-US',
dialogState: 'STARTED',
intent,
};

return dummyControlInput(canFulfillIntentRequest);
}
}

// TODO: API: unify with SkillInvoker
Expand Down
88 changes: 88 additions & 0 deletions test/systemActs/ContentActs.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { suite, test } from 'mocha';
import { ContainerControl } from '../../src/controls/ContainerControl';
import { Control } from '../../src/controls/Control';
import { ControlManager } from '../../src/controls/ControlManager';
import { ControlHandler } from '../../src/runtime/ControlHandler';
import { SkillInvoker, TestResponseObject } from '../../src/utils/testSupport/SkillInvoker';
import { TestInput, testTurn } from '../../src/utils/testSupport/TestingUtils';
import { ControlInput } from '../../src/controls/ControlInput';
import { ControlResultBuilder } from '../../src/controls/ControlResult';
import { CanFulfillIntentAct } from '../../src/systemActs/ContentActs';
import { canfulfill } from 'ask-sdk-model';

suite('Test CanFulfillIntentRequest', () => {
const canFulfillIntent: canfulfill.CanFulfillIntent = {
canFulfill: 'YES',
slots: {
Artist: {
canUnderstand: 'YES',
canFulfill: 'YES',
},
Song: {
canUnderstand: 'YES',
canFulfill: 'YES',
},
DedicatedPerson: {
canUnderstand: 'YES',
canFulfill: 'YES',
},
},
};
class TestControlManager extends ControlManager {
createControlTree(): Control {
return new CustomRootControl({ id: 'root' });
}
}

class CustomRootControl extends ContainerControl {
async canHandle(input: ControlInput): Promise<boolean> {
return input.request.type === 'CanFulfillIntentRequest';
}

async handle(input: ControlInput, resultBuilder: ControlResultBuilder): Promise<void> {
if (input.request.type === 'CanFulfillIntentRequest') {
resultBuilder.addAct(
new CanFulfillIntentAct(this, {
intent: canFulfillIntent,
}),
);
}
return;
}
}

test('CanFulfillIntentRequest', async () => {
const requestHandler = new ControlHandler(new TestControlManager());
const invoker = new SkillInvoker(requestHandler);
const intentName = 'SendSongRequest';
const expectedResponse: TestResponseObject = {
responseEnvelope: {
version: '',
response: {
canFulfillIntent,
},
},
prompt: '',
};
const slots = {
Artist: {
name: 'Artist',
confirmationStatus: 'NONE',
},
Song: {
name: 'Song',
confirmationStatus: 'NONE',
},
DedicatedPerson: {
name: 'DedicatedPerson',
confirmationStatus: 'NONE',
},
};
await testTurn(
invoker,
'U: __',
TestInput.canFulfillIntentRequest(intentName, slots),
expectedResponse,
);
});
});

0 comments on commit 7587a46

Please sign in to comment.