Skip to content

Commit 4fc426f

Browse files
authored
Merge pull request #213 from genomoncology/ux-trial-filter-help-text
Clarify trial filter help: facility modes, phase 1/2 semantics, sex all no-op
2 parents dde13bb + 777c204 commit 4fc426f

File tree

2 files changed

+74
-3
lines changed

2 files changed

+74
-3
lines changed

spec/04-trial.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,20 @@ out="$(biomcp get trial NCT02576665 locations --limit 3)"
141141
echo "$out" | mustmatch like "## Locations"
142142
echo "$out" | mustmatch like "| Facility | City | Country | Status | Contact |"
143143
```
144+
145+
## Trial Help Explains Special Filter Semantics
146+
147+
The trial help output should explain the three non-obvious filter behaviors that
148+
otherwise surprise operators: facility text-search versus geo-verify cost,
149+
ClinicalTrials.gov's combined `1/2` phase label, and `--sex all` meaning no sex
150+
restriction.
151+
152+
```bash
153+
out="$(biomcp search trial --help)"
154+
echo "$out" | mustmatch like "text-search mode"
155+
echo "$out" | mustmatch like "geo-verify mode"
156+
echo "$out" | mustmatch like "materially more expensive"
157+
echo "$out" | mustmatch like "combined Phase 1/Phase 2 label"
158+
echo "$out" | mustmatch like "not Phase 1 OR Phase 2"
159+
echo "$out" | mustmatch like "no sex restriction"
160+
```

src/cli/mod.rs

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -463,11 +463,20 @@ See also: biomcp list trial")]
463463
#[arg(short = 'i', long, num_args = 1..)]
464464
intervention: Vec<String>,
465465

466-
/// Filter by institution/facility name
466+
/// Filter by institution/facility name (text-search mode by default).
467+
///
468+
/// Without `--lat`/`--lon`/`--distance`, this uses cheap CTGov
469+
/// `query.locn` text-search mode. With all three geo flags, it enters
470+
/// geo-verify mode and performs extra per-study location fetches to
471+
/// confirm the facility match within the requested distance. Geo-verify
472+
/// mode is materially more expensive, especially with `--count-only`.
467473
#[arg(long, num_args = 1..)]
468474
facility: Vec<String>,
469475

470-
/// Filter by phase [values: NA, 1, 1/2, 2, 3, 4, EARLY_PHASE1, PHASE1-PHASE4]
476+
/// Filter by phase [values: NA, 1, 1/2, 2, 3, 4, EARLY_PHASE1, PHASE1, PHASE2, PHASE3, PHASE4].
477+
///
478+
/// `1/2` matches the ClinicalTrials.gov combined Phase 1/Phase 2 label
479+
/// (studies tagged as both phases), not Phase 1 OR Phase 2.
471480
#[arg(short = 'p', long)]
472481
phase: Option<String>,
473482
/// Study type (e.g., interventional, observational)
@@ -478,7 +487,11 @@ See also: biomcp list trial")]
478487
#[arg(long)]
479488
age: Option<f32>,
480489

481-
/// Eligible sex [values: female, male, all]
490+
/// Eligible sex filter [values: female, male, all].
491+
///
492+
/// `all` (also `any`/`both`) resolves to no sex restriction, so no sex
493+
/// filter is sent to ClinicalTrials.gov. Use `female` or `male` to
494+
/// apply an actual restriction.
482495
#[arg(long)]
483496
sex: Option<String>,
484497

@@ -4944,6 +4957,47 @@ mod tests {
49444957
assert!(help.contains("serve-http"));
49454958
}
49464959

4960+
fn render_trial_search_long_help() -> String {
4961+
let mut command = Cli::command();
4962+
let search = command
4963+
.find_subcommand_mut("search")
4964+
.expect("search subcommand should exist");
4965+
let trial = search
4966+
.find_subcommand_mut("trial")
4967+
.expect("trial subcommand should exist");
4968+
let mut help = Vec::new();
4969+
trial
4970+
.write_long_help(&mut help)
4971+
.expect("trial help should render");
4972+
String::from_utf8(help).expect("help should be utf-8")
4973+
}
4974+
4975+
#[test]
4976+
fn trial_facility_help_names_text_search_and_geo_verify_modes() {
4977+
let help = render_trial_search_long_help();
4978+
4979+
assert!(help.contains("text-search mode"));
4980+
assert!(help.contains("geo-verify mode"));
4981+
assert!(help.contains("materially more expensive"));
4982+
}
4983+
4984+
#[test]
4985+
fn trial_phase_help_explains_combined_phase_label() {
4986+
let help = render_trial_search_long_help();
4987+
4988+
assert!(help.contains("1/2"));
4989+
assert!(help.contains("combined Phase 1/Phase 2 label"));
4990+
assert!(help.contains("not Phase 1 OR Phase 2"));
4991+
}
4992+
4993+
#[test]
4994+
fn trial_sex_help_explains_all_means_no_restriction() {
4995+
let help = render_trial_search_long_help();
4996+
4997+
assert!(help.contains("all"));
4998+
assert!(help.contains("no sex restriction"));
4999+
}
5000+
49475001
#[test]
49485002
fn parse_trial_location_paging_extracts_offset_limit_flags() {
49495003
let sections = vec![

0 commit comments

Comments
 (0)