Determine an empty event loop - javascript

Is there a way to determine if there is an empty event loop?
For example,
// Example 1
setInterval(() => console.log("hi"), 1000);
// event loop is not empty
// Example 2
console.log("hi");
// event loop is now empty

Based on your comment:
I want to exit a process once the event loop is empty
Node.js got you covered. Node process will exit automatically when the event-loop is empty.
If you opened this question because your tests (using Jest) were hanged for some reason, it means that the event loop was not empty at the end of all the afterEach and afterAll hooks, so if you are running a single test-file, Jest will usally hang. If you are running multiple tests files, jest will print an error which indicated that Jest forced to (not-gracefully) close the node-process of one of the test-files.
To fix that, make sure you don't forget to await to any promise, close all conections and clear all timeouts.

Related

How to error handle in cypress for element not found

The below block successfully executes when tr is found, but sometimes it will be empty and no tr. How to handle the exception if tr not found?
cy.get('tbody.ant-table-tbody tr').then((rows) => {
// success
});
There is no catch block chained here.
cy.get() will always fail if it cannot find the element (unless you run cy.get('foo').should('not.exist'), but that can't be used in combination with if/else.)
You can instead use JQuery in combination with Cypress to check for an element's existence without failing a test. In this case, we'll yield the result from the parent element, and search it with JQuery.
cy.get('tbody.ant-table-tbody').then(($parent) => {
if ($parent.find('tr').length) { // check if the length is > 0
// Code to run if tr is found
} else {
// Code to run if tr is not found
}
});
All of that being said, I would push back on needing to use something like this. Tests should be deterministic, and you should know before the test runs if tr exists or not. Consider the ways that you can pre-determine before the test runs (maybe seeding a database, or intercepting a network request). Also consider, what happens if tr never exists -- that functionality is never being tested. Or, if tr always exists, then the functionality of when it doesn't exist is never being tested.
There is an add-on package cypress-if written by former lead engineer at Cypress that addressed this problem.
The syntax is simple, just chain .if() and eveything after it only runs if the element is found.
cy.get('tbody.ant-table-tbody tr')
.if() // checks for 4 seconds
.then((rows) => {
// success
})
.else()
.then(() => {
//no rows
})
.finally(() => {
// either way
})
It will suppress the error that usually occurs when the element is missing.
It will use Cypress retry for asynchronous element loading, will will not happen if you use the jQuery method.
Don't do this if rows are fetched asynchronously
cy.get('tbody.ant-table-tbody').then(($parent) => {
// This will evaluate immediately and fail if the row is still loading
if ($parent.find('tr').length) {
...
But cypress-if is broken in Cypress v12
Cypress v12 split cypress commands into "commands" and "queries" (cy.get() is a query) and blocked overwriting of queries. This breaks a whole lot of prior code, including cypress-if.
Expect the change to be reversed before long.
Please see issue Can we please overwrite query commands #25078

How to run next Cypress cy commands while other is still processing?

I am maintaining a react project that uses Cypress. Cypress by default is asynchronous. How to perform next cy commands while the above cy command is still processing?
Example:
cy.get('showDialog').click() // Instantly closes due to some react states
cy.get('showDialogCloseButton').click() // still loading looking for showDialogCloseButton which eventually fails
// need to execute this again to show dialog and complete above cy command:
cy.get('showDialog').click()
However, the last command can't be executed since it needs the above command to be finished (which resulted to failure)
Using cy.wait() after the cy.get('showDialogCloseButton').click()
ex:
cy.get('showDialogCloseButton').click();
cy.wait(1000);
With this 3rd command will execute after 1s, always
but will make your test suite unnecessarily slow.
So then you can try by increase the timeout(s)
cy.get('showDialog',{timeout: 30000}).click({timeout: 30000});
This command will only fail after 30 seconds of not being able to find the object, or, when it finds it, 30 seconds of not being able to click it.
You can try your own timeout
So you can easily do that with validate also,
cy.get('showDialog', { timeout: 30000 }).should('be.visible').then(() => {
cy.get('showDialog').click();
})

Non of the webdriverio methods work to wait until an element is shown using Appium & WebDriverIO (JavaScript)

I am trying to write a test case use in JavaScript with webdriverio (using appium server) for a native android app.
My test case requires me to log in the app, and after logging (which takes 3-4 seconds) I should click a button (element). I tried all of the WebDriverIO APIs like waitForDisplayed, isDisplayed(), non of them work, most the time the error message is that :
TypeError: client.element(...).waitForDisplayed is not a function
at Context.<anonymous> (test-auto-obi-copy.js:142:14)
at processImmediate (internal/timers.js:439:21)
at process.topLevelDomainCallback (domain.js:130:23)
Here is the WebDriverIO Documentation for waitForDisplayed https://webdriver.io/docs/api/element/waitForClickable.html
My code looks like this:
it("should press the profile button", function () {
return client
.element('android=new UiSelector().resourceId("com.example.dev:id/nav_graph_profile")')
.waitForDisplayed(undefined, true)
.click('android=new UiSelector().resourceId("com.example.dev:id/nav_graph_profile")')
.then( function() {
//whatever
})
})
The login test completes succesfully, but after the LOG-IN button is pressed I want to make my test suite "sleep" until the next page loads, to achieve this I was trying to wait until this particular Profile button (element) becomes available, but it seems impossible to wait for it.
Can anyone suggest me what to do in this case, how can I wait?
WebDriverIO changed the names of some of their functions when moving from v4 -> v5 .waitForDisplayed() was one of them, as seen in the changelogs.
WebdriverIO v4 -> .waitForVisible()
WebdriverIO v5 -> .waitForDisplayed()
There's a fair few functions that changed names slightly, so it's worth a look - Additionally, the Docs for v4 still exist though are a little harder to search - Here is the entry for .waitForVisible()
Also, by passing undefined as the first parameter, your delay will only wait for the default 500ms. You'll probably want something like this instead
.waitForDisplayed(5000, true)

Set timeout for Cypress expect assertion

My issue is that I'd like to have a timeout on the expect assertion from Cypress's library but can't seem to figure out a method to do so.
I've tried greatly increasing the global timeout in cypress.conf; however, that didn't work.
if ($widget.find('report-widget')) {
SVGCount++;
expect(barGraphsChange[index]).to.not.equal(undefined)
console.log(barGraphsChange, index)
cy.getBarGraphTotal(SVGCount, barGraphsChange[index])
}
If not a timeout then a reasonable workaround would be nice as well, Thanks!
Also a note: barGraphsChange[index] is in the process of getting calculated and assigned from a called custom Cypress command earlier on during this phase.
You can customise your expectations with should(), and this will automatically retry your assertions for either the specified timeout, or the global defaultCommandTimeout if none provided.
In your case I could probably imagine wrapping your object, specify a timeout and then passing your logic to should:
cy.wrap(someFunction, {timeout: 25000}).should(someFunction => expect(someFunction()).to.eq(someValue))
Read more here: https://docs.cypress.io/api/commands/should.html#Function

Meteor Accounts.onLogin infinite loop

In the Meteor forums I read that it is suggested to put Meteor.logoutOtherClients inside Accounts.onLogin(). Although this works, there is a problem to it, and that is the Accounts.onLogin() gets called multiple times when there are multiple TABS (not browsers) opened. Is this the expected output?
Here is my code below:
Accounts.onLogin(() => {
console.log('onLogin called')
Meteor.logoutOtherClients((error) => {
if (error) {
console.log(`error: ${error.error}`)
}
})
// Some Meteor Method calls here
alert('Welcome User!')
})
Another problem is that I got method calls in the same Accounts.onLogin() block and it gets called every time.
meteor#1.4.2.6
accounts-base#1.2.17
Question
How should I prevent this infinite calls from happening?
If I can't prevent this, where should I dispatch method calls when user logs in? Because obviously if I put it inside this code block it causes the dispatches to get called infinitely and that alert gets fired infinitely.
You can also see the details reported here: https://github.com/meteor/meteor/issues/8669
This is a confirmed bug #8669. So my workaround is I created a manual token for the user instead of using the default from accounts-base. I also handled the checking manually so basically getting rid of "magic" Meteor offers.

Categories

Resources