diff --git a/rocrate_validator/profiles/five-safes-crate/may/4_sign_off.ttl b/rocrate_validator/profiles/five-safes-crate/may/4_sign_off.ttl new file mode 100644 index 00000000..b30dedc2 --- /dev/null +++ b/rocrate_validator/profiles/five-safes-crate/may/4_sign_off.ttl @@ -0,0 +1,58 @@ +# Copyright (c) 2025 eScience Lab, The University of Manchester +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +@prefix ro: <./> . +@prefix ro-crate: . +@prefix five-safes-crate: . +@prefix rdf: . +@prefix schema: . +@prefix sh: . +@prefix validator: . +@prefix xsd: . +@prefix shp: . + + +five-safes-crate:SignOffPhaseStartTime + a sh:NodeShape ; + sh:name "SignOffPhaseStartTime" ; + + sh:target [ + a sh:SPARQLTarget ; + sh:select """ + PREFIX schema: + PREFIX shp: + SELECT ?this + WHERE { + ?this schema:additionalType shp:SignOff ; + schema:actionStatus ?status . + FILTER(?status IN ( + "http://schema.org/ActiveActionStatus", + "http://schema.org/CompletedActionStatus", + "http://schema.org/FailedActionStatus" + )) + } + """ ; + ] ; + + sh:property [ + a sh:PropertyShape ; + sh:name "StartTime" ; + sh:path schema:startTime ; + sh:minCount 1 ; + sh:maxCount 1 ; + sh:pattern "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-9]{2}([.|,][0-9]+)?(Z|z|[+-][0-9]{2}:[0-9]{2})$" ; + sh:severity sh:Info ; + sh:description "Sign Off object MAY have a startTime property if action is active, completed or failed. This must follow ISO-8601 syntax" ; + sh:message "Sign Off object MAY have a startTime property if action is active, completed or failed. This must follow ISO-8601 syntax" ; + ] . diff --git a/rocrate_validator/profiles/five-safes-crate/must/4_sign_off.ttl b/rocrate_validator/profiles/five-safes-crate/must/4_sign_off.ttl new file mode 100644 index 00000000..2b61a259 --- /dev/null +++ b/rocrate_validator/profiles/five-safes-crate/must/4_sign_off.ttl @@ -0,0 +1,89 @@ +# Copyright (c) 2025 eScience Lab, The University of Manchester +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +@prefix ro: <./> . +@prefix ro-crate: . +@prefix five-safes-crate: . +@prefix rdf: . +@prefix schema: . +@prefix purl: . +@prefix sh: . +@prefix validator: . +@prefix xsd: . + +five-safes-crate:SignOffObjectActionAndName + a sh:NodeShape ; + sh:name "SignOff" ; + sh:description "Sign Off phase" ; + + sh:target [ + a sh:SPARQLTarget ; + sh:select """ + PREFIX schema: + PREFIX shp: + SELECT ?this + WHERE { + ?this schema:additionalType shp:SignOff . + } + """ ; + ] ; + + sh:property [ + sh:path schema:name ; + sh:datatype xsd:string ; + sh:minCount 1 ; + sh:severity sh:Violation ; + sh:message "Sign Off phase MUST have a human-readable name string." ; + ] ; + + sh:property [ + sh:path rdf:type ; + sh:minCount 1 ; + sh:hasValue schema:AssessAction; + sh:severity sh:Violation ; + sh:message "Sign Off phase MUST be a `schema:AssessAction`." ; + ] . + +five-safes-crate:SignOffObjectHasActionStatus + a sh:NodeShape ; + sh:name "SignOffStatus" ; + sh:description "Sign Off Phase Action Status" ; + + sh:target [ + a sh:SPARQLTarget ; + sh:select """ + PREFIX schema: + PREFIX shp: + SELECT ?this + WHERE { + ?this schema:additionalType shp:SignOff ; + schema:actionStatus ?status . + } + """ ; + ] ; + + sh:property [ + a sh:PropertyShape ; + sh:name "actionStatus" ; + sh:description "The value of actionStatus MUST be one of the allowed values." ; + sh:path schema:actionStatus ; + sh:in ( + "http://schema.org/PotentialActionStatus" + "http://schema.org/ActiveActionStatus" + "http://schema.org/CompletedActionStatus" + "http://schema.org/FailedActionStatus" + ) ; + sh:severity sh:Violation ; + sh:message "The value of actionStatus MUST be one of the allowed values: PotentialActionStatus; ActiveActionStatus; CompletedActionStatus; FailedActionStatus." ; + ] . diff --git a/rocrate_validator/profiles/five-safes-crate/should/4_sign_off.ttl b/rocrate_validator/profiles/five-safes-crate/should/4_sign_off.ttl new file mode 100644 index 00000000..d671a0d9 --- /dev/null +++ b/rocrate_validator/profiles/five-safes-crate/should/4_sign_off.ttl @@ -0,0 +1,178 @@ +# Copyright (c) 2025 eScience Lab, The University of Manchester +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +@prefix ro: <./> . +@prefix ro-crate: . +@prefix five-safes-crate: . +@prefix rdf: . +@prefix schema: . +@prefix sh: . +@prefix validator: . +@prefix xsd: . +@prefix shp: . + + +# There SHOULD be a Sign-Off Phase +five-safes-crate:SignOffPhase + a sh:NodeShape ; + sh:targetNode <./> ; + sh:description "Check the Sign-Off Phase" ; + sh:sparql [ + sh:select """ + PREFIX schema: + PREFIX shp: + SELECT $this + WHERE { + FILTER NOT EXISTS { + ?action schema:additionalType shp:SignOff . + } + } + """ ; + sh:severity sh:Warning ; + sh:message "There SHOULD be a Sign-Off Phase in the Final RO-Crate" ; + ] ; + sh:sparql [ + sh:select """ + PREFIX schema: + PREFIX shp: + SELECT $this + WHERE { + ?action schema:additionalType shp:SignOff . + FILTER NOT EXISTS { + $this schema:mentions ?action . + } + } + """ ; + sh:severity sh:Warning ; + sh:message "The Root Data Entity SHOULD mention a Sign-Off Phase Object" ; + ] . + + +five-safes-crate:SignOffPhaseProperties + a sh:NodeShape ; + sh:description "Check Sign-Off Phase Properties" ; + sh:target [ + a sh:SPARQLTarget ; + sh:select """ + PREFIX schema: + PREFIX shp: + SELECT ?this + WHERE { + ?this schema:additionalType shp:SignOff . + } + """ + ] ; + sh:property [ + sh:description "Check if the Sign Off phase has an actionStatus" ; + sh:path schema:actionStatus ; + sh:minCount 1 ; + sh:severity sh:Warning ; + sh:message "The Sign-Off Phase SHOULD have an actionStatus" ; + ] ; + sh:property [ + sh:description "Check if the Sign Off phase has an agent" ; + sh:path schema:agent ; + sh:minCount 1 ; + sh:severity sh:Warning ; + sh:message "The Sign-Off Phase SHOULD have an agent" ; + ] ; + sh:property [ + sh:description "Check if the Sign Off phase has an instrument (TRE Policy)" ; + sh:path schema:instrument ; + sh:class schema:CreativeWork ; + sh:nodeKind sh:IRI; + sh:minCount 1 ; + sh:severity sh:Warning ; + sh:message "The Sign-Off Phase SHOULD have an TRE policy (instrument) with type CreativeWork" ; + ] ; + sh:property [ + sh:description "Check if the Sign Off phase has an instrument (TRE Policy)" ; + sh:path ( schema:instrument schema:name ) ; + sh:datatype xsd:string ; + sh:minCount 1 ; + sh:severity sh:Warning ; + sh:message "The Sign-Off Phase SHOULD have an TRE policy (instrument) with a human-readable name" ; + ] ; + sh:sparql [ + a sh:SPARQLConstraint ; + sh:description "Check if the Sign Off phase lists the workflow as an object" ; + sh:select """ + PREFIX schema: + PREFIX rocrate: + SELECT $this + WHERE { + ?root a schema:Dataset ; + schema:mainEntity ?mainEntity ; + rdf:type rocrate:RootDataEntity . + FILTER NOT EXISTS { + $this schema:object ?mainEntity . + } + } + """ ; + sh:severity sh:Warning ; + sh:message "The Sign-Off Phase SHOULD list the workflow (mainEntity) as an object" ; + ]; + sh:sparql [ + a sh:SPARQLConstraint ; + sh:description "Check if the Sign Off phase lists the Responsible Project as an object" ; + sh:select """ + PREFIX schema: + PREFIX rocrate: + SELECT $this + WHERE { + ?root a schema:Dataset ; + rdf:type rocrate:RootDataEntity ; + schema:sourceOrganization ?sourceOrg . + FILTER NOT EXISTS { + $this schema:object ?sourceOrg . + } + } + """ ; + sh:severity sh:Warning ; + sh:message "The Sign-Off Phase SHOULD list the Responsible Project (sourceOrganization) as an object" ; + ]. + + +five-safes-crate:SignOffPhaseEndTime + a sh:NodeShape ; + sh:description "Sign Off end time check" ; + + sh:target [ + a sh:SPARQLTarget ; + sh:select """ + PREFIX schema: + PREFIX shp: + SELECT ?this + WHERE { + ?this schema:additionalType shp:SignOff ; + schema:actionStatus ?status . + FILTER(?status IN ( + "http://schema.org/CompletedActionStatus", + "http://schema.org/FailedActionStatus" + )) + } + """ ; + ] ; + + sh:property [ + a sh:PropertyShape ; + sh:name "EndTime" ; + sh:path schema:endTime ; + sh:minCount 1 ; + sh:maxCount 1 ; + sh:pattern "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-9]{2}([.|,][0-9]+)?(Z|z|[+-][0-9]{2}:[0-9]{2})$" ; + sh:severity sh:Warning ; + sh:description "Sign Off object SHOULD have endTime property if action completed or failed. This must follow ISO-8601 syntax" ; + sh:message "Sign Off object SHOULD have endTime property if action completed or failed. This must follow ISO-8601 syntax" ; + ] . diff --git a/tests/data/crates/valid/five-safes-crate-result/ro-crate-metadata.json b/tests/data/crates/valid/five-safes-crate-result/ro-crate-metadata.json index f1f48cd9..3401e529 100644 --- a/tests/data/crates/valid/five-safes-crate-result/ro-crate-metadata.json +++ b/tests/data/crates/valid/five-safes-crate-result/ro-crate-metadata.json @@ -277,6 +277,7 @@ }, "name": "Sign-off of execution according to Agreement policy: approved", "endTime": "2023-04-19T17:15:12+01:00", + "startTime": "2023-04-19T10:15:12+01:00", "object": [ { "@id": "./" diff --git a/tests/integration/profiles/five-safes-crate/test_5src_4_signoff_phase.py b/tests/integration/profiles/five-safes-crate/test_5src_4_signoff_phase.py new file mode 100644 index 00000000..7f9cd8f3 --- /dev/null +++ b/tests/integration/profiles/five-safes-crate/test_5src_4_signoff_phase.py @@ -0,0 +1,579 @@ +# Copyright (c) 2024-2025 CRS4 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import logging + +from rocrate_validator.models import Severity +from tests.ro_crates import ValidROC +from tests.shared import do_entity_test, SPARQL_PREFIXES + +# set up logging +logger = logging.getLogger(__name__) + + +# ---- SHOULD fails tests + + +def test_5src_no_signoff_phase(): + """ + Test a Five Safes Crate where no Sign-Off phase is listed. + """ + + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + <#signoff-3b741265-cfef-49ea-8138-a2fa149bf2f0> ?p ?o . + } + WHERE { + <#signoff-3b741265-cfef-49ea-8138-a2fa149bf2f0> ?p ?o . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["SignOffPhase"], + expected_triggered_issues=[ + "There SHOULD be a Sign-Off Phase in the Final RO-Crate" + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_no_name(): + """ + Test a Five Safes Crate where the Sign-Off phase has no name. + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?signoff schema:name ?name . + } + WHERE { + ?signoff a schema:AssessAction ; + schema:additionalType ; + schema:name ?name . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.REQUIRED, + expected_validation_result=False, + expected_triggered_requirements=["SignOff"], + expected_triggered_issues=[ + "Sign Off phase MUST have a human-readable name string." + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_wrong_type(): + """ + Test a Five Safes Crate where the Sign-Off phase has no name. + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?signoff rdf:type ?type . + } + INSERT { + ?signoff rdf:type . + } + WHERE { + ?signoff a schema:AssessAction ; + schema:additionalType ; + rdf:type ?type . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.REQUIRED, + expected_validation_result=False, + expected_triggered_requirements=["SignOff"], + expected_triggered_issues=[ + "Sign Off phase MUST be a `schema:AssessAction`." + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_wrong_action_status(): + """ + Test a Five Safes Crate where the Sign-Off phase has the wrong action status. + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?signoff schema:actionStatus ?status . + } + INSERT { + ?signoff schema:actionStatus . + } + WHERE { + ?signoff a schema:AssessAction ; + schema:additionalType ; + schema:actionStatus ?status . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.REQUIRED, + expected_validation_result=False, + expected_triggered_requirements=["SignOffStatus"], + expected_triggered_issues=[ + "The value of actionStatus MUST be one of the allowed values:" + + " PotentialActionStatus; ActiveActionStatus; CompletedActionStatus; FailedActionStatus." + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_not_mentioned(): + """ + Test a Five Safes Crate where the Sign-Off phase is not mentioned by the MainRootEntity. + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + <./> schema:mentions <#signoff-3b741265-cfef-49ea-8138-a2fa149bf2f0> . + } + WHERE { + <./> schema:mentions <#signoff-3b741265-cfef-49ea-8138-a2fa149bf2f0> . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["SignOffPhase"], + expected_triggered_issues=[ + "The Root Data Entity SHOULD mention a Sign-Off Phase Object" + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_no_endtime(): + """ + Test a Five Safes Crate where the Sign-Off phase has no endTime. + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?signoff schema:endTime ?endTime . + } + WHERE { + ?signoff a schema:AssessAction ; + schema:additionalType ; + schema:endTime ?endTime . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["SignOffPhaseEndTime"], + expected_triggered_issues=[ + "Sign Off object SHOULD have endTime property if action completed or failed." + + " This must follow ISO-8601 syntax" + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_malformed_endtime(): + """ + Test a Five Safes Crate where the Sign-Off phase has an endTime + in the wrong format. + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?signoff schema:endTime ?endTime . + } + INSERT { + ?signoff schema:endTime <2025-10-20> . + } + WHERE { + ?signoff a schema:AssessAction ; + schema:additionalType ; + schema:endTime ?endTime . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["SignOffPhaseEndTime"], + expected_triggered_issues=[ + "Sign Off object SHOULD have endTime property if action completed or failed." + + " This must follow ISO-8601 syntax" + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_no_starttime(): + """ + Test a Five Safes Crate where the Sign-Off phase has no startTime. + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?signoff schema:startTime ?startTime . + } + WHERE { + ?signoff a schema:AssessAction ; + schema:additionalType ; + schema:startTime ?startTime . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.OPTIONAL, + expected_validation_result=False, + expected_triggered_requirements=["SignOffPhaseStartTime"], + expected_triggered_issues=[ + "Sign Off object MAY have a startTime property if action is active, completed or failed." + + " This must follow ISO-8601 syntax" + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_malformed_starttime(): + """ + Test a Five Safes Crate where the Sign-Off phase has a startTime + in the wrong format. + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?signoff schema:startTime ?startTime . + } + INSERT { + ?signoff schema:startTime <2025-10-20> . + } + WHERE { + ?signoff a schema:AssessAction ; + schema:additionalType ; + schema:startTime ?startTime . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.OPTIONAL, + expected_validation_result=False, + expected_triggered_requirements=["SignOffPhaseStartTime"], + expected_triggered_issues=[ + "Sign Off object MAY have a startTime property if action is active, completed or failed." + + " This must follow ISO-8601 syntax" + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_no_actionstatus(): + """ + Test a Five Safes Crate where the Sign-Off phase has no actionStatus. + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?signoff schema:actionStatus ?actionStatus . + } + WHERE { + ?signoff a schema:AssessAction ; + schema:additionalType ; + schema:actionStatus ?actionStatus . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["SignOffPhaseProperties"], + expected_triggered_issues=[ + "The Sign-Off Phase SHOULD have an actionStatus" + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_no_agent(): + """ + Test a Five Safes Crate where the Sign-Off phase has no agent. + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?signoff schema:agent ?agent . + } + WHERE { + ?signoff a schema:AssessAction ; + schema:additionalType ; + schema:agent ?agent . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["SignOffPhaseProperties"], + expected_triggered_issues=[ + "The Sign-Off Phase SHOULD have an agent" + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_no_instrument(): + """ + Test a Five Safes Crate where the Sign-Off phase has no TRE policy (instrument). + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?signoff schema:instrument ?instrument . + } + WHERE { + ?signoff a schema:AssessAction ; + schema:additionalType ; + schema:instrument ?instrument . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["SignOffPhaseProperties"], + expected_triggered_issues=[ + "The Sign-Off Phase SHOULD have an TRE policy (instrument) with type CreativeWork" + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_instrument_not_iri(): + """ + Test a Five Safes Crate where the Sign-Off phase TRE policy (instrument) is not an IRI. + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?signoff schema:instrument ?instrument . + } + INSERT { + ?signoff schema:instrument "Not a cross-reference" . + } + WHERE { + ?signoff a schema:AssessAction ; + schema:additionalType ; + schema:instrument ?instrument . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["SignOffPhaseProperties"], + expected_triggered_issues=[ + "The Sign-Off Phase SHOULD have an TRE policy (instrument) with type CreativeWork" + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_instrument_no_type(): + """ + Test a Five Safes Crate where the Sign-Off phase instrument has no type. + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?instrument rdf:type ?type . + } + WHERE { + ?signoff a schema:AssessAction ; + schema:additionalType ; + schema:instrument ?instrument . + ?instrument rdf:type ?type . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["SignOffPhaseProperties"], + expected_triggered_issues=[ + "The Sign-Off Phase SHOULD have an TRE policy (instrument) with type CreativeWork" + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_instrument_no_name(): + """ + Test a Five Safes Crate where the Sign-Off phase instrument has no type. + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?instrument schema:name ?name . + } + WHERE { + ?signoff a schema:AssessAction ; + schema:additionalType ; + schema:instrument ?instrument . + ?instrument schema:name ?name . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["SignOffPhaseProperties"], + expected_triggered_issues=[ + "The Sign-Off Phase SHOULD have an TRE policy (instrument) with a human-readable name" + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_object_notworkflow(): + """ + Test a Five Safes Crate where there is no workflow in the Sign-Off objects. + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?signoff schema:object . + } + INSERT { + ?signoff schema:object . + } + WHERE { + ?signoff a schema:AssessAction ; + schema:additionalType ; + schema:object . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["SignOffPhaseProperties"], + expected_triggered_issues=[ + "The Sign-Off Phase SHOULD list the workflow (mainEntity) as an object" + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_signoff_phase_object_not_responsible_project(): + """ + Test a Five Safes Crate where there is no Responsible Project in the Sign-Off objects. + """ + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?signoff schema:object <#project-be6ffb55-4f5a-4c14-b60e-47e0951090c70> . + } + INSERT { + ?signoff schema:object . + } + WHERE { + ?signoff a schema:AssessAction ; + schema:additionalType ; + schema:object <#project-be6ffb55-4f5a-4c14-b60e-47e0951090c70> . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["SignOffPhaseProperties"], + expected_triggered_issues=[ + "The Sign-Off Phase SHOULD list the Responsible Project (sourceOrganization) as an object" + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + )