How to wait for WebSocket STOMP messages in Cypress.io - websocket

In one of my tests I want to wait for WebSocket STOMP messages. Is this possible with Cypress.io?

If the websocket you'd like to access is being established by your application, you could follow this basic process:
Obtain a reference to the WebSocket instance from inside your test.
Attach an event listener to the WebSocket.
Return a Cypress Promise that is resolved when your WebSocket receives the message.
This is a bit difficult for me to test out, absent a working application, but something like this should work:
In your application code:
// assuming you're using stomp-websocket: https://github.com/jmesnil/stomp-websocket
const Stomp = require('stompjs');
// bunch of app code here...
const client = Stomp.client(url);
if (window.Cypress) {
// running inside of a Cypress test, so expose this websocket globally
// so that the tests can access it
window.stompClient = client
}
In your Cypress test code:
cy.window() // yields Window of application under test
.its('stompClient') // will automatically retry until `window.stompClient` exists
.then(stompClient => {
// Cypress will wait for this Promise to resolve before continuing
return new Cypress.Promise(resolve => {
const onReceive = () => {
subscription.unsubscribe() // clean up our subscription
resolve() // resolve so Cypress continues
}
// create a new subscription on the stompClient
const subscription = stompClient.subscribe("/something/you're/waiting/for", onReceive)
})
})

Related

Listen to XRPL payments: Google Cloud Run container failed to start and listen to the port

I have an XRP wallet and I'm trying to monitor incoming payments to this address with WebSockets.
My code works fine locally.
After I subscribed to the wallet address, I simply listen to "transaction" events and get the details about the payments made to that address.
But, I need it to run 24/7 on the cloud. Nothing heavy is here. It is simply a single connection running forever.
The problem is, when I deploy my code to Google Cloud Run, I get the following error:
The user-provided container failed to start and listen on the port defined provided by the PORT=8080 environment variable.
So here is my question:
Given that I'm listening to "transactions" via wss://xrplcluster.com/ (with no ports), how should I modify my code to resolve the Cloud Run complain.
Here you are my code and thanks in advance.
import { Client } from 'xrpl';
const client = new Client("wss://xrplcluster.com/");
async function main() {
await client.connect();
const response = await client.request({
command: "subscribe",
accounts: ["my-wallet-address"]
})
client.on("transaction", tx => {
if (tx.validated) {
const transaction = {
amount: tx.transaction.Amount,
from: tx.transaction.Account,
};
console.log(transaction);
}
});
client.on("disconnected", async code => {
console.log(`The wss client is disconnected with code: ${code}`);
await client.connect();
});
}
main();

How to send error manually in the websocket?

I want to send errors in the websocket after successful connection inside tests.
I have a file which will start a websocket server and inside another method there is another websocket that will be connected to another websocket server.
client -> Main file server -> Another server
Client is the test which will connect to the main file's websocket server. I created another websocket server inside beforeEach block of the test with predefined port that will be used from main file to connect to it.
My test file looks like -
describe("some test", async () =>{
beforeEach(async () => {
await new Promise(resolve => {
anotherServer = new WebSocketServer({port:8000, path: '/ws'});
anotherServer.on('connection', function connection(ws) {
ws.on('message', async(data) => {
ws.send(data);
});
ws.on('error',(err) => {
ws.close();
})
ws.on('close',async() =>{
ws.close();
})
ws.send("Connected");
});
resolve(true);
})
})
it("handle error in another server socket",async ()=> {
await main.start(3000);
wb = new Websocket(uri,options);
await new Promise(resolve => { wb.onopen = resolve});
// here I want to send error event in the another server's socket and assert on the logs which are present in the main code.
})
});
My main file has all the event listners for error event and close events. I want to test both of them by sending error and close event in the socket from another server.

Apollo Server Subscription subscribe method is never called

