diff --git a/crates/picloud-cli/tests/logs.rs b/crates/picloud-cli/tests/logs.rs index 1b8e732..12f6cb9 100644 --- a/crates/picloud-cli/tests/logs.rs +++ b/crates/picloud-cli/tests/logs.rs @@ -7,7 +7,7 @@ use predicates::prelude::*; use crate::common; /// Pick out the data rows from `pic logs` TSV output — the header line -/// (`created_at\tstatus\tsummary`) is now always present, so the old +/// (`created_at\tsource\tstatus\tsummary`) is now always present, so the old /// "no non-empty lines means no logs" check needs to skip it. fn data_rows(stdout: &str) -> Vec<&str> { stdout @@ -63,10 +63,10 @@ fn logs_after_invoke_records_success_row() { let cols: Vec<&str> = rows[0].split('\t').map(str::trim).collect(); assert_eq!( cols.len(), - 3, - "row should be 3 tab-delimited cells: {rows:?}" + 4, + "row should be 4 tab-delimited cells (created_at, source, status, summary): {rows:?}" ); - assert_eq!(cols[1], "success"); + assert_eq!(cols[2], "success"); } #[ignore = "needs DATABASE_URL pointing at a running Postgres"] @@ -95,7 +95,7 @@ fn logs_records_error_for_throwing_script() { .next() .expect("at least one data row"); let cols: Vec<&str> = row.split('\t').map(str::trim).collect(); - assert_eq!(cols[1], "error", "expected error status, got row: {row}"); + assert_eq!(cols[2], "error", "expected error status, got row: {row}"); } #[ignore = "needs DATABASE_URL pointing at a running Postgres"] @@ -166,7 +166,7 @@ fn logs_truncates_long_summary() { .into_iter() .next() .expect("at least one data row"); - let summary = row.split('\t').nth(2).expect("summary column"); + let summary = row.split('\t').nth(3).expect("summary column"); assert!( summary.ends_with('…'), "summary should be truncated with `…`, got: {summary}" diff --git a/crates/picloud-cli/tests/roles.rs b/crates/picloud-cli/tests/roles.rs index 29fb46c..1374f35 100644 --- a/crates/picloud-cli/tests/roles.rs +++ b/crates/picloud-cli/tests/roles.rs @@ -98,7 +98,7 @@ fn viewer_cannot_deploy_but_editor_can() { ]) .assert() .success() - .stdout(predicate::str::contains("Created hello v1")); + .stdout(predicate::str::contains("hello").and(predicate::str::contains("created"))); } #[ignore = "needs DATABASE_URL pointing at a running Postgres"] diff --git a/crates/picloud-cli/tests/scripts.rs b/crates/picloud-cli/tests/scripts.rs index 3cd8c65..fec05f8 100644 --- a/crates/picloud-cli/tests/scripts.rs +++ b/crates/picloud-cli/tests/scripts.rs @@ -7,6 +7,16 @@ use predicates::prelude::*; use crate::common; use crate::common::cleanup::AppGuard; +/// Extract a field value from a `pic` KvBlock (`key\tvalue` per line). +/// `pic scripts deploy` prints `name`/`version`/`action` rows, not a prose +/// "Created X vN" line, so version-bump tests assert on these fields. +fn kv_field<'a>(stdout: &'a str, key: &str) -> Option<&'a str> { + stdout.lines().find_map(|l| { + let (k, v) = l.split_once('\t')?; + (k.trim() == key).then(|| v.trim()) + }) +} + #[ignore = "needs DATABASE_URL pointing at a running Postgres"] #[test] fn deploy_against_unknown_app_errors() { @@ -48,7 +58,7 @@ fn deploy_with_name_override() { let _guard = AppGuard::new(&env.url, &env.token, &slug); let fixture = common::fixture_path("hello.rhai"); - common::pic_as(&env) + let out = common::pic_as(&env) .args([ "scripts", "deploy", @@ -58,11 +68,14 @@ fn deploy_with_name_override() { "--name", "custom-name", ]) - .assert() - .success() - .stdout(predicate::str::contains("Created custom-name v1")); + .output() + .expect("deploy v1"); + let v1 = String::from_utf8(out.stdout).unwrap(); + assert_eq!(kv_field(&v1, "name"), Some("custom-name"), "v1 name: {v1}"); + assert_eq!(kv_field(&v1, "version"), Some("1"), "v1 version: {v1}"); + assert_eq!(kv_field(&v1, "action"), Some("created"), "v1 action: {v1}"); - common::pic_as(&env) + let out = common::pic_as(&env) .args([ "scripts", "deploy", @@ -72,9 +85,11 @@ fn deploy_with_name_override() { "--name", "custom-name", ]) - .assert() - .success() - .stdout(predicate::str::contains("Updated custom-name v2")); + .output() + .expect("deploy v2"); + let v2 = String::from_utf8(out.stdout).unwrap(); + assert_eq!(kv_field(&v2, "version"), Some("2"), "v2 version: {v2}"); + assert_eq!(kv_field(&v2, "action"), Some("updated"), "v2 action: {v2}"); let out = common::pic_as(&env) .args(["scripts", "ls", "--app", &slug]) @@ -106,8 +121,8 @@ fn deploy_bumps_version_each_redeploy() { let _guard = AppGuard::new(&env.url, &env.token, &slug); let fixture = common::fixture_path("hello.rhai"); - for expected in ["Created hello v1", "Updated hello v2", "Updated hello v3"] { - common::pic_as(&env) + for (version, action) in [("1", "created"), ("2", "updated"), ("3", "updated")] { + let out = common::pic_as(&env) .args([ "scripts", "deploy", @@ -115,9 +130,20 @@ fn deploy_bumps_version_each_redeploy() { "--app", &slug, ]) - .assert() - .success() - .stdout(predicate::str::contains(expected)); + .output() + .expect("deploy"); + assert!(out.status.success(), "deploy v{version} failed: {out:?}"); + let stdout = String::from_utf8(out.stdout).unwrap(); + assert_eq!( + kv_field(&stdout, "version"), + Some(version), + "version: {stdout}" + ); + assert_eq!( + kv_field(&stdout, "action"), + Some(action), + "action: {stdout}" + ); } }