bespoken / virtual-alexa

:robot: Easily test and debug Alexa skills programmatically

Home Page:https://bespoken.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

resolutions information for custom slot types

schiller-manuel opened this issue · comments

I want to test my code which relies on the resolutions information for custom slot types.
As far as I understood, virtual-alexa does not yet support this.
Is my understanding correct?
If yes, is this feature planned in virtual-alexa?
Would you accept a PR?

Hi @DachZiegel - we do not provide support for that built into the library.

However, you can filter the request before it is sent to your skill, and add additional data, such as resolution information, with code like this:

reply = await alexa.filter(function (payload) {
    console.log("Payload: " + JSON.stringify(payload, null, 2));
    payload.request.intent.slots.City.resolutions = {
        resolutionsPerAuthority: [
            {
                authority: "amzn1.er-authority.echo-sdk.<skill-id>.AMAZON.US_CITY",
                status: {
                    code: "ER_SUCCESS_MATCH"
                },
                values: [
                    {
                        value: {
                            id: "ORD",
                            name: "the windy city"
                        }
                    }
                ]
            }
        ]
    }
}).utter("go to chicago");

I hope that helps! Let me know.

👍 Thanks, that looks like a good solution for now.

Handling this automatically inside virtual-alexa would still be nice :)

We would also like access to the id field in the resolutions. It would be awesome to know if this is on your roadmap, as we'd love to migrate over to using this library for our testing!

Hi @JoshTumath - it is certainly on our roadmap - I'll follow-up and let you know exactly when we expect to have it. Did you happen to see the workaround above BTW? Would that work for you?

Thanks @jkelvie. And yes, the example above was very helpful. We noticed the filter method in the API docs, but weren't sure what it was used for because there were no examples.

I would also like to see this feature added, especially the ability to set resolution values in my tests (for both matches and non-matches). I was using filter and it works. Here are some gotchas:

Don't forget to reset the filter after use by calling alexa.resetFilter() as otherwise the filter will be applied to every subsequent request too.

Because the IntentRequest may trigger other events to be sent to the skill, e.g. audio player events, before you can call resetFilter(), we also need to apply a condition so that the filter only applies to the IntentRequest.

Following the example above:

reply = await alexa.filter(function (payload) {
    console.log("Payload: " + JSON.stringify(payload, null, 2));

    if (payload.request.type !== "IntentRequest") {
        return;
    }

    payload.request.intent.slots.City.resolutions = {
       resolutionsPerAuthority: [
           {
               authority: "amzn1.er-authority.echo-sdk.<skill-id>.AMAZON.US_CITY",
               status: {
                   code: "ER_SUCCESS_MATCH"
               },
               values: [
                   {
                       value: {
                           id: "ORD",
                           name: "the windy city"
                       }
                   }
               ]
           }
       ]
   }
}).utter("go to chicago");

alexa.resetFilter();

Hi @DachZiegel @JoshTumath @leihelondon - we have released a new version of Virtual Alexa with support for entity resolution. You can read about how it works here:
https://github.com/bespoken/virtual-alexa/blob/master/docs/EntityResolution.md

The version is 0.6.1 - please give it a try and let me know how it goes for you.

Following up on resetFilter(). When should it be called? I tried calling it like this

it('Phone message', function () {
ALEXA.filter((payload) => {
payload.session.attributes.current_location = {'title':'Location', 'phone':'1234567890', 'street_address':'XXXXXX', 'city': 'XXXX', 'state':'XX', 'zip':'11111'};
});
return ALEXA.utter('what is their phone number').then( (result) => {
ASSERT.include(result.response.outputSpeech.ssml, '1234567890');
});
ALEXA.resetFilter();
});
I am calling resetFilter after utter and it is not working.
I am using Mocha and Chai.

I tried to place it in afterEach() too, but nothing is working.
Any help is greatly appreciated.

Thankyou,
Kranthi.

in this case is not working because it's being called after the return.
For this one example to work for example you can do

return ALEXA.utter('what is their phone number').then( (result) => {
ASSERT.include(result.response.outputSpeech.ssml, '1234567890');
ALEXA.resetFilter();
});

It also should work on the afterEach as long it's at the same level of the rest of the tests.

Hi Perata,

I am sorry to say that this one also did not work.

Here is my full example

describe.only('Phone Test', function () {
afterEach( function () {
ALEXA.resetFilter();
});

it('Phone message',  function () {
	ALEXA.filter((payload) => {
		payload.session.attributes.current_location =  {'title':'NAME', 'phone':'1234567890', 'street_address':'XXXX', 'city': 'XXXX', 'state':'XX', 'zip':'XXXXX'};
	});		
	return ALEXA.utter('what is their phone number').then( (result) => {
		ASSERT.include(result.response.outputSpeech.ssml, '1234567890');
		ALEXA.resetFilter();
	});
});

it('Phone message with out location',  function () {
	return ALEXA.utter('what is their phone number').then( (result) => {
		ASSERT.include(result.response.outputSpeech.ssml, 'Please choose a location to get its phone number');
	});
});

});

In this my first test case passes and second one fails.
Second one is inferring the session attributes from the first test case.

Please advice.
--Kranthi.

Thanks for the full example, the issue here is not the filters but the context (which is only cleaned by default when the session ends in the alexa interaction), since you need to clean both of them between tests, you can change your afterEach to:

afterEach( async function () {
ALEXA.resetFilter();
await ALEXA.endSession();
});

I got it now. I understand what the problem is and this solution helped me. Thank you.