Testcafe .presskey for multiple presses - javascript

I'm trying to write TestCafe Javascript to test a webpage using the keyboard as sole navigation (i.e. 'tabbing through the options').
TestCafe runs these tests, but they run extremely fast (5 seconds max), and nothing happens on the screen. So I'm wondering if it's even actually working.
On top of that, I'm trying to find a way to DRY out my code. From what I read in the docs, each time I want a key pressed, I need to call .pressKey('tab'). If I need to hit 'tab' 5 times in a row, I have 5 lines of that in my code. Is there any way to eliminate this unnecessary repetition?
Thanks!

TestCafe sets focus to the next element on the page when the .pressKey('tab') action is called. To make your code cleaner, you can pass several keys separated with spaces to the pressKey action.
I've created a simple example for this stackoverflow page:
import { Selector } from 'testcafe';
fixture `stackoverflow`
.page `https://stackoverflow.com/questions/46612440/testcafe-presskey-for-multiple-presses`;
test('tab', async t => {
await t
.click(Selector('#search').find('[name="q"]'))
.pressKey('tab tab tab tab tab tab tab tab tab tab tab tab tab tab');
});
Here is a screencast that demonstrates how it works (I've set the test run speed to 0.5 via the --speed option): https://www.screencast.com/t/dERD60nGc4f

If you want to slow it down to visually check, you can interleave calls to wait(x)
await t.pressKey(TAB);
await t.wait(800);
await t.pressKey(TAB);
await t.wait(800);
etc.

Related

Delay javascript execution? Not sure what I have to do in this case

Basically, I'm using the accordion thing in Bootstrap 5, but because I have a lot of text, inside the body of the accordion, it takes longer to close the first one when opening the second one.
What I want is for it to maybe delay the execution of a JS function so that it'll wait until the first accordion header has fully closed, and then run the function.
This is basically what it looks like: https://prnt.sc/17wa079
when pressing Header 1, I have onclick=goToHeader1 and that's basically just using scrollIntoView() so that Header 1 is at the very top of the screen. If you don't close Header 1 before opening header 2, it's all weird and only shows the bottom of header 2 at the top (where it should show actually show "Header 2", it shows the bottom part of the body of Header 2) or it just doesn't even show Header 2 at all.
So I figured that perhaps if you could delay onclick="goToHeading2()
you could wait for Header 1 to fully close (give it like 1 or 2 seconds) then execute function goToHeading2() and then that would fix it.
Just haven't figured out how to delay it by 1 or 2 seconds, so if anyone could suggest how, that would be great. Or if anyone has a better way to doing it, that would be even better.
I think if you want to delay your js code you can do it using :
await new Promise( resolve => setTimeout( resolve, 1000 ));
// this part of your code will be executed after 1 sec
But I don't think this a good idea as the time taken to run the previous function will be different on different devices.
I think you are calling Element.scrollIntoView on the full accordion, it will better if you call scrollIntoView on just the accordion-header block.
Moreover, scrollIntoView has some options like alignToTop which you can use for better results.
element.scrollIntoView();
element.scrollIntoView(alignToTop); // Boolean parameter
element.scrollIntoView(scrollIntoViewOptions); // Object parameter
In your case, element.scrollIntoView(true); will bring the best results.
You can read more on this here.

Click event not triggering for every iteration of for loop

I want to automate this page to generate exam results. I want to generate exam results from one particular date to some other particular date. On clicking the submit button, the page generates another page in a new tab.
Manually clicking 10 times will generate 10 tabs. But see the following code:
for(let i=0;i<10;i++)
{
document.querySelector('#reg1').click();
console.log(`clicked ${i}th time`)
}
I want to trigger a click 10 times and it should generate 10 tabs accordingly. But the problem is that the click works only works on the 10th iteration and spawns 1 tab only. Help me.
see
Edit:
#Jesse
See my utility full code:
var dateFrom=new Date('2017-01')
var dateTo=new Date('2019-01')
for(var i=dateFrom;i<dateTo;i.setMonth(i.getMonth()+1))
{
// console.log(`${i.getFullYear()}-${i.getMonth()}`);
// var dd=`${i.getFullYear()}-${i.getMonth()}`;
var dd=new Date(i).toISOString().substr(0,7);
console.log(dd);
document.querySelector("input#picker.form-control").value=dd;
var type='Supplementary'
document.querySelector("select#result_type.form-control.form-email.selectoption").value=type;
document.querySelector('#reg1').click();
}
Somehow you have to execute the subsequence clicking in an asynchronous manner. I got this work by this:
let i=0;
(function doClick(){
document.querySelector('#reg1').click();
i++;
if(i<10) setTimeout(() => doClick());
})()
Another approach using async function:
(async function doClick() {
for(let i=0;i<10;i++) {
document.querySelector('#reg1').click();
await new Promise(setTimeout);
}
})()
I just figured out that my browser's popup blocker is stopping the subsequent tabs from being opened.
Try turning off your popup blocker. I was able to trigger the behavior you're after with mine off.
It works when you click it because it's a user interaction, so the blocker assumes it's something you're actively trying to do. If you trigger it programmatically, repeatedly, it gets blocked. This makes sense given that one of your browser's popup blocker's primary functions is to prevent sites from trapping you in infinite popup hell.
It's because you're using the same ID. Either switch to using a class or change the ID names so they aren't identical.

Speeded up a slow jQuery Mobile page transition - why?

Background: I have a jQuery mobile app (single .htm, multi-jqm pages) where one of the pages contains a listview with a reasonably large number of list items (300-500 say). I'm testing the boundaries of performance here so currently my custom "paging" will use CSS to hide all but 25 of the items at a time. The app is deployed to devices using PhoneGap.
So, to my question.
I've found that when clicking on an item in the list, navigation to the page the list item links to is extremely sluggish on devices when I use the code below. This handles the click, extracts an id from the list item and stores it, then allows the click to perform the page navigation:
$('#largeListView').on('vclick', 'a[href="#subView"]', function (e) {
theSubView.setId($(this).data("id"));
});
However, the code below is much quicker. It stores the id also but then prevents the click causing the navigation and manually changes the page instead:
$('#largeListView').on('vclick', 'a[href="#subView"]', function (e) {
theSubView.setId($(this).data("id"));
e.preventDefault();
$.mobile.changePage('#subView');
});
The only downside of the quicker solution (as far as I know) is that the item does not show any UI feedback that a click occurred.
Does anyone know why I get the vast speed improvement here and if there is a way of speeding up option 1 instead?
I don't like circumventing the design in this way and would prefer to use option 1 if I can get good performance.
Thanks!
Chris.
just a guess but maybe this happens due to the fact that the default browser behavior triggers custom events and invokes some scrolling mechanism whereas the $.mobile call avoids this overhead...
I do not think you can improve that so easily but maybe try to use a small delay to perform this asynchronously
$('#largeListView').on('vclick', 'a[href="#subView"]', function (e) {
var id = $(this).data("id");
setTimeout(function() {
theSubView.setId(id);
}, 0);
});

rules for "prevent this page from creating additional dialogs"

I try to understand Firefox's behavior regarding the added "prevent this page from creating additional dialogs" on dialog boxes.
Using jquery, if I add the following listeners :
//html
<input class="testInput" />
//javascript
$('.testInput')
.click(function(){ alert('clicked') })
.keyup(function(){ alert('keyup') })
When clicking on the input, the alert box appears normally, until the
~13th time.
When hitting a key, on the other hand, the second message box already
appears with the message "prevent this page from creating additional
dialogs". Actually, there seems to be some tiemout, and if I wait
like 2 seconds between two keystrokes, the message disappears.
From my informal tests, 2. actually applies whenever the alert box is not called from within a onclick callback (e.g : keyup callback, displaying an alert box in answer to an ajax action...)
I am using Firefox 9.0.1 under Ubuntu, as far as I know I haven't tweaked firefox's settings regarding these thresholds.
I imagine it happens with any recent version of any browser.
I am using the jQuery library, but I don't think it is relevant here.
My question is :
What are the exact rules which make this warning appear in a dialog box ?
[Edit]
Using Chromium/Ubuntu (version 17.0.963.26), the threshold seems to be only the delay between two dialog boxes.
You can test this from jsfiddle here (thx Rory McCrossan)
The exact rule(s): A timed interval between the dialog boxes popping up.
The value used to determine this is set in SUCCESSIVE_DIALOG_TIME_LIMIT
Check out line 2614 in the link below the snippet:
nsGlobalWindow::DialogOpenAttempted()
TimeDuration dialogDuration(TimeStamp::Now() - topWindow->mLastDialogQuitTime);
if (dialogDuration.ToSeconds() < Preferences::GetInt("dom.successive_dialog_time_limit",SUCCESSIVE_DIALOG_TIME_LIMIT)){topWindow->mDialogAbuseCount++;return (topWindow->GetPopupControlState() > openAllowed || topWindow->mDialogAbuseCount > MAX_DIALOG_COUNT);}topWindow->mDialogAbuseCount = 0; return false;}
Link to source
You can kick around the Firefox source if you like. Note that different browsers will have different rules.
The relevant code for Firefox is in nsGlobalWindow.cpp and nsGlobalWindow.h (the links below are to line numbers, and so will slowly rot as the source changes). It appears to be controlled by the constants MAX_DIALOG_COUNT (10) in nsGlobalWindow.h and SUCCESSIVE_DIALOG_TIME_LIMIT (3, units are seconds). nsGlobalWindow.cpp keeps a count (mDialogAbuseCount). Apparently, the dialogDuration function either increments or clears mDialogAbuseCount depending on whether the dialog has been open longer than the SUCCESSIVE_DIALOG_TIME_LIMIT. The AreDialogsBlocked function uses the mDialogAbuseCount (in part) to decide whether they're blocked.
So in short: If you're repeatedly opening pop-ups and then closing them within three seconds, after 10 or so you'll trigger something.

