From 39d74406c6c5825f250c17f0bb46db3cb9893053 Mon Sep 17 00:00:00 2001 From: EttoreM Date: Mon, 8 Dec 2025 09:38:57 +0000 Subject: [PATCH 01/11] First commit --- .../may/14_workflow_retrieval_phase.ttl | 56 +++ .../must/14_workflow_retrieval_phase.ttl | 132 ++++++ .../should/14_workflow_retrieval_phase.ttl | 180 ++++++++ .../test_5src_14_workflow_retrieval_phase.py | 389 ++++++++++++++++++ 4 files changed, 757 insertions(+) create mode 100644 rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl create mode 100644 rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl create mode 100644 rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl create mode 100644 tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py diff --git a/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl new file mode 100644 index 00000000..ab9057c1 --- /dev/null +++ b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl @@ -0,0 +1,56 @@ +# 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:CheckValueMayHaveStartTimeIfBegun + a sh:NodeShape ; + sh:name "DownloadAction" ; + sh:description "" ; + sh:target [ + a sh:SPARQLTarget ; + sh:select """ + PREFIX schema: + PREFIX rdf: + SELECT ?this + WHERE { + ?this rdf:type schema:DownloadAction ; + schema:actionStatus ?status . + FILTER(?status IN ( + "http://schema.org/CompletedActionStatus", + "http://schema.org/FailedActionStatus", + "http://schema.org/ActiveActionStatus" + )) + } + """ ; + ] ; + + sh:property [ + a sh:PropertyShape ; + sh:name "StartTime" ; + sh:path schema:startTime ; + sh:minCount 1 ; + sh:maxCount 1 ; + sh:severity sh:Info ; + sh:message "`DownloadAction` MAY have the `startTime` property if it has begun." ; + ] . diff --git a/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl new file mode 100644 index 00000000..6abc97ae --- /dev/null +++ b/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl @@ -0,0 +1,132 @@ +# 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:DownloadActionObjectHasDescriptiveName + a sh:NodeShape ; + sh:name "DownloadAction" ; + sh:targetClass schema:DownloadAction ; + sh:description "" ; + + sh:property [ + a sh:PropertyShape ; + sh:name "name" ; + sh:description "DownloadAction MUST have a human readable name string of at least 10 characters." ; + sh:path schema:name ; + sh:minCount 1 ; + sh:maxCount 1 ; + sh:datatype xsd:string ; + sh:minLength 10 ; + sh:severity sh:Violation ; + sh:message "DownloadAction MUST have a human readable name string of at least 10 characters." ; + ] . + +five-safes-crate:DownloadActionStartTimeMustFollowISOStandard + a sh:NodeShape ; + sh:name "DownloadAction" ; + sh:description "" ; + sh:target [ + a sh:SPARQLTarget ; + sh:select """ + PREFIX schema: + PREFIX rdf: + + SELECT ?this + WHERE { + ?this rdf:type schema:DownloadAction ; + schema:startTime ?o . + } + """ ; + ] ; + + sh:property [ + a sh:PropertyShape ; + sh:name "StartTime" ; + sh:path schema:startTime ; + sh:pattern "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(Z|[+-][0-9]{2}:[0-9]{2})$" ; + sh:severity sh:Violation ; + sh:message "`DownloadAction` --> `startTime` MUST follows the RFC 3339 standard." ; + ] . + + +five-safes-crate:DownloadActionEndTimeMustFollowISOStandard + a sh:NodeShape ; + sh:name "DownloadAction" ; + sh:description "" ; + sh:target [ + a sh:SPARQLTarget ; + sh:select """ + PREFIX schema: + PREFIX rdf: + + SELECT ?this + WHERE { + ?this rdf:type schema:DownloadAction ; + schema:endTime ?o . + } + """ ; + ] ; + + sh:property [ + a sh:PropertyShape ; + sh:name "EndTime" ; + sh:path schema:endTime ; + sh:pattern "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(Z|[+-][0-9]{2}:[0-9]{2})$" ; + sh:severity sh:Violation ; + sh:message "`DownloadAction` --> `endTime` MUST follows the RFC 3339 standard." ; + ] . + + +five-safes-crate:CheckValueActionStatusMustHaveAllowedValues + a sh:NodeShape ; + sh:name "DownloadAction" ; + sh:description "" ; + + sh:target [ + a sh:SPARQLTarget ; + sh:select """ + PREFIX schema: + PREFIX rdf: + + SELECT ?this + WHERE { + ?this rdf:type schema:DownloadAction ; + schema:actionStatus ?status . + } + """ ; + ] ; + + sh:property [ + a sh:PropertyShape ; + sh:name "ActionStatus" ; + 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 "`DownloadAction` --> `actionStatus` MUST have one of the allowed values (see https://schema.org/ActionStatusType)." ; + ] . diff --git a/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl new file mode 100644 index 00000000..f692d883 --- /dev/null +++ b/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl @@ -0,0 +1,180 @@ +# 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:RootDataEntityShouldMentionDownloadActionObjectIfItExists + a sh:NodeShape ; + sh:name "RootDataEntity" ; + sh:targetClass ro-crate:RootDataEntity ; + sh:description "" ; + + sh:sparql [ + a sh:SPARQLConstraint ; + sh:name "mentions" ; + sh:description "RootDataEntity SHOULD mention the DownloadAction object." ; + sh:select """ + PREFIX schema: + PREFIX rdf: + SELECT $this ?download + WHERE { + ?download rdf:type schema:DownloadAction . + FILTER NOT EXISTS{ + $this schema:mentions ?download . + } + } + """ ; + sh:severity sh:Warning ; + sh:message "RootDataEntity SHOULD mention the DownloadAction object." ; + ] . + + +# five-safes-crate:CheckValueObjectShouldPointToRootDataEntity +# a sh:NodeShape ; +# sh:name "CheckValue" ; +# sh:description "" ; +# sh:target [ +# a sh:SPARQLTarget ; +# sh:select """ +# PREFIX schema: +# PREFIX shp: +# SELECT ?this +# WHERE { +# ?this schema:additionalType shp:CheckValue . +# } +# """ ; +# ] ; + +# sh:property [ +# a sh:PropertyShape ; +# sh:name "object" ; +# sh:path schema:object ; +# sh:minCount 1 ; +# sh:hasValue <./> ; +# sh:severity sh:Warning ; +# sh:message "`CheckValue` --> `object` SHOULD point to the root of the RO-Crate" ; +# ] . + + +# five-safes-crate:CheckValueInstrumentShouldPointToEntityTypedDefinedTerm +# a sh:NodeShape ; +# sh:name "CheckValue" ; +# sh:description "" ; +# sh:target [ +# a sh:SPARQLTarget ; +# sh:select """ +# PREFIX schema: +# PREFIX shp: +# SELECT ?this +# WHERE { +# ?this schema:additionalType shp:CheckValue . +# } +# """ ; +# ] ; + +# sh:property [ +# a sh:PropertyShape ; +# sh:name "instrument" ; +# sh:path schema:instrument ; +# sh:minCount 1 ; +# sh:class schema:DefinedTerm ; +# sh:severity sh:Warning ; +# sh:message "`CheckValue` --> `instrument` SHOULD point to an entity typed `schema:DefinedTerm`" ; +# ] . + + +# five-safes-crate:CheckValueAgentShouldIdentifyTheAgentWhoPerformnedTheCheck +# a sh:NodeShape ; +# sh:name "CheckValue" ; +# sh:description "" ; +# sh:target [ +# a sh:SPARQLTarget ; +# sh:select """ +# PREFIX schema: +# PREFIX shp: +# SELECT ?this +# WHERE { +# ?this schema:additionalType shp:CheckValue . +# } +# """ ; +# ] ; + +# sh:property [ +# a sh:PropertyShape ; +# sh:name "agent" ; +# sh:path schema:agent ; +# sh:minCount 1 ; +# sh:nodeKind sh:IRI ; +# sh:severity sh:Warning ; +# sh:message "`CheckValue` --> `agent` SHOULD reference the agent who initiated the check" ; +# ] . + + +five-safes-crate:DownloadActionShouldHaveEndTimeIfEnded + a sh:NodeShape ; + sh:name "DownloadAction" ; + sh:description "" ; + sh:target [ + a sh:SPARQLTarget ; + sh:select """ + PREFIX schema: + PREFIX rdf: + + SELECT ?this + WHERE { + ?this rdf:type schema:DownloadAction ; + 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:severity sh:Warning ; + sh:message "`DownloadAction` SHOULD have the `endTime` property if it has ended." ; + ] . + + +five-safes-crate:DownloadActionShouldHaveActionStatus + a sh:NodeShape ; + sh:name "DownloadAction" ; + sh:targetClass schema:DownloadAction ; + sh:description "" ; + + sh:property [ + a sh:PropertyShape ; + sh:name "ActionStatus" ; + sh:path schema:actionStatus ; + sh:minCount 1 ; + sh:severity sh:Warning ; + sh:message "`DownloadAction` SHOULD have `actionStatus` property." ; + ] . + diff --git a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py new file mode 100644 index 00000000..1a4968e7 --- /dev/null +++ b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py @@ -0,0 +1,389 @@ +# 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 + +# set up logging +logger = logging.getLogger(__name__) + + +# ----- MUST fails tests + +# # TO BE CHECKED AGAIN +# def test_5src_check_value_not_of_type_assess_action(): +# sparql = """ +# PREFIX schema: +# PREFIX shp: +# PREFIX rdf: + +# DELETE { +# ?this rdf:type ?type . +# } +# INSERT { +# ?this rdf:type . +# } +# WHERE { +# ?this a schema:AssessAction ; +# schema:additionalType shp:CheckValue ; +# rdf:type ?type . +# } +# """ + +# do_entity_test( +# rocrate_path=ValidROC().five_safes_crate_result, +# requirement_severity=Severity.REQUIRED, +# expected_validation_result=False, +# expected_triggered_requirements=["CheckValue"], +# expected_triggered_issues=["CheckValue MUST be a `schema:AssessAction`."], +# profile_identifier="five-safes-crate", +# rocrate_entity_mod_sparql=sparql, +# ) + + +# def test_5src_check_value_name_not_a_string(): +# sparql = """ +# PREFIX schema: +# PREFIX shp: +# PREFIX rdf: + +# DELETE { +# ?this schema:name ?name . +# } +# INSERT { +# ?this schema:name 123 . +# } +# WHERE { +# ?this schema:additionalType shp:CheckValue . +# } +# """ + +# do_entity_test( +# rocrate_path=ValidROC().five_safes_crate_result, +# requirement_severity=Severity.REQUIRED, +# expected_validation_result=False, +# expected_triggered_requirements=["CheckValue"], +# expected_triggered_issues=["CheckValue MUST have a human readable name string of at least 20 characters."], +# profile_identifier="five-safes-crate", +# rocrate_entity_mod_sparql=sparql, +# ) + + +# def test_5src_check_value_name_not_long_enough(): +# sparql = """ +# PREFIX schema: +# PREFIX shp: +# PREFIX rdf: + +# DELETE { +# ?this schema:name ?name . +# } +# INSERT { +# ?this schema:name "Short" . +# } +# WHERE { +# ?this schema:additionalType shp:CheckValue . +# } +# """ + +# do_entity_test( +# rocrate_path=ValidROC().five_safes_crate_result, +# requirement_severity=Severity.REQUIRED, +# expected_validation_result=False, +# expected_triggered_requirements=["CheckValue"], +# expected_triggered_issues=["CheckValue MUST have a human readable name string of at least 20 characters."], +# profile_identifier="five-safes-crate", +# rocrate_entity_mod_sparql=sparql, +# ) + + +# def test_5src_check_value_start_time_not_iso_standard(): +# sparql = """ +# PREFIX schema: +# PREFIX shp: +# PREFIX rdf: + +# DELETE { +# ?c schema:startTime ?t . +# } +# INSERT { +# ?c schema:startTime "1st of Jan 2021" . +# } +# WHERE { +# ?c schema:additionalType shp:CheckValue ; +# schema:startTime ?t . +# } +# """ + +# do_entity_test( +# rocrate_path=ValidROC().five_safes_crate_result, +# requirement_severity=Severity.REQUIRED, +# expected_validation_result=False, +# expected_triggered_requirements=["CheckValue"], +# expected_triggered_issues=["`CheckValue` --> `startTime` MUST follows the RFC 3339 standard."], +# profile_identifier="five-safes-crate", +# rocrate_entity_mod_sparql=sparql, +# ) + + +# def test_5src_check_value_end_time_not_iso_standard(): +# sparql = """ +# PREFIX schema: +# PREFIX shp: +# PREFIX rdf: + +# DELETE { +# ?c schema:endTime ?t . +# } +# INSERT { +# ?c schema:endTime "1st of Jan 2021" . +# } +# WHERE { +# ?c schema:additionalType shp:CheckValue ; +# schema:endTime ?t . +# } +# """ + +# do_entity_test( +# rocrate_path=ValidROC().five_safes_crate_result, +# requirement_severity=Severity.REQUIRED, +# expected_validation_result=False, +# expected_triggered_requirements=["CheckValue"], +# expected_triggered_issues=["`CheckValue` --> `endTime` MUST follows the RFC 3339 standard."], +# profile_identifier="five-safes-crate", +# rocrate_entity_mod_sparql=sparql, +# ) + + +# def test_5src_check_value_has_action_status_with_not_allowed_value(): +# sparql = """ +# PREFIX schema: +# PREFIX shp: +# PREFIX rdf: + +# DELETE { +# ?s schema:actionStatus ?o . +# } +# INSERT { +# ?s schema:actionStatus "Not a good action status" . +# } +# WHERE { +# ?s schema:additionalType ; +# schema:actionStatus ?o . +# } +# """ + +# do_entity_test( +# rocrate_path=ValidROC().five_safes_crate_result, +# requirement_severity=Severity.REQUIRED, +# expected_validation_result=False, +# expected_triggered_requirements=["CheckValue"], +# expected_triggered_issues=["`CheckValue` --> `actionStatus` MUST have one of the allowed values."], +# profile_identifier="five-safes-crate", +# rocrate_entity_mod_sparql=sparql, +# ) + + +# # ----- SHOULD fails tests + +# def test_5src_root_data_entity_does_not_mention_check_value_entity(): +# sparql = """ +# PREFIX schema: +# PREFIX shp: + +# DELETE { +# <./> schema:mentions ?o . +# } +# WHERE { +# ?o schema:additionalType shp:CheckValue ; +# } +# """ + +# do_entity_test( +# rocrate_path=ValidROC().five_safes_crate_result, +# requirement_severity=Severity.RECOMMENDED, +# expected_validation_result=False, +# expected_triggered_requirements=["RootDataEntity"], +# expected_triggered_issues=["RootDataEntity SHOULD mention a check value object."], +# profile_identifier="five-safes-crate", +# rocrate_entity_mod_sparql=sparql, +# ) + + +# def test_5src_check_value_object_does_not_point_to_root_data_entity(): +# sparql = """ +# PREFIX schema: +# PREFIX shp: + +# DELETE { +# ?s schema:object <./> . +# } +# INSERT { +# ?s schema:object "not the RootDataEntity" . +# } +# WHERE { +# ?s schema:additionalType shp:CheckValue ; +# } +# """ + +# do_entity_test( +# rocrate_path=ValidROC().five_safes_crate_result, +# requirement_severity=Severity.RECOMMENDED, +# expected_validation_result=False, +# expected_triggered_requirements=["CheckValue"], +# expected_triggered_issues=["`CheckValue` --> `object` SHOULD point to the root of the RO-Crate"], +# profile_identifier="five-safes-crate", +# rocrate_entity_mod_sparql=sparql, +# ) + + +# def test_5src_check_value_instrument_does_not_point_to_entity_with_type_defined_term(): +# sparql = """ +# PREFIX schema: +# PREFIX shp: +# PREFIX rdf: + +# DELETE { +# ?s rdf:type schema:DefinedTerm . +# } +# INSERT { +# ?s rdf:type schema:Persona . +# } +# WHERE { +# ?cv schema:additionalType shp:CheckValue ; +# schema:instrument ?s . +# ?s rdf:type schema:DefinedTerm . +# } +# """ + +# do_entity_test( +# rocrate_path=ValidROC().five_safes_crate_result, +# requirement_severity=Severity.RECOMMENDED, +# expected_validation_result=False, +# expected_triggered_requirements=["CheckValue"], +# expected_triggered_issues=[ +# "`CheckValue` --> `instrument` SHOULD point to an entity typed `schema:DefinedTerm`" +# ], +# profile_identifier="five-safes-crate", +# rocrate_entity_mod_sparql=sparql, +# ) + + +# def test_5src_check_value_does_not_have_end_time(): +# sparql = """ +# PREFIX schema: +# PREFIX shp: +# PREFIX rdf: + +# DELETE { +# ?c schema:endTime ?t . +# } +# WHERE { +# ?c schema:additionalType shp:CheckValue ; +# schema:endTime ?t . +# } +# """ + +# do_entity_test( +# rocrate_path=ValidROC().five_safes_crate_result, +# requirement_severity=Severity.RECOMMENDED, +# expected_validation_result=False, +# expected_triggered_requirements=["CheckValue"], +# expected_triggered_issues=["`CheckValue` SHOULD have the `endTime` property."], +# profile_identifier="five-safes-crate", +# rocrate_entity_mod_sparql=sparql, +# ) + + +# def test_5src_check_value_does_not_have_action_status_property(): +# sparql = """ +# PREFIX schema: +# PREFIX shp: +# PREFIX rdf: + +# DELETE { +# ?s schema:actionStatus ?o . +# } +# WHERE { +# ?s schema:additionalType shp:CheckValue ; +# schema:actionStatus ?o . +# } +# """ + +# do_entity_test( +# rocrate_path=ValidROC().five_safes_crate_result, +# requirement_severity=Severity.RECOMMENDED, +# expected_validation_result=False, +# expected_triggered_requirements=["CheckValue"], +# expected_triggered_issues=["CheckValue SHOULD have actionStatus property."], +# profile_identifier="five-safes-crate", +# rocrate_entity_mod_sparql=sparql, +# ) + + +# def test_5src_check_value_does_not_point_to_an_agent(): +# sparql = """ +# PREFIX schema: +# PREFIX shp: +# PREFIX rdf: + +# DELETE { +# ?s schema:agent ?o . +# } +# WHERE { +# ?s schema:additionalType shp:CheckValue ; +# schema:agent ?o . +# } +# """ + +# do_entity_test( +# rocrate_path=ValidROC().five_safes_crate_result, +# requirement_severity=Severity.RECOMMENDED, +# expected_validation_result=False, +# expected_triggered_requirements=["CheckValue"], +# expected_triggered_issues=["`CheckValue` --> `agent` SHOULD reference the agent who initiated the check"], +# profile_identifier="five-safes-crate", +# rocrate_entity_mod_sparql=sparql, +# ) + + +# # ----- MAY fails tests + +# def test_5src_check_value_does_not_have_start_time(): +# sparql = """ +# PREFIX schema: +# PREFIX shp: +# PREFIX rdf: + +# DELETE { +# ?c schema:startTime ?t . +# } +# WHERE { +# ?c schema:additionalType shp:CheckValue ; +# schema:startTime ?t . +# } +# """ + +# do_entity_test( +# rocrate_path=ValidROC().five_safes_crate_result, +# requirement_severity=Severity.OPTIONAL, +# expected_validation_result=False, +# expected_triggered_requirements=["CheckValue"], +# expected_triggered_issues=["`CheckValue` MAY have the `startTime` property."], +# profile_identifier="five-safes-crate", +# rocrate_entity_mod_sparql=sparql, +# ) From eac2fcf2af91a74de43c3bb255f8e85b2a290df8 Mon Sep 17 00:00:00 2001 From: EttoreM Date: Mon, 8 Dec 2025 15:27:20 +0000 Subject: [PATCH 02/11] Added tests. --- .../must/14_workflow_retrieval_phase.ttl | 23 +- .../test_5src_14_workflow_retrieval_phase.py | 622 ++++++++---------- 2 files changed, 264 insertions(+), 381 deletions(-) diff --git a/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl index 6abc97ae..be2646d6 100644 --- a/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl @@ -64,9 +64,9 @@ five-safes-crate:DownloadActionStartTimeMustFollowISOStandard a sh:PropertyShape ; sh:name "StartTime" ; sh:path schema:startTime ; - sh:pattern "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(Z|[+-][0-9]{2}:[0-9]{2})$" ; + 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:Violation ; - sh:message "`DownloadAction` --> `startTime` MUST follows the RFC 3339 standard." ; + sh:message "`DownloadAction` --> `startTime` MUST follows the RFC 3339 standard (YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." ; ] . @@ -74,27 +74,16 @@ five-safes-crate:DownloadActionEndTimeMustFollowISOStandard a sh:NodeShape ; sh:name "DownloadAction" ; sh:description "" ; - sh:target [ - a sh:SPARQLTarget ; - sh:select """ - PREFIX schema: - PREFIX rdf: - - SELECT ?this - WHERE { - ?this rdf:type schema:DownloadAction ; - schema:endTime ?o . - } - """ ; - ] ; + sh:targetClass schema:DownloadAction ; sh:property [ a sh:PropertyShape ; sh:name "EndTime" ; + sh:minCount 0; sh:path schema:endTime ; - sh:pattern "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(Z|[+-][0-9]{2}:[0-9]{2})$" ; + 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:Violation ; - sh:message "`DownloadAction` --> `endTime` MUST follows the RFC 3339 standard." ; + sh:message "`DownloadAction` --> `endTime` MUST follows the RFC 3339 standard (YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." ; ] . diff --git a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py index 1a4968e7..4706b86d 100644 --- a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py +++ b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py @@ -16,7 +16,7 @@ from rocrate_validator.models import Severity from tests.ro_crates import ValidROC -from tests.shared import do_entity_test +from tests.shared import do_entity_test, SPARQL_PREFIXES # set up logging logger = logging.getLogger(__name__) @@ -24,366 +24,260 @@ # ----- MUST fails tests -# # TO BE CHECKED AGAIN -# def test_5src_check_value_not_of_type_assess_action(): -# sparql = """ -# PREFIX schema: -# PREFIX shp: -# PREFIX rdf: - -# DELETE { -# ?this rdf:type ?type . -# } -# INSERT { -# ?this rdf:type . -# } -# WHERE { -# ?this a schema:AssessAction ; -# schema:additionalType shp:CheckValue ; -# rdf:type ?type . -# } -# """ - -# do_entity_test( -# rocrate_path=ValidROC().five_safes_crate_result, -# requirement_severity=Severity.REQUIRED, -# expected_validation_result=False, -# expected_triggered_requirements=["CheckValue"], -# expected_triggered_issues=["CheckValue MUST be a `schema:AssessAction`."], -# profile_identifier="five-safes-crate", -# rocrate_entity_mod_sparql=sparql, -# ) - - -# def test_5src_check_value_name_not_a_string(): -# sparql = """ -# PREFIX schema: -# PREFIX shp: -# PREFIX rdf: - -# DELETE { -# ?this schema:name ?name . -# } -# INSERT { -# ?this schema:name 123 . -# } -# WHERE { -# ?this schema:additionalType shp:CheckValue . -# } -# """ - -# do_entity_test( -# rocrate_path=ValidROC().five_safes_crate_result, -# requirement_severity=Severity.REQUIRED, -# expected_validation_result=False, -# expected_triggered_requirements=["CheckValue"], -# expected_triggered_issues=["CheckValue MUST have a human readable name string of at least 20 characters."], -# profile_identifier="five-safes-crate", -# rocrate_entity_mod_sparql=sparql, -# ) - - -# def test_5src_check_value_name_not_long_enough(): -# sparql = """ -# PREFIX schema: -# PREFIX shp: -# PREFIX rdf: - -# DELETE { -# ?this schema:name ?name . -# } -# INSERT { -# ?this schema:name "Short" . -# } -# WHERE { -# ?this schema:additionalType shp:CheckValue . -# } -# """ - -# do_entity_test( -# rocrate_path=ValidROC().five_safes_crate_result, -# requirement_severity=Severity.REQUIRED, -# expected_validation_result=False, -# expected_triggered_requirements=["CheckValue"], -# expected_triggered_issues=["CheckValue MUST have a human readable name string of at least 20 characters."], -# profile_identifier="five-safes-crate", -# rocrate_entity_mod_sparql=sparql, -# ) - - -# def test_5src_check_value_start_time_not_iso_standard(): -# sparql = """ -# PREFIX schema: -# PREFIX shp: -# PREFIX rdf: - -# DELETE { -# ?c schema:startTime ?t . -# } -# INSERT { -# ?c schema:startTime "1st of Jan 2021" . -# } -# WHERE { -# ?c schema:additionalType shp:CheckValue ; -# schema:startTime ?t . -# } -# """ - -# do_entity_test( -# rocrate_path=ValidROC().five_safes_crate_result, -# requirement_severity=Severity.REQUIRED, -# expected_validation_result=False, -# expected_triggered_requirements=["CheckValue"], -# expected_triggered_issues=["`CheckValue` --> `startTime` MUST follows the RFC 3339 standard."], -# profile_identifier="five-safes-crate", -# rocrate_entity_mod_sparql=sparql, -# ) - - -# def test_5src_check_value_end_time_not_iso_standard(): -# sparql = """ -# PREFIX schema: -# PREFIX shp: -# PREFIX rdf: - -# DELETE { -# ?c schema:endTime ?t . -# } -# INSERT { -# ?c schema:endTime "1st of Jan 2021" . -# } -# WHERE { -# ?c schema:additionalType shp:CheckValue ; -# schema:endTime ?t . -# } -# """ - -# do_entity_test( -# rocrate_path=ValidROC().five_safes_crate_result, -# requirement_severity=Severity.REQUIRED, -# expected_validation_result=False, -# expected_triggered_requirements=["CheckValue"], -# expected_triggered_issues=["`CheckValue` --> `endTime` MUST follows the RFC 3339 standard."], -# profile_identifier="five-safes-crate", -# rocrate_entity_mod_sparql=sparql, -# ) - - -# def test_5src_check_value_has_action_status_with_not_allowed_value(): -# sparql = """ -# PREFIX schema: -# PREFIX shp: -# PREFIX rdf: - -# DELETE { -# ?s schema:actionStatus ?o . -# } -# INSERT { -# ?s schema:actionStatus "Not a good action status" . -# } -# WHERE { -# ?s schema:additionalType ; -# schema:actionStatus ?o . -# } -# """ - -# do_entity_test( -# rocrate_path=ValidROC().five_safes_crate_result, -# requirement_severity=Severity.REQUIRED, -# expected_validation_result=False, -# expected_triggered_requirements=["CheckValue"], -# expected_triggered_issues=["`CheckValue` --> `actionStatus` MUST have one of the allowed values."], -# profile_identifier="five-safes-crate", -# rocrate_entity_mod_sparql=sparql, -# ) - - -# # ----- SHOULD fails tests - -# def test_5src_root_data_entity_does_not_mention_check_value_entity(): -# sparql = """ -# PREFIX schema: -# PREFIX shp: - -# DELETE { -# <./> schema:mentions ?o . -# } -# WHERE { -# ?o schema:additionalType shp:CheckValue ; -# } -# """ - -# do_entity_test( -# rocrate_path=ValidROC().five_safes_crate_result, -# requirement_severity=Severity.RECOMMENDED, -# expected_validation_result=False, -# expected_triggered_requirements=["RootDataEntity"], -# expected_triggered_issues=["RootDataEntity SHOULD mention a check value object."], -# profile_identifier="five-safes-crate", -# rocrate_entity_mod_sparql=sparql, -# ) - - -# def test_5src_check_value_object_does_not_point_to_root_data_entity(): -# sparql = """ -# PREFIX schema: -# PREFIX shp: - -# DELETE { -# ?s schema:object <./> . -# } -# INSERT { -# ?s schema:object "not the RootDataEntity" . -# } -# WHERE { -# ?s schema:additionalType shp:CheckValue ; -# } -# """ - -# do_entity_test( -# rocrate_path=ValidROC().five_safes_crate_result, -# requirement_severity=Severity.RECOMMENDED, -# expected_validation_result=False, -# expected_triggered_requirements=["CheckValue"], -# expected_triggered_issues=["`CheckValue` --> `object` SHOULD point to the root of the RO-Crate"], -# profile_identifier="five-safes-crate", -# rocrate_entity_mod_sparql=sparql, -# ) - - -# def test_5src_check_value_instrument_does_not_point_to_entity_with_type_defined_term(): -# sparql = """ -# PREFIX schema: -# PREFIX shp: -# PREFIX rdf: - -# DELETE { -# ?s rdf:type schema:DefinedTerm . -# } -# INSERT { -# ?s rdf:type schema:Persona . -# } -# WHERE { -# ?cv schema:additionalType shp:CheckValue ; -# schema:instrument ?s . -# ?s rdf:type schema:DefinedTerm . -# } -# """ - -# do_entity_test( -# rocrate_path=ValidROC().five_safes_crate_result, -# requirement_severity=Severity.RECOMMENDED, -# expected_validation_result=False, -# expected_triggered_requirements=["CheckValue"], -# expected_triggered_issues=[ -# "`CheckValue` --> `instrument` SHOULD point to an entity typed `schema:DefinedTerm`" -# ], -# profile_identifier="five-safes-crate", -# rocrate_entity_mod_sparql=sparql, -# ) - - -# def test_5src_check_value_does_not_have_end_time(): -# sparql = """ -# PREFIX schema: -# PREFIX shp: -# PREFIX rdf: - -# DELETE { -# ?c schema:endTime ?t . -# } -# WHERE { -# ?c schema:additionalType shp:CheckValue ; -# schema:endTime ?t . -# } -# """ - -# do_entity_test( -# rocrate_path=ValidROC().five_safes_crate_result, -# requirement_severity=Severity.RECOMMENDED, -# expected_validation_result=False, -# expected_triggered_requirements=["CheckValue"], -# expected_triggered_issues=["`CheckValue` SHOULD have the `endTime` property."], -# profile_identifier="five-safes-crate", -# rocrate_entity_mod_sparql=sparql, -# ) - - -# def test_5src_check_value_does_not_have_action_status_property(): -# sparql = """ -# PREFIX schema: -# PREFIX shp: -# PREFIX rdf: - -# DELETE { -# ?s schema:actionStatus ?o . -# } -# WHERE { -# ?s schema:additionalType shp:CheckValue ; -# schema:actionStatus ?o . -# } -# """ - -# do_entity_test( -# rocrate_path=ValidROC().five_safes_crate_result, -# requirement_severity=Severity.RECOMMENDED, -# expected_validation_result=False, -# expected_triggered_requirements=["CheckValue"], -# expected_triggered_issues=["CheckValue SHOULD have actionStatus property."], -# profile_identifier="five-safes-crate", -# rocrate_entity_mod_sparql=sparql, -# ) - - -# def test_5src_check_value_does_not_point_to_an_agent(): -# sparql = """ -# PREFIX schema: -# PREFIX shp: -# PREFIX rdf: - -# DELETE { -# ?s schema:agent ?o . -# } -# WHERE { -# ?s schema:additionalType shp:CheckValue ; -# schema:agent ?o . -# } -# """ - -# do_entity_test( -# rocrate_path=ValidROC().five_safes_crate_result, -# requirement_severity=Severity.RECOMMENDED, -# expected_validation_result=False, -# expected_triggered_requirements=["CheckValue"], -# expected_triggered_issues=["`CheckValue` --> `agent` SHOULD reference the agent who initiated the check"], -# profile_identifier="five-safes-crate", -# rocrate_entity_mod_sparql=sparql, -# ) - - -# # ----- MAY fails tests - -# def test_5src_check_value_does_not_have_start_time(): -# sparql = """ -# PREFIX schema: -# PREFIX shp: -# PREFIX rdf: - -# DELETE { -# ?c schema:startTime ?t . -# } -# WHERE { -# ?c schema:additionalType shp:CheckValue ; -# schema:startTime ?t . -# } -# """ - -# do_entity_test( -# rocrate_path=ValidROC().five_safes_crate_result, -# requirement_severity=Severity.OPTIONAL, -# expected_validation_result=False, -# expected_triggered_requirements=["CheckValue"], -# expected_triggered_issues=["`CheckValue` MAY have the `startTime` property."], -# profile_identifier="five-safes-crate", -# rocrate_entity_mod_sparql=sparql, -# ) +def test_5src_download_action_does_not_have_name(): + sparql = (SPARQL_PREFIXES + """ + DELETE { + ?this schema:name ?name . + } + WHERE { + ?this schema:name ?name ; + rdf:type schema:DownloadAction . + } + """) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.REQUIRED, + expected_validation_result=False, + expected_triggered_requirements=["DownloadAction"], + expected_triggered_issues=[ + "DownloadAction MUST have a human readable name string of at least 10 characters." + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_download_action_name_not_a_string(): + sparql = (SPARQL_PREFIXES + """ + DELETE { + ?this schema:name ?name . + } + INSERT { + ?this schema:name 123 . + } + WHERE { + ?this rdf:type schema:DownloadAction . + } + """) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.REQUIRED, + expected_validation_result=False, + expected_triggered_requirements=["DownloadAction"], + expected_triggered_issues=[ + "DownloadAction MUST have a human readable name string of at least 10 characters." + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_download_action_name_not_long_enough(): + sparql = (SPARQL_PREFIXES + """ + DELETE { + ?this schema:name ?name . + } + INSERT { + ?this schema:name "Short" . + } + WHERE { + ?this rdf:type schema:DownloadAction . + } + """) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.REQUIRED, + expected_validation_result=False, + expected_triggered_requirements=["DownloadAction"], + expected_triggered_issues=[ + "DownloadAction MUST have a human readable name string of at least 10 characters." + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_download_action_start_time_not_iso_standard(): + sparql = (SPARQL_PREFIXES + """ + DELETE { + ?c schema:startTime ?t . + } + INSERT { + ?c schema:startTime "1st of Jan 2021" . + } + WHERE { + ?c rdf:type schema:DownloadAction ; + schema:startTime ?t . + } + """) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.REQUIRED, + expected_validation_result=False, + expected_triggered_requirements=["DownloadAction"], + expected_triggered_issues= [( + "`DownloadAction` --> `startTime` MUST follows the RFC 3339 standard " + "(YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." + )], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_check_value_end_time_not_iso_standard(): + sparql = (SPARQL_PREFIXES + """ + DELETE { + ?c schema:endTime ?t . + } + INSERT { + ?c schema:endTime "1st of Jan 2021" . + } + WHERE { + ?c rdf:type schema:DownloadAction ; + schema:endTime ?t . + } + """) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.REQUIRED, + expected_validation_result=False, + expected_triggered_requirements=["DownloadAction"], + expected_triggered_issues=[( + "`DownloadAction` --> `endTime` MUST follows the RFC 3339 standard " + "(YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." + )], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_download_action_has_action_status_with_not_allowed_value(): + sparql = (SPARQL_PREFIXES + """ + DELETE { + ?s schema:actionStatus ?o . + } + INSERT { + ?s schema:actionStatus "Not a good action status" . + } + WHERE { + ?s rdf:type schema:DownloadAction ; + schema:actionStatus ?o . + } + """) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.REQUIRED, + expected_validation_result=False, + expected_triggered_requirements=["DownloadAction"], + expected_triggered_issues=[( + "`DownloadAction` --> `actionStatus` MUST have one of the allowed values " + "(see https://schema.org/ActionStatusType)." + )], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +# ----- SHOULD fails tests + +def test_5src_root_data_entity_does_not_mention_download_action_entity(): + sparql = (SPARQL_PREFIXES + """ + DELETE { + <./> schema:mentions ?o . + } + WHERE { + ?o rdf:type schema:DownloadAction ; + } + """) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["RootDataEntity"], + expected_triggered_issues=[ + "RootDataEntity SHOULD mention the DownloadAction object." + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_download_action_does_not_have_end_time(): + sparql = (SPARQL_PREFIXES + """ + DELETE { + ?c schema:endTime ?t . + } + WHERE { + ?c rdf:type schema:DownloadAction ; + schema:endTime ?t . + } + """) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["DownloadAction"], + expected_triggered_issues=[ + "`DownloadAction` SHOULD have the `endTime` property if it has ended." + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_download_action_does_not_have_action_status_property(): + sparql = (SPARQL_PREFIXES + """ + DELETE { + ?s schema:actionStatus ?o . + } + WHERE { + ?s rdf:type schema:DownloadAction ; + schema:actionStatus ?o . + } + """) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["DownloadAction"], + expected_triggered_issues=[ + "`DownloadAction` SHOULD have `actionStatus` property." + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +# ----- MAY fails tests + +def test_5src_download_action_does_not_have_start_time(): + sparql = (SPARQL_PREFIXES + """ + DELETE { + ?c schema:startTime ?t . + } + WHERE { + ?c rdf:type schema:DownloadAction ; + schema:startTime ?t . + } + """) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.OPTIONAL, + expected_validation_result=False, + expected_triggered_requirements=["DownloadAction"], + expected_triggered_issues=[ + "`DownloadAction` MAY have the `startTime` property if it has begun." + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) From 3fd348e77765d1ca844ab73389b81c02168aafe0 Mon Sep 17 00:00:00 2001 From: EttoreM Date: Mon, 8 Dec 2025 15:49:00 +0000 Subject: [PATCH 03/11] Removed lint error. --- .../five-safes-crate/test_5src_14_workflow_retrieval_phase.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py index 4706b86d..fb1520a8 100644 --- a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py +++ b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py @@ -119,7 +119,7 @@ def test_5src_download_action_start_time_not_iso_standard(): requirement_severity=Severity.REQUIRED, expected_validation_result=False, expected_triggered_requirements=["DownloadAction"], - expected_triggered_issues= [( + expected_triggered_issues=[( "`DownloadAction` --> `startTime` MUST follows the RFC 3339 standard " "(YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." )], From 6ef4c67ead81452c070769d0e0ed9a3fa035ea7a Mon Sep 17 00:00:00 2001 From: EttoreM Date: Tue, 9 Dec 2025 12:12:35 +0000 Subject: [PATCH 04/11] Addressed (most) of Doug's comment on the PR. --- .../may/14_workflow_retrieval_phase.ttl | 4 +- .../must/14_workflow_retrieval_phase.ttl | 2 +- .../should/14_workflow_retrieval_phase.ttl | 83 +------------ .../test_5src_14_workflow_retrieval_phase.py | 115 ++++++++++++------ 4 files changed, 83 insertions(+), 121 deletions(-) diff --git a/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl index ab9057c1..bd918479 100644 --- a/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl @@ -23,7 +23,7 @@ @prefix xsd: . -five-safes-crate:CheckValueMayHaveStartTimeIfBegun +five-safes-crate:DownloadActionMayHaveStartTimeIfBegun a sh:NodeShape ; sh:name "DownloadAction" ; sh:description "" ; @@ -52,5 +52,5 @@ five-safes-crate:CheckValueMayHaveStartTimeIfBegun sh:minCount 1 ; sh:maxCount 1 ; sh:severity sh:Info ; - sh:message "`DownloadAction` MAY have the `startTime` property if it has begun." ; + sh:message "`DownloadAction` SHOULD have the `endTime` property if `actionStatus` is either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." ; ] . diff --git a/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl index be2646d6..f67b0280 100644 --- a/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl @@ -117,5 +117,5 @@ five-safes-crate:CheckValueActionStatusMustHaveAllowedValues "http://schema.org/FailedActionStatus" ) ; sh:severity sh:Violation ; - sh:message "`DownloadAction` --> `actionStatus` MUST have one of the allowed values (see https://schema.org/ActionStatusType)." ; + 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/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl index f692d883..e310adb5 100644 --- a/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl @@ -49,87 +49,6 @@ five-safes-crate:RootDataEntityShouldMentionDownloadActionObjectIfItExists ] . -# five-safes-crate:CheckValueObjectShouldPointToRootDataEntity -# a sh:NodeShape ; -# sh:name "CheckValue" ; -# sh:description "" ; -# sh:target [ -# a sh:SPARQLTarget ; -# sh:select """ -# PREFIX schema: -# PREFIX shp: -# SELECT ?this -# WHERE { -# ?this schema:additionalType shp:CheckValue . -# } -# """ ; -# ] ; - -# sh:property [ -# a sh:PropertyShape ; -# sh:name "object" ; -# sh:path schema:object ; -# sh:minCount 1 ; -# sh:hasValue <./> ; -# sh:severity sh:Warning ; -# sh:message "`CheckValue` --> `object` SHOULD point to the root of the RO-Crate" ; -# ] . - - -# five-safes-crate:CheckValueInstrumentShouldPointToEntityTypedDefinedTerm -# a sh:NodeShape ; -# sh:name "CheckValue" ; -# sh:description "" ; -# sh:target [ -# a sh:SPARQLTarget ; -# sh:select """ -# PREFIX schema: -# PREFIX shp: -# SELECT ?this -# WHERE { -# ?this schema:additionalType shp:CheckValue . -# } -# """ ; -# ] ; - -# sh:property [ -# a sh:PropertyShape ; -# sh:name "instrument" ; -# sh:path schema:instrument ; -# sh:minCount 1 ; -# sh:class schema:DefinedTerm ; -# sh:severity sh:Warning ; -# sh:message "`CheckValue` --> `instrument` SHOULD point to an entity typed `schema:DefinedTerm`" ; -# ] . - - -# five-safes-crate:CheckValueAgentShouldIdentifyTheAgentWhoPerformnedTheCheck -# a sh:NodeShape ; -# sh:name "CheckValue" ; -# sh:description "" ; -# sh:target [ -# a sh:SPARQLTarget ; -# sh:select """ -# PREFIX schema: -# PREFIX shp: -# SELECT ?this -# WHERE { -# ?this schema:additionalType shp:CheckValue . -# } -# """ ; -# ] ; - -# sh:property [ -# a sh:PropertyShape ; -# sh:name "agent" ; -# sh:path schema:agent ; -# sh:minCount 1 ; -# sh:nodeKind sh:IRI ; -# sh:severity sh:Warning ; -# sh:message "`CheckValue` --> `agent` SHOULD reference the agent who initiated the check" ; -# ] . - - five-safes-crate:DownloadActionShouldHaveEndTimeIfEnded a sh:NodeShape ; sh:name "DownloadAction" ; @@ -159,7 +78,7 @@ five-safes-crate:DownloadActionShouldHaveEndTimeIfEnded sh:minCount 1 ; sh:maxCount 1 ; sh:severity sh:Warning ; - sh:message "`DownloadAction` SHOULD have the `endTime` property if it has ended." ; + sh:message "`DownloadAction` SHOULD have the `endTime` property if `actionStatus` is either CompletedActionStatus or FailedActionStatus." ; ] . diff --git a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py index fb1520a8..083771cd 100644 --- a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py +++ b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py @@ -24,8 +24,11 @@ # ----- MUST fails tests + def test_5src_download_action_does_not_have_name(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?this schema:name ?name . } @@ -33,7 +36,8 @@ def test_5src_download_action_does_not_have_name(): ?this schema:name ?name ; rdf:type schema:DownloadAction . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, @@ -42,14 +46,16 @@ def test_5src_download_action_does_not_have_name(): expected_triggered_requirements=["DownloadAction"], expected_triggered_issues=[ "DownloadAction MUST have a human readable name string of at least 10 characters." - ], + ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, ) def test_5src_download_action_name_not_a_string(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?this schema:name ?name . } @@ -59,7 +65,8 @@ def test_5src_download_action_name_not_a_string(): WHERE { ?this rdf:type schema:DownloadAction . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, @@ -68,14 +75,16 @@ def test_5src_download_action_name_not_a_string(): expected_triggered_requirements=["DownloadAction"], expected_triggered_issues=[ "DownloadAction MUST have a human readable name string of at least 10 characters." - ], + ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, ) def test_5src_download_action_name_not_long_enough(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?this schema:name ?name . } @@ -85,7 +94,8 @@ def test_5src_download_action_name_not_long_enough(): WHERE { ?this rdf:type schema:DownloadAction . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, @@ -101,7 +111,9 @@ def test_5src_download_action_name_not_long_enough(): def test_5src_download_action_start_time_not_iso_standard(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?c schema:startTime ?t . } @@ -112,24 +124,29 @@ def test_5src_download_action_start_time_not_iso_standard(): ?c rdf:type schema:DownloadAction ; schema:startTime ?t . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, requirement_severity=Severity.REQUIRED, expected_validation_result=False, expected_triggered_requirements=["DownloadAction"], - expected_triggered_issues=[( - "`DownloadAction` --> `startTime` MUST follows the RFC 3339 standard " - "(YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." - )], + expected_triggered_issues=[ + ( + "`DownloadAction` --> `startTime` MUST follows the RFC 3339 standard " + "(YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." + ) + ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, ) def test_5src_check_value_end_time_not_iso_standard(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?c schema:endTime ?t . } @@ -140,24 +157,29 @@ def test_5src_check_value_end_time_not_iso_standard(): ?c rdf:type schema:DownloadAction ; schema:endTime ?t . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, requirement_severity=Severity.REQUIRED, expected_validation_result=False, expected_triggered_requirements=["DownloadAction"], - expected_triggered_issues=[( - "`DownloadAction` --> `endTime` MUST follows the RFC 3339 standard " - "(YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." - )], + expected_triggered_issues=[ + ( + "`DownloadAction` --> `endTime` MUST follows the RFC 3339 standard " + "(YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." + ) + ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, ) def test_5src_download_action_has_action_status_with_not_allowed_value(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?s schema:actionStatus ?o . } @@ -168,17 +190,20 @@ def test_5src_download_action_has_action_status_with_not_allowed_value(): ?s rdf:type schema:DownloadAction ; schema:actionStatus ?o . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, requirement_severity=Severity.REQUIRED, expected_validation_result=False, expected_triggered_requirements=["DownloadAction"], - expected_triggered_issues=[( - "`DownloadAction` --> `actionStatus` MUST have one of the allowed values " - "(see https://schema.org/ActionStatusType)." - )], + 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, ) @@ -186,15 +211,19 @@ def test_5src_download_action_has_action_status_with_not_allowed_value(): # ----- SHOULD fails tests + def test_5src_root_data_entity_does_not_mention_download_action_entity(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { <./> schema:mentions ?o . } WHERE { ?o rdf:type schema:DownloadAction ; } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, @@ -210,7 +239,9 @@ def test_5src_root_data_entity_does_not_mention_download_action_entity(): def test_5src_download_action_does_not_have_end_time(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?c schema:endTime ?t . } @@ -218,7 +249,8 @@ def test_5src_download_action_does_not_have_end_time(): ?c rdf:type schema:DownloadAction ; schema:endTime ?t . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, @@ -226,7 +258,10 @@ def test_5src_download_action_does_not_have_end_time(): expected_validation_result=False, expected_triggered_requirements=["DownloadAction"], expected_triggered_issues=[ - "`DownloadAction` SHOULD have the `endTime` property if it has ended." + ( + "`DownloadAction` SHOULD have the `endTime` property " + "if `actionStatus` is either CompletedActionStatus or FailedActionStatus." + ) ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, @@ -234,7 +269,9 @@ def test_5src_download_action_does_not_have_end_time(): def test_5src_download_action_does_not_have_action_status_property(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?s schema:actionStatus ?o . } @@ -242,7 +279,8 @@ def test_5src_download_action_does_not_have_action_status_property(): ?s rdf:type schema:DownloadAction ; schema:actionStatus ?o . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, @@ -259,8 +297,11 @@ def test_5src_download_action_does_not_have_action_status_property(): # ----- MAY fails tests + def test_5src_download_action_does_not_have_start_time(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?c schema:startTime ?t . } @@ -268,7 +309,8 @@ def test_5src_download_action_does_not_have_start_time(): ?c rdf:type schema:DownloadAction ; schema:startTime ?t . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, @@ -276,7 +318,8 @@ def test_5src_download_action_does_not_have_start_time(): expected_validation_result=False, expected_triggered_requirements=["DownloadAction"], expected_triggered_issues=[ - "`DownloadAction` MAY have the `startTime` property if it has begun." + "`DownloadAction` SHOULD have the `endTime` property " + "if `actionStatus` is either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, From 7e08f91a3089b1fdbf3d90a04b559c0f07cdb8e9 Mon Sep 17 00:00:00 2001 From: EttoreM Date: Wed, 10 Dec 2025 08:30:24 +0000 Subject: [PATCH 05/11] Allowed for comma to separate seconds from fractions of seconds in timestamps. --- .../five-safes-crate/must/14_workflow_retrieval_phase.ttl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl index f67b0280..1315d276 100644 --- a/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl @@ -64,7 +64,7 @@ five-safes-crate:DownloadActionStartTimeMustFollowISOStandard a sh:PropertyShape ; sh:name "StartTime" ; sh:path schema:startTime ; - 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: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:Violation ; sh:message "`DownloadAction` --> `startTime` MUST follows the RFC 3339 standard (YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." ; ] . @@ -81,7 +81,7 @@ five-safes-crate:DownloadActionEndTimeMustFollowISOStandard sh:name "EndTime" ; sh:minCount 0; sh:path schema:endTime ; - 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: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:Violation ; sh:message "`DownloadAction` --> `endTime` MUST follows the RFC 3339 standard (YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." ; ] . From 69584f0ef437558343754801b675cf9ddb514733 Mon Sep 17 00:00:00 2001 From: EttoreM Date: Thu, 18 Dec 2025 10:55:09 +0000 Subject: [PATCH 06/11] (i) Added extra SHACL shapes. (ii) Changed violation severity of existing SHACL shapes based on redefined rules in excel file. (iii) Added tests to validate SHACL shapes. --- "qq\033OA" | 164 +++++++++++++++ .../may/14_workflow_retrieval_phase.ttl | 2 +- .../must/14_workflow_retrieval_phase.ttl | 103 +++++++-- .../should/14_workflow_retrieval_phase.ttl | 80 ++++++- .../ro-crate-metadata.json | 2 +- .../test_5src_14_workflow_retrieval_phase.py | 197 +++++++++++++++++- 6 files changed, 517 insertions(+), 31 deletions(-) create mode 100644 "qq\033OA" diff --git "a/qq\033OA" "b/qq\033OA" new file mode 100644 index 00000000..f89407e2 --- /dev/null +++ "b/qq\033OA" @@ -0,0 +1,164 @@ +    + The following requirements have not meet:    + + [profile: Five Safes RO-Crate 0.4] + [ five-safes-crate-0.4_5 ]: Downloaded Workflow   + + Profile Requirement Downloaded Workflow + +  Failed checks    +    + [ five-safes-crate-0.4_5.0 ] Downloaded Workflow:   +  Detected issues    + - [Violation"file:///home/ettore/Work/rocrate-validator/tests/data/crates/valid/five-safes-crate-result/workflow/289/" on <./workflow/289/>]: DownloadedWorkflow --> `distribution` MUST be  + referesed by `DownloadAction` --> `object`. + + + + [profile: RO-Crate Metadata Specification 1.1] + [ ro-crate-1.1_22 ]: RO-Crate Root Data Entity RECOMMENDED properties   + + The Root Data Entity SHOULD have the properties name, description and license defined as described in the RO-Crate specification https://www.researchobject.org/ro-crate/1.1/root-data-entity.html + +  Failed checks    +    + [ ro-crate-1.1_22.1 ] Root Data Entity: `licence` SHOULD link to a Contextual Entity:   + Check if the Root Data Entity includes a license property that links to a Contextual Entity with type schema_org:CreativeWork to describe the license. +  Detected issues    + - [Violation of http://schema.org/license="http://spdx.org/licenses/CC-BY-4.0" on <./>]: The Root Data Entity SHOULD have a link to a Contextual Entity representing the schema_org:license + type + + + [ ro-crate-1.1_22.2 ] Root Data Entity: `author` property:   + Check if the Root Data Entity includes a author property (as specified by schema.org) to provide information about its author. +  Detected issues    + - [Violation on <./>]: The Root Data Entity SHOULD have a link to a Contextual Entity representing the `author` of the RO-Crate + + + + [profile: RO-Crate Metadata Specification 1.1] + [ ro-crate-1.1_25 ]: Directory Data Entity: RECOMMENDED value restriction   + + A Directory Data Entity SHOULD end with / + +  Failed checks    +    + [ ro-crate-1.1_25.1 ] Directory Data Entity: RECOMMENDED value restriction:   + Check if the Directory Data Entity ends with / +  Detected issues    + - [Violation of na464348be5bf4fa48130a7e5297e81c6b7="https://workflowhub.eu/workflows/289?version=1" on <https://github.com/crs4/rocrate-validator/profiles/ro-crate/Directory>]: Every Data + Entity Directory URI SHOULD end with `/` + + + + [profile: RO-Crate Metadata Specification 1.1] + [ ro-crate-1.1_26 ]: File Data Entity: RECOMMENDED properties   + + A File Data Entity SHOULD have detailed descriptions encodings through the encodingFormat property + +  Failed checks    +    + [ ro-crate-1.1_26.1 ] File Data Entity: RECOMMENDED `encodingFormat` property:   + Check if the File Data Entity has a detailed description of encodings through the encodingFormat property. The encodingFormat property SHOULD be a PRONOM identifier (e.g., + application/pdf) or, to add more detail, SHOULD be linked using a PRONOM to a Contextual Entity of type WebSite (see Adding detailed descriptions of encodings). +  Detected issues    + - [Violation on <./input1.txt>]: Missing or invalid `encodingFormat` linked to the `File Data Entity` + + + + [profile: RO-Crate Metadata Specification 1.1] + [ ro-crate-1.1_27 ]: Web-based Data Entity: RECOMMENDED resource availability   + + Web-based Data Entity instances SHOULD be available at the URIs specified in the @id property of the Web-based Data Entity. + +  Failed checks    +    + [ ro-crate-1.1_27.1 ] Web-based Data Entity: resource availability:   + Check if the Web-based Data Entity is directly downloadable by a simple retrieval (e.g. HTTP GET) permitting redirection and HTTP/HTTPS URIs +  Detected issues    + - [Violation]: Web-based Data Entity https://workflowhub.eu/workflows/289?version=1 is not available + + + + [profile: RO-Crate Metadata Specification 1.1] + [ ro-crate-1.1_30 ]: Organization: RECOMMENDED properties   + + The recommended properties for an Organization are name and url. + +  Failed checks    +    + [ ro-crate-1.1_30.2 ] Organization: RECOMMENDED url property:   + Check if the organization has a URL. +  Detected issues    + - [Violation on <https://ror.org/027m9bs27>]: The organization SHOULD have a URL. + - [Violation on <https://ror.org/01ee9ar58>]: The organization SHOULD have a URL. + - [Violation on <https://tre72.example.com/>]: The organization SHOULD have a URL. + + + + [profile: RO-Crate Metadata Specification 1.1] + [ ro-crate-1.1_31 ]: Directory Data Entity: OPTIONAL `distribution` property   + + A Directory Data Entity MAY have a distribution property to denote the distribution of the files within the directory + +  Failed checks    +    + [ ro-crate-1.1_31.1 ] Directory Data Entity: optional `distribution` property:   + Check if the Directory Data Entity has a distribution property +  Detected issues    + - [Violation on <./input1.txt>]: The Directory Data Entity MAY have a `distribution` property to denote the distribution of the files within the directory + - [Violation on <./outputs/qa.csv>]: The Directory Data Entity MAY have a `distribution` property to denote the distribution of the files within the directory + + + + [profile: RO-Crate Metadata Specification 1.1] + [ ro-crate-1.1_32 ]: File Data Entity with web presence: OPTIONAL properties   + + A File Data Entity which have a corresponding web presence, for instance a landing page that describes the file, including persistence identifiers (e.g. DOI), resolving to an intermediate HTML page + instead of the downloadable file directly. These can included for File Data Entities as additional metadata by using the properties: ìdentifier, url, subjectOfand mainEntityOfPage + +  Failed checks    +    + [ ro-crate-1.1_32.1 ] File Data Entity: optional formal `identifier` (e.g. DOI):   + Check if the File Data Entity has a formal identifier string such as a DOI +  Detected issues    + - [Violation on <./input1.txt>]: The File Data Entity MAY have a formal identifier specified through an `identifier` property + - [Violation on <./outputs/qa.csv>]: The File Data Entity MAY have a formal identifier specified through an `identifier` property + + + [ ro-crate-1.1_32.2 ] File Data Entity: optional `url` property:   + Check if the File Data Entity has an optional download link +  Detected issues    + - [Violation on <./input1.txt>]: The File Data Entity MAY use a `url` property to denote a `download` link + - [Violation on <./outputs/qa.csv>]: The File Data Entity MAY use a `url` property to denote a `download` link + + + [ ro-crate-1.1_32.3 ] File Data Entity: optional `subjectOf` property:   + Check if the File Data Entity includes a subjectOf property to link CreativeWork instances that mention it. +  Detected issues    + - [Violation on <./input1.txt>]: The File Data Entity MAY include a `subjectOf` property to link `CreativeWork` instances that mention it. + - [Violation on <./outputs/qa.csv>]: The File Data Entity MAY include a `subjectOf` property to link `CreativeWork` instances that mention it. + + + [ ro-crate-1.1_32.4 ] File Data Entity: optional `mainEntityOfPage` property:   + Check if the File Data Entity has a mainEntityOfPage property +  Detected issues    + - [Violation on <./input1.txt>]: The File Data Entity MAY have a `mainEntityOfPage` property + - [Violation on <./outputs/qa.csv>]: The File Data Entity MAY have a `mainEntityOfPage` property + + + + [profile: RO-Crate Metadata Specification 1.1] + [ ro-crate-1.1_34 ]: Root Data Entity: optional properties   + + Define the optional properties for the Root Data Entity (e.g., license) + +  Failed checks    +    + [ ro-crate-1.1_34.1 ] License:   + Check if the RO-Crate has a license property with a URI or a textual description +  Detected issues    + - [Violation of http://schema.org/license="http://spdx.org/licenses/CC-BY-4.0" on <./>]: MAY have a URI (eg for Creative Commons or Open Source licenses). + MAY, if necessary be a textual description of how the RO-Crate may be used. + + diff --git a/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl index bd918479..6562af2a 100644 --- a/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl @@ -52,5 +52,5 @@ five-safes-crate:DownloadActionMayHaveStartTimeIfBegun sh:minCount 1 ; sh:maxCount 1 ; sh:severity sh:Info ; - sh:message "`DownloadAction` SHOULD have the `endTime` property if `actionStatus` is either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." ; + sh:message "`DownloadAction` MAY have the `startTime` property if `actionStatus` is either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." ; ] . diff --git a/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl index 1315d276..2355bbb2 100644 --- a/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl @@ -23,7 +23,7 @@ @prefix xsd: . -five-safes-crate:DownloadActionObjectHasDescriptiveName +five-safes-crate:DownloadActionObjectMUSTHavesDescriptiveName a sh:NodeShape ; sh:name "DownloadAction" ; sh:targetClass schema:DownloadAction ; @@ -42,27 +42,16 @@ five-safes-crate:DownloadActionObjectHasDescriptiveName sh:message "DownloadAction MUST have a human readable name string of at least 10 characters." ; ] . -five-safes-crate:DownloadActionStartTimeMustFollowISOStandard +five-safes-crate:DownloadActionStartTimeMUSTFollowISOStandard a sh:NodeShape ; sh:name "DownloadAction" ; sh:description "" ; - sh:target [ - a sh:SPARQLTarget ; - sh:select """ - PREFIX schema: - PREFIX rdf: - - SELECT ?this - WHERE { - ?this rdf:type schema:DownloadAction ; - schema:startTime ?o . - } - """ ; - ] ; + sh:targetClass schema:DownloadAction ; sh:property [ a sh:PropertyShape ; sh:name "StartTime" ; + sh:minCount 0; sh:path schema:startTime ; 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:Violation ; @@ -70,7 +59,7 @@ five-safes-crate:DownloadActionStartTimeMustFollowISOStandard ] . -five-safes-crate:DownloadActionEndTimeMustFollowISOStandard +five-safes-crate:DownloadActionEndTimeMUSTFollowISOStandard a sh:NodeShape ; sh:name "DownloadAction" ; sh:description "" ; @@ -87,7 +76,87 @@ five-safes-crate:DownloadActionEndTimeMustFollowISOStandard ] . -five-safes-crate:CheckValueActionStatusMustHaveAllowedValues +five-safes-crate:WorkflowSameAsAndRootDataEntityMainEntityMUSTBeTheSame + a sh:NodeShape ; + sh:name "Downloaded Workflow" ; + sh:description "" ; + sh:target [ + a sh:SPARQLTarget ; + sh:select """ + PREFIX schema: + PREFIX rdf: + + SELECT ?this + WHERE { + ?this rdf:type schema:Dataset . + ?s rdf:type schema:DownloadAction ; + schema:result ?this . + } + """ ; + ]; + + sh:sparql [ + a sh:SPARQLConstraint ; + sh:select """ + PREFIX schema: + PREFIX rdf: + + SELECT $this + WHERE { + FILTER NOT EXISTS { + $this schema:sameAs ?o . + ?s schema:mainEntity ?o . + # ?o rdf:type schema:Dataset . + } + } + """ ; + sh:severity sh:Violation ; + sh:description "The property `sameAs` of the entity representing the downloaded workflow MUST point to the same entity as `RootDataEntity` --> `mainEntity`." ; + sh:message "The property `sameAs` of the entity representing the downloaded workflow MUST point to the same entity as `RootDataEntity` --> `mainEntity`." ; + ] . + + +five-safes-crate:DownloadedWorkflowDistributionAndDownloadActionObjectMUSTBeTheSame + a sh:NodeShape ; + sh:name "Downloaded Workflow" ; + sh:description "" ; + sh:target [ + a sh:SPARQLTarget ; + sh:select """ + PREFIX schema: + PREFIX rdf: + + SELECT ?this + WHERE { + ?this rdf:type schema:Dataset . + ?s rdf:type schema:DownloadAction ; + schema:result ?this . + } + """ ; + ]; + + sh:sparql [ + a sh:SPARQLConstraint ; + sh:name "" ; + sh:select """ + PREFIX schema: + PREFIX rdf: + + SELECT $this + WHERE { + ?action rdf:type schema:DownloadAction . + FILTER NOT EXISTS { + $this schema:distribution ?url . + ?action schema:object ?url . + } + } + """ ; + sh:severity sh:Violation ; + sh:message "DownloadedWorkflow --> `distribution` MUST reference the same entity as `DownloadAction` --> `object`." ; + ] . + + +five-safes-crate:DownloadActionActionStatusMUSTHaveAllowedValues a sh:NodeShape ; sh:name "DownloadAction" ; sh:description "" ; diff --git a/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl index e310adb5..71aff2fb 100644 --- a/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl @@ -23,29 +23,55 @@ @prefix xsd: . -five-safes-crate:RootDataEntityShouldMentionDownloadActionObjectIfItExists +five-safes-crate:DownloadActionEntitySHOULDExist a sh:NodeShape ; sh:name "RootDataEntity" ; + sh:description "" ; sh:targetClass ro-crate:RootDataEntity ; + + sh:sparql [ + a sh:SPARQLConstraint ; + sh:name "" ; + sh:select """ + PREFIX schema: + PREFIX rdf: + + SELECT $this + WHERE { + FILTER NOT EXISTS { + ?s rdf:type schema:DownloadAction . + } + } + """ ; + sh:severity sh:Warning ; + sh:message "An entity typed DownloadAction SHOULD exist." ; + ] . + + + +five-safes-crate:RootDataEntitySHOULDMentionDownloadActionIfPresent + a sh:NodeShape ; + sh:name "RootDataEntity" ; sh:description "" ; + sh:targetClass ro-crate:RootDataEntity ; sh:sparql [ a sh:SPARQLConstraint ; - sh:name "mentions" ; - sh:description "RootDataEntity SHOULD mention the DownloadAction object." ; + sh:name "" ; sh:select """ PREFIX schema: PREFIX rdf: - SELECT $this ?download + + SELECT $this ?da WHERE { - ?download rdf:type schema:DownloadAction . - FILTER NOT EXISTS{ - $this schema:mentions ?download . + ?da rdf:type schema:DownloadAction . + FILTER NOT EXISTS { + $this schema:mentions ?da . } } - """ ; + """ ; sh:severity sh:Warning ; - sh:message "RootDataEntity SHOULD mention the DownloadAction object." ; + sh:message "RootDataEntity SHOULD mention DownloadAction if this exists." ; ] . @@ -82,6 +108,42 @@ five-safes-crate:DownloadActionShouldHaveEndTimeIfEnded ] . +five-safes-crate:DownloadedWorkflowSHOULDExistAndBeReferencedByDownloadActionResult + a sh:NodeShape ; + sh:name "DownloadAction" ; + sh:description "Validates that DownloadAction result references an existing entity" ; + sh:targetClass schema:DownloadAction ; + + sh:property [ + a sh:PropertyShape ; + sh:name "Result" ; + sh:description "The result property must reference an existing entity in the RO-Crate" ; + sh:path schema:result ; + sh:minCount 1 ; + sh:nodeKind sh:IRI ; + + sh:sparql [ + a sh:SPARQLConstraint ; + sh:select """ + PREFIX rdf: + PREFIX schema: + + SELECT $this $value + WHERE { + $this schema:result $value . + + # Entity must have BOTH type AND name (proper definition) + FILTER NOT EXISTS { + $value rdf:type schema:Dataset . + } + } + """ ; + sh:severity sh:Warning ; + sh:message "The entity represented the downloaded workflow is not properly defined in the RO-Crate and/or it is not referenced by `DownloadAction` --> `result`." ; + ] ; + ] . + + five-safes-crate:DownloadActionShouldHaveActionStatus a sh:NodeShape ; sh:name "DownloadAction" ; 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 d3823981..d9e2264d 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 @@ -306,7 +306,7 @@ "@id": "https://w3id.org/shp#DisclosureCheck" }, "name": "Disclosure check of workflow results: approved", - "startTime": "2023-04-24T00:00:00+01:00", + "startTime": "2023-04-25T15:00:00+01:00", "endTime": "2023-04-25T16:00:00+01:00", "object": { "@id": "./" diff --git a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py index 083771cd..d183d0df 100644 --- a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py +++ b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py @@ -176,6 +176,74 @@ def test_5src_check_value_end_time_not_iso_standard(): ) +def test_5src_downloaded_workflow_same_as_is_not_the_same_as_root_data_entity_main_entity(): + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?wf schema:sameAs ?me . + } + INSERT { + ?wf schema:sameAs "This is not the same as the main entity" . + } + WHERE { + ?wf schema:sameAs ?me . + <./> schema:mainEntity ?me . + ?da schema:result ?wf ; + rdf:type schema:DownloadAction . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.REQUIRED, + expected_validation_result=False, + expected_triggered_requirements=["Downloaded Workflow"], + expected_triggered_issues=[ + ( + "The property `sameAs` of the entity representing the downloaded workflow " + "MUST point to the same entity as `RootDataEntity` --> `mainEntity`." + ) + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_downloaded_workflow_distribution_is_not_the_same_as_download_action_object(): + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?s schema:object ?o . + } + INSERT { + ?s schema:result "This is not the downloaded workflow entity" . + } + WHERE { + ?s schema:object ?o ; + rdf:type schema:DownloadAction . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.REQUIRED, + expected_validation_result=False, + expected_triggered_requirements=["Downloaded Workflow"], + expected_triggered_issues=[ + ( + "DownloadedWorkflow --> `distribution` MUST reference " + "the same entity as `DownloadAction` --> `object`." + ) + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + def test_5src_download_action_has_action_status_with_not_allowed_value(): sparql = ( SPARQL_PREFIXES @@ -212,6 +280,31 @@ def test_5src_download_action_has_action_status_with_not_allowed_value(): # ----- SHOULD fails tests +def test_5src_download_action_is_not_present(): + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?da ?p ?o . + } + WHERE { + ?da rdf:type schema:DownloadAction ; + ?p ?o . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["RootDataEntity"], + expected_triggered_issues=["An entity typed DownloadAction SHOULD exist."], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + def test_5src_root_data_entity_does_not_mention_download_action_entity(): sparql = ( SPARQL_PREFIXES @@ -231,7 +324,7 @@ def test_5src_root_data_entity_does_not_mention_download_action_entity(): expected_validation_result=False, expected_triggered_requirements=["RootDataEntity"], expected_triggered_issues=[ - "RootDataEntity SHOULD mention the DownloadAction object." + "RootDataEntity SHOULD mention DownloadAction if this exists." ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, @@ -268,6 +361,104 @@ def test_5src_download_action_does_not_have_end_time(): ) +def test_5src_downloaded_workflow_is_not_represented_by_its_own_entity(): + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?wf ?p ?o . + } + WHERE { + ?wf ?p ?o . + ?da schema:result ?wf ; + rdf:type schema:DownloadAction . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["DownloadAction"], + expected_triggered_issues=[ + ( + "The entity represented the downloaded workflow is not properly defined in the " + "RO-Crate and/or it is not referenced by `DownloadAction` --> `result`." + ) + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_downloaded_workflow_is_not_referenced_by_download_action_result(): + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?s schema:result ?o . + } + INSERT { + ?s schema:result "This is not the downloaded workflow entity" . + } + WHERE { + ?s schema:result ?o ; + rdf:type schema:DownloadAction . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["DownloadAction"], + expected_triggered_issues=[ + ( + "The entity represented the downloaded workflow is not properly defined in the " + "RO-Crate and/or it is not referenced by `DownloadAction` --> `result`." + ) + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + +def test_5src_downloaded_workflow_entity_is_not_of_type_dataset(): + sparql = ( + SPARQL_PREFIXES + + """ + DELETE { + ?wf rdf:type schema:Dataset . + } + INSERT { + ?wf rdf:type schema:Person . + } + WHERE { + ?wf rdf:type schema:Dataset . + ?da schema:result ?wf ; + rdf:type schema:DownloadAction . + } + """ + ) + + do_entity_test( + rocrate_path=ValidROC().five_safes_crate_result, + requirement_severity=Severity.RECOMMENDED, + expected_validation_result=False, + expected_triggered_requirements=["DownloadAction"], + expected_triggered_issues=[ + ( + "The entity represented the downloaded workflow is not properly defined in the " + "RO-Crate and/or it is not referenced by `DownloadAction` --> `result`." + ) + ], + profile_identifier="five-safes-crate", + rocrate_entity_mod_sparql=sparql, + ) + + def test_5src_download_action_does_not_have_action_status_property(): sparql = ( SPARQL_PREFIXES @@ -318,8 +509,8 @@ def test_5src_download_action_does_not_have_start_time(): expected_validation_result=False, expected_triggered_requirements=["DownloadAction"], expected_triggered_issues=[ - "`DownloadAction` SHOULD have the `endTime` property " - "if `actionStatus` is either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." + "`DownloadAction` MAY have the `startTime` property if `actionStatus` " + "is either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, From 166bd0f09dac0a419129c5f9b2d07e8702ed760a Mon Sep 17 00:00:00 2001 From: EttoreM Date: Tue, 23 Dec 2025 08:35:51 +0000 Subject: [PATCH 07/11] (i) Removed minimum length requirement for name of DownloadAction. (ii) Existence of entity representing the downloaded workflow is now a MAY (before it was a SHOULD). --- .../may/14_workflow_retrieval_phase.ttl | 36 +++++++ .../must/14_workflow_retrieval_phase.ttl | 5 +- .../should/14_workflow_retrieval_phase.ttl | 36 ------- .../test_5src_14_workflow_retrieval_phase.py | 93 +++++++------------ 4 files changed, 70 insertions(+), 100 deletions(-) diff --git a/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl index 6562af2a..ebf5dcf8 100644 --- a/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl @@ -23,6 +23,42 @@ @prefix xsd: . +five-safes-crate:DownloadedWorkflowSHOULDExistAndBeReferencedByDownloadActionResult + a sh:NodeShape ; + sh:name "DownloadAction" ; + sh:description "Validates that DownloadAction result references an existing entity" ; + sh:targetClass schema:DownloadAction ; + + sh:property [ + a sh:PropertyShape ; + sh:name "Result" ; + sh:description "The result property must reference an existing entity in the RO-Crate" ; + sh:path schema:result ; + sh:minCount 1 ; + sh:nodeKind sh:IRI ; + + sh:sparql [ + a sh:SPARQLConstraint ; + sh:select """ + PREFIX rdf: + PREFIX schema: + + SELECT $this $value + WHERE { + $this schema:result $value . + + # Entity must have BOTH type AND name (proper definition) + FILTER NOT EXISTS { + $value rdf:type schema:Dataset . + } + } + """ ; + sh:severity sh:Info ; + sh:message "The entity represented the downloaded workflow is not properly defined in the RO-Crate and/or it is not referenced by `DownloadAction` --> `result`." ; + ] ; + ] . + + five-safes-crate:DownloadActionMayHaveStartTimeIfBegun a sh:NodeShape ; sh:name "DownloadAction" ; diff --git a/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl index 2355bbb2..b9cc96b0 100644 --- a/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/must/14_workflow_retrieval_phase.ttl @@ -32,14 +32,13 @@ five-safes-crate:DownloadActionObjectMUSTHavesDescriptiveName sh:property [ a sh:PropertyShape ; sh:name "name" ; - sh:description "DownloadAction MUST have a human readable name string of at least 10 characters." ; + sh:description "DownloadAction MUST have a human readable name string." ; sh:path schema:name ; sh:minCount 1 ; sh:maxCount 1 ; sh:datatype xsd:string ; - sh:minLength 10 ; sh:severity sh:Violation ; - sh:message "DownloadAction MUST have a human readable name string of at least 10 characters." ; + sh:message "DownloadAction MUST have a human readable name string." ; ] . five-safes-crate:DownloadActionStartTimeMUSTFollowISOStandard diff --git a/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl index 71aff2fb..f2bd9dd8 100644 --- a/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/should/14_workflow_retrieval_phase.ttl @@ -108,42 +108,6 @@ five-safes-crate:DownloadActionShouldHaveEndTimeIfEnded ] . -five-safes-crate:DownloadedWorkflowSHOULDExistAndBeReferencedByDownloadActionResult - a sh:NodeShape ; - sh:name "DownloadAction" ; - sh:description "Validates that DownloadAction result references an existing entity" ; - sh:targetClass schema:DownloadAction ; - - sh:property [ - a sh:PropertyShape ; - sh:name "Result" ; - sh:description "The result property must reference an existing entity in the RO-Crate" ; - sh:path schema:result ; - sh:minCount 1 ; - sh:nodeKind sh:IRI ; - - sh:sparql [ - a sh:SPARQLConstraint ; - sh:select """ - PREFIX rdf: - PREFIX schema: - - SELECT $this $value - WHERE { - $this schema:result $value . - - # Entity must have BOTH type AND name (proper definition) - FILTER NOT EXISTS { - $value rdf:type schema:Dataset . - } - } - """ ; - sh:severity sh:Warning ; - sh:message "The entity represented the downloaded workflow is not properly defined in the RO-Crate and/or it is not referenced by `DownloadAction` --> `result`." ; - ] ; - ] . - - five-safes-crate:DownloadActionShouldHaveActionStatus a sh:NodeShape ; sh:name "DownloadAction" ; diff --git a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py index d183d0df..81b72511 100644 --- a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py +++ b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py @@ -45,7 +45,7 @@ def test_5src_download_action_does_not_have_name(): expected_validation_result=False, expected_triggered_requirements=["DownloadAction"], expected_triggered_issues=[ - "DownloadAction MUST have a human readable name string of at least 10 characters." + "DownloadAction MUST have a human readable name string." ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, @@ -74,36 +74,7 @@ def test_5src_download_action_name_not_a_string(): expected_validation_result=False, expected_triggered_requirements=["DownloadAction"], expected_triggered_issues=[ - "DownloadAction MUST have a human readable name string of at least 10 characters." - ], - profile_identifier="five-safes-crate", - rocrate_entity_mod_sparql=sparql, - ) - - -def test_5src_download_action_name_not_long_enough(): - sparql = ( - SPARQL_PREFIXES - + """ - DELETE { - ?this schema:name ?name . - } - INSERT { - ?this schema:name "Short" . - } - WHERE { - ?this rdf:type schema:DownloadAction . - } - """ - ) - - do_entity_test( - rocrate_path=ValidROC().five_safes_crate_result, - requirement_severity=Severity.REQUIRED, - expected_validation_result=False, - expected_triggered_requirements=["DownloadAction"], - expected_triggered_issues=[ - "DownloadAction MUST have a human readable name string of at least 10 characters." + "DownloadAction MUST have a human readable name string." ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, @@ -361,16 +332,18 @@ def test_5src_download_action_does_not_have_end_time(): ) -def test_5src_downloaded_workflow_is_not_represented_by_its_own_entity(): +def test_5src_downloaded_workflow_is_not_referenced_by_download_action_result(): sparql = ( SPARQL_PREFIXES + """ DELETE { - ?wf ?p ?o . + ?s schema:result ?o . + } + INSERT { + ?s schema:result "This is not the downloaded workflow entity" . } WHERE { - ?wf ?p ?o . - ?da schema:result ?wf ; + ?s schema:result ?o ; rdf:type schema:DownloadAction . } """ @@ -392,19 +365,20 @@ def test_5src_downloaded_workflow_is_not_represented_by_its_own_entity(): ) -def test_5src_downloaded_workflow_is_not_referenced_by_download_action_result(): +def test_5src_downloaded_workflow_entity_is_not_of_type_dataset(): sparql = ( SPARQL_PREFIXES + """ DELETE { - ?s schema:result ?o . + ?wf rdf:type schema:Dataset . } INSERT { - ?s schema:result "This is not the downloaded workflow entity" . + ?wf rdf:type schema:Person . } WHERE { - ?s schema:result ?o ; - rdf:type schema:DownloadAction . + ?wf rdf:type schema:Dataset . + ?da schema:result ?wf ; + rdf:type schema:DownloadAction . } """ ) @@ -425,20 +399,16 @@ def test_5src_downloaded_workflow_is_not_referenced_by_download_action_result(): ) -def test_5src_downloaded_workflow_entity_is_not_of_type_dataset(): +def test_5src_download_action_does_not_have_action_status_property(): sparql = ( SPARQL_PREFIXES + """ DELETE { - ?wf rdf:type schema:Dataset . - } - INSERT { - ?wf rdf:type schema:Person . + ?s schema:actionStatus ?o . } WHERE { - ?wf rdf:type schema:Dataset . - ?da schema:result ?wf ; - rdf:type schema:DownloadAction . + ?s rdf:type schema:DownloadAction ; + schema:actionStatus ?o . } """ ) @@ -449,46 +419,47 @@ def test_5src_downloaded_workflow_entity_is_not_of_type_dataset(): expected_validation_result=False, expected_triggered_requirements=["DownloadAction"], expected_triggered_issues=[ - ( - "The entity represented the downloaded workflow is not properly defined in the " - "RO-Crate and/or it is not referenced by `DownloadAction` --> `result`." - ) + "`DownloadAction` SHOULD have `actionStatus` property." ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, ) -def test_5src_download_action_does_not_have_action_status_property(): +# ----- MAY fails tests + + +def test_5src_downloaded_workflow_is_not_represented_by_its_own_entity(): sparql = ( SPARQL_PREFIXES + """ DELETE { - ?s schema:actionStatus ?o . + ?wf ?p ?o . } WHERE { - ?s rdf:type schema:DownloadAction ; - schema:actionStatus ?o . + ?wf ?p ?o . + ?da schema:result ?wf ; + rdf:type schema:DownloadAction . } """ ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, - requirement_severity=Severity.RECOMMENDED, + requirement_severity=Severity.OPTIONAL, expected_validation_result=False, expected_triggered_requirements=["DownloadAction"], expected_triggered_issues=[ - "`DownloadAction` SHOULD have `actionStatus` property." + ( + "The entity represented the downloaded workflow is not properly defined in the " + "RO-Crate and/or it is not referenced by `DownloadAction` --> `result`." + ) ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, ) -# ----- MAY fails tests - - def test_5src_download_action_does_not_have_start_time(): sparql = ( SPARQL_PREFIXES From 765296afc9b0fc46acb7e3f77e8ab26925806039 Mon Sep 17 00:00:00 2001 From: EttoreM Date: Tue, 23 Dec 2025 09:00:10 +0000 Subject: [PATCH 08/11] Removed redundant tests. --- .../may/14_workflow_retrieval_phase.ttl | 5 +- .../test_5src_14_workflow_retrieval_phase.py | 72 +------------------ 2 files changed, 7 insertions(+), 70 deletions(-) diff --git a/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl index ebf5dcf8..148dd1cd 100644 --- a/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl @@ -54,7 +54,10 @@ five-safes-crate:DownloadedWorkflowSHOULDExistAndBeReferencedByDownloadActionRes } """ ; sh:severity sh:Info ; - sh:message "The entity represented the downloaded workflow is not properly defined in the RO-Crate and/or it is not referenced by `DownloadAction` --> `result`." ; + sh:message ("The entity representing the downloaded workflow is not defined, " + "OR is not referenced by `DownloadAction` --> `result`, " + "OR is not of type `schema:Dataset`." + ) ; ] ; ] . diff --git a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py index 81b72511..77ced3a1 100644 --- a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py +++ b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py @@ -332,73 +332,6 @@ def test_5src_download_action_does_not_have_end_time(): ) -def test_5src_downloaded_workflow_is_not_referenced_by_download_action_result(): - sparql = ( - SPARQL_PREFIXES - + """ - DELETE { - ?s schema:result ?o . - } - INSERT { - ?s schema:result "This is not the downloaded workflow entity" . - } - WHERE { - ?s schema:result ?o ; - rdf:type schema:DownloadAction . - } - """ - ) - - do_entity_test( - rocrate_path=ValidROC().five_safes_crate_result, - requirement_severity=Severity.RECOMMENDED, - expected_validation_result=False, - expected_triggered_requirements=["DownloadAction"], - expected_triggered_issues=[ - ( - "The entity represented the downloaded workflow is not properly defined in the " - "RO-Crate and/or it is not referenced by `DownloadAction` --> `result`." - ) - ], - profile_identifier="five-safes-crate", - rocrate_entity_mod_sparql=sparql, - ) - - -def test_5src_downloaded_workflow_entity_is_not_of_type_dataset(): - sparql = ( - SPARQL_PREFIXES - + """ - DELETE { - ?wf rdf:type schema:Dataset . - } - INSERT { - ?wf rdf:type schema:Person . - } - WHERE { - ?wf rdf:type schema:Dataset . - ?da schema:result ?wf ; - rdf:type schema:DownloadAction . - } - """ - ) - - do_entity_test( - rocrate_path=ValidROC().five_safes_crate_result, - requirement_severity=Severity.RECOMMENDED, - expected_validation_result=False, - expected_triggered_requirements=["DownloadAction"], - expected_triggered_issues=[ - ( - "The entity represented the downloaded workflow is not properly defined in the " - "RO-Crate and/or it is not referenced by `DownloadAction` --> `result`." - ) - ], - profile_identifier="five-safes-crate", - rocrate_entity_mod_sparql=sparql, - ) - - def test_5src_download_action_does_not_have_action_status_property(): sparql = ( SPARQL_PREFIXES @@ -451,8 +384,9 @@ def test_5src_downloaded_workflow_is_not_represented_by_its_own_entity(): expected_triggered_requirements=["DownloadAction"], expected_triggered_issues=[ ( - "The entity represented the downloaded workflow is not properly defined in the " - "RO-Crate and/or it is not referenced by `DownloadAction` --> `result`." + "The entity representing the downloaded workflow is not defined, " + "OR is not referenced by `DownloadAction` --> `result`, " + "OR is not of type `schema:Dataset`." ) ], profile_identifier="five-safes-crate", From f55c2affd1560c563c640accce77439f84555639 Mon Sep 17 00:00:00 2001 From: EttoreM Date: Wed, 24 Dec 2025 10:14:28 +0000 Subject: [PATCH 09/11] Fixed issues due to malformatted strings --- .../may/11_workflow_execution_phase.ttl | 15 +- .../may/14_workflow_retrieval_phase.ttl | 16 ++- .../test_5src_11_workflow_execution.py | 129 ++++++++++++------ .../test_5src_14_workflow_retrieval_phase.py | 9 +- 4 files changed, 115 insertions(+), 54 deletions(-) diff --git a/rocrate_validator/profiles/five-safes-crate/may/11_workflow_execution_phase.ttl b/rocrate_validator/profiles/five-safes-crate/may/11_workflow_execution_phase.ttl index 4a043d09..215dd9c0 100644 --- a/rocrate_validator/profiles/five-safes-crate/may/11_workflow_execution_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/may/11_workflow_execution_phase.ttl @@ -25,7 +25,10 @@ five-safes-crate:WorkflowexecutionObjectHasStartTimeIfBegun a sh:NodeShape ; sh:name "WorkflowExecution" ; - sh:description "The workflow execution object MAY have a startTime if execution was initiated." ; + sh:description ( + "The workflow execution object MAY have a startTime if actionStatus is " + "either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." + ) ; sh:target [ a sh:SPARQLTarget ; @@ -53,6 +56,12 @@ five-safes-crate:WorkflowexecutionObjectHasStartTimeIfBegun sh:minCount 1 ; sh:maxCount 1 ; sh:severity sh:Info ; - sh:description "The workflow execution object MAY have a startTime if execution was initiated." ; - sh:message "The workflow execution object MAY have a startTime if execution was initiated." ; + sh:description ( + "The workflow execution object MAY have a startTime if actionStatus is " + "either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." + ) ; + sh:message ( + "The workflow execution object MAY have a startTime if actionStatus is " + "either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." + ) ; ] . diff --git a/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl index 148dd1cd..a4b1b9e0 100644 --- a/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl @@ -54,10 +54,7 @@ five-safes-crate:DownloadedWorkflowSHOULDExistAndBeReferencedByDownloadActionRes } """ ; sh:severity sh:Info ; - sh:message ("The entity representing the downloaded workflow is not defined, " - "OR is not referenced by `DownloadAction` --> `result`, " - "OR is not of type `schema:Dataset`." - ) ; + sh:message "The entity representing the downloaded workflow is not defined, OR is not referenced by `DownloadAction` --> `result`, OR is not of type `schema:Dataset`." ; ] ; ] . @@ -65,12 +62,17 @@ five-safes-crate:DownloadedWorkflowSHOULDExistAndBeReferencedByDownloadActionRes five-safes-crate:DownloadActionMayHaveStartTimeIfBegun a sh:NodeShape ; sh:name "DownloadAction" ; - sh:description "" ; + sh:description ( + "`DownloadAction` MAY have the `startTime` property if `actionStatus` " + "is either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." + ); + sh:target [ a sh:SPARQLTarget ; sh:select """ PREFIX schema: PREFIX rdf: + SELECT ?this WHERE { ?this rdf:type schema:DownloadAction ; @@ -91,5 +93,9 @@ five-safes-crate:DownloadActionMayHaveStartTimeIfBegun sh:minCount 1 ; sh:maxCount 1 ; sh:severity sh:Info ; + sh:description ( + "`DownloadAction` MAY have the `startTime` property if `actionStatus` " + "is either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." + ); sh:message "`DownloadAction` MAY have the `startTime` property if `actionStatus` is either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." ; ] . diff --git a/tests/integration/profiles/five-safes-crate/test_5src_11_workflow_execution.py b/tests/integration/profiles/five-safes-crate/test_5src_11_workflow_execution.py index 7bbefd94..6e84c643 100644 --- a/tests/integration/profiles/five-safes-crate/test_5src_11_workflow_execution.py +++ b/tests/integration/profiles/five-safes-crate/test_5src_11_workflow_execution.py @@ -26,9 +26,9 @@ def test_5src_workflow_object_with_no_name(): - sparql = ( - SPARQL_PREFIXES + """ + SPARQL_PREFIXES + + """ DELETE { ?this schema:name ?name . } @@ -37,21 +37,26 @@ def test_5src_workflow_object_with_no_name(): schema:name ?name . <./> schema:mentions ?this . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, requirement_severity=Severity.REQUIRED, expected_validation_result=False, expected_triggered_requirements=["WorkflowExecution"], - expected_triggered_issues=["Workflow (CreateAction) MUST have a name string of at least 10 characters."], + expected_triggered_issues=[ + "Workflow (CreateAction) MUST have a name string of at least 10 characters." + ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, ) def test_5src_workflow_object_with_name_not_string(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?this schema:name ?name . } @@ -63,21 +68,26 @@ def test_5src_workflow_object_with_name_not_string(): schema:name ?name . <./> schema:mentions ?this . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, requirement_severity=Severity.REQUIRED, expected_validation_result=False, expected_triggered_requirements=["WorkflowExecution"], - expected_triggered_issues=["Workflow (CreateAction) MUST have a name string of at least 10 characters."], + expected_triggered_issues=[ + "Workflow (CreateAction) MUST have a name string of at least 10 characters." + ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, ) def test_5src_workflow_object_with_not_long_enough_name(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?this schema:name ?name . } @@ -89,21 +99,26 @@ def test_5src_workflow_object_with_not_long_enough_name(): schema:name ?name . <./> schema:mentions ?this . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, requirement_severity=Severity.REQUIRED, expected_validation_result=False, expected_triggered_requirements=["WorkflowExecution"], - expected_triggered_issues=["Workflow (CreateAction) MUST have a name string of at least 10 characters."], + expected_triggered_issues=[ + "Workflow (CreateAction) MUST have a name string of at least 10 characters." + ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, ) def test_5src_workflow_object_has_no_properly_formatted_start_time(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?s schema:startTime ?time . } @@ -114,24 +129,29 @@ def test_5src_workflow_object_has_no_properly_formatted_start_time(): ?s rdf:type schema:CreateAction ; schema:startTime ?time . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, requirement_severity=Severity.REQUIRED, expected_validation_result=False, expected_triggered_requirements=["WorkflowExecution"], - expected_triggered_issues=[( - "The startTime of the workflow execution object MUST follow the RFC 3339 standard " - "(YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." - )], + expected_triggered_issues=[ + ( + "The startTime of the workflow execution object MUST follow the RFC 3339 standard " + "(YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." + ) + ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, ) def test_5src_workflow_object_has_no_properly_formatted_end_time(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?s schema:endTime ?time . } @@ -142,24 +162,29 @@ def test_5src_workflow_object_has_no_properly_formatted_end_time(): ?s rdf:type schema:CreateAction ; schema:endTime ?time . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, requirement_severity=Severity.REQUIRED, expected_validation_result=False, expected_triggered_requirements=["WorkflowExecution"], - expected_triggered_issues=[( - "The endTime of the workflow execution object MUST follow the RFC 3339 standard " - "(YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." - )], + expected_triggered_issues=[ + ( + "The endTime of the workflow execution object MUST follow the RFC 3339 standard " + "(YYYY-MM-DD'T'hh:mm:ss[.fraction](Z | ±hh:mm))." + ) + ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, ) def test_5src_workflow_object_with_no_action_status(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?this schema:actionStatus ?o . } @@ -167,24 +192,29 @@ def test_5src_workflow_object_with_no_action_status(): ?this schema:actionStatus ?o ; rdf:type schema:CreateAction . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, requirement_severity=Severity.REQUIRED, expected_validation_result=False, expected_triggered_requirements=["WorkflowExecution"], - expected_triggered_issues=[( - "WorkflowExecution MUST have an actionStatus " - "with an allowed value (see https://schema.org/ActionStatusType)." - )], + expected_triggered_issues=[ + ( + "WorkflowExecution MUST have an actionStatus " + "with an allowed value (see https://schema.org/ActionStatusType)." + ) + ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, ) def test_5src_workflow_object_with_no_properly_valued_action_status(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?this schema:actionStatus ?o . } @@ -195,17 +225,20 @@ def test_5src_workflow_object_with_no_properly_valued_action_status(): ?this schema:actionStatus ?o ; rdf:type schema:CreateAction . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, requirement_severity=Severity.REQUIRED, expected_validation_result=False, expected_triggered_requirements=["WorkflowExecution"], - expected_triggered_issues=[( - "WorkflowExecution MUST have an actionStatus " - "with an allowed value (see https://schema.org/ActionStatusType)." - )], + expected_triggered_issues=[ + ( + "WorkflowExecution MUST have an actionStatus " + "with an allowed value (see https://schema.org/ActionStatusType)." + ) + ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, ) @@ -215,14 +248,17 @@ def test_5src_workflow_object_with_no_properly_valued_action_status(): def test_5src_workflow_object_not_mentioned_by_root_data_entity(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { <./> schema:mentions ?o . } WHERE { ?o rdf:type schema:CreateAction . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, @@ -238,7 +274,9 @@ def test_5src_workflow_object_not_mentioned_by_root_data_entity(): def test_5src_workflow_object_has_no_end_time_if_ended(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?s schema:endTime ?time . } @@ -246,7 +284,8 @@ def test_5src_workflow_object_has_no_end_time_if_ended(): ?s rdf:type schema:CreateAction ; schema:endTime ?time . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, @@ -265,15 +304,18 @@ def test_5src_workflow_object_has_no_end_time_if_ended(): def test_5src_workflow_object_has_no_start_time_if_begun(): - sparql = (SPARQL_PREFIXES + """ + sparql = ( + SPARQL_PREFIXES + + """ DELETE { ?s schema:startTime ?time . } WHERE { ?s rdf:type schema:CreateAction; - schema:startTime ?time + schema:startTime ?time . } - """) + """ + ) do_entity_test( rocrate_path=ValidROC().five_safes_crate_result, @@ -281,7 +323,10 @@ def test_5src_workflow_object_has_no_start_time_if_begun(): expected_validation_result=False, expected_triggered_requirements=["WorkflowExecution"], expected_triggered_issues=[ - "The workflow execution object MAY have a startTime if execution was initiated." + ( + "The workflow execution object MAY have a startTime if actionStatus is " + "either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." + ) ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, diff --git a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py index 77ced3a1..c8e5b371 100644 --- a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py +++ b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py @@ -361,7 +361,6 @@ def test_5src_download_action_does_not_have_action_status_property(): # ----- MAY fails tests - def test_5src_downloaded_workflow_is_not_represented_by_its_own_entity(): sparql = ( SPARQL_PREFIXES @@ -399,11 +398,11 @@ def test_5src_download_action_does_not_have_start_time(): SPARQL_PREFIXES + """ DELETE { - ?c schema:startTime ?t . + ?s schema:startTime ?time . } WHERE { - ?c rdf:type schema:DownloadAction ; - schema:startTime ?t . + ?s rdf:type schema:DownloadAction ; + schema:startTime ?time . } """ ) @@ -414,8 +413,10 @@ def test_5src_download_action_does_not_have_start_time(): expected_validation_result=False, expected_triggered_requirements=["DownloadAction"], expected_triggered_issues=[ + ( "`DownloadAction` MAY have the `startTime` property if `actionStatus` " "is either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." + ) ], profile_identifier="five-safes-crate", rocrate_entity_mod_sparql=sparql, From 0a53211fd9df33f5af54d1a94caeb086e0f40126 Mon Sep 17 00:00:00 2001 From: EttoreM Date: Wed, 24 Dec 2025 10:18:29 +0000 Subject: [PATCH 10/11] Removed lint error --- .../five-safes-crate/test_5src_14_workflow_retrieval_phase.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py index c8e5b371..3d66d3a8 100644 --- a/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py +++ b/tests/integration/profiles/five-safes-crate/test_5src_14_workflow_retrieval_phase.py @@ -414,8 +414,8 @@ def test_5src_download_action_does_not_have_start_time(): expected_triggered_requirements=["DownloadAction"], expected_triggered_issues=[ ( - "`DownloadAction` MAY have the `startTime` property if `actionStatus` " - "is either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." + "`DownloadAction` MAY have the `startTime` property if `actionStatus` " + "is either ActiveActionStatus, CompletedActionStatus or FailedActionStatus." ) ], profile_identifier="five-safes-crate", From d2443cc25d56dd670223d9c5bd748c46da337118 Mon Sep 17 00:00:00 2001 From: EttoreM Date: Wed, 24 Dec 2025 12:35:21 +0000 Subject: [PATCH 11/11] (Trying) to remove error in test --- .../five-safes-crate/may/14_workflow_retrieval_phase.ttl | 1 + 1 file changed, 1 insertion(+) diff --git a/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl index a4b1b9e0..43866821 100644 --- a/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl +++ b/rocrate_validator/profiles/five-safes-crate/may/14_workflow_retrieval_phase.ttl @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + @prefix ro: <./> . @prefix ro-crate: . @prefix five-safes-crate: .