tests work properly
This commit is contained in:
9
rust/prepare-test-instance.sh
Executable file
9
rust/prepare-test-instance.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
cd $( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
|
||||
set -o nounset
|
||||
|
||||
export SQLX_OFFLINE=true
|
||||
|
||||
exec cargo build
|
||||
@@ -1,13 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
sleep 100
|
||||
cd $( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
|
||||
set -o nounset
|
||||
|
||||
port="${1}"
|
||||
|
||||
db="$(mktemp)"
|
||||
|
||||
export SQLX_OFFLINE=true
|
||||
export DATABASE_URL="sqlite://${db}"
|
||||
|
||||
cargo run -- --port "${port}"
|
||||
exec ./target/debug/packager --port "${port}"
|
||||
|
||||
@@ -39,6 +39,17 @@ impl From<InputType> for &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
fn trip_state_icon(state: &TripState) -> &'static str {
|
||||
match state {
|
||||
TripState::Init => "mdi-magic-staff",
|
||||
TripState::Planning => "mdi-text-box-outline",
|
||||
TripState::Planned => "mdi-clock-outline",
|
||||
TripState::Active => "mdi-play",
|
||||
TripState::Review => "mdi-magnify",
|
||||
TripState::Done => "mdi-check",
|
||||
}
|
||||
}
|
||||
|
||||
pub struct TripTable;
|
||||
|
||||
impl TripTable {
|
||||
@@ -66,10 +77,15 @@ impl TripTable {
|
||||
@for trip in trips {
|
||||
tr ."h-10" ."even:bg-gray-100" ."hover:bg-purple-100" ."h-full" {
|
||||
(TripTableRow::build(trip.id, &trip.name))
|
||||
(TripTableRow::build(trip.id, trip.date_start))
|
||||
(TripTableRow::build(trip.id, trip.date_end))
|
||||
(TripTableRow::build(trip.id, trip.date_start.to_string()))
|
||||
(TripTableRow::build(trip.id, trip.date_end.to_string()))
|
||||
(TripTableRow::build(trip.id, (trip.date_end - trip.date_start).whole_days()))
|
||||
(TripTableRow::build(trip.id, trip.state))
|
||||
(TripTableRow::build(trip.id, html!(
|
||||
span .flex .flex-row .items-center {
|
||||
span ."mdi" .(trip_state_icon(&trip.state)) ."text-xl" ."mr-2" {}
|
||||
span { (trip.state) }
|
||||
}
|
||||
)))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,7 +97,7 @@ impl TripTable {
|
||||
pub struct TripTableRow;
|
||||
|
||||
impl TripTableRow {
|
||||
pub fn build(trip_id: Uuid, value: impl std::fmt::Display) -> Markup {
|
||||
pub fn build(trip_id: Uuid, value: impl maud::Render) -> Markup {
|
||||
html!(
|
||||
td ."border" ."p-0" ."m-0" {
|
||||
a ."inline-block" ."p-2" ."m-0" ."w-full"
|
||||
@@ -441,7 +457,12 @@ impl TripInfo {
|
||||
))
|
||||
tr .h-full {
|
||||
td ."border" ."p-2" { "State" }
|
||||
td ."border" ."p-2" { (trip.state) }
|
||||
td ."border" {
|
||||
span .flex .flex-row .items-center .justify-start ."gap-2" {
|
||||
span ."mdi" .(trip_state_icon(&trip.state)) ."text-2xl" ."pl-2" {}
|
||||
span ."pr-2" ."py-2" { (trip.state) }
|
||||
}
|
||||
}
|
||||
@let prev_state = trip.state.prev();
|
||||
@let next_state = trip.state.next();
|
||||
|
||||
|
||||
@@ -6,7 +6,10 @@ use std::thread;
|
||||
use thirtyfour::common::capabilities::firefox::FirefoxPreferences;
|
||||
use thirtyfour::{FirefoxCapabilities, WebDriver};
|
||||
|
||||
use std::time;
|
||||
|
||||
use std::future::Future;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
const PORT: u16 = 3001;
|
||||
const BASEURL: &'static str = "http://localhost";
|
||||
@@ -31,6 +34,14 @@ impl From<WebDriverError> for TestError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for TestError {
|
||||
fn from(error: std::io::Error) -> Self {
|
||||
Self::AppError {
|
||||
message: error.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn random_name() -> String {
|
||||
let mut rng = rand::thread_rng();
|
||||
let length = { 1..=20 }.choose(&mut rng).unwrap();
|
||||
@@ -49,27 +60,105 @@ where
|
||||
R: Future<Output = Result<(), TestError>>,
|
||||
{
|
||||
let event_in_parent = Arc::new((Mutex::new(false), Condvar::new()));
|
||||
|
||||
let event_in_subprocess = Arc::clone(&event_in_parent);
|
||||
let app = thread::spawn(move || {
|
||||
use std::process::Command;
|
||||
|
||||
// panic!();
|
||||
let script = concat!(env!("CARGO_MANIFEST_DIR"), "/run-test-instance.sh");
|
||||
let prepared_event_in_parent = Arc::new((Mutex::new(false), Condvar::new()));
|
||||
let prepared_event_in_subprocess = Arc::clone(&prepared_event_in_parent);
|
||||
|
||||
println!("starting script {script}");
|
||||
let mut handle = Command::new(script).arg(PORT.to_string()).spawn().unwrap();
|
||||
let app = thread::spawn(move || -> Result<(), TestError> {
|
||||
{
|
||||
let script = concat!(env!("CARGO_MANIFEST_DIR"), "/../prepare-test-instance.sh");
|
||||
|
||||
let (lock, cvar) = &*event_in_subprocess;
|
||||
let mut done = lock.lock().unwrap();
|
||||
while !*done {
|
||||
done = cvar.wait(done).unwrap();
|
||||
println!("[sub] starting prepare script {script}");
|
||||
let handle_prepare = Command::new(script)
|
||||
.stdin(Stdio::null())
|
||||
// .stdout(Stdio::null())
|
||||
// .stderr(Stdio::null())
|
||||
.output()?;
|
||||
|
||||
assert!(handle_prepare.status.success());
|
||||
println!("[sub] preparation ok");
|
||||
}
|
||||
|
||||
let mut handle_gecko = {
|
||||
let script = concat!(env!("CARGO_MANIFEST_DIR"), "/../run-test-instance.sh");
|
||||
|
||||
println!("[sub] starting script {script}");
|
||||
let handle = Command::new("geckodriver")
|
||||
.stdin(Stdio::null())
|
||||
// .stdout(Stdio::null())
|
||||
// .stderr(Stdio::null())
|
||||
.spawn()?;
|
||||
println!("[sub] geckodriver started");
|
||||
handle
|
||||
};
|
||||
|
||||
{
|
||||
println!("[sub] sending prepared event");
|
||||
let (lock, cvar) = &*prepared_event_in_subprocess;
|
||||
let mut prepared = lock.lock().unwrap();
|
||||
*prepared = true;
|
||||
cvar.notify_all();
|
||||
println!("[sub] sent prepared event");
|
||||
}
|
||||
|
||||
let mut handle_app = {
|
||||
let script = concat!(env!("CARGO_MANIFEST_DIR"), "/../run-test-instance.sh");
|
||||
|
||||
println!("[sub] starting script {script}");
|
||||
let handle = Command::new(script)
|
||||
.arg(PORT.to_string())
|
||||
.stdin(Stdio::null())
|
||||
// .stdout(Stdio::null())
|
||||
// .stderr(Stdio::null())
|
||||
.spawn()?;
|
||||
println!("[sub] app started");
|
||||
handle
|
||||
};
|
||||
|
||||
{
|
||||
let (lock, cvar) = &*event_in_subprocess;
|
||||
let mut done = lock.lock().unwrap();
|
||||
while !*done {
|
||||
println!("[sub] waiting for done event");
|
||||
done = cvar.wait(done).unwrap();
|
||||
}
|
||||
println!("[sub] done received");
|
||||
}
|
||||
|
||||
// at worst, the child already exited, so we don't care about the
|
||||
// return code
|
||||
let _ = handle.kill();
|
||||
println!("[sub] killing app subprocess");
|
||||
let _ = handle_app.kill()?;
|
||||
handle_app.wait()?;
|
||||
println!("[sub] killed app subprocess");
|
||||
|
||||
println!("[sub] killing gecko subprocess");
|
||||
let _ = handle_gecko.kill()?;
|
||||
handle_gecko.wait()?;
|
||||
println!("[sub] killed gecko subprocess");
|
||||
|
||||
println!("[sub] done");
|
||||
|
||||
Ok(())
|
||||
});
|
||||
|
||||
thread::spawn(move || {
|
||||
let (lock, cvar) = &*prepared_event_in_parent;
|
||||
let mut prepared = lock.lock().unwrap();
|
||||
while !*prepared {
|
||||
println!("waiting for prepared event");
|
||||
prepared = cvar.wait(prepared).unwrap();
|
||||
}
|
||||
println!("prepared received");
|
||||
})
|
||||
.join()
|
||||
.unwrap();
|
||||
|
||||
println!("preparations done, starting tests in 1s");
|
||||
|
||||
thread::sleep(time::Duration::from_secs(1));
|
||||
|
||||
let prefs = FirefoxPreferences::new();
|
||||
let mut caps = FirefoxCapabilities::new();
|
||||
caps.set_preferences(prefs)?;
|
||||
@@ -79,20 +168,35 @@ where
|
||||
// cloning works for closing, so it's good enough
|
||||
let driver_handle = driver.clone();
|
||||
|
||||
// call the actual function
|
||||
println!("calling test function");
|
||||
let result = inner(driver).await;
|
||||
// let result: Result<(), TestError> = Ok(());
|
||||
println!("test function done");
|
||||
|
||||
println!("deinitializing selenium driver");
|
||||
driver_handle.quit().await?;
|
||||
|
||||
// if the child panicked and cannot receive the event, we don't care and just
|
||||
// exit
|
||||
let (lock, cvar) = &*event_in_parent;
|
||||
let mut done = lock.lock().unwrap();
|
||||
*done = true;
|
||||
cvar.notify_one();
|
||||
// this has to be done in a separate thread, otherwise the condvar handling
|
||||
// does not work. it's not sure why.
|
||||
thread::spawn(move || {
|
||||
// if the child panicked and cannot receive the event, we don't care and just
|
||||
// continue to the exit
|
||||
println!("sending done event");
|
||||
let (lock, cvar) = &*event_in_parent;
|
||||
let mut done = lock.lock().unwrap();
|
||||
*done = true;
|
||||
cvar.notify_all();
|
||||
println!("sent done event");
|
||||
})
|
||||
.join()
|
||||
.unwrap();
|
||||
|
||||
let _ = app.join().map_err(|_| TestError::AppError {
|
||||
println!("waiting for subprocess");
|
||||
app.join().map_err(|_| TestError::AppError {
|
||||
message: "app panicked".to_string(),
|
||||
});
|
||||
})??;
|
||||
println!("all done");
|
||||
Ok(result?)
|
||||
}
|
||||
|
||||
@@ -145,6 +249,31 @@ async fn check_table(
|
||||
|
||||
#[tokio::test]
|
||||
async fn test() -> Result<(), TestError> {
|
||||
let mut handle = {
|
||||
let script = concat!(env!("CARGO_MANIFEST_DIR"), "/../run-test-instance.sh");
|
||||
|
||||
println!("[sub] starting script {script}");
|
||||
let handle = Command::new(script)
|
||||
.arg(PORT.to_string())
|
||||
.stdin(Stdio::null())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.spawn()?;
|
||||
println!("[sub] started");
|
||||
handle
|
||||
};
|
||||
|
||||
// at worst, the child already exited, so we don't care about the
|
||||
// return code
|
||||
println!("[sub] killing subprocess");
|
||||
let _ = handle.kill().expect("failed to kill child");
|
||||
handle.wait().unwrap();
|
||||
println!("[sub] killed subprocess");
|
||||
|
||||
println!("[sub] done");
|
||||
|
||||
// return Ok(());
|
||||
|
||||
run_test(|driver: WebDriver| async move {
|
||||
for js_enabled in [true] {
|
||||
driver.goto(url("/")).await?;
|
||||
|
||||
Reference in New Issue
Block a user