Testing stdout and stdin of a Dart console app - dart

I have this simple file:
class Console {
const Console();
void run() {
stdout
..writeln('Choose:\n')
..writeln(' 1) A')
..writeln(' 2) B\n')
final input = stdin.readLineSync() ?? '';
stdout.write('You have chosen $input');
}
}
How do I unit test this?
My best try is the following:
test('Making sure that invalid inputs return an error message', () async {
final process = await Process.start('dart', ['run', r'../bin/demo.dart']);
process.stdin.write('1');
process.stdout.transform(Utf8Decoder()).listen(print);
});
Since I have no idea on how to check for the stdout printed text, I am trying to at least display the strings
Choose:
1) A
2) B
using transform(Utf8Decoder()) but it's not working. Could you please point me towards the right direction?
Note: the main() function is located in lib/demo.dart so that's why I'm passing ../bin/demo.dart

Related

can we use the toHaveScreenshot() and toMatchSnaphot() out side the test

Can we use the toHaveScreenshot() and toMatchSnaphot() outside the test without using config file only simple install NPM i playwright in package.json
I have already one snapshot I want to compare snapshot using toHaveScreenshot() method but I am confused we can use outside the test context?
const { chromium } =require( "playwright");
const example = async () => {
const browser = await chromium.launch({ headless: false });
const page = await browser.newPage();
await page.goto("https://zversal.com/");
await page.toHaveScreenshot("zeversal.png", {
fullPage: false,
maxDiffPixelRatio: 0.24,
});
};
example();
Console reports error:
toHaveScreenshot() must be called during the test
I don't think this is possible. Afaik, toHaveScreenshot() is part of the #playwright/test package.
If I'm looking at the Page API docs there's no toHaveScreenshot() listed. I'd say it's only available in combination with Playwright Test and it's provided expect method.
await expect(page).toHaveScreenshot();
As similarly noted by stefan judis in his answer, toHaveScreenshot is an assertion matchers method provided by expect which comes from the Playwright Test library and is made to be used inside tests.
While that assertion can’t be used, you can still take screenshots using Playwright, and then compare them manually or with another tool.
I don't know if it's possible to use it outside of testing, but you can create a PlaywrightDevPage helper class to encapsulate common operations on the page.
Simple Usage =>
// models/PlaywrightDevPage.js
class PlaywrightDevPage {
/**
* #param {import('playwright').Page} page
*/
constructor(page) {
this.page = page;
this.getStartedLink = page.locator('a', { hasText: 'Get started' });
this.gettingStartedHeader = page.locator('h1', { hasText: 'Installation' });
this.pomLink = page.locator('li', { hasText: 'Playwright Test' }).locator('a', { hasText: 'Page Object Model' });
this.tocList = page.locator('article div.markdown ul > li > a');
}
async getStarted() {
await this.getStartedLink.first().click();
await expect(this.gettingStartedHeader).toBeVisible();
}
async pageObjectModel() {
await this.getStarted();
await this.pomLink.click();
}
}
module.exports = { PlaywrightDevPage };
More Info => PlaywrightDevPage

How can I receive data by POST in Hyper?

What I want to do is really what the title says. I would like to know how I can receive data per post in hyper, for example, suppose I execute the following command (with a server in hyper running on port :8000):
curl -X POST -F "field=#/path/to/file.txt" -F "tool=curl" -F "other-file=#/path/to/other.jpg" http://localhost:8000
Now, I'm going to take parf of the code on the main page of hyper as an example:
use std::{convert::Infallible, net::SocketAddr};
use hyper::{Body, Request, Response, Server};
use hyper::service::{make_service_fn, service_fn};
async fn handle(_: Request<Body>) -> Result<Response<Body>, Infallible> {
Ok(Response::new("Hello, World!".into()))
}
#[tokio::main]
async fn main() {
let addr = SocketAddr::from(([127, 0, 0, 1], 8000));
let make_svc = make_service_fn(|_conn| async {
Ok::<_, Infallible>(service_fn(handle))
});
let server = Server::bind(&addr).serve(make_svc);
if let Err(e) = server.await {
eprintln!("server error: {}", e);
}
}
So, now, with this basic code, how can I receive the data per post that my curl command above would send? How do I adapt my code to read the data? I've tried to search the internet, but what I found was that hyper doesn't actually split the request body depending on the HTTP method, it's all part of the same body. But I haven't been able to find a way to process data like the above with code like mine. Thanks in advance.
Edit
I tried the exact code that they left me in the answer. That is, this code:
async fn handle(req: Request<Body>) -> Result<Response<Body>, Infallible> {
let mut files = multipart::server::Multipart::from(req);
.....
}
But I get this error:
expected struct multipart::server::Multipart, found struct
hyper::Request
How can I solve that?
It is a single body, but the data is encoded in a way that contains the multiple files.
This is called multipart, and in order to parse the body correctly you need a multipart library such as https://crates.io/crates/multipart
To hyper integration you need to add the feature flag hyper in Cargo.toml
multipart = { version = "*", features = ["hyper"] }
Then
async fn handle(mut files: multipart::server::Multipart) -> Result<Response<Body>, Infallible> {
files.foreach_entry(|field| {
// contains name, filename, type ..
println!("Info: {:?}",field.headers);
// contains data
let mut bytes:Vec<u8> = Vec::new();
field.data.read_to_end(&mut bytes);
});
Ok(Response::new("Received the files!".into()))
}
You can also use it like this
async fn handle(req: Request<Body>) -> Result<Response<Body>, Infallible> {
let mut files = multipart::server::Multipart::from(req);
.....
}

