I'm trying to test my live web server data responses (e.g. no stubbing/mocking). I tried using cy.server() with cy.route(), but since the content type of the response is application/json apparently cy.server() does not cover this and the cypress error message tells me to use cy.request().
However, I can not use cy.wait() with cy.request() . I have to resort to nesting the second cy.request() in the callback of the first. Is there a way to not nest the second cy.request inside the callback of the first cy.request?
So in this contrived example, I need to grab the user data first before making the call to get book data. I could only get this to work by nesting the book request within the callback of the user request. I would prefer to use something akin to the cy.wait() API instead of nesting.
it(`should get book based on user`, () => {
cy.request({
url: `/user`,
}).as('user');
cy.get('#user').then((userResp) => {
const user = userResp.body;
cy.request({
url: `/user/${user.id}/book`,
}).as('userBook');
cy.get('#userBook').then((userBookResp) => {
cy.log(userBookResp);
});
});
});
Related
In my sveltekit app I make AJAX calls to my api endpoints. For example:
+page.svelte
<script>
async function get_card() {
const url = '/api/card/?category=' + $page.params.slug;
const response = await fetch(url, {
method: 'GET',
})
const card = await response.json();
return card;
}
</script>
In the browser javascript console I get this warning:
Loading /api/card/?category=Neurology using `window.fetch`.
For best results, use the `fetch` that is passed to your `load`
function: https://kit.svelte.dev/docs/load#making-fetch-requests
But as far as I can tell, that fetch function is only accessible to me on the server, and I do not see a way to use it in a script that may run on the client (such as +page.svelte). I tried passing the function as part of the data object from load:
+layout.server.js
export const load = async ({ fetch, locals }) => {
return {
email: locals.user.email,
group: locals.user.group,
fetch: fetch
}
}
But, not surprisingly, that does not work since the function is not serializable.
Am I Doing It Wrong™, or should I just ignore the warning?
fetch is originally a browser API and SvelteKit defines it on the server as well, if it does not exist. The warning is there to tell you that you are creating another round trip to the server (one for the page and one for the data) when you possibly could have loaded the data on the server so it could be transmitted as part of the page (during server-side rendering).
If the code of your function is not executed right away, then this is a false positive (recent issue on this). I.e. if the data should be requested at a significantly later point, there is no way to bundle the request with the page.
(You are definitely not meant to pass on the fetch of load, you are supposed to use it to get the data.)
im using express and nodejs for my api server,
and now im implementing pdf download (im using pdf-creator-node) for converting html to pdf.
the pdf-creator-node will create a stream when converting a html, and when i pipe it, all my middleware (notFoundHandler, errorHandler,responseLogger) got skipped
router.get(
'/generatePDF', authenticate, schemaValidation({ params: generatePDFschema }),
(req, res, next) => {
generatePDF(details) {
const template = readFile('./src/templates/da-template.html');
const receipt = {
html: template,
data: payload,
type: 'stream'
};
const generatedPdf = pdf.create(receipt, advisOptions);
return generatedPdf;
}
const pdfStream = generatePDF(details);
res.setHeader('Content-type', 'application/pdf');
pdfStream.pipe(res);
},
notFoundHandler,
errorHandler,
responseLogger
);
is there any express api can i use to pipe a stream?
The middleware you show is passed to router.get() AFTER your request handler so it will not get a chance to run unless you call next() in your request handler. When you pass multiple request handlers to a router.get(), they will run sequentially in order and the 2nd one will only get a chance to run if the first one calls next(). Same for the 3rd one, and so on.
Furthermore, pdfStream.pipe(res); does not call next().
I don't know exactly what those middleware functions are supposed to do, but making a guess based on their names, perhaps they are supposed to run BEFORE your request handler, not after so they can put things in place for various error conditions.
If you want further help, then please show the code for those three middleware functions so we can see more specifically what they are trying to do.
I'm wondering if there's any way to listen for console messages and act on console messages when they're received. Mainly, is there any way to do this without an external module, and using the http module?
The goal is to trigger a NodeJS function or code snippet on an event like click in the HTML. If there's also a way to do this, then that's great. But once again, I'd like to do this without an external module, and just use those that are built-in to NodeJS.
Use onclick() function in JavaScript to trigger a function call when clicking on a element. Then use fetch to make a api call to the nodejs server.
I know #Haris Wilson already got the answer, but I'd just like to provide a code example.
Instead of trying to catch a console message and then execute a function if we find it, we can use fetch() to make a request to whatever URL we need, and this can allow us to make other requests.
In this case, we can use the url module and the http module to parse the url and serve the API and website, respectively.
const url = require('url')
const http = require('http')
const requestListener = async function (req, res) {
// Basic server setup
res.writeHead(200, {
'Content-Type': 'text/html'
});
res.end(/** Content here */)
// API
if (url.parse(req.url, true).pathname === '/APIcall') {
let arguments = url.parse(req.url, true).query
// Preform necassary actions here
}
}
We can now use onClick to call a function inside our webpage JavaScript, and use fetch([API URL]) to give our NodeJS data to preform an action. We can use URL params to do this, such as https://localhost:8080/APIcall?data=someData&moreParam=more-data, where ?data=someData&moreParam=more-data are the URL params.
I'd like to execute one http get request after another has completed. The endpoint URL for the second request will need to depend on the first request.
I've tried nesting the requests with something like this in Angular:
this.http.get(endpoint1).subscribe(
success => {
this.http.get(endpoint2 + success).subscribe(
anotherSuccess => console.log('hello stackoverflow!')
);
}
);
First question here on stackoverflow, please let me know if I should provide more detail.
here you can find how to do that, you have various options:
with subscribe:
this.http.get('/api/people/1').subscribe(character => {
this.http.get(character.homeworld).subscribe(homeworld => {
character.homeworld = homeworld;
this.loadedCharacter = character;
});
});
with mergeMap
this.homeworld = this.http
.get('/api/people/1')
.pipe(mergeMap(character => this.http.get(character.homeworld)));
There is a version with forkJoin but isn't explicit compared with subscribe and mergeMap.
You should probably try using ngrx (redux) triggering the second request depending on a success action.
The flow should be something like this: dispatch an action from a component -> call the first request -> the request triggers a success action -> success effect triggers the second request with a payload from the previous request.
Read the docs here
I'm trying to test behaviour following a redirect request performed with fetch API.
I've been using sinon to mock window.fetch and have it return the desired response. Here's what I do, simplified:
windowFetch = sinon.stub(window, 'fetch');
windowFetch.withArgs('http://example.com/resource')
.returns(Promise.resolve(new Response(body, {
status: 200,
headers: new Headers(headers)
})));
This works fine for standard responses. To handle redirects I want to access the Response#url property but I haven't found a way to have it set in unit tests.
It's not possible to set it using the new Response() constructor and it's read only so I also can't do that.
Finally, I tried calling Response.redirect(toAddr) but it creates the redirect response and the one that follows. The one the browser transparently returns.