Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 115 additions & 71 deletions crates/registryctl/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1278,46 +1278,8 @@ mod tests {
"Relay authority: 0 source integrations, 1 records API service, 1 materialized entity definition"
));

let temporary = tempfile::tempdir().expect("temporary directory");
let project = temporary.path().join("notary-only-evaluation");
std::fs::create_dir_all(project.join("environments"))
.expect("environment directory creates");
std::fs::write(
project.join("registry-stack.yaml"),
r#"version: 1
registry: { id: fictional-evaluation-registry }
services:
applicant-evaluation:
kind: evidence
version: 1
purpose: application-processing
legal_basis: application-processing
consent: not_required
access: { scopes: ["evidence:application:read"] }
claims:
application-complete:
cel: "true"
value: { type: boolean }
disclosure: predicate
credential_profiles: {}
"#,
)
.expect("project writes");
std::fs::write(
project.join("environments/local.yaml"),
r#"version: 1
callers:
application-service:
api_key_fingerprint: { secret: APPLICATION_SERVICE_TOKEN_HASH }
scopes: ["evidence:application:read"]
deployment:
profile: local
notary: { service: evaluation-notary }
"#,
)
.expect("environment writes");
let notary_report = registryctl::check_registry_project(&ProjectCheckOptions {
project_directory: project,
project_directory: fixtures.join("notary-only-evaluation"),
environment: "local".to_string(),
explain: true,
against: None,
Expand All @@ -1333,35 +1295,117 @@ deployment:
}

#[test]
fn project_test_watch_reruns_each_maintained_starter_after_an_authored_change() {
let starters = [
(ProjectStarter::Http, "person-record", "active-person"),
(
ProjectStarter::Dhis2Tracker,
"health-record",
"complete-health-match",
),
(
ProjectStarter::OpencrvsDci,
"birth-record",
"birth-record-match",
),
(ProjectStarter::FhirR4, "coverage", "coverage-active"),
(
ProjectStarter::Snapshot,
"person-snapshot",
"snapshot-match",
),
];

for (starter, integration, fixture) in starters {
let temporary = tempfile::tempdir().expect("temporary directory");
let project_directory = temporary.path().join("registry-project");
registryctl::init_registry_project(&ProjectInitOptions {
fn project_test_watch_reruns_each_maintained_fixture_journey_after_an_authored_change() {
fn copy_directory(source: &std::path::Path, destination: &std::path::Path) -> Result<()> {
std::fs::create_dir_all(destination)?;
for entry in std::fs::read_dir(source)? {
let entry = entry?;
let target = destination.join(entry.file_name());
if entry.file_type()?.is_dir() {
copy_directory(&entry.path(), &target)?;
} else {
std::fs::copy(entry.path(), target)?;
}
}
Ok(())
}

let manifest_root = std::path::Path::new(env!("CARGO_MANIFEST_DIR"));
let repository_root = manifest_root.join("../..");
let catalog: serde_yaml::Value = serde_yaml::from_slice(
&std::fs::read(manifest_root.join("tests/fixtures/project-authoring-journeys.yaml"))
.expect("project-authoring journey catalog reads"),
)
.expect("project-authoring journey catalog parses");
let mut journeys = Vec::new();
for workspace in catalog["workspaces"]
.as_sequence()
.expect("catalog workspaces")
{
if !workspace["steps"]
.as_sequence()
.expect("catalog steps")
.iter()
.any(|step| step.as_str() == Some("watch"))
{
continue;
}
assert_eq!(
workspace["classification"].as_str(),
Some("maintained"),
"watch is a maintained authoring journey"
);
let starter = workspace["starter"].as_str().map(|starter| match starter {
"http" => ProjectStarter::Http,
"dhis2-tracker" => ProjectStarter::Dhis2Tracker,
"opencrvs-dci" => ProjectStarter::OpencrvsDci,
"fhir-r4" => ProjectStarter::FhirR4,
"snapshot" => ProjectStarter::Snapshot,
other => panic!("unknown catalog starter {other}"),
});
let id = workspace["id"].as_str().expect("watch id").to_string();
let project_dir = workspace["project_dir"]
.as_str()
.expect("watch project directory")
.to_string();
let source = repository_root.join(
workspace["source"]
.as_str()
.expect("catalog workspace source"),
);
let project: serde_yaml::Value = serde_yaml::from_slice(
&std::fs::read(source.join("registry-stack.yaml")).expect("catalog project reads"),
)
.expect("catalog project parses");
let integrations = project["integrations"]
.as_mapping()
.expect("watch journey integrations");
assert_eq!(integrations.len(), 1, "watch journey integration");
let (integration, reference) = integrations.iter().next().expect("watch integration");
let integration = integration.as_str().expect("integration id").to_string();
let integration_file = reference["file"].as_str().expect("integration file");
let fixture_file = workspace["focused_fixture_file"]
.as_str()
.expect("focused fixture file");
let fixture_path = source
.join(integration_file)
.parent()
.expect("integration directory")
.join("fixtures")
.join(fixture_file);
let fixture: serde_yaml::Value =
serde_yaml::from_slice(&std::fs::read(fixture_path).expect("watch fixture reads"))
.expect("watch fixture parses");
journeys.push((
id,
starter,
directory: project_directory.clone(),
})
.expect("maintained starter initializes");
source,
project_dir,
integration,
fixture["name"]
.as_str()
.expect("watch fixture name")
.to_string(),
));
}
assert_eq!(
journeys.len(),
9,
"every maintained fixture journey watches"
);

for (id, starter, source, project_dir, integration, fixture) in journeys {
let temporary = tempfile::tempdir().expect("temporary directory");
let project_directory = temporary.path().join(project_dir);
if let Some(starter) = starter {
registryctl::init_registry_project(&ProjectInitOptions {
starter,
directory: project_directory.clone(),
})
.expect("maintained starter initializes");
} else {
copy_directory(&source, &project_directory).expect("maintained non-starter copies");
}

let mut observed_runs = 0;
watch_project_tests_until(
Expand All @@ -1371,9 +1415,9 @@ deployment:
live: false,
},
ProjectTestSelection {
integration: Some(integration.to_string()),
fixture: Some(fixture.to_string()),
trace: true,
integration: Some(integration),
fixture: Some(fixture),
trace: false,
},
|completed_runs, root| {
observed_runs = completed_runs;
Expand All @@ -1393,7 +1437,7 @@ deployment:
},
)
.expect("offline watch reruns after an authored project file changes");
assert_eq!(observed_runs, 2, "{starter:?}");
assert_eq!(observed_runs, 2, "{id}");
}
}

Expand Down
171 changes: 171 additions & 0 deletions crates/registryctl/tests/fixtures/project-authoring-journeys.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
version: 1
workspaces:
- id: http
label: Custom HTTP
summary: One fixed bounded HTTP request with a closed response projection.
source: crates/registryctl/assets/project-starters/bounded-http
classification: maintained
topology: combined
starter: http
project_dir: registry-project
focused_fixture_file: active.yaml
steps: [init, editor, trace, watch, test, check, build]
environment: local
check_explain: true

- id: custom-system
label: Custom HTTP conformance workspace
summary: Combined HTTP acquisition and registry-backed evidence coverage.
source: crates/registryctl/tests/fixtures/project-authoring/custom-system
classification: maintained
topology: combined
project_dir: crates/registryctl/tests/fixtures/project-authoring/custom-system
focused_fixture_file: eligible.yaml
steps: [trace, watch, test, check, build]
environment: local
check_explain: true

- id: dhis2-script
label: DHIS2 script conformance workspace
summary: Conformance coverage for the bounded Script adapter surface.
source: crates/registryctl/tests/fixtures/project-authoring/dhis2-script
classification: conformance-only
topology: combined
project_dir: crates/registryctl/tests/fixtures/project-authoring/dhis2-script
steps: [test, check, build]
environment: local
check_explain: true

- id: dhis2-tracker
label: DHIS2 Tracker
summary: A product-neutral script adapter applied to a bounded DHIS2 Tracker read journey.
source: crates/registryctl/tests/fixtures/project-authoring/dhis2-tracker
classification: maintained
topology: combined
starter: dhis2-tracker
project_dir: dhis2-project
focused_fixture_file: match.yaml
steps: [init, editor, trace, watch, test, check, build]
environment: local
check_explain: true

- id: fhir-r4-coverage-active
label: FHIR R4
summary: A product-neutral script adapter with bounded FHIR R4 search-set parsing.
source: crates/registryctl/tests/fixtures/project-authoring/fhir-r4-coverage-active
classification: maintained
topology: combined
starter: fhir-r4
project_dir: fhir-project
focused_fixture_file: match.yaml
steps: [init, editor, trace, watch, test, check, build]
environment: local
check_explain: true

- id: nia-attribute-release
label: NIA attribute release
summary: Solmara-focused conformance coverage for a bounded Relay attribute-release profile.
source: crates/registryctl/tests/fixtures/project-authoring/nia-attribute-release
classification: conformance-only
focus: solmara
topology: relay-only
project_dir: crates/registryctl/tests/fixtures/project-authoring/nia-attribute-release
steps: [check, build]
environment: local
check_explain: true

- id: opencrvs-dci
label: OpenCRVS DCI
summary: A product-neutral script adapter with the signed DCI search verification profile.
source: crates/registryctl/tests/fixtures/project-authoring/opencrvs
classification: maintained
topology: combined
starter: opencrvs-dci
project_dir: opencrvs-project
focused_fixture_file: match.yaml
steps: [init, editor, trace, watch, test, check, build]
environment: local
check_explain: true

- id: opencrvs-country-variant
label: OpenCRVS country variant
summary: Country-owned DCI mapping coverage for match, no-match, and ambiguity.
source: crates/registryctl/tests/fixtures/project-authoring/opencrvs-country-variant
classification: maintained
topology: combined
project_dir: crates/registryctl/tests/fixtures/project-authoring/opencrvs-country-variant
focused_fixture_file: match.yaml
steps: [trace, watch, test, check, build]
environment: local
check_explain: true

- id: openspp-exact
label: OpenSPP exact lookup
summary: Offline fixture evidence only, pending the owner-run holdout in GH#357.
source: crates/registryctl/tests/fixtures/project-authoring/openspp-exact
classification: maintained
topology: combined
evidence: offline-fixture-only-pending-357
project_dir: crates/registryctl/tests/fixtures/project-authoring/openspp-exact
focused_fixture_file: match.yaml
steps: [trace, watch, test, check, build]
environment: local
check_explain: true

- id: relay-only-materialization
label: Relay-only materialization
summary: Fixtureless Relay materialization configuration with no public records service.
source: crates/registryctl/tests/fixtures/project-authoring/relay-only-materialization
classification: maintained
topology: relay-only
project_dir: crates/registryctl/tests/fixtures/project-authoring/relay-only-materialization
steps: [check, build]
environment: local
check_explain: true

- id: relay-only-records
label: Relay-only records API
summary: Fixtureless Relay records configuration with no Notary inputs.
source: crates/registryctl/tests/fixtures/project-authoring/relay-only-records
classification: maintained
topology: relay-only
project_dir: crates/registryctl/tests/fixtures/project-authoring/relay-only-records
steps: [check, build]
environment: local
check_explain: true

- id: snapshot
label: Exact snapshot
summary: An exact lookup over one immutable local materialization.
source: crates/registryctl/tests/fixtures/project-authoring/snapshot-exact
classification: maintained
topology: combined
starter: snapshot
project_dir: snapshot-project
focused_fixture_file: match.yaml
steps: [init, editor, trace, watch, test, check, build]
environment: local
check_explain: true

- id: snapshot-with-records
label: Snapshot with records API
summary: Match and no-match evidence sharing one authorized Relay materialization with records.
source: crates/registryctl/tests/fixtures/project-authoring/snapshot-with-records
classification: maintained
topology: combined
project_dir: crates/registryctl/tests/fixtures/project-authoring/snapshot-with-records
focused_fixture_file: match.yaml
steps: [trace, watch, test, check, build]
environment: local
check_explain: true

- id: notary-only-evaluation
label: Notary-only evaluation
summary: Local policy evaluation only, with no credential profile, issuance, or direct source capability.
source: crates/registryctl/tests/fixtures/project-authoring/notary-only-evaluation
classification: maintained
topology: notary-only
project_dir: crates/registryctl/tests/fixtures/project-authoring/notary-only-evaluation
steps: [check, build]
environment: local
check_explain: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: 1
callers:
application-service:
api_key_fingerprint: { secret: APPLICATION_SERVICE_TOKEN_HASH }
scopes: ["evidence:application:read"]
deployment:
profile: local
notary: { service: evaluation-notary }
Loading
Loading