I'm trying to capture all the requests that occur during the test.
My application uses WebSocket and with the intercept command I can't catch wss requests.
Is there any way to do this?
I don't think web sockets can be caught directly by the intercept command.
One approach is to observe the results of ws communication, as shown here Testing a websocket application with Cypress between two instance of Cypress runner.
If your app talks between app and server, then start the server in /cypress/plugins/index.js and use cy.task() to get the server end of the communication.
There is also a library cypress-websocket-testing which uses rxjs, which is quite powerful but takes some getting used to.
cy.streamRequest(config, options).then(results => {
expect(results).to.not.be.undefined;
})
// When in need of a bit more flexibility
cy.stream(config).then(subject => {
subject
.pipe(
takeUntil(timer(1000)),
reduce((acc , val) => acc.concat([val]), [])
)
.subscribe({
next: (results) => {
expect(results).to.not.be.undefined;
},
error: (err) => {},
complete: done
});
});
Not supported in Cypress as of now only xhr requests are supported by cy.intercept, you need to create wesbsocket server and listen at a port and it needed to be started in another process and then using fixtures send the required response data
Related
To eliminate cors OPTIONS requests I want to proxy API calls through the Next.JS server. I've added this configuration change to my next.config.js file:
const withImages = require("next-images");
const { environment } = require("./environments/environment");
module.exports = withImages({
rewrites: async () => [
{ source: "/proxy/api/:match*", destination: `${environment.apiUrl}/:match*` },
],
});
I'm running next version 10.2.3 (latest at time of posting).
Calls to the back-end are performed through fetch within React components. In the browser dev tools I can see that the HTTP request is being performed. A request is sent out to "http://localhost:4200/proxy/api/user/me". It hits the Next server. But after that the Next server does not hit the API server. It responds immediately with a 404. It seems that it hasn't recognized the "rewrites" configuration at all.
This was an issue with an outdated version of nx
My idea was to build a client app using react and urql and a graphql api using elixir and absinthe but at the moment it looks as if these don't really play that well together.
Is there a way to actually use the Absinthe subscriptions with any other client than Apollo? I've tried to use urql but I fail with the ws connection getting the following error:
WebSocket connection to 'ws://localhost:4000/socket/websocket' failed:
Error during WebSocket handshake: Sent non-empty
'Sec-WebSocket-Protocol' header but no response was received
Only thing I've found so far which seems to be related to this issue is this library absinthe/socket-apollo-link (https://github.com/absinthe-graphql/absinthe-socket/tree/master/packages/socket-apollo-link) but it's obviously only for Apollo.
In my failed attempt I did the following:
import React from 'react'
import { Provider, Client, dedupExchange, fetchExchange, subscriptionExchange } from 'urql'
import { cacheExchange } from '#urql/exchange-graphcache'
import { SubscriptionClient } from 'subscriptions-transport-ws'
const DataProvider = ({ children }) => {
const cache = cacheExchange({})
const subscriptionClient = new SubscriptionClient('ws://localhost:4000/socket/websocket', {})
const client = new Client({
url: 'http://localhost:4000/api',
exchanges: [
dedupExchange,
cache,
fetchExchange,
subscriptionExchange({
forwardSubscription: operations => subscriptionClient.request(operations),
}),
],
})
return <Provider value={client}>{children}</Provider>
}
export default DataProvider
This 'subscriptions-transport-ws' I found from a tutorial and that mysterious '/websocket' at the end of the ws url was mentioned in some gh issue but it seems to work (before adding that to the end of the url there was no ws connection at all).
This doesn't directly answer the question, but in case someone ends up with the same confusion and as a response to your comment here:
I found from a tutorial and that mysterious '/websocket' at the end of the ws url was mentioned in some gh issue but it seems to work (before adding that to the end of the url there was no ws connection at all).
This is due to both longpoll and websocket being viable transports. You likely had your socket defined in your Endpoint with websocket: true which gave you that route. Running mix phx.routes | grep socket would have been a helpful command.
This is obviously a late reply, but I'll try my best anyway. It seems that Absinthe has an alternative client library that's different from subscriptions-transport-ws, notably it's here: https://github.com/absinthe-graphql/absinthe-socket/blob/master/packages/socket-apollo-link/src/createAbsintheSocketLink.js#L8
If you integrate with this library instead then presumably it'll work. So that means you likely have to integrate with PhoenixSocket instead, as shown here: https://github.com/absinthe-graphql/absinthe-socket/tree/master/packages/socket-apollo-link#examples
I am trying to mock a server in some UI tests that I am writing using cypress. I am probably making some basic mistake and might not be understanding how cypress is stubbing requests. Here is an example app that I copied straight from expressjs -
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => res.send('Hello from /'));
app.get('/user', (req, res) => res.send('Hello from /user'));
app.listen(port, () => console.log(`Example app listening on port ${port}!`));
And then wrote a simple test using cypress -
describe('Stubbed request', () => {
it('sends whatever response you want', () => {
cy.visit('http://localhost:3000/');
cy.server();
cy.route({
method: 'GET',
url: '/user',
response: [],
}).as('bar');
cy.visit('http://localhost:3000/user'); // cy.request() has same behavior
cy.wait('#bar');
})
})
I was hoping that instead of 'Hello from user/', I should get an empty response since I have stubbed it with cypress. Even cy.wait fails with message - "CypressError: Timed out retrying: cy.wait() timed out waiting 5000ms for the 1st request to the route: 'bar'. No request ever occurred." I am obviously doing something wrong. Can someone please help me understand what am I doing wrong? Thanks in advance.
You can only stub/spy XHR requests that are created within your app. cy.visit will never make such a xhr request. neither you can stub a request made with cy.request because thise requests are intended to work indepentent from all active network stubs.
This means, you are able to stub /users but in your test you can make a real request to that route by using cy.request.
In your case, you must deliver a static html site with express that e.g. contains a button. And after the button is clicked, you can execute e.g. $.get(' /user'). Then this request will be stubbed.
Currently I am not at home so I can not provide a runnable example. But with the hints above you should be able to do this. Let me know if you need further assistance.
Also you can take a look at cypress XHR API call validation in test cases . Here I have provided a runnable example fir stubbing and spying.
I am working on an app using a React frontend and Express backend, with GraphQL setup through Apollo (I am following and modifying tutorial https://www.youtube.com/playlist?list=PLN3n1USn4xlkdRlq3VZ1sT6SGW0-yajjL)
I am currently attempting deployment, and am doing so with Heroku. Everything functions perfectly on my local machine before deployment and on Heroku in Google Chrome. However, I get the aforementioned errors in Safari and Firefox, respectively. Wondering why this is happening in these browsers and how to fix.
I have spent about 10 hrs doing research on this. Things I tried that made no difference:
I tried adding CORS to my express backend
I tried serving the graphql endpoint as HTTPS
Moving app.use(express.static) in main app.js server file
I couldn't find many other things to try. Everywhere I looked seemed to say that CORS fixed the problem, but mine persists.
Github link: https://github.com/LucaProvencal/thedrumroom
Live Heroku App: https://powerful-shore-83650.herokuapp.com/
App.js (express backend):
const cors = require('cors')
// const fs = require('fs')
// const https = require('https')
// const http = require('http')
app.use(express.static(path.join(__dirname, 'client/build')));
app.use(cors('*')); //NEXT TRY app.use(cors('/login')) etc...
app.use(cors('/*'));
app.use(cors('/'));
app.use(cors('/register'));
app.use(cors('/login'));
app.get('/login', (req, res) => {
res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});
app.get('/register', (req, res) => {
res.sendFile(path.join(__dirname, "client", "build", "index.html"));
});
server.applyMiddleware({ app }); // app is from the existing express app. allows apollo server to run on same listen command as app
const portVar = (process.env.PORT || 3001) // portVar cuz idk if it will screw with down low here im tired of dis
models.sequelize.sync(/*{ force: true }*/).then(() => { // syncs sequelize models to postgres, then since async call starts the server after
app.listen({ port: portVar }, () =>
console.log(`🚀 ApolloServer ready at http://localhost:3001${server.graphqlPath}`)
)
app.on('error', onError);
app.on('listening', onListening);
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
Full file is on Github, I tried to post only relevant parts above.
The expected result is that it works in all browsers. It seems from my research that since Heroku serves on HTTPS, Safari and Firefox do not allow requests to HTTP (which is where the graphql server is located, http://localhost:3001/graphql'). When I tried serving Apollo on HTTPS, Heroku just crashed, giving me H13 and 503 errors.
Thanks for any help...
This may also happen during local development when running the front end using HTTPS, but the back end using HTTP.
This is because CORS treats two URLs as having the same origin "only when the scheme, host, and port all match". Matching scheme means matching protocols e.g. both http, or both https.
One solution for local development is to proxy the back end using a tool such as ngrok.
Suppose the front end uses an environment variable which indicates the back end's URL:
BACK_END_API_URL=http://localhost:3005. Then do the following.
Install ngrok
Identify what port the back end is running on e.g. 3005
Run ngrok http 3005 at the command line, which will establish both http and https endpoints. Both will ultimately proxy the requests to the same back end endpoint: http://localhost:3005
After running ngrok it will display the http and https endpoints you can use. Put the one that matches the front end protocol you're using (e.g. https) into your front end environment variable that indicates the back end's URL e.g.
BACK_END_API_URL=https://1234asdf5678ghjk.ngrok.io
Was going to delete this because it is such a silly problem but maybe it will help someone in the future:
I simply replaced all of my 'http://localhost:PORT' endpoints in development with '/graphql'. I assumed that localhost meant local the machine running the code. But an app running on Heroku does not point to localhost. The express server is served on the url (https://powerful-shore-83650.herokuapp.com/) in our case...
At any rate I am so glad I came to a solution. I have a full stack app deployed and connected to a db. Hopefully this post can save someone lots of time.
Cross site ajax request with Vue.js 1.0 and Vue Resource. I get the following error: XMLHttpRequest cannot load http://dev.markitondemand.com/MODApis/Api/v2/Lookup/jsonp?input=NFLX&callback=handleResponse. No 'Access-Control-Allow-Origin' header is present on the requested resource.
I have a basic understanding of the problem but not sure how to add a callback function with the request or if that is the best solution for this example. I put in the full request URL here just to make it easier to follow.
new Vue({
el: '#stockList',
data: function() {
return {
query: '',
stocks: []
};
},
ready: function() {
this.getStocks();
},
methods: {
getStocks: function() {
this.$http.get('http://dev.markitondemand.com/MODApis/Api/v2/Lookup/jsonp?input=NFLX&callback=handleResponse',
function(data) {
this.stocks = data;
}
);
}
}
})
I have almost zero understanding of networking, but I was able to get several remote apis to work using:
this.$http.jsonp
instead of
this.$http.get
"No Access-Control-Allow-Origin" header usually is a problem with the server. It means that the server is configured to only allow a person access to the API if the request comes from the same domain as the server. You either need to run the script from the website that you are requesting data from, or you need to change the server config to allow access to all domains.
If you don't have access to the server, and you don't want to run the script in the browser, then I think what you could do is use a headless browser like PhantomJS to navigate to the page, insert a script element into the dom that contains you script, execute the function and then return the data from the API. I could write the code out for you, but to be honest, it's a bit complex. You would have to know how to use node.js, and phantom.js. I've personally only used phantom.js for the Node 'html-pdf' package, but I'm sure with a little bit of reading you could figure out how to do it.
Set your local environment to http instead of https if you have no control over dev.markitondemand.com.