Checking if host is online in Cypress - cypress

My tests run on a IOT device which is controlled via a web interface. I want to create a factory reset test which involves a reboot of the device and I want to check in a loop if the device is online ("pingable") again. Is there a way to execute the ping command inside of Cypress and get a return value of it.

Presuming you mean the standard ping protocol, this is the form. Substitute your device address and reply message.
cy.exec('ping google.com')
.then(reply => {
expect(reply.code).to.eq(0)
const expectedMsg = 'Pinging google.com [142.250.66.206] with 32 bytes of data:\r\nReply from 142.250.66.206: bytes=32'
expect(reply.stdout).to.satisfy(msg => msg.startsWith(expectedMsg))
})
A loop may not be needed, but if so I'd use a recursive function
function doPing(count = 0) {
if (count === 10) throw 'Failed to ping';
cy.exec('ping google.com')
.then(reply => {
if (reply.code > 0) {
cy.wait(1000) // whatever back-off time is required
doPing(++count)
} else {
expect(reply.stdout).to.satisfy(msg => ...)
}
})
}
doPing()

Related

React Redux dispatch getting called multiple times

MERN Stack application with Login and Register working properly.
On opening dashboard ("/" path), it dispatches "getWallets" 3 times, instead of 1:
Dashboard.jsx :
useEffect(() => {
if (isError) {
console.log(message)
}
if (!user) {
navigate("/login")
}
else {
dispatch(getWallets())
}
return () => {
dispatch(reset())
}
}, [user, navigate, isError, message, dispatch])
It also dispatches "getWalletData" 9 times instead of one (since I only have 1 wallet atm).
TestWalletsData.jsx (component inserted on Dashboard.jsx):
useEffect(() => {
if (isError) {
console.log(message)
}
if (wallets.length > 0 && walletsData.length <= wallets.length) {
wallets.forEach(wallet => {
dispatch(getWalletData(wallet))
dispatch(reset())
})
}
return () => {
dispatch(reset())
}
}, [wallets, wallets.length, walletsData, isError, message, dispatch])
At this point the application is running ok since I don't permit another object to get pushed to the state if it's already there , but since I'm using a limited rate API to get wallets data this isn't the road I want to path.
I'm assuming the issue arrives with the re-rendering of components and the wrong use of useEffect, but I just don't know how to fix it.
I've tried setting the environment to production as suggested by this comment but everything stays the same. https://stackoverflow.com/a/72301433/14399239
PS: Never worked with React Redux or Redux for that matter before trying it out on this project. Tried to follow a tutorial logic and apply it on my use case but having serious difficulties.
EDIT
Managed to solve the issue by removing the React.StrictMode !

systematic failure when trying to execute a system command with Cypress

