Same Cypress tests reporting different results on different machines using Chrome & Electron - google-chrome

My colleague & I are running the same Cypress test suite on our machines, but getting different results.
The version of Cypress we are using is 3.8.3.
When they run .\node_modules\.bin\cypress run, all tests are passing.
But when I try to run the same command on my machine, one of the tests is failing.
I get the below error message:
<failure message="cy.type() can only be called on a single element.
Your subject contained 8 elements." type="CypressError">
<![CDATA[CypressError: cy.type() can only be called on a single element. Your subject contained 8 elements.
I can understand what the test is saying, but I don't know why we are getting different results on different machines when running the same tests.
One difference I can spot is that they have the option to run tests on Chrome, while I only have the option to run on Electron.
Can someone please help to explain what is causing this issue, & how it can be resolved

Cypress automatically detects browsers installed on your local machine. So please check if you have chrome installed. Electron comes directly with cypress.
The application behavior can vary from machine to machine and also from browser to browser depending on the configurations and also on the internet speed. So its always good to use Test Retries which will retry the test as per the defined value before finally marking the test as fail. Test retries were introduced in cypress 5.0.
You can apply them globally through your cypress.json
{
"retries": {
// Configure retry attempts for `cypress run`
// Default is 0
"runMode": 2,
// Configure retry attempts for `cypress open`
// Default is 0
"openMode": 0
}
Or, you can also add it to a specific test -
describe('User sign-up and login', () => {
// `it` test block with no custom configuration
it('should redirect unauthenticated user to sign-in page', () => {
// ...
})
// `it` test block with custom configuration
it(
'allows user to login',
{
retries: {
runMode: 2,
openMode: 1,
},
},
() => {
// ...
}
)
})
Or to a specific test suite as well -
// Customizing retry attempts for a suite of tests
describe('User bank accounts', {
retries: {
runMode: 2,
openMode: 1,
}
}, () => {
// The per-suite configuration is applied to each test
// If a test fails, it will be retried
it('allows a user to view their transactions', () => {
// ...
}
it('allows a user to edit their transactions', () => {
// ...
}
})

Related

next-pwa runtimecaching does not produce strategies

I start using next-pwa and the basic setup worked like a charm. Now it want to play with the runtime caching option, which does not work for me:
My next.config.js includes the standard cache entries plus a custom one that should use the strategy StaleWhileRevalidate for each request going to /api/todoitem:
const withPWA = require("next-pwa");
const defaultRuntimeCaching = require("next-pwa/cache");
module.exports = withPWA({
reactStrictMode: true,
pwa: {
dest: "public",
disable: false, // disable PWA
register: true,
skipWaiting: true,
runtimeCaching: [
{
urlPattern: /\/api\/todoitem/,
method: "GET",
handler: "StaleWhileRevalidate",
options: {
cacheName: "todoApp-api",
expiration: {
maxEntries: 64,
maxAgeSeconds: 24 * 60 * 60, // 24 hours
},
},
},
...defaultRuntimeCaching,
],
},
});
Restart npm run dev fire up the browser -> fetch GET /api/todoitem -> and console.log tells me
workbox Network request for '/api/todoitem' returned a response with status '200'.
workbox Using NetworkOnly to respond to '/api/todoitem'
I tried a number of combinations of regexes, including defaultRuntimeCaching before or after my runtimeCache entry to no avail.
Any hints to get custom runtimeCache rules working would be greatly appreciated.
next.js 12.0.7
next-pwa 5.4.4
node.js v14.18.2
After some research I found:
In development mode, next-pwa creates a service worker that disables caching. It even tells me so on the console ;-):
[PWA] Build in development mode, cache and precache
are mostly disabled. This means offline support is
disabled, but you can continue developing other
functions in service worker.
When building the app via next build it creates a service worker that uses my custom rules and when starting the app next start the rules seem to work.
A bit hard to debug, so I tried to set mode: "production" on my developer machine but then for some reason the service worker gets rebuilt at every other request which brings the app to a grinding halt.

Debugging service worker 'trying to install' in Chrome

I have what I assumed was a pretty standard service worker at http://www.espruino.com/ide/serviceworker.js for the page http://www.espruino.com/ide
However recently, when I have "Update on reload" set in the Chrome dev console for Service Workers the website stays with its loading indicator on, and the status shows a new service worker is "Trying to Install".
Eventually I see a red 'x' by the new service worker and a '1' with a link, but that doesn't do anything or provide any tooltip. Clicking on serviceworker.js brings me to the source file with the first line highlighted in yellow, but there are no errors highlighted.
I've done the usual and checked that all files referenced by the service worker exist and they do, and I have no idea what to look at next.
Does anyone have any clues how to debug this further?
thanks!
I'm on Chrome Beta.
I updated to the newest release a magically everything works. So I guess it was a bug in Chrome or the devtools, not my code.
For those running in to this issue with the latest version of Chrome, I was able to fix it by caching each resource in its own cache. Just call caches.open for every file you want to store. You can do this because caches.match will automatically find the file in your sea of caches.
As a messy example:
self.addEventListener('install', event => {
event.waitUntil(swpromise);
var swpromise = new Promise(function(resolve,reject) {
for (var i = 0; i < resources_array.length; i++) {
addToCache(i,resources_array[i]);
}
function addToCache(index,url) {
caches.open(version+"-"+index).then(cache => cache.addAll([url])).then(function() {cacheDone()});
}
var havedone = 0;
function cacheDone() {
havedone++;
if (havedone == resources_array.length) {
resolve();
}
}
})
I used the version number and the index of the file as the cache key for each file. I then delete all of the old caches on activation of the service worker with something similar to the following code:
addEventListener('activate', e => {
e.waitUntil(caches.keys().then(keys => {
return Promise.all(keys.map(key => {
if (key.indexOf(version+"-") == -1) return caches.delete(key);
}));
}));
});
Hopefully this works for you, it did in my case.

Cypress throwing SecurityError

I am currently running with Chrome 74 and trying to use Cypress to test a style-guide in my app. When I load up Cypress it throws this error:
SecurityError: Blocked a frame with origin "http://localhost:3000"
from accessing a cross-origin frame.
Please let me know if there is a solution to this!
I had tried to follow along with this:
https://github.com/cypress-io/cypress/issues/1951
But nothing has changed/worked for me. :(
My code is shown below: cypress/plugins/index.js
module.exports = (on, config) => {
on('before:browser:launch', (browser = {}, args) => {
// browser will look something like this
// {
// name: 'chrome',
// displayName: 'Chrome',
// version: '63.0.3239.108',
// path: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
// majorVersion: '63'
// }
if (browser.name === 'chrome') {
args.push('--disable-site-isolation-trials');
return args
}
if (browser.name === 'electron') {
args['fullscreen'] = true
// whatever you return here becomes the new args
return args
}
})
}
in my cypress/support/index.js
This will load the site before every test I run to save myself from having to write cy.visit in every test.
beforeEach(() =>{
cy.visit('http://localhost:3000/style-guide')
})
I had the very same issue yesterday and the answer from #jsjoeio in the cypress issue #1951 you've referenced in your question actually helped me.
So basically only thing I've done was to modify my cypress.json and add following value:
{
"chromeWebSecurity": false
}
You can disable security to overcome this issue.
Go to cypress.json file.
Write { "chromeWebSecurity": false } and save.
Run the test again.
I had exactly the same problem, I advise you to do as DurkoMatko recommends. Documentation chromeWebSecurity
But I encountered another problem with a link pointing to localhost in an iframe.
If you want to use a link in an iframe I recommend this :
cy.get('iframe').then((iframe) => {
const body = iframe.contents().find('body');
cy.wrap(body).find('a').click();
});
I have also faced this issue. My application was using service workers. Disabling service workers while visiting a page solved the issue.
cy.visit('index.html', {
onBeforeLoad (win) {
delete win.navigator.__proto__.serviceWorker
}
})
Ref: https://glebbahmutov.com/blog/cypress-tips-and-tricks/#disable-serviceworker
So, at least for me, my further problem was an internal one with tokens, logins, etc. BUT!
the code I posted for how the index in the plugin folder is correct to bypass the chrome issue. That is how you want to fix it!
Goto your cypress.json file.
Set chrome web security as false
{
"chromeWebSecurity": false
}
To get around these restrictions, Cypress implements some strategies involving JavaScript code, the browser's internal APIs, and network proxying to play by the rules of same-origin policy.
Acess your project
In file 'cypress.json' insert
{
"chromeWebSecurity": false
}
Reference: Cypress Documentation

ava: Logs generated outside tests are not shown in the console

My problem
ava logging (t.log) only work inside a test, but not during setup (before, beforeEach) or teardown (after*) functions.
This means that meaningful setup / teardown data, which is very useful for debugging and reproducing, is lost. This happens both for successful and failed tests, and with and without the --verbose flag.
Code
import test from 'ava';
test.before(t => {
// This runs before all tests
t.log('before - 1');
});
test.before(t => {
// This runs after the above, but before tests
t.log('before - 2');
});
test.after('cleanup', t => {
// This runs after all tests
t.log('after');
});
test.after.always('guaranteed cleanup', t => {
// This will always run, regardless of earlier failures
t.log('after always');
});
test.beforeEach(t => {
// This runs before each test
t.log('beforeEach');
});
test.afterEach(t => {
// This runs after each test
t.log('afterEach');
});
test.afterEach.always(t => {
// This runs after each test and other test hooks, even if they failed
t.log('afterEachAlways');
});
test(t => {
t.log('A test');
t.pass();
});
test(t => {
t.log('A test');
t.fail();
});
Output
$ ava run.js --verbose
✔ [anonymous]
ℹ A test
✖ [anonymous] Test failed via `t.fail()`
ℹ A test
1 test failed [00:22:08]
[anonymous]
ℹ A test
/Users/adam/Personal/tmp/ava-bug-log-in-before-each/run.js:46
45: t.log('A test');
46: t.fail();
47: });
Test failed via `t.fail()`
Note that only the printouts from the test (A test) are show. All other logs are lost.
My question
How can I see the logs from the setup and teardown steps of the test suite?
Could you open an issue for this? https://github.com/avajs/ava/issues
I agree this should work.

WebSQL changeVersion always fail

I'm trying to create a bookmark extension in Chrome and I want to leverage WebSQL to store all kind of information about bookmarks locally. Here's what I've done so far:
(function() {
var Home,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
window.requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
Home = (function() {
function Home() {
this.onDBInit = __bind(this.onDBInit, this); this.db = openDatabase("Journal", "", "Bookmarks Stats", 5 * 1024 * 1024, this.onDBInit, this.onDBError);
}
Home.prototype.onDBInit = function(db) {
console.log(db.version);
db.changeVersion("", "1.0", this.initDB, this.onDBError);
return console.log(db);
};
Home.prototype.initDB = function(t) {
console.log(t);
return t.executeSql('CREATE TABLE bookmarks (id, title, url)');
};
Home.prototype.onDBError = function(e) {
return console.log(e);
};
return Home;
})();
window.Registerable(Home);
}).call(this);
For some reason, changeVersion ALWAYS fails. I have tried to delete the database, restart chrome, etc. Chrome version: 18.
In my limited experience, changeVersion does work on Chrome. I've also read complaints here about it not working properly on Safari, but it does.
However, there are two catches:
Catch 1:
Often, changeVersion appears to fail (it gives an error and db.version will still return the old value), but the transaction callback will fire and when you re-open the web page and its database, the version number will be correct.
Catch 2:
It seems you must supply precisely five arguments, including three callbacks. If you don't supply these five arguments, for example you only do the first three, then the current version will remain unchanged. So if you were to follow the instruction in this tutorial that everyone's referring to, you would be disappointed.
This is the case for Chrome and Safari on Windows.
Arguments are:
1: expected version
2: new version
3: transaction callback (you can execute SQL here as part of the version change)
4: failure callback (if version change or transaction callback failed)
5: succes callback (if version change and transaction callback succeeded)
I haven’t tested this on iOS devices but it matches the Safari specifications provided here:
https://developer.apple.com/library/safari/#documentation/iphone/conceptual/safarijsdatabaseguide/usingthejavascriptdatabase/usingthejavascriptdatabase.html
In Opera, changeVersion waits with setting db.version to its new value until after you've executed an actual sql transaction using executeSql. So I use a SELECT statement that has no further consequence. This does not actually have to be inside the transaction callback: I discovered it when I tried a separate executeSql statement in the browser console after trying a whole bunch of changeVersion commands.
This is Chrome bug: you can not change the version of the database with an empty string in the value.
And according to the specifications in the call creationCallback (in your case, the function onDBInit) version of the database is exposed to an empty string:
the callback is invoked with the database having the empty string as its version regardless of the given database version
This error is detected two years ago and described in detail, but is still not corrected
I have decided this issue in the following ways: I removed the initialization of the database structure of creationCallback and made it the first transaction to the database.
var db = openDatabase("Journal", "0.1", "Bookmarks Stats", 5 * 1024 * 1024);
db.transaction(function (t) {
t.executeSql('CREATE TABLE IF NOT EXISTS bookmarks (id, title, url)');
});