I recently tried to intercept all image requests following the example in their documentation:
await page.route('**/*.{png,jpg,jpeg}', route => route.abort());
// Abort based on the request type
await page.route('**/*', route => {
return route.request().resourceType() === 'image' ?
route.abort() : route.continue();
});
But it was not working at all.
How can I make it work?
There is a missing string in the types (or they are outdated in v1.15.1):
When logging route.request().resourceType() into console, I noticed there is a "images" resource type. So you can easily intercept any images including "images" to your check.
For instance you could do like this:
await page.route('**/*', route => {
return route.request().resourceType().match(/(image)s?/) ?
route.abort() : route.continue();
});
Related
Within the AstroJS framework (https://astro.build/) you can have .astro files that are route, you can also import these files into other astro files and use them as components. I've seen an issue that depending on what Astro.request properties are called, you're only allow to call them when the file is used as a route. Is it possible to conditionally know if the file is a route or a component?
Response difference
I found a way how to differentiate the route from the component which is by looking at the response. The reason is that the response is sent at the end of the route frontmatter and before the components frontmatter, that's why the header list is going to have more entries.
Although this is possible, I recommend to differentiate between routes and components by design, such as adding properties with default values not to rely on the response structure. Also the response is not to be used by child components but only by the route, this allows Astro to have an optimized stream response.
reference ( caution section https://docs.astro.build/en/guides/server-side-rendering/#astrorequestheaders)
response log in route and in component
{
status: 200,
statusText: 'OK',
headers: HeadersList {
[Symbol(headers map)]: Map(1) { 'content-type' => 'text/html' },
[Symbol(headers map sorted)]: null
}
}
{
status: 200,
statusText: 'OK',
headers: HeadersList {
[Symbol(headers map)]: Map(1) { 'content-type' => 'text/html' },
[Symbol(headers map sorted)]: Map(1) { 'content-type' => 'text/html' }
}
}
Clarifications
talking about routes, assumed mode is SSR
Not talking about integration API but about SSR components runtime API https://docs.astro.build/en/reference/api-reference/
It is possible for '.astro' file to be both a component and a route when let's say a pages/404.astro is a route but is also used by a component from pages/[...any].astro
That nasty case would not allow to check the path where it is in with import.meta.url so it could be in pages even if used as component for another route.
Test of Request similarity
route = [...any].astro
component = pages/404.astro
in each of them the following log is placed
console.log(Astro.request)
console.log(Astro.request.headers)
console.log(Astro.url)
console.log(Astro.params)
console.log(Astro.props)
the test is performed with a single request call (page load) where the execution goes first through 404.astro when it is imported then through [...].astro when its frontmatter is executed.
The log is then compared with a diff tool
I want to cypress.log() out a specific field in the request header whenever my webapp makes requests that way when it fails and adds screenshots/logs I can grab that that requestId that failed.
Is there a way to setup cypress so that for all network requests it checks for this field and log it?
I can add a cy.intercept within each individual file but I want a more generic way to handle this.
Cypress.log is the synchronous version of cy.log().
Add middleware: true to the intercept to pass request to other intercepts.
cy.intercept({ url: '*', middleware: true }, (req) => {
const headerValue = req.headers?['x-custom-headers']
if (headerValue) {
Cypress.log({
name: 'x-custom-header',
message: headerValue
})
}
})
You'll get an Cypress promise error if you try to use cy.log() to log out every request header in an cy.intercept() within a routeHandler callback. This would also make it kind of tough to log to a CI terminal as well.
Instead you can console.log to dev tools. To make it apply to all tests, you can wrap it in a beforeEach() and place it in the support/index.js file.
// support/index.js
beforeEach(() => {
cy.intercept('*', (req) => {
req.continue((res) => {
console.log(JSON.stringify(req.headers))
})
})
})
I am using asyncData query in one of my pages:
async asyncData({$axios, query}) {
const id = query.id;
try {
const {data} = await $axios.$get(`http://localhost:8000/api/question/${id}`);
return {
question: data
}
} catch (e) {
console.log(e);
}
},
Whenever I try to access another route from this page, for example:
#click="$router.push('/solution'); addTodo(question.keywords); addTodo(option.keywords)">
It redirects me to this page /solution, but the request to access API still goes from previous page (question/id)
Accessing localhost:3000/solution page:
CORS works in every other page, so I think the issue is here with redirections.
What would be possible solutions to fix this?
Also, this is what I see in Network tab:
I think referer should be: localhost:3000/solution
Adding 'paths' => ['api/*'] to Laravel back-end CORS config helped.
:) I chose for automated testing a tool Cypress.io.
I need some tests for my sitemap.xml document and I dont know how to do that :(
I have tried install an npm package libxmljs
npm install libxmljs --save
and load it as plugin in cypress/plugins/index.js
const libxmljs = require('libxmljs');
But there is a problem with this. It shows an error
The plugins file is missing or invalid.
Your pluginsFile is set to /home/my-app/cypress/plugins/index.js, but
either the file is missing,
it contains a syntax error, or threw an error when required.
The pluginsFile must be a .js or .coffee file.
Please fix this, or set pluginsFile to false if a plugins file is not
necessary for your project.
Error: The module '/home/my-app/node_modules/libxmljs/build/Release/xmljs.node'
Please help me, how can I use libxmljs in Cypress.io or how i should write tests for Sitemap.xml in this end-to-end testing tool.
Thanks for your time! :)
Although #NoriSte's answer is correct, I found a simpler alternative without the need for any 3rd party code.
Cypress API exposes all the necessary methods to:
load a file (the sitemap.xml in your case): cy.request.
parse XML file (it exposes the jQuery API): Cypress.$
check if a page successfully loads (with a 200 status code): cy.visit
This is the following test that I use to test if all of the pages declared in the sitemap are loading (and make sure it doesn't point to any 404):
describe('Sitemap', () => {
// initialize the url array
let urls = []
// be sure to get the url list before executing any tests
before(async () => {
// getch the sitemap content
const response = await cy.request('sitemap.xml')
// convert sitemap xml body to an array of urls
urls = Cypress.$(response.body)
// according to the sitemap.xml spec,
// the url value should reside in a <loc /> node
// https://www.google.com/sitemaps/protocol.html
.find('loc')
// map to a js array
.toArray()
// get the text of the <loc /> node
.map(el => el.innerText)
})
it('should succesfully load each url in the sitemap', () => {
urls.forEach(cy.visit)
})
})
If you want to use libxmljs to parse your sitemap you should
read the sitemap itself with cy.request
add a custom task to Cypress (because libxmljs is a node library, cy.task is the only way to consume Node.js scripts from your Cypress tests)
returns the parsed data from your task
assert about it in a Cypress test
Those are the high-level steps you need to do 😉
To add to a great answer by gion_13, here’s his solution refactored to utilize Cypress promise-like-commands instead of async calls.
describe('Sitemap', () => {
let urls = [];
before(() => {
cy.request('sitemap.xml')
.as('sitemap')
.then((response) => {
urls = Cypress.$(response.body)
.find('loc')
.toArray()
.map(el => el.innerText);
});
});
it('should succesfully load each url in the sitemap', () => {
urls.forEach(cy.visit);
});
});
Using async in Cypress may raise error ‘Cypress detected that you returned a promise in a test, but also invoked one or more cy commands inside of that promise’.
describe('Sitemap', () => {
let urls = [];
before(() => {
const parser = new DOMParser();
cy.request('/sitemap.xml').then((response) => {
const document = parser.parseFromString(response.body, 'application/xml');
const parsedUrls = document.getElementsByTagName('loc');
urls = Array.from(parsedUrls).map((item) => item.innerHTML);
});
});
it('Should load each url from the sitemap', () => {
urls.forEach(cy.visit);
});
});
I'm implementing a route guard (CanActivate interface) and I need to redirect to not found page under certain conditions. This can be achieved with the following sentence:
if (isNode){
let res : Response = Zone.current.get('res');
res.status(404).redirect('/not-found');
}else{
this.router.navigate(['not-found']);
}
This works, but raises an exception server side (Error: Can't set headers after they are sent), because angular2-universal still sends the rendered page, regardless of the redirection.
Is there any way to solve this properly?
Thanks in advance.
There is actually a solution for bypassing the error.
In server.ts in the res.render method add callback function and check for res.headersSent boolean.
server.get('*', (req, res) => {
res.render('../public/index.html', {req, res},
(error, html) => {
if(error)
// error handle
if (!res.headersSent) {
res.send(html);
}
});
});
Obviously, send the html only if res.headersSent is false.