I'm new to Cypress and Javascript
I'm trying to send system commands through Cypress. I've been through several examples but even the simplest does not work.
it always fails with the following message
Information about the failure:
Code: 127
Stderr:
/c/Program: Files\Git\usr\bin\bash.exe: No such file or directory`
I'm trying cy.exec('pwd') or 'ls' to see where it is launched from but it does not work.
Is there a particular include I am missing ? some particular configuration ?
EDIT :
indeed, I'm not clear about the context I'm trying to use the command in. However, I don't set any path explicitely.
I send requests on a linux server but I also would like to send system commands.
My cypress project is in /c/Cypress/test_integration/cypress
I work with a .feature file located in /c/Cypress/test_integration/cypress/features/System and my scenario calls a function in a file system.js located in /c/Cypress/test_integration/cypress/step_definitions/generic.
System_operations.features:
Scenario: [0004] - Restore HBox configuration
Given I am logging with "Administrator" account from API
And I store the actual configuration
...
Then I my .js file, I want to send a system command
system.js:
Given('I store the actual configuration', () => {
let nb_elem = 0
cy.exec('ls -l')
...
})
I did no particular path configuration in VS Code for the use of bash command (I just configured the terminal in bash instead of powershell)
Finally, with some help, I managed to call system functions by using tasks.
In my function I call :
cy.task('send_system_cmd', 'pwd').then((output) => {
console.log("output = ", output)
})
with a task created as follows:
on('task', {
send_system_cmd(cmd) {
console.log("task test command system")
const execSync = require('child_process').execSync;
const output = execSync(cmd, { encoding: 'utf-8' });
return output
}
})
this works at least for simple commands, I haven't tried much further for the moment.
UPDATE for LINUX system commands as the previous method works for WINDOWS
(sorry, I can't remember where I found this method, it's not my credit. though it fulfills my needs)
This case requires node-ssh
Still using tasks, the function call is done like this
cy.task('send_system_cmd', {cmd:"<my_command>", endpoint:<address>,user:<ssh_login>, pwd:<ssh_password>}).then((output) => {
<process output.stdout or output.stderr>
})
with the task being build like this:
// send system command - remote
on('task', {
send_system_cmd({cmd, endpoint, user, pwd}) {
return new Promise((resolve, reject) => {
const { NodeSSH } = require('node-ssh')
const ssh = new NodeSSH()
let ssh_output = {}
ssh.connect({
host: endpoint,
username: user,
password: pwd
})
.then(() => {
if(!ssh.isConnected())
reject("ssh connection not set")
//console.log("ssh connection OK, send command")
ssh.execCommand(cmd).then(function (result) {
ssh_output["stderr"] = result.stderr
ssh_output["stdout"] = result.stdout
resolve(ssh_output)
});
})
.catch((err)=>{
console.log(err)
reject(err)
})
})
}
})

How to get Web Bluetooth to send multiple `characteristicvaluechanged` events?

[paraphrasing an IRC conversation]
Trying to build a temperature sensor with ardunio and a DHT11 sensor and a HM10 bluetooth sensor. When getting the temperature values with Web Bluetooth but it doesn't seem to be firing the characteristicvaluechanged event. It only gives the initial value.
document.querySelector('button')
.addEventListener('click', connectBluetooth)
function connectBluetooth() {
navigator.bluetooth
.requestDevice({
optionalServices: [ 0xffe0 ],
acceptAllDevices: true
})
.then(device => device.gatt.connect())
.then(server => server.getPrimaryService(0xffe0))
.then(service => service.getCharacteristic(0xffe1))
.then(characteristic => {
characteristic.addEventListener('characteristicvaluechanged',
handleValueChanged)
return characteristic.readValue()
})
.catch(err => console.error(err))
}
function handleValueChanged(event) {
console.log('Handling...')
let value = event.target.value.getUint8(0)
console.log(`The value is: ${value}`)
}
You never subscribed to notifications. See https://googlechrome.github.io/samples/web-bluetooth/notifications.html for an example. Registering the event listener is not sufficient, you must also call characteristic.startNotifications(). The readValue was returning one result, so just replace it with startNotifications.

How to listen to ACK packages on ephemeral ports

I need to write a tftp client implementation to send a file from a windows phone 8.1 to a piece of hardware.
Because I need to be able to support windows 8.1 I need to use the Windows.Networking.Sockets classes.
I'm able to send my Write request package but I am having troubles to receive the ack package (wireshark). This ack package is sent to an "ephemeral port" according to the TFTP specification but the port is blocked according to wireshark.
I know how to use sockets on a specific port but I don't know how to be able to receive ack packages send to different (ephemeral) ports. I need to use the port used for that ack package to continue the TFTP communication.
How would I be able to receive the ACK packages and continue to work on a different port? Do I need to bind the socket to multiple ports? I've been trying to find answers on the microsoft docs and google but other implementations gave me no luck so far.
As reference my current implementation:
try {
hostName = new Windows.Networking.HostName(currentIP);
} catch (error) {
WinJS.log && WinJS.log("Error: Invalid host name.", "sample", "error");
return;
}
socketsSample.clientSocket = new Windows.Networking.Sockets.DatagramSocket();
socketsSample.clientSocket.addEventListener("messagereceived", onMessageReceived);
socketsSample.clientSocket.bindEndpointAsync(new Windows.Networking.HostName(hostName), currentPort);
WinJS.log && WinJS.log("Client: connection started.", "sample", "status");
socketsSample.clientSocket.connectAsync(hostName, serviceName).done(function () {
WinJS.log && WinJS.log("Client: connection completed.", "sample", "status");
socketsSample.connected = true;
var remoteFile = "test.txt";
var tftpMode = Modes.Octet;
var sndBuffer = createRequestPacket(Opcodes.Write, remoteFile, tftpMode);
if (!socketsSample.clientDataWriter) {
socketsSample.clientDataWriter =
new Windows.Storage.Streams.DataWriter(socketsSample.clientSocket.outputStream);
}
var writer = socketsSample.clientDataWriter;
var reader;
var stream;
writer.writeBytes(sndBuffer);
// The call to store async sends the actual contents of the writer
// to the backing stream.
writer.storeAsync().then(function () {
// For the in-memory stream implementation we are using, the flushAsync call
// is superfluous, but other types of streams may require it.
return writer.flushAsync();
});
}, onError);
Finally found the issue.
Instead of connectAsynch I used getOutputStreamAsynch and now it receives messages on the client socket:
Some code:
tftpSocket.clientSocket.getOutputStreamAsync(new Windows.Networking.HostName(self.hostName), tftpSocket.serviceNameConnect).then(function (stream) {
console.log("Client: connection completed.", "sample", "status");
var writer = new Windows.Storage.Streams.DataWriter(stream); //use the stream that was created when calling getOutputStreamAsync
tftpSocket.clientDataWriter = writer; //keep the writer in case we need to close sockets we also close the writer
writer.writeBytes(sndBytes);
// The call to store async sends the actual contents of the writer
// to the backing stream.
writer.storeAsync().then(function () {
// For the in-memory stream implementation we are using, the flushAsync call
// is superfluous, but other types of streams may require it.
return writer.flushAsync();
});
}, self.onError);

how to make boost asio async_accept to accept only one single connection?

I'm using the exmple in http://www.boost.org/doc/libs/1_58_0/doc/html/boost_asio/examples/cpp11_examples.html
HTTP server
How to change the example to accept only one single connection at once. That is just accept the next connection when the previous one has finished.
Thanks
In server::do_accept simply do not include the last line (which is to start another async_accept).
void server::do_accept()
{
acceptor_.async_accept(socket_,
[this](boost::system::error_code ec)
{
// Check whether the server was stopped by a signal before this
// completion handler had a chance to run.
if (!acceptor_.is_open())
{
return;
}
if (!ec)
{
connection_manager_.start(std::make_shared<connection>(
std::move(socket_), connection_manager_, request_handler_));
}
// do_accept(); // REMOVE THIS LINE
});
}
As you can see this already used to stop accepting connections on close.
I did with:
if (0 == connection_manager_.size()) {
connection_manager_.start(std::make_shared<connection>(
std::move(socket_), connection_manager_, request_handler_));
} else {
std::move(socket_).close();
}

Resources