electron ipcRenderer passing string one letter at a time

I am trying to pass a string from render to main using the ipc process. For some reason its a) firing repeatedly, and b) only sending one letter at a time, even though I can definitively see that the whole string is set before sending. What the heck is going on and how do I compress this back to a single call that has the correct string in it?
renderer:
const electron = window.require('electron');
.
.
.
//by now username = "demouser"
electron.ipcRenderer.once('verifySubscriptionResponse', (event, token, errorMessage) => {
console.log('handleLoginAttempt');
console.log('username variable:' + username);
electron.ipcRenderer.send("proceedToApp", username);
}
main:
const { ipcMain } = require('electron');
ipcMain.on("proceedToApp", (event, username) => {
console.log('passed in username:' + username);
global.loggedInUser = username;
console.log('set username:' + global.loggedInUser)
}
in renderer, im getting the simple output
> handleLoginAttempt
> usernameVariable: demouser
but in main, I get this output:
passed in username:d
set username:d
passed in username:de
set username:de
passed in username:dem
set username:dem
passed in username:demo
set username:demo
passed in username:demou
set username:demou
passed in username:demous
set username:demous
EDIT:
One clue to the puzzle, username was a state hook variable, I swapped it out with a literal string and it now sends the entire string, but is still sending several times. So half this problem may be that electron doesnt play well with react hooks logic.

Dart Unit Test - Always passing

All,
Here is a unit test for checking the size of a collection
main() {
test("Resource Manager Image Load", () {
ResourceManager rm = new ResourceManager();
int WRONG_SIZE = 1000000;
rm.loadImageManifest("data/rm/test_images.yaml").then((_){
print("Length="+ rm.images.length.toString()); // PRINTS '6' - WHICH IS CORRECT
expect(rm.images, hasLength(WRONG_SIZE));
});
});
}
I am running this from a browser (client-side Dart libraries are in use) and it ALWAYS passes, no matter what the value of WRONG_SIZE.
Help appreciated.
In such simple cases you can just return the future. The unit test framework recognizes it and waits for the future to complete. This also works for setUp/tearDown.
main() {
test("Resource Manager Image Load", () {
ResourceManager rm = new ResourceManager();
int WRONG_SIZE = 1000000;
return rm.loadImageManifest("data/rm/test_images.yaml").then((_) {
//^^^^
print("Length="+ rm.images.length.toString()); // PRINTS '6' - WHICH IS CORRECT
expect(rm.images, hasLength(WRONG_SIZE));
});
});
}
The problem is that your code returns a Future, and your test completes before the code in the Future has finished, so there's nothing to cause it to fail.
Check out the Asynchronous Tests section on the Dart site. There are methods like expectAsync that allow the future to be passed to the test framework so that it can wait for them to complete and handle the result correctly.
Here's an example (note the expect call is now inside the function passed to expectAsync)
test('callback is executed once', () {
// wrap the callback of an asynchronous call with [expectAsync] if
// the callback takes 0 arguments...
var timer = Timer.run(expectAsync(() {
int x = 2 + 3;
expect(x, equals(5));
}));
});

Console Application - terminal input

Could someone please show me an example of terminal input (question and response) in Dart (console) (latest r22223). The only example that I have seen doesn't appear to work or is incomplete.
Here's another option:
import "dart:async";
import "dart:io";
void main() {
stdout.write('> '); // stdout.write() rather than print() to avoid newline
new StringDecoder().bind(stdin).listen((str) { // Listen to a Stream<String>
print('"${str.trim()}"'); // Quote and parrot back the input
stdout.write('> '); // Prompt and keep listening
}, onDone: () => print('\nBye!')); // Stream is done, say bye
}
This appears to work fine on Linux and Windows. It quotes back to you whatever you enter at the prompt. You can exit by inputting EOF (control-D on Linux and other UNIX-like systems, control-Z followed by enter on Windows).
import "dart:async";
import "dart:io";
void main() {
print("Do you want to say something?");
Stream<String> input = stdin.transform(new StringDecoder());
StreamSubscription sub;
sub = input.listen((user_input) {
print("Really? \"${user_input.trim()}\"? That's all you have to say?");
sub.cancel();
});
}
Which example did you find, and how exactly was it wrong?

Resources