I would like to be able to use Cypress to test an application when Javascript is disabled.
Cypress makes itself appear to run from the same domain as the application under test and Chrome allows Javascript to be disable by domain only, so Javascript cannot be disabled without affecting Cypress itself.
The ability to disable javascript for the url under test, possibly with:
This is very possible, seems like all that needs to done is strip all the script
tags and inline js and make sure <noscript>
tags get rendered
well, we can strip all JavaScript tags and inline handlers, but this does not make noscript
tags visible. To truly do this we would need to embed the application iframe with sandbox
attribute, which would disable the injection script we use to set the document domain to localhost
. Hmm.
Could we not simply strip <noscript>
and </noscript>
, but leave everything inside the tags there?
We could strip all JS but that would not force the browser iframe to show noscript elements
Sent from my iPhone
On Apr 23, 2018, at 21:10, Ben Kucera notifications@github.com wrote:
Could we not simply strip , but leave everything inside the tags there?
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.
+1 to this, (apologies for commenting but not contributing). I just wanted to say this would be really useful for sites which have to support browsers with javascript disabled. It often gets missed in automated tests.
@maxcbc if you :+1: the top level comment, that will help us sort issues by community interest
My use case is slightly different - I want to check how the page behaves before JS runs to see if it matches our SEO needs.
Is there any known workaround to achieving that?
Any update on this? my case is javascript will call html output to the page when i turn off javascript the html will load.
I would really appreciate this feature for SEO purposes too.
Likewise, I want it to test if my react server side rendering is working. For now I'm going to settle with making an http request and grepping the resulting text or something - but it's far from ideal.
someone could try loading a no-script extension and match it to only run on the aut-iframe
url. Not sure if that would work.
I'd love the ability to do this. I've recently attempted to migrate a project dependencies and 2 of them broke Next.js SSR support. A way for automating such tests would be great.
https://github.com/UnlyEd/next-right-now/pull/27
Because I didn't automatically detect this SSR regression, I updated multiple other packages before understanding SSR was broken. Then, I had to replay the online preview of each manually, by disabling JS in the browser.
At some point, I figured out that the issue was coming from next-with-apollo dependency (MAJOR version update) (see https://github.com/lfades/next-with-apollo/issues/126) and tried to rollback this particular dep to its previous version, which, surprisingly, didn't work out because another dependency that I also had updated was causing the same regression (react-apollo (PATCH version update), see https://github.com/apollographql/react-apollo/pull/3902)
Eventually, I had to rewrite my git history to get back in time and replay all commits one by one until I figured this whole plot out. Which took me some 3-5h of investigation.
All this to say that I'd love a way to automate this, and ensure some other PATCH dependency update doesn't break some feature again in the future.
And, I got lucky here, because I had been meticulous and deployed an online version after each package update (gave me ability to test afterwards and find origin of regression). Otherwise it could (would) have taken me days to figure this out.
So is this in theory possible to implement? If so where would I start for creating a PR?
I've been using @bahmutov 's handy guide here: https://glebbahmutov.com/blog/ssr-e2e/
Issue is if I have two such tests, the second write(html)
just appends to the first, so now I have two of each element, and hence my selectors break.
This guide is nice and helps a bit. It still does not reveal the noscript
tags content though :(
I am trying
cy.state("window").parent.document.querySelector(".iframes-container iframe").sandbox = "";
but it seems the iframe is already sandboxed but it does not show the noscript
tags.
Update:
This seems to be almost done:
describe("noscript", function () {
it("should not show the Get Codes button", function() {
cy.request("/")
.its("body")
.then(html => {
debugger
const parentDocument = cy.state("window").parent.document
const iframe = parentDocument.createElement("iframe")
const oldIframe = parentDocument.querySelector(".iframes-container iframe")
iframe.id = oldIframe.id
iframe.className = oldIframe.className
iframe.sandbox.add("allow-forms")
iframe.srcdoc = html
oldIframe.parentNode.replaceChild(iframe, oldIframe)
//cy.state("document").write(html)
})
cy.get('#encrypt').should('be.disabled')
})
});
It shows all the <noscript>
tags, the CSS is working!
But the cy.get('#encrypt').should('be.disabled')
fails now with Timed out retrying: Expected to find element: #encrypt, but never found it.
I guess that's because the cy.get
method has no access to the newly created iframe.
Any ideas @bahmutov?
One step more: With chromeWebSecurity
disabled in the cypress.json
it works like this:
describe("noscript", function () {
it("should not show the Get Codes button", function() {
const parentDocument = cy.state("window").parent.document
const iframe = parentDocument.querySelector(".iframes-container iframe")
iframe.sandbox.add("allow-forms")
iframe.src = "http://htpc:4000/"
cy.get('#encrypt').should('be.disabled')
})
});
It was complaining about Cross-Site access, which does not make much sense since the iframe uses the same host like the spec.
This could be neatly packaged into extending the visit
command using a new, non-breaking script
option, which is by default true
like this:
Cypress.Commands.overwrite('visit', (orig, url, options = {}) => {
const parentDocument = cy.state("window").parent.document
const iframe = parentDocument.querySelector(".iframes-container iframe")
if (false === options.script) {
if (false !== Cypress.config("chromeWebSecurity")) {
throw new TypeError("When you disable script you also have to set 'chromeWebSecurity' in your config to 'false'")
}
iframe.sandbox = ""
} else {
// In case it was added by a visit before, the attribute has to be removed from the iframe
iframe.removeAttribute("sandbox")
}
return orig(url, options);
})
And the spec gets very clean then:
describe("noscript", function () {
it("should not show the Get Codes button", function() {
cy.visit("/", { script: false })
cy.contains("The password is encrypted locally and for that you need to enable JavaScript.").should("exist")
cy.get('button')
.first()
.should('be.disabled')
.contains("Please enable JavaScript")
})
});
Any thoughts on my solution @bahmutov?
Most helpful comment
My use case is slightly different - I want to check how the page behaves before JS runs to see if it matches our SEO needs.
Is there any known workaround to achieving that?