I have an existing Express ApolloServer . I added subscription to that . I can see when I fire the subscription from Playground, the resolve method is called . But, the subscribe method is never called
const { PubSub, withFilter } = require ('apollo-server');
const pubsub = new PubSub();
const SOMETHING_CHANGED_TOPIC = 'something_changed';
const mySubscription = {
Subscription: {
somethingChanged: {
resolve: root => {
console.log('subscription server resolve', { root })
return root
},
subscribe: () => {
console.log('I AM HERE IN SUBSCRIPTION', pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC))
return pubsub.asyncIterator(SOMETHING_CHANGED_TOPIC)
}
}
}
};
module.exports = { mySubscription}
I can see the console.log('subscription server resolve', { root }) getting printed although root is undefined. But the similar console.log('````') in subscribe is not executed .
You need to call pubsub.publish somewhere (usually in one of your resolvers) to trigger the subscription.
https://www.apollographql.com/docs/apollo-server/data/subscriptions/#subscriptions-example
I had a similar issue, there were a couple things I needed to achieve to accomplish this.
I had to remove my resolve() function to get it working. For some reason, having the resolve() function defined caused my subscription not to work.
I also had failed to follow the
https://www.apollographql.com/docs/react/data/subscriptions/#setting-up-the-transport. I was trying to request my subscription over the http link instead of over a ws link.
In general, a good test to see where the issue lies is to try to subscribe to your message using the GraphQL sandbox at http://localhost:4000/graphql (or wherever your sandbox is setup to run at when you start your server). If the sandbox subscribes successfully, the issue lies in your client code. If the sandbox fails to subscribe, the issue lies in your server code.
Please let me know if you are still having the issue and I will try to help.

Flutter websocket disconnect listening

In Flutter, I wanna listen to websocket disconnect event, how to achieve that?
The websocket connect will be drop when app goes to background, I still not found a method to let it continuesly running in background (does anyone have solution?), So I have to detect if a websocket connect is lost or something, so that I can re-connect when lost connection.
Pls help if anyone knows how to achieve that.
You can find out if websocket is closed by implementing onDone callback. See the example below:
_channel = IOWebSocketChannel.connect(
'ws://yourserver.com:port',
);
///
/// Start listening to new notifications / messages
///
_channel.stream.listen(
(dynamic message) {
debugPrint('message $message');
},
onDone: () {
debugPrint('ws channel closed');
},
onError: (error) {
debugPrint('ws error $error');
},
);
Hope that helps.
If your server closes the connection just use pinginterval like this
ws.pingInterval = const Duration(seconds: 5);
onDone should be called.
basic ping pong is enough.
Other answers around SO and the web suggest that you can't just keep sockets open in the background (which seems reasonable, you'd be keeping open network connections that may affect battery life). Depending on your use case, you might be better looking at Push Notifications or something that checks on a schedule.
How to keep iphone ios xmpp connection alive while in the background?
Websocket paused when android app goes to background
https://www.quora.com/How-do-I-keep-Socket-IO-running-in-the-background-on-iOS
WebSocketChannel channel = WebSocketChannel.connect(uri );
Stream stream = channel.stream;
stream.listen((event) {
print('Event from Stream: $event');
},onError: (e){
Future.delayed(Duration(seconds: 10)).then((value) {
connectAndListen();
},);
},
onDone: (() {
Future.delayed(Duration(seconds: 10)).then((value) {
connectAndListen();
},);
})
);
I recommend you to use this multiplatform websocket package https://pub.dev/packages/websocket_universal , there you can even track all WS events happening (and even built-in ping measurment if you need any):
import 'package:websocket_universal/websocket_universal.dart';
/// Example works with Postman Echo server
void main() async {
/// Postman echo ws server (you can use your own server URI)
/// 'wss://ws.postman-echo.com/raw'
/// For local server it could look like 'ws://127.0.0.1:42627/websocket'
const websocketConnectionUri = 'wss://ws.postman-echo.com/raw';
const textMessageToServer = 'Hello server!';
const connectionOptions = SocketConnectionOptions(
pingIntervalMs: 3000, // send Ping message every 3000 ms
timeoutConnectionMs: 4000, // connection fail timeout after 4000 ms
/// see ping/pong messages in [logEventStream] stream
skipPingMessages: false,
/// Set this attribute to `true` if do not need any ping/pong
/// messages and ping measurement. Default is `false`
pingRestrictionForce: false,
);
/// Example with simple text messages exchanges with server
/// (not recommended for applications)
/// [<String, String>] generic types mean that we receive [String] messages
/// after deserialization and send [String] messages to server.
final IMessageProcessor<String, String> textSocketProcessor =
SocketSimpleTextProcessor();
final textSocketHandler = IWebSocketHandler<String, String>.createClient(
websocketConnectionUri, // Postman echo ws server
textSocketProcessor,
connectionOptions: connectionOptions,
);
// Listening to webSocket status changes
textSocketHandler.socketHandlerStateStream.listen((stateEvent) {
// ignore: avoid_print
print('> status changed to ${stateEvent.status}');
});
// Listening to server responses:
textSocketHandler.incomingMessagesStream.listen((inMsg) {
// ignore: avoid_print
print('> webSocket got text message from server: "$inMsg" '
'[ping: ${textSocketHandler.pingDelayMs}]');
});
// Listening to debug events inside webSocket
textSocketHandler.logEventStream.listen((debugEvent) {
// ignore: avoid_print
print('> debug event: ${debugEvent.socketLogEventType}'
' [ping=${debugEvent.pingMs} ms]. Debug message=${debugEvent.message}');
});
// Listening to outgoing messages:
textSocketHandler.outgoingMessagesStream.listen((inMsg) {
// ignore: avoid_print
print('> webSocket sent text message to server: "$inMsg" '
'[ping: ${textSocketHandler.pingDelayMs}]');
});
// Connecting to server:
final isTextSocketConnected = await textSocketHandler.connect();
if (!isTextSocketConnected) {
// ignore: avoid_print
print('Connection to [$websocketConnectionUri] failed for some reason!');
return;
}
textSocketHandler.sendMessage(textMessageToServer);
await Future<void>.delayed(const Duration(seconds: 30));
// Disconnecting from server:
await textSocketHandler.disconnect('manual disconnect');
// Disposing webSocket:
textSocketHandler.close();
}