ASP.NET/jQuery Post-Back, but not when using browser's "Back" button

I'm working on an ASP.NET Web Project with some AJAX magic. As my GridView's data needs up to 15 seconds to be gathered, I send the page to the client and fire an asynchronous update of an UpdatePanel via jQuery/JScript (see below).
This works well, so far. Now I'd like to skip this step when the user navigates to the next page (e.g. record detail view) and comes back via the "Back" button. Is there a way to get his, and what's the most elegant one?
This one does not work (hasDonePostBack's value isn't kept by the browser):
var hasDonePostBack = false;
function fRefreshAsyncOnce(id, param) {
$(document).ready(function() {
if (!hasDonePostBack) {
__doPostBack(id, param);
hasDonePostBack = true;
}
});
}
Any help would be great!
The reason why this is important: Regetting the data takes another 15 seconds. Moreover, the grid is working with controls and more client script (e.g. checkboxes that can be checked, CSS classes that are toggled, etc.), and all this should be the same after returning.
Cheers,
Matthias
You may want to look at the history point feature; you may be able to take advantage of that for this feature: http://msdn.microsoft.com/en-us/library/cc488548.aspx
However, that is the nature of the beast when triggering client-side operations... the other option is allowing the user to cancel the postback (or try to interpret a way to cancel it yourself) using this technique: http://msdn.microsoft.com/en-us/library/bb398789.aspx

Categories

Resources