Sending Down key with WebDriverJS - accessibility

I am writing an acceptance test using Webdriver.io, Mocha & Chai which involves navigating around some autocomplete lists using only the keyboard.
I have used the API's inbuilt keys() function as below to send a Tab key press, a string 'Hello' and then an Enter key press.
it('should be navigable using only the keyboard', () =>
browser
.keys('Tab')
.keys('Hello')
.keys('Enter')
//more steps
);
The problem occurs when I need to send a press of the down arrow key to select an option from the autocomplete list. I've tried the following:
browser
.keys('Down')
.keys('Down_arrow')
and other similar variations, but these just result in the string 'Down' being sent to the autocomplete box rather than a down key press being simulated.
I have checked the webdriver.io API documentation for the keys() function but it just points you in the direction of the Selenium gihub repo and I haven't been able to find any information on keys from that.

I've now solved this. The answer was
.keys('Down arrow')
So close!
It turns out the documentation is now in the wiki section of the repo and the keys info is under JsonWireProtocol.

Related

Understand Dynamic Links Firebase

I would like to understand better Firebase Dynamic Links because i am very new to this subject.
What i would like to know :
FirebaseDynamicLinks.instance.getInitialLink() is supposed to return "only" the last dynamic link created with the "initial" url (before it was shorten) ?
Or why FirebaseDynamicLinks.instance.getInitialLink() doesn't take a String url as a parameter ?
FirebaseDynamicLinks.instance.getDynamicLink(String url) doesn't read custom parameters if the url was shorten, so how can we retrieve custom parameters from a shorten link ?
My use case is quite simple, i am trying to share an object through messages in my application, so i want to save the dynamic link in my database and be able to read it to run a query according to specific parameters.
FirebaseDynamicLinks.instance.getInitialLink() returns the link that opened the app and if the app was not opened by a dynamic link, then it will return null.
Future<PendingDynamicLinkData?> getInitialLink()
Attempts to retrieve the dynamic link which launched the app.
This method always returns a Future. That Future completes to null if
there is no pending dynamic link or any call to this method after the
the first attempt.
https://pub.dev/documentation/firebase_dynamic_links/latest/firebase_dynamic_links/FirebaseDynamicLinks/getInitialLink.html
FirebaseDynamicLinks.instance.getInitialLink() does not accept a string url as parameter because it is just meant to return the link that opened the app.
Looks like there's no straightforward answer to getting the query parameters back from a shortened link. Take a look at this discussion to see if any of the workarounds fit your use case.

Display Text for QnAMaker follow-on prompts

I'm attempting to use follow-on prompts within QnAMaker but am confused about the purpose of the field labelled "Display text" in the "Follow-up prompt" creation dialogue. https://learn.microsoft.com/en-us/azure/cognitive-services/qnamaker/how-to/multiturn-conversation describes this field as "The custom text to display in the follow-up prompt.". To me, that suggests that it's just a label for the follow-up prompt which is typically rendered as a button. I therefore assumed that the text had no purpose other than as a label and that the button would be directly linked to the chosen question / answer pair. However, from experimenting with a QnAMaker knowledge base, it seems that the "Display text" is actually passed to the QnAMaker service and this text is used to search for the answer. This means that the "Display text" value has to be chosen for the purpose of both labelling the button and successfully finding the follow-on answer.
This means I can't use short follow-on prompts such as "How do I pay for it?" or "How do I join it?" where the main Q/A pair relates to one of various services as these strings won't reliably return the intended answer. Rather, the prompts will have to be the more verbose "How do I pay for service A" and "How do I join service A".
Have I understood this correctly? I don't think the documentation makes this at all clear...
Multi-turn QnA Maker conversations are still in preview and there is currently no SDK to help you build a bot that knows how to interact with the follow-up prompt API. You are ultimately in control, and so you get to have your bot treat the display text however it wants. All the "display text" is is a value that you've inserted into an answer in your knowledge base so that it gets returned along with the answer after a call to generateAnswer.
It can be very helpful to have your display text match the text of the question you're linking to because then the prompt's display text can be used to access the correct follow-up QnA pair, so long as the context is included in the API call. That's what happens in this sample. It sounds like you want to get it to work without having the prompt's display text match the text of the follow-up question. That can get tricky, but here's something you can do.
Remember that you specify more than just display text when you make follow-up prompts. You also link to a specific QnA pair. This allows the API to return that QnA ID to you along with the display text. You haven't mentioned which channel your bot is targeting, but if you're using a channel that supports postBack or messageBack actions then you can pass the QnA ID to your bot invisibly and then your bot can use that to access the answer. If you go this route, you may not even need to worry about dialogs or state. You also haven't mentioned what language you're coding your bot in, but here's an example of how this might be implemented in Node.js:
async testQnAMaker(turnContext) {
var qna = new QnAMaker({
knowledgeBaseId: '<GUID>',
endpointKey: '<GUID>',
host: 'https://<APPNAME>.azurewebsites.net/qnamaker'
});
var value = turnContext.activity.value;
var qnaId = value && value.qnaId;
// qnaId will be undefined if value is empty
var results = await qna.getAnswers(turnContext, { qnaId });
var firstResult = results[0];
if (firstResult) {
var answer = firstResult.answer;
var resultContext = firstResult.context;
var prompts = resultContext && resultContext.prompts;
if (prompts && prompts.length) {
var card = CardFactory.heroCard(
answer,
[],
prompts.map(prompt => ({
type: 'messageBack',
title: prompt.displayText,
displayText: prompt.displayText,
text: prompt.displayText,
value: { qnaId: prompt.qnaId }
}))
);
answer = MessageFactory.attachment(card);
}
await turnContext.sendActivity(answer);
} else {
await turnContext.sendActivity("I can't answer that");
}
}
Note that this does have some limitations. Because it works by retreiving the QnA ID from the activity's value property, it may not be able to find the correct QnA pair if the user types in the text of the button manually instead of clicking the button.
If you want to make the display text work on its own without relying on the QnA ID, you could save your own mappings so that your bot knows which display text values correspond to each QnA ID in each context. However, you might also consider just adding the display text as an alternative phrasing of the question in the QnA pair. So "How do I pay for service A" and "How do I pay for service B" could both have "How do I pay for it" as a form of the question. Because you'll now have duplicated phrasings in multiple QnA pairs, you'll need to pass the context in your calls to generateAnswer for this to work.
See this answer for more info about multi-turn conversations.