How listen for events in Hyperledger Fabric Composer?

I haven't received any event notifications and am wondering if I am missing something.
I followed the instructions from the Fabric Composer website to define the BasicEvent in my cto model and added the code for creating and emitting events in a transaction and updated the network. I created a separate eventListener.js program that subscribes to the events using the businessNetworkConnection using the code sample from the website.
After I start my eventListener.js app it seems to be listening (after receiving the connected status message in console, nothing else happens...it doesn't go back to the normal prompt line.)
I then execute the transaction that should emit the event and it runs successfully but no event is received in the other terminal window where the eventlistener.js is running.
Here is the key part of the eventListener.js program:
businessNetworkConnection.connect(connectionProfile, businessNetworkIdentifier, participantId, participantPwd)
.then((result) => {
businessNetworkDefinition = result;
console.log('Connected: BusinessNetworkDefinition obtained=' + businessNetworkDefinition.getIdentifier());
});
businessNetworkConnection.on('event', (event) => {
// event: { "$class": "org.namespace.BasicEvent", "eventId": "0000-0000-0000-000000#0" }
console.log(event);
});
Is the businessNetworkConnection.on('event', (event) ... command supposed to cause the program to appear to hang while its listening?
If so, is there something else that could be done to troubleshoot where the problem is?
I'm using v0.6 HLF on local Docker.
I think your issue is that you don't wait for the businessNetworkDefinition to be connected before you register your listener. Remember that the then block is executed asynchronously and your following businessNetworkConnection.on code will execute immediately.
You should add a second then block to register your listener after the businessNetworkDefinition has been connected.
e.g.
return adminConnection.connect('hlfv1', 'admin', 'adminpw')
.then(() => {
return BusinessNetworkDefinition.fromDirectory(path.resolve(__dirname, '..'));
})
.then((businessNetworkDefinition) => {
return adminConnection.deploy(businessNetworkDefinition);
// return true;
})
.then(() => {
businessNetworkConnection = new BusinessNetworkConnection();
return businessNetworkConnection.connect('hlfv1', 'my-network', 'admin', 'adminpw');
})
.then(() => {
businessNetworkConnection.on('event', (event) => {
console.log( '****** received the event ' + JSON.stringify(businessNetworkConnection.getBusinessNetwork().getSerializer().toJSON(event)));
});
});
I wrote a sample code for a basic sample application developed by Hyperledger team. You can check out about from this code snippet: SampleEventListener

Resources