diff --git a/src/test/java/com/knowledgepixels/nanodash/GovernedVersionsTest.java b/src/test/java/com/knowledgepixels/nanodash/GovernedVersionsTest.java index bfc8c9a89..44cc636d8 100644 --- a/src/test/java/com/knowledgepixels/nanodash/GovernedVersionsTest.java +++ b/src/test/java/com/knowledgepixels/nanodash/GovernedVersionsTest.java @@ -15,6 +15,14 @@ class GovernedVersionsTest { + /** + * Fixtures normally belong in the nanopub test suite rather than in this repository (#620), + * but these two stay here: they are hand-built, unsigned, and carry placeholder artifact + * codes, because they exist to exercise Nanodash's own governance logic rather than to test + * whether an implementation reads nanopublications correctly. A suite for validating + * nanopublication implementations is not their home, and an unsigned nanopub with a made-up + * code has no business in its {@code valid/} folder. + */ private static Nanopub load(String fileName) throws MalformedNanopubException, IOException { return new NanopubImpl(new File("src/test/resources/" + fileName), RDFFormat.TRIG); } diff --git a/src/test/java/com/knowledgepixels/nanodash/GrlcQueryTest.java b/src/test/java/com/knowledgepixels/nanodash/GrlcQueryTest.java index 10fc9d763..e79985a25 100644 --- a/src/test/java/com/knowledgepixels/nanodash/GrlcQueryTest.java +++ b/src/test/java/com/knowledgepixels/nanodash/GrlcQueryTest.java @@ -11,9 +11,11 @@ import org.mockito.MockedStatic; import org.nanopub.*; import org.nanopub.extra.services.QueryRef; +import org.nanopub.testsuite.NanopubTestSuite; +import org.nanopub.testsuite.TestSuiteCategory; +import org.nanopub.testsuite.TestSuiteEntry; import org.nanopub.vocabulary.KPXL_GRLC; -import java.io.File; import java.io.IOException; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @@ -42,6 +44,19 @@ class GrlcQueryTest { */ private static final String SPARQL_WITH_NON_BREAKING_SPACE = "select ?thing where { ?thing ?p\u00A0?o }"; + /** + * The published "Get participation links" query. It lives in the nanopub test suite rather + * than in this repository, so that the fixture is shared with the other implementations + * instead of being copied into each of them (#620). Its absence is a failure rather than a + * reason to skip: it would mean the entry has been renamed or removed. + */ + private static Nanopub queryNanopub() throws MalformedNanopubException, IOException { + TestSuiteEntry entry = NanopubTestSuite.getLatest() + .getByArtifactCode(NANOPUB_ID, TestSuiteCategory.VALID) + .orElseThrow(() -> new IllegalStateException("Not in the nanopub test suite: " + NANOPUB_ID)); + return new NanopubImpl(entry.toFile(), RDFFormat.TRIG); + } + @AfterEach void tearDown() throws NoSuchFieldException, IllegalAccessException { // Using reflection to clear the instance map to ensure a fresh start for each test @@ -198,7 +213,7 @@ void getQuerySuffix() { @Test void getNanopub() throws MalformedNanopubException, IOException { GrlcQuery query = GrlcQuery.get(NANOPUB_URI); - Nanopub nanopub = new NanopubImpl(new File("src/test/resources/np-grlc-query.trig"), RDFFormat.TRIG); + Nanopub nanopub = queryNanopub(); assertEquals(query.getNanopub(), nanopub); } @@ -247,7 +262,7 @@ void createParamFields() { void getSparql() throws MalformedNanopubException, IOException { GrlcQuery query = GrlcQuery.get(NANOPUB_URI); String sparql = query.getSparql(); - Nanopub nanopub = new NanopubImpl(new File("src/test/resources/np-grlc-query.trig"), RDFFormat.TRIG); + Nanopub nanopub = queryNanopub(); AtomicReference sparqlFromNanopub = new AtomicReference<>(); nanopub.getAssertion().forEach(st -> { if (st.getPredicate().equals(KPXL_GRLC.SPARQL)) { diff --git a/src/test/java/com/knowledgepixels/nanodash/NanopubElementTest.java b/src/test/java/com/knowledgepixels/nanodash/NanopubElementTest.java index 56898788c..29810fd2d 100644 --- a/src/test/java/com/knowledgepixels/nanodash/NanopubElementTest.java +++ b/src/test/java/com/knowledgepixels/nanodash/NanopubElementTest.java @@ -10,6 +10,8 @@ import org.nanopub.NanopubImpl; import org.nanopub.extra.security.MalformedCryptoElementException; import org.nanopub.extra.security.SignatureUtils; +import org.nanopub.testsuite.NanopubTestSuite; +import org.nanopub.testsuite.TestSuiteCategory; import org.nanopub.vocabulary.NPX; import java.io.File; @@ -23,7 +25,17 @@ class NanopubElementTest { - private final File np = new File("src/test/resources/np-grlc-query.trig"); + /** + * The published "Get participation links" query. It lives in the nanopub test suite rather + * than in this repository, so that the fixture is shared with the other implementations + * instead of being copied into each of them (#620). + */ + private static final String QUERY_CODE = "RA6T-YLqLnYd5XfnqR9PaGUjCzudvHdYjcG4GvOc7fdpA"; + + private final File np = NanopubTestSuite.getLatest() + .getByArtifactCode(QUERY_CODE, TestSuiteCategory.VALID) + .orElseThrow(() -> new IllegalStateException("Not in the nanopub test suite: " + QUERY_CODE)) + .toFile(); @Test void getWithURI() throws MalformedNanopubException, IOException { diff --git a/src/test/java/com/knowledgepixels/nanodash/component/SparqlPlaceholderValidationTest.java b/src/test/java/com/knowledgepixels/nanodash/component/SparqlPlaceholderValidationTest.java index aebc4f31a..842cf6ec6 100644 --- a/src/test/java/com/knowledgepixels/nanodash/component/SparqlPlaceholderValidationTest.java +++ b/src/test/java/com/knowledgepixels/nanodash/component/SparqlPlaceholderValidationTest.java @@ -29,11 +29,8 @@ import org.nanopub.vocabulary.KPXL_GRLC; import org.nanopub.vocabulary.NTEMPLATE; -import java.util.Optional; - import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assumptions.assumeTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.when; @@ -124,7 +121,8 @@ void onlyTheSparqlHoldingPlaceholderIsRecognised() throws Exception { * The artifact code of the published "Defining a grlc query" template, which is what query * nanopublications are created from. It lives in the nanopub test suite rather than in this * repository, so that the fixture is shared with the other implementations instead of being - * copied into each of them. + * copied into each of them. Its absence is a failure rather than a reason to skip: it would + * mean the entry has been renamed or removed. */ private static final String QUERY_TEMPLATE_CODE = "RAEFAt-QcFK0ZhqfvlsmS10BnzGJA0xwOICZXkO-ai87k"; @@ -133,11 +131,11 @@ void onlyTheSparqlHoldingPlaceholderIsRecognised() throws Exception { // version of that template moves the SPARQL field, this fails rather than quietly skipping. @Test void theRealQueryTemplateHasItsSparqlFieldRecognised() throws Exception { - Optional entry = NanopubTestSuite.getLatest() - .getByArtifactCode(QUERY_TEMPLATE_CODE, TestSuiteCategory.VALID); - assumeTrue(entry.isPresent(), - "The grlc query template is not in the test suite yet: Nanopublication/nanopub-testsuite#5"); - Nanopub np = new NanopubImpl(entry.get().toFile(), RDFFormat.TRIG); + TestSuiteEntry entry = NanopubTestSuite.getLatest() + .getByArtifactCode(QUERY_TEMPLATE_CODE, TestSuiteCategory.VALID) + .orElseThrow(() -> new IllegalStateException( + "Not in the nanopub test suite: " + QUERY_TEMPLATE_CODE)); + Nanopub np = new NanopubImpl(entry.toFile(), RDFFormat.TRIG); Template template = TemplateTestUtil.parseTemplate(np); String base = np.getUri().stringValue() + "/"; assertTrue(template.isSparqlPlaceholder(vf.createIRI(base + "sparql"))); diff --git a/src/test/java/com/knowledgepixels/nanodash/component/StatusLineTest.java b/src/test/java/com/knowledgepixels/nanodash/component/StatusLineTest.java index a4e752332..37d135832 100644 --- a/src/test/java/com/knowledgepixels/nanodash/component/StatusLineTest.java +++ b/src/test/java/com/knowledgepixels/nanodash/component/StatusLineTest.java @@ -10,6 +10,9 @@ import org.nanopub.NanopubImpl; import org.nanopub.extra.services.ApiResponse; import org.nanopub.extra.services.ApiResponseEntry; +import org.nanopub.testsuite.NanopubTestSuite; +import org.nanopub.testsuite.TestSuiteCategory; +import org.nanopub.testsuite.TestSuiteEntry; import java.io.File; @@ -20,6 +23,15 @@ class StatusLineTest { + /** + * A published retraction, which is one of the shapes a status line is drawn from. It lives + * in the nanopub test suite rather than in this repository, so that the fixture is shared + * with the other implementations instead of being copied into each of them (#620). Its + * absence is a failure rather than a reason to skip: it would mean the entry has been + * renamed or removed. + */ + private static final String RETRACTION_CODE = "RA58YcJyv1h-UmS8jI6UfFP6_LTAh59GTgpU_4lvBv7a4"; + private WicketTester wicketTester; @BeforeEach @@ -37,7 +49,10 @@ private static ApiResponseEntry entry(String newerVersion, String retractedBy, S @Test void createComponentReturnsNonNullComponent() throws Exception { - Nanopub np = new NanopubImpl(new File("src/test/resources/np-statusline-example.trig"), RDFFormat.TRIG); + TestSuiteEntry entry = NanopubTestSuite.getLatest() + .getByArtifactCode(RETRACTION_CODE, TestSuiteCategory.VALID) + .orElseThrow(() -> new IllegalStateException("Not in the nanopub test suite: " + RETRACTION_CODE)); + Nanopub np = new NanopubImpl(entry.toFile(), RDFFormat.TRIG); Component component = StatusLine.createComponent("statusLine", np); assertNotNull(component); diff --git a/src/test/resources/np-grlc-query.trig b/src/test/resources/np-grlc-query.trig deleted file mode 100644 index 7c97dfdc5..000000000 --- a/src/test/resources/np-grlc-query.trig +++ /dev/null @@ -1,73 +0,0 @@ -@prefix this: . -@prefix sub: . -@prefix np: . -@prefix dct: . -@prefix nt: . -@prefix npx: . -@prefix xsd: . -@prefix rdfs: . -@prefix orcid: . -@prefix ns1: . -@prefix prov: . -@prefix foaf: . - -sub:Head { - this: np:hasAssertion sub:assertion; - np:hasProvenance sub:provenance; - np:hasPublicationInfo sub:pubinfo; - a np:Nanopublication . -} - -sub:assertion { - sub:get-participation dct:description "This query returns all participation links."; - dct:license ; - a ; - rdfs:label "Get participation links"; - ; - """prefix rdfs: -prefix dct: -prefix np: -prefix npa: -prefix npx: -prefix wd: - -select ?person ?event ?np ?date where { - graph npa:graph { - ?np npa:hasValidSignatureForPublicKey ?pubkey . - filter not exists { ?npx npx:invalidates ?np ; npa:hasValidSignatureForPublicKey ?pubkey . } - ?np dct:created ?date . - ?np np:hasAssertion ?a . - optional { ?np rdfs:label ?label } - } - graph ?a { - ?person wd:P1344 ?event . - } -} order by desc(?date)""" . -} - -sub:provenance { - sub:assertion prov:wasAttributedTo orcid:0000-0002-1267-0234 . -} - -sub:pubinfo { - orcid:0000-0002-1267-0234 foaf:name "Tobias Kuhn" . - - this: dct:created "2025-06-03T10:39:46.322Z"^^xsd:dateTime; - dct:creator orcid:0000-0002-1267-0234; - dct:license ; - npx:embeds sub:get-participation; - npx:supersedes ; - npx:wasCreatedAt ; - a npx:ExampleNanopub; - nt:wasCreatedFromProvenanceTemplate ; - nt:wasCreatedFromPubinfoTemplate ns1:RAXflINqt3smqxV5Aq7E9lzje4uLdkKIOefa6Bp8oJ8CY, - , , - ; - nt:wasCreatedFromTemplate . - - sub:sig npx:hasAlgorithm "RSA"; - npx:hasPublicKey "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQD4Wj537OijfOWVtsHMznuXKISqBhtGDQZfdO6pbb4hg9EHMcUFGTLbWaPrP783PHv8HMAAPjvEkHLaOHMIknqhaIa5236lfBO3r+ljVdYBElBcLvROmwG+ZGtmPNZf7lMhI15xf5TfoaSa84AFRd5J2EXekK6PhaFQhRm1IpSYtwIDAQAB"; - npx:hasSignature "bmf4gPxGC32ednx00sJ13pB+6dNtwfPR+ev7RzVRtSqr5IHR8I4URq44kS4xTLKY7ZeHsfLLoFavN9PqJIhsMRjeXRoxUVSYLBUPTPY5s1nGKKvgp9ktx1kTU8RJuiBJ5Un0VA612dmNxbrU/G6Ul9gsE0bRjiN6WF7RTfY3izA="; - npx:hasSignatureTarget this:; - npx:signedBy orcid:0000-0002-1267-0234 . -} diff --git a/src/test/resources/np-statusline-example.trig b/src/test/resources/np-statusline-example.trig deleted file mode 100644 index ffc416b78..000000000 --- a/src/test/resources/np-statusline-example.trig +++ /dev/null @@ -1,39 +0,0 @@ -@prefix this: . -@prefix sub: . -@prefix np: . -@prefix dct: . -@prefix pav: . -@prefix rdf: . -@prefix owl: . -@prefix rdfg: . -@prefix dce: . -@prefix xsd: . -@prefix rdfs: . -@prefix prov: . -@prefix npx: . - -sub:Head { - this: a np:Nanopublication; - np:hasAssertion sub:assertion; - np:hasProvenance sub:provenance; - np:hasPublicationInfo sub:pubinfo . -} - -sub:assertion { - npx:retracts . -} - -sub:provenance { - sub:assertion prov:wasAttributedTo . -} - -sub:pubinfo { - this: dct:creator . - - sub:sig npx:hasAlgorithm "RSA"; - npx:hasPublicKey "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApbztY8l4lWqVF8L/djJ1knoc7Nm5kVHT9NqSe0fXO9Hel3DRO2IyxJYVEvThhllBuHNtZK32ww23AlglArokhxPCSBPKvVgQS6r46khF2D85tnd5htaBq+bfjMqL+LDlQh3LdBpAqrLmsmfsPkU65CCxSGufBs2v39p41z5FkRXE1JKJ/UZe+1OUq+CibjOfo1g1Nz6HO0fZML7GnQBj5X9lvU0llmDk/sqdNMxAJDSQh2/Zh0kz7+Dm7vJOx3mNEXU4FuzVzKBYwTotvEcJod7Vot1fPOJXPGoNDVNKMQffCala9o4pqT739LS7R7ZFVMjzPkLUxYCjnEgOZI5t6wIDAQAB"; - npx:hasSignature "b02egVbAt/XzvcLq12zscVfRJYYeC/d7Vc8bV+EEoYFT9Mk2zT2eE/wugXCTsB1DalLrtjyHd1r9xiBKyZuj161O8b5KKlYUYvEh4wpnd6xdJevGH9Ad9LK+VI3a5dNXVxJAKlYX87MvuHPohLeu0EHT1IochUDyAVWtU7roHaxJHZ6SB4FnJv6XrJ2detnkx2LeT6nNLUvPxgE62qjdML2hgEhZNDVTCma7/ub6gk0n5MIgtthX8IpafvJH9VvePtZg+L2pp3cGW2MQPFkG7fnnYlli6OX37yu1Q4YAS0JLubqPaUGL4rI82zkIT6CpLhJfU13TruqzzWZE30e1jQ=="; - npx:hasSignatureTarget this:; - npx:signedBy . -} - diff --git a/src/test/resources/templates/new-style-assertion-template.trig b/src/test/resources/templates/new-style-assertion-template.trig deleted file mode 100644 index 20c9be60d..000000000 --- a/src/test/resources/templates/new-style-assertion-template.trig +++ /dev/null @@ -1,47 +0,0 @@ -@prefix this: . -@prefix sub: . -@prefix np: . -@prefix dct: . -@prefix npx: . -@prefix nt: . -@prefix xsd: . -@prefix rdf: . -@prefix rdfs: . -@prefix prov: . - -sub:Head { - this: a np:Nanopublication ; - np:hasAssertion sub:assertion ; - np:hasProvenance sub:provenance ; - np:hasPublicationInfo sub:pubinfo . -} - -sub:assertion { - sub:template a nt:AssertionTemplate ; - dct:isVersionOf sub:test-template-kind ; - rdfs:label "Test template with embedded identity" ; - dct:description "A test template whose template node is an embedded IRI (not the assertion graph URI), per docs/template-identity-and-governance.md." ; - nt:hasStatement sub:st01 . - - sub:st01 rdf:subject sub:thing ; - rdf:predicate rdfs:label ; - rdf:object sub:name . - - sub:thing a nt:UriPlaceholder ; - rdfs:label "URI of the thing to label" . - - sub:name a nt:LiteralPlaceholder ; - rdfs:label "label text" . -} - -sub:provenance { - sub:assertion prov:wasAttributedTo . -} - -sub:pubinfo { - this: dct:created "2026-07-08T00:00:00Z"^^xsd:dateTime ; - dct:creator ; - dct:license ; - npx:embeds sub:template ; - npx:introduces sub:test-template-kind . -}