Telegram bot: How to mention user by its id (not its username)

I am creating a telegram bot and using sendMessage method to send the messages.
it is easy to mention user using #username, But how to mention user when they don't have username?
If using the telegram app/web, we can mentioned the user by #integer_id (name), and telegram app/web will convert it into clickable text. integer_id will be generated automatically when we select the user, after typing #.
another background:
I am trying to use forceReply and I want to target user, if they have username, I can easily target them, by mentioning them on the text on sendMessage method.
the bot I am creating is a "quiz" like bot. where each player need to take turn, and the bot is sending them the question, each msg from bot will target different player.
NOTE: I am not disabling the Privacy Mode, I don't want telegram bombing my server with msg I don't need. it was overloading my cheap nasty server. so, disabling it not an option.
I am open for other solution, where the bot can listen to selected player.
thanks.
UPDATE 21/10:
I've spoke to BotSupport for telegram, they said, for now Bots can't mention user without username.
so in my case, I still keep using forceReply, and also, gave a short msg to user which doesn't have username to set it up, so they can get the benefit from forceReply function.
According to official documentation it is possible to mention user by its numerical id with markup:
[inline mention of a user](tg://user?id=123456789)
According to this link :
it is possible to mention user by its numerical id with markup:
Markdown style
To use this mode, pass Markdown in the parse_mode field
when using sendMessage. Use the following syntax in your message:
[inline mention of a user](tg://user?id=123456789)
and you can also use HTML style :
HTML style
To use this mode, pass HTML in the parse_mode field when using sendMessage. The following tags are currently supported:
inline mention of a user
Try this:
#bot.message_handler(func=lambda message: True)
def echo_message(message):
cid = message.chat.id
message_text = message.text
user_id = message.from_user.id
user_name = message.from_user.first_name
mention = "["+user_name+"](tg://user?id="+str(user_id)+")"
bot_msg = f"Hi, {mention}"
if message_text.lower() == "hi":
bot.send_message(cid, bot_msg, parse_mode="Markdown")
For python-telegram-bot you can do the following:
user_id = update.message.from_user['id']
user_name = update.message.from_user['username']
mention = "["+user_name+"](tg://user?id="+str(user_id)+")"
response = f"Hi, {mention}"
context.bot.sendMessage(chat_id=update.message.chat_id,text=response,parse_mode="Markdown")
No, this restriction is related to Telegram's privacy policy and prevention of abuse.
It is possible to mention a user when sending messages (BOT API), but that is not what you need:
[inline mention of a user](tg://user?id=<user_id>)
Links tg://user?id= can be used to mention a user by their id without using a username. Please note:
These links will work only if they are used inside an inline link. For example, they will not work, when used in an inline keyboard button or in a message text.
These mentions are only guaranteed to work if the user has contacted the bot in the past, has sent a callback query to the bot via inline button or is a member in the group where he was mentioned.
https://core.telegram.org/bots/api#markdown-style
you need to link to the text: "tg://user?id=" and id
user_id = 123456XX # id of the user to mention
chat_id = 123456XXX # chat id where to mention
user_name = name of user
await bot.send_message(chat_id, f"<a href='tg://user?id={user_id}'>{user_name}</a>", "HTML")
here is an example:
#dp.message_handler()
async def mention(msg: types.Message):
await msg.answer(f"<a href='tg://user?id={msg.from_user.id}'>{msg.from_user.full_name}</a>", "HTML")
Bots are able to tag users by their ID, they just can't do this using the official HTTP Bot API.
Update: Not necessairy anymore, since Telegram added native Support for this.
If you log into your bots account with MadelineProto (PHP) you can use this 'link' to mention someone by it's ID with parse_mode set to markdown
[Daniil Gentili](mention:#danogentili)

Google Form email notification

I'm looking to have the information submitted on a google form to be on the email notification that I receive. I have tried several things but I can't seem to get it to work. Any ideas?
Create a new form in Google Docs, if you haven’t done that yet, add the necessary fields to the form and save your changes. Now go back to Google Docs and open the spreadsheet corresponding to that particular form.
Choose Tools > Notification rules... and select the option that says Notify me when... A user submits a form. You can also set how frequently you would like to be notified – right away or with daily digest.
Reference: https://support.google.com/docs/answer/91588
To get the notification in your email, you can refer to the this Google add-on.
Also to enable the data or responses to appear in notification you have to enter a script in the form. which basically tries to extract the columns from the spreadsheet. Sample:
var p = SpreadsheetApp.getActiveSheet();
var column = p.getRange(1,1,1,s.getLastColumn()).getValues()[0];
I hope you build the script by yourself!

How to test a confirm dialog with Cucumber?

I am using Ruby on Rails with Cucumber and Capybara.
How would I go about testing a simple confirm command ("Are you sure?")?
Also, where could I find further documentation on this issue?
The selenium driver now supports this
From Capybara you would access it like this:
page.driver.browser.switch_to.alert.accept
or
page.driver.browser.switch_to.alert.dismiss
or
page.driver.browser.switch_to.alert.text
Seems like there's no way to do it in Capybara, unfortunately. But if you're running your tests with the Selenium driver (and probably other drivers that support JavaScript), you can hack it. Just before performing the action that would bring up the confirm dialog, override the confirm method to always return true. That way the dialog will never be displayed, and your tests can continue as if the user had pressed the OK button. If you want to simulate the reverse, simply change it to return false.
page.evaluate_script('window.confirm = function() { return true; }')
page.click('Remove')
I've implemented these two web steps in /features/step_definitions/web_steps.rb:
When /^I confirm popup$/ do
page.driver.browser.switch_to.alert.accept
end
When /^I dismiss popup$/ do
page.driver.browser.switch_to.alert.dismiss
end
If you want to specifically test the message being displayed, here's a particularly hacky way to do so. I don't endorse it as beautiful code, but it gets the job done. You'll need to load http://plugins.jquery.com/node/1386/release, or change it to do cookies natively if you don't want jQuery.
Use this sort of story:
Given I am on the menu page for the current booking
And a confirmation box saying "The menu is £3.50 over budget. Click Ok to confirm anyway, or Cancel if you want to make changes." should pop up
And I want to click "Ok"
When I press "Confirm menu"
Then the confirmation box should have been displayed
And these steps
Given /^a confirmation box saying "([^"]*)" should pop up$/ do |message|
#expected_message = message
end
Given /^I want to click "([^"]*)"$/ do |option|
retval = (option == "Ok") ? "true" : "false"
page.evaluate_script("window.confirm = function (msg) {
$.cookie('confirm_message', msg)
return #{retval}
}")
end
Then /^the confirmation box should have been displayed$/ do
page.evaluate_script("$.cookie('confirm_message')").should_not be_nil
page.evaluate_script("$.cookie('confirm_message')").should eq(#expected_message)
page.evaluate_script("$.cookie('confirm_message', null)")
end
Updating this for current releases of Capybara. Most Capybara drivers today support the modal API. To accept a confirm modal you would do
accept_confirm do # dismiss_confirm if not accepting
click_link 'delete' # whatever action triggers the modal to appear
end
This can be used in Cucumber with something like
When /^(?:|I )press "([^"]*)" and confirm "([^"]*)"$/ do |button, msg|
accept_confirm msg do
click_button(button)
end
end
which will click the named button and then accept a confirm box with text matching msg
The capybara-webkit driver supports this as well.
Scenario: Illustrate an example has dialog confirm with text
#
When I confirm the browser dialog with tile "Are you sure?"
#
=====================================================================
my step definition here:
And(/^I confirm the browser dialog with title "([^"]*)"$/) do |title|
if page.driver.class == Capybara::Selenium::Driver
page.driver.browser.switch_to.alert.text.should eq(title)
page.driver.browser.switch_to.alert.accept
elsif page.driver.class == Capybara::Webkit::Driver
sleep 1 # prevent test from failing by waiting for popup
page.driver.browser.confirm_messages.should eq(title)
page.driver.browser.accept_js_confirms
else
raise "Unsupported driver"
end
end
Prickle adds some handy convenience methods for working with popups in selenium and webkit
This gist has steps to test a JS confirm dialog in Rails 2 and 3 with any Capybara driver.
It's an adaptation of a previous answer, but doesn't need the jQuery Cookie plugin.
Tried the above answers with no luck. In the end this worked for me:
#browser.alert.ok

Resources