From 4e58b2b8db101c1003e03e45bde4889f9730d6bb Mon Sep 17 00:00:00 2001 From: sdevalk Date: Tue, 26 Nov 2024 21:54:37 +0100 Subject: [PATCH 1/9] add new props; update SPARQL queries --- .../api/src/research-guides/definitions.ts | 4 +- .../fetcher.integration.test.ts | 113 ++++++++++-------- packages/api/src/research-guides/fetcher.ts | 63 ++++++---- .../research-guides/index.integration.test.ts | 6 +- .../src/research-guides/rdf-helpers.test.ts | 60 +++++++++- .../api/src/research-guides/rdf-helpers.ts | 30 ++++- 6 files changed, 194 insertions(+), 82 deletions(-) diff --git a/packages/api/src/research-guides/definitions.ts b/packages/api/src/research-guides/definitions.ts index f73a2060..8eea51e8 100644 --- a/packages/api/src/research-guides/definitions.ts +++ b/packages/api/src/research-guides/definitions.ts @@ -1,12 +1,14 @@ -import {Place, Term, Thing} from '../definitions'; +import {Event, Place, Term, Thing} from '../definitions'; export type Citation = Thing & {url?: string}; export type ResearchGuide = Thing & { + alternateName?: string; identifier?: string; abstract?: string; text?: string; encodingFormat?: string; + contentReferenceTimes?: Event[]; contentLocations?: Place[]; keywords?: Term[]; citations?: Citation[]; diff --git a/packages/api/src/research-guides/fetcher.integration.test.ts b/packages/api/src/research-guides/fetcher.integration.test.ts index 288cccf4..7772a903 100644 --- a/packages/api/src/research-guides/fetcher.integration.test.ts +++ b/packages/api/src/research-guides/fetcher.integration.test.ts @@ -23,90 +23,90 @@ describe('getTopLevels', () => { 'Research aides for conducting provenance research into colonial collections', text: 'On this page you find various research aides that can assist...', encodingFormat: 'text/markdown', - seeAlso: expect.arrayContaining([ + seeAlso: [ { - id: 'https://guides.example.org/level-3-set', - identifier: '3', - seeAlso: expect.arrayContaining([ + id: 'https://guides.example.org/sub-set-2', + name: 'Name 2', + seeAlso: [ { - id: 'https://guides.example.org/level-3c', - name: 'Kunsthandel Van Lier', + id: 'https://guides.example.org/sub-set-2a', + name: 'Military and navy', seeAlso: [ { - id: 'https://guides.example.org/level-2a', - name: 'Military and navy', + id: 'https://guides.example.org/sub-set-3a', + name: 'Royal Cabinet of Curiosities', }, ], }, { - id: 'https://guides.example.org/level-3a', - name: 'Royal Cabinet of Curiosities', + id: 'https://guides.example.org/sub-set-2c', + name: 'Trade', seeAlso: [ { - id: 'https://guides.example.org/level-2c', - name: 'Trade', + id: 'https://guides.example.org/sub-set-3c', + name: 'Kunsthandel Van Lier', }, ], }, - ]), + ], }, { - id: 'https://guides.example.org/level-2-set', - identifier: '2', - seeAlso: expect.arrayContaining([ + id: 'https://guides.example.org/sub-set-3', + name: 'Name 3', + seeAlso: [ { - id: 'https://guides.example.org/level-2c', - name: 'Trade', + id: 'https://guides.example.org/sub-set-3c', + name: 'Kunsthandel Van Lier', seeAlso: [ { - id: 'https://guides.example.org/level-3c', - name: 'Kunsthandel Van Lier', + id: 'https://guides.example.org/sub-set-2a', + name: 'Military and navy', }, ], }, { - id: 'https://guides.example.org/level-2a', - name: 'Military and navy', + id: 'https://guides.example.org/sub-set-3a', + name: 'Royal Cabinet of Curiosities', seeAlso: [ { - id: 'https://guides.example.org/level-3a', - name: 'Royal Cabinet of Curiosities', + id: 'https://guides.example.org/sub-set-2c', + name: 'Trade', }, ], }, - ]), + ], }, { - id: 'https://guides.example.org/level-1-set', - identifier: '1', - seeAlso: expect.arrayContaining([ + id: 'https://guides.example.org/sub-set-1', + name: 'Name 1', + seeAlso: [ { - id: 'https://guides.example.org/level-1b', + id: 'https://guides.example.org/sub-set-1b', name: 'How can I use the data hub for my research?', }, { - id: 'https://guides.example.org/level-1c', + id: 'https://guides.example.org/sub-set-1c', name: 'Sources', seeAlso: [ { - id: 'https://guides.example.org/level-2c', + id: 'https://guides.example.org/sub-set-2c', name: 'Trade', }, ], }, { - id: 'https://guides.example.org/level-1a', + id: 'https://guides.example.org/sub-set-1a', name: 'Doing research', seeAlso: [ { - id: 'https://guides.example.org/level-2a', + id: 'https://guides.example.org/sub-set-2a', name: 'Military and navy', }, ], }, - ]), + ], }, - ]), + ], }, ]); }); @@ -130,17 +130,17 @@ describe('getByIds', () => { it('returns the research guides that match the IDs', async () => { const researchGuides = await researchGuideFetcher.getByIds({ ids: [ - 'https://guides.example.org/level-2a', - 'https://guides.example.org/level-2c', + 'https://guides.example.org/sub-set-1a', + 'https://guides.example.org/sub-set-2a', ], }); expect(researchGuides).toMatchObject([ { - id: 'https://guides.example.org/level-2a', + id: 'https://guides.example.org/sub-set-1a', }, { - id: 'https://guides.example.org/level-2c', + id: 'https://guides.example.org/sub-set-2a', }, ]); }); @@ -165,19 +165,34 @@ describe('getById', () => { it('returns the research guide that matches the ID', async () => { const researchGuide = await researchGuideFetcher.getById({ - id: 'https://guides.example.org/level-2a', + id: 'https://guides.example.org/sub-set-2a', }); expect(researchGuide).toStrictEqual({ - id: 'https://guides.example.org/level-2a', + id: 'https://guides.example.org/sub-set-2a', name: 'Military and navy', + alternateName: 'Navy', abstract: 'Army and Navy personnel who operated in colonized territories collected objects in various ways during the colonial era.', text: 'Dutch authority in the [Dutch East Indies](https://www.geonames.org/1643084/republic-of-indonesia.html), [Suriname](https://www.geonames.org/3382998/republic-of-suriname.html) and on the [Caribbean Islands](https://www.geonames.org/8505032/netherlands-antilles.html) relied heavily on the use of the military...', encodingFormat: 'text/markdown', + contentReferenceTimes: [ + { + id: expect.stringContaining( + 'https://data.colonialcollections.nl/.well-known/genid/' + ), + date: { + id: expect.stringContaining( + 'https://data.colonialcollections.nl/.well-known/genid/' + ), + startDate: new Date('1924-01-01T00:00:00.000Z'), + endDate: new Date('1996-12-31T23:59:59.999Z'), + }, + }, + ], seeAlso: expect.arrayContaining([ { - id: 'https://guides.example.org/level-3a', + id: 'https://guides.example.org/sub-set-3a', name: 'Royal Cabinet of Curiosities', }, ]), @@ -217,19 +232,20 @@ describe('getById', () => { describe('get with localized names', () => { it('returns a research guide with English names', async () => { const researchGuide = await researchGuideFetcher.getById({ - id: 'https://guides.example.org/level-2a', + id: 'https://guides.example.org/sub-set-2a', locale: 'en', }); expect(researchGuide).toMatchObject({ - id: 'https://guides.example.org/level-2a', + id: 'https://guides.example.org/sub-set-2a', name: 'Military and navy', + alternateName: 'Navy', abstract: 'Army and Navy personnel who operated in colonized territories collected objects in various ways during the colonial era.', text: 'Dutch authority in the [Dutch East Indies](https://www.geonames.org/1643084/republic-of-indonesia.html), [Suriname](https://www.geonames.org/3382998/republic-of-suriname.html) and on the [Caribbean Islands](https://www.geonames.org/8505032/netherlands-antilles.html) relied heavily on the use of the military...', seeAlso: expect.arrayContaining([ { - id: 'https://guides.example.org/level-3a', + id: 'https://guides.example.org/sub-set-3a', name: 'Royal Cabinet of Curiosities', }, ]), @@ -255,19 +271,20 @@ describe('get with localized names', () => { it('returns a research guide with Dutch names', async () => { const researchGuide = await researchGuideFetcher.getById({ - id: 'https://guides.example.org/level-2a', + id: 'https://guides.example.org/sub-set-2a', locale: 'nl', }); expect(researchGuide).toMatchObject({ - id: 'https://guides.example.org/level-2a', + id: 'https://guides.example.org/sub-set-2a', name: 'Leger en Marine', + alternateName: 'Marine', abstract: 'Leger- en marinepersoneel dat actief was in gekoloniseerde gebieden, verzamelde op verschillende manieren objecten tijdens het koloniale tijdperk.', text: 'Het Nederlandse gezag in [Nederlands-Indië](https://www.geonames.org/1643084/republic-of-indonesia.html), [Suriname](https://www.geonames.org/3382998/republic-of-suriname.html) en op de [Caribische eilanden](https://www.geonames.org/8505032/netherlands-antilles.html) steunde in belangrijke mate op de inzet van het leger.', seeAlso: expect.arrayContaining([ { - id: 'https://guides.example.org/level-3a', + id: 'https://guides.example.org/sub-set-3a', name: 'Koninklijk Kabinet van Zeldzaamheden', }, ]), diff --git a/packages/api/src/research-guides/fetcher.ts b/packages/api/src/research-guides/fetcher.ts index 39ca255c..4b4743b7 100644 --- a/packages/api/src/research-guides/fetcher.ts +++ b/packages/api/src/research-guides/fetcher.ts @@ -70,7 +70,7 @@ export class ResearchGuideFetcher { ex:seeAlso ?subSet . ?subSet a ex:CreativeWork ; - ex:identifier ?identifier ; + ex:name ?subSetName ; ex:seeAlso ?guide . ?guide a ex:CreativeWork ; @@ -86,7 +86,7 @@ export class ResearchGuideFetcher { } OPTIONAL { - ?topSet schema:name ?topSetName ; + ?topSet schema:name ?topSetName FILTER(LANG(?topSetName) = "${options.locale}") } @@ -96,7 +96,7 @@ export class ResearchGuideFetcher { } OPTIONAL { - ?topSet schema:text ?topSetText ; + ?topSet schema:text ?topSetText FILTER(LANG(?topSetText) = "${options.locale}") } @@ -106,10 +106,8 @@ export class ResearchGuideFetcher { OPTIONAL { ?topSet la:has_member ?subSet . - - OPTIONAL { - ?subSet crm:P1_is_identified_by/crm:P190_has_symbolic_content ?identifier - } + ?subSet schema:name ?subSetName + FILTER(LANG(?subSetName) = "${options.locale}") # Get a selection of information from member guides, if any OPTIONAL { @@ -171,20 +169,22 @@ export class ResearchGuideFetcher { CONSTRUCT { ?this a ex:CreativeWork ; ex:name ?name ; + ex:alternateName ?alternateName ; ex:abstract ?abstract ; ex:text ?text ; ex:encodingFormat ?encodingFormat ; ex:seeAlso ?relatedGuide ; - ex:contentLocation ?contentLocation ; + ex:contentLocation ?spatial ; ex:keyword ?keyword ; - ex:citation ?citation . + ex:citation ?citation ; + ex:contentReferenceTime ?contentReferenceTime . ?relatedGuide a ex:CreativeWork ; ex:name ?relatedGuideName . - ?contentLocation a ex:Place ; - ex:name ?contentLocationName ; - ex:sameAs ?contentLocationSameAs . + ?spatial a ex:Place ; + ex:name ?spatialName ; + ex:sameAs ?spatialSameAs . ?keyword a ex:DefinedTerm ; ex:name ?keywordName ; @@ -194,6 +194,10 @@ export class ResearchGuideFetcher { ex:name ?citationName ; ex:description ?citationDescription ; ex:url ?citationUrl . + + ?contentReferenceTime a ex:Event ; + ex:startDate ?contentReferenceTimeStartDate ; + ex:endDate ?contentReferenceTimeEndDate . } WHERE { VALUES ?this { @@ -204,22 +208,27 @@ export class ResearchGuideFetcher { schema:additionalType . # "Guides" OPTIONAL { - ?this schema:name ?name . + ?this schema:name ?name FILTER(LANG(?name) = "${options.locale}") } OPTIONAL { - ?this schema:abstract ?abstract . + ?this schema:alternateName ?alternateName + FILTER(LANG(?alternateName) = "${options.locale}") + } + + OPTIONAL { + ?this schema:abstract ?abstract FILTER(LANG(?abstract) = "${options.locale}") } OPTIONAL { - ?this schema:text ?text . + ?this schema:text ?text FILTER(LANG(?text) = "${options.locale}") } OPTIONAL { - ?this schema:encodingFormat ?encodingFormat . + ?this schema:encodingFormat ?encodingFormat } # Get a selection of information from related guides, if any @@ -230,15 +239,15 @@ export class ResearchGuideFetcher { } OPTIONAL { - ?this schema:contentLocation ?contentLocation . + ?this schema:spatial ?spatial . OPTIONAL { - ?contentLocation schema:name ?contentLocationName . - FILTER(LANG(?contentLocationName) = "${options.locale}") + ?spatial schema:name ?spatialName + FILTER(LANG(?spatialName) = "${options.locale}") } OPTIONAL { - ?contentLocation schema:sameAs ?contentLocationSameAs + ?spatial schema:sameAs ?spatialSameAs } } @@ -246,7 +255,7 @@ export class ResearchGuideFetcher { ?this schema:keywords ?keyword . OPTIONAL { - ?keyword schema:name ?keywordName . + ?keyword schema:name ?keywordName FILTER(LANG(?keywordName) = "${options.locale}") } @@ -259,19 +268,25 @@ export class ResearchGuideFetcher { ?this schema:citation ?citation . OPTIONAL { - ?citation schema:name ?citationName . + ?citation schema:name ?citationName FILTER(LANG(?citationName) = "${options.locale}") } OPTIONAL { - ?citation schema:description ?citationDescription . + ?citation schema:description ?citationDescription FILTER(LANG(?citationDescription) = "${options.locale}") } OPTIONAL { - ?citation schema:url ?citationUrl . + ?citation schema:url ?citationUrl } } + + OPTIONAL { + ?this schema:contentReferenceTime ?contentReferenceTime . + ?contentReferenceTime schema:startDate ?contentReferenceTimeStartDate ; + schema:endDate ?contentReferenceTimeEndDate . + } } `; diff --git a/packages/api/src/research-guides/index.integration.test.ts b/packages/api/src/research-guides/index.integration.test.ts index bc13d1f1..cecba100 100644 --- a/packages/api/src/research-guides/index.integration.test.ts +++ b/packages/api/src/research-guides/index.integration.test.ts @@ -26,8 +26,8 @@ describe('getByIds', () => { it('returns the research guides', async () => { const results = await researchGuides.getByIds({ ids: [ - 'https://guides.example.org/level-2a', - 'https://guides.example.org/level-2c', + 'https://guides.example.org/sub-set-1a', + 'https://guides.example.org/sub-set-2a', ], }); @@ -38,7 +38,7 @@ describe('getByIds', () => { describe('getById', () => { it('returns the research guide', async () => { const researchGuide = await researchGuides.getById({ - id: 'https://guides.example.org/level-2a', + id: 'https://guides.example.org/sub-set-1a', }); expect(researchGuide).not.toBeUndefined(); diff --git a/packages/api/src/research-guides/rdf-helpers.test.ts b/packages/api/src/research-guides/rdf-helpers.test.ts index 88c88895..aafa71c3 100644 --- a/packages/api/src/research-guides/rdf-helpers.test.ts +++ b/packages/api/src/research-guides/rdf-helpers.test.ts @@ -2,7 +2,11 @@ import {describe, expect, it} from '@jest/globals'; import {StreamParser} from 'n3'; import {RdfObjectLoader, Resource} from 'rdf-object'; import streamifyString from 'streamify-string'; -import {createCitations, createResearchGuide} from './rdf-helpers'; +import { + createCitations, + createEvents, + createResearchGuide, +} from './rdf-helpers'; const loader = new RdfObjectLoader({ context: { @@ -21,9 +25,15 @@ beforeAll(async () => { ex:researchGuide2 a ex:CreativeWork ; ex:identifier "1" ; ex:name "Name 2" ; + ex:alternateName "Alternate name 2" ; ex:abstract "Abstract 2" ; ex:text "Text" ; ex:encodingFormat "text/html" ; + ex:contentReferenceTime [ + a ex:Event ; + ex:startDate "1924" ; + ex:endDate "1996" ; + ] ; ex:contentLocation [ ex:name "Content Location" ; ex:sameAs ; @@ -65,6 +75,35 @@ beforeAll(async () => { await loader.import(streamParser); }); +describe('contentReferenceTimes', () => { + let resource: Resource; + + beforeEach(() => { + resource = loader.resources['https://example.org/researchGuide2']; + }); + + it('returns undefined if property does not exist', () => { + const citations = createCitations(resource, 'ex:unknown'); + + expect(citations).toBeUndefined(); + }); + + it('returns events if property exists', () => { + const events = createEvents(resource, 'ex:contentReferenceTime'); + + expect(events).toStrictEqual([ + { + id: expect.any(String), + date: { + id: expect.any(String), + startDate: new Date('1924-01-01T00:00:00.000Z'), + endDate: new Date('1996-12-31T23:59:59.999Z'), + }, + }, + ]); + }); +}); + describe('createCitations', () => { let resource: Resource; @@ -83,7 +122,7 @@ describe('createCitations', () => { expect(citations).toStrictEqual([ { - id: 'n3-2', + id: expect.any(String), name: 'Citation', description: 'Citation Description', url: 'https://example.org/citation', @@ -111,9 +150,20 @@ describe('createResearchGuide', () => { id: 'https://example.org/researchGuide2', identifier: '1', name: 'Name 2', + alternateName: 'Alternate name 2', abstract: 'Abstract 2', text: 'Text', encodingFormat: 'text/html', + contentReferenceTimes: [ + { + id: expect.any(String), + date: { + id: expect.any(String), + startDate: new Date('1924-01-01T00:00:00.000Z'), + endDate: new Date('1996-12-31T23:59:59.999Z'), + }, + }, + ], seeAlso: [ { id: 'https://example.org/researchGuide3', @@ -136,21 +186,21 @@ describe('createResearchGuide', () => { ], contentLocations: [ { - id: 'n3-0', + id: expect.any(String), name: 'Content Location', sameAs: 'https://example.org/place', }, ], keywords: [ { - id: 'n3-1', + id: expect.any(String), name: 'Keyword', sameAs: 'https://example.org/keyword', }, ], citations: [ { - id: 'n3-2', + id: expect.any(String), name: 'Citation', description: 'Citation Description', url: 'https://example.org/citation', diff --git a/packages/api/src/research-guides/rdf-helpers.ts b/packages/api/src/research-guides/rdf-helpers.ts index f09bdbd2..b60fbd4e 100644 --- a/packages/api/src/research-guides/rdf-helpers.ts +++ b/packages/api/src/research-guides/rdf-helpers.ts @@ -1,13 +1,14 @@ import { createPlaces, createThings, + createTimeSpan, getPropertyValues, onlyOne, removeNullish, } from '../rdf-helpers'; import type {Resource} from 'rdf-object'; import {Citation, ResearchGuide} from './definitions'; -import {Term} from '../definitions'; +import {Event, Term} from '../definitions'; function createCitation(citationResource: Resource) { const name = onlyOne(getPropertyValues(citationResource, 'ex:name')); @@ -46,6 +47,24 @@ function createResearchGuides( return researchGuides.length > 0 ? researchGuides : undefined; } +function createEvent(eventResource: Resource) { + const timespan = createTimeSpan(eventResource); + + const event: Event = { + id: eventResource.value, + date: timespan, + }; + + return event; +} + +export function createEvents(resource: Resource, propertyName: string) { + const properties = resource.properties[propertyName]; + const events = properties.map(property => createEvent(property)); + + return events.length > 0 ? events : undefined; +} + export function createResearchGuide( researchGuideResource: Resource, stackSize = 1 @@ -54,6 +73,9 @@ export function createResearchGuide( getPropertyValues(researchGuideResource, 'ex:identifier') ); const name = onlyOne(getPropertyValues(researchGuideResource, 'ex:name')); + const alternateName = onlyOne( + getPropertyValues(researchGuideResource, 'ex:alternateName') + ); const abstract = onlyOne( getPropertyValues(researchGuideResource, 'ex:abstract') ); @@ -73,6 +95,10 @@ export function createResearchGuide( ); } + const contentReferenceTimes = createEvents( + researchGuideResource, + 'ex:contentReferenceTime' + ); const contentLocations = createPlaces( researchGuideResource, 'ex:contentLocation' @@ -84,9 +110,11 @@ export function createResearchGuide( id: researchGuideResource.value, identifier, name, + alternateName, abstract, text, encodingFormat, + contentReferenceTimes, seeAlso, contentLocations, keywords, From 2f37072fda86e902164d9551a9e03d9efa14e3fe Mon Sep 17 00:00:00 2001 From: sdevalk Date: Tue, 26 Nov 2024 21:55:15 +0100 Subject: [PATCH 2/9] fix integration tests --- .../src/datasets/index.integration.test.ts | 2 +- .../src/datasets/searcher.integration.test.ts | 9 +++++++-- packages/api/src/definitions.ts | 5 +++++ ...-constituents-wikidata.integration.test.ts | 18 +++++++++--------- .../src/objects/searcher.integration.test.ts | 19 +++++++++++++++++++ 5 files changed, 41 insertions(+), 12 deletions(-) diff --git a/packages/api/src/datasets/index.integration.test.ts b/packages/api/src/datasets/index.integration.test.ts index 58ff3be6..e8d5981f 100644 --- a/packages/api/src/datasets/index.integration.test.ts +++ b/packages/api/src/datasets/index.integration.test.ts @@ -30,7 +30,7 @@ describe('search', () => { const result = await datasets.search(); expect(result).toMatchObject({ - totalCount: 14, + totalCount: 15, }); }); }); diff --git a/packages/api/src/datasets/searcher.integration.test.ts b/packages/api/src/datasets/searcher.integration.test.ts index 0fc43ba1..ad00a222 100644 --- a/packages/api/src/datasets/searcher.integration.test.ts +++ b/packages/api/src/datasets/searcher.integration.test.ts @@ -21,7 +21,7 @@ describe('search', () => { const result = await datasetSearcher.search(); expect(result).toStrictEqual({ - totalCount: 14, + totalCount: 15, offset: 0, limit: 10, sortBy: 'name', @@ -687,6 +687,11 @@ describe('search', () => { id: 'The Museum', name: 'The Museum', }, + { + totalCount: 1, + id: 'NIOD Institute for War, Holocaust and Genocide Studies', + name: 'NIOD Institute for War, Holocaust and Genocide Studies', + }, { totalCount: 1, id: 'Research Organisation', @@ -695,7 +700,7 @@ describe('search', () => { ], licenses: [ { - totalCount: 6, + totalCount: 7, id: 'CC0 1.0 Universal (CC0 1.0) Public Domain Dedication', name: 'CC0 1.0 Universal (CC0 1.0) Public Domain Dedication', }, diff --git a/packages/api/src/definitions.ts b/packages/api/src/definitions.ts index cc815383..557dd35e 100644 --- a/packages/api/src/definitions.ts +++ b/packages/api/src/definitions.ts @@ -76,6 +76,11 @@ export type HeritageObject = Thing & { isPartOf?: Dataset; }; +export type Event = { + id: string; + date?: TimeSpan; +}; + export enum ProvenanceEventType { Acquisition = 'acquisition', TransferOfCustody = 'transferOfCustody', diff --git a/packages/api/src/enrichments/searcher-constituents-wikidata.integration.test.ts b/packages/api/src/enrichments/searcher-constituents-wikidata.integration.test.ts index 2acb0687..0e297bbd 100644 --- a/packages/api/src/enrichments/searcher-constituents-wikidata.integration.test.ts +++ b/packages/api/src/enrichments/searcher-constituents-wikidata.integration.test.ts @@ -25,14 +25,14 @@ describe('search', () => { description: 'uitgeverij uit Utrecht', }, { - id: 'http://www.wikidata.org/entity/Q105964347', + id: 'http://www.wikidata.org/entity/Q131287465', name: 'Rembrandt', - description: 'Metaalwarenfabriek Rembrandt BV', + description: 'fotograaf', }, { - id: 'http://www.wikidata.org/entity/Q17330745', - name: 'Rembrandts vader', - description: 'Nederlands acteur', + id: 'http://www.wikidata.org/entity/Q375926', + name: 'Rembrandt Peale', + description: 'Amerikaans kunstschilder (1778-1860)', }, ], }); @@ -48,9 +48,9 @@ describe('search', () => { expect(result).toStrictEqual({ things: [ { - id: 'http://www.wikidata.org/entity/Q352864', - name: 'Pieter Lastman', - description: 'Dutch painter', + id: 'http://www.wikidata.org/entity/Q29885090', + name: 'Neeltje Willemsdr. Zuytbrouck', + description: "Rembrandt's mother", }, { id: 'http://www.wikidata.org/entity/Q105964347', @@ -60,7 +60,7 @@ describe('search', () => { { id: 'http://www.wikidata.org/entity/Q1300641', name: 'Rembrandt Bugatti', - description: '1884-1916 Italian sculptor', + description: 'Italian sculptor (1884–1916)', }, ], }); diff --git a/packages/api/src/objects/searcher.integration.test.ts b/packages/api/src/objects/searcher.integration.test.ts index 19b04cea..db888f6d 100644 --- a/packages/api/src/objects/searcher.integration.test.ts +++ b/packages/api/src/objects/searcher.integration.test.ts @@ -108,6 +108,25 @@ describe('search', () => { name: 'Vincent van Gogh', }, ]), + types: expect.arrayContaining([ + { + id: expect.stringContaining( + 'https://data.colonialcollections.nl/.well-known/genid/' + ), + }, + ]), + materials: expect.arrayContaining([ + { + id: expect.stringContaining( + 'https://data.colonialcollections.nl/.well-known/genid/' + ), + }, + { + id: expect.stringContaining( + 'https://data.colonialcollections.nl/.well-known/genid/' + ), + }, + ]), dateCreated: { id: expect.stringContaining( 'https://data.colonialcollections.nl/.well-known/genid/' From 637a1e4f17fd481094de069aaea00145275301d0 Mon Sep 17 00:00:00 2001 From: sdevalk Date: Wed, 27 Nov 2024 05:16:49 +0100 Subject: [PATCH 3/9] remove obsolete 'identifier' prop --- packages/api/src/research-guides/definitions.ts | 1 - packages/api/src/research-guides/rdf-helpers.test.ts | 2 -- packages/api/src/research-guides/rdf-helpers.ts | 4 ---- 3 files changed, 7 deletions(-) diff --git a/packages/api/src/research-guides/definitions.ts b/packages/api/src/research-guides/definitions.ts index 8eea51e8..29d0bcb9 100644 --- a/packages/api/src/research-guides/definitions.ts +++ b/packages/api/src/research-guides/definitions.ts @@ -4,7 +4,6 @@ export type Citation = Thing & {url?: string}; export type ResearchGuide = Thing & { alternateName?: string; - identifier?: string; abstract?: string; text?: string; encodingFormat?: string; diff --git a/packages/api/src/research-guides/rdf-helpers.test.ts b/packages/api/src/research-guides/rdf-helpers.test.ts index aafa71c3..b5b82191 100644 --- a/packages/api/src/research-guides/rdf-helpers.test.ts +++ b/packages/api/src/research-guides/rdf-helpers.test.ts @@ -23,7 +23,6 @@ beforeAll(async () => { ex:name "Name 1" . ex:researchGuide2 a ex:CreativeWork ; - ex:identifier "1" ; ex:name "Name 2" ; ex:alternateName "Alternate name 2" ; ex:abstract "Abstract 2" ; @@ -148,7 +147,6 @@ describe('createResearchGuide', () => { expect(researchGuide).toStrictEqual({ id: 'https://example.org/researchGuide2', - identifier: '1', name: 'Name 2', alternateName: 'Alternate name 2', abstract: 'Abstract 2', diff --git a/packages/api/src/research-guides/rdf-helpers.ts b/packages/api/src/research-guides/rdf-helpers.ts index b60fbd4e..ee173c67 100644 --- a/packages/api/src/research-guides/rdf-helpers.ts +++ b/packages/api/src/research-guides/rdf-helpers.ts @@ -69,9 +69,6 @@ export function createResearchGuide( researchGuideResource: Resource, stackSize = 1 ) { - const identifier = onlyOne( - getPropertyValues(researchGuideResource, 'ex:identifier') - ); const name = onlyOne(getPropertyValues(researchGuideResource, 'ex:name')); const alternateName = onlyOne( getPropertyValues(researchGuideResource, 'ex:alternateName') @@ -108,7 +105,6 @@ export function createResearchGuide( const researchGuideWithUndefinedValues: ResearchGuide = { id: researchGuideResource.value, - identifier, name, alternateName, abstract, From d6a97a0f4f7f41f4971c53ea73e8c76240cd9741 Mon Sep 17 00:00:00 2001 From: sdevalk Date: Sun, 1 Dec 2024 06:54:05 +0100 Subject: [PATCH 4/9] update number of retrievable levels; update tests with new URIs --- .../fetcher.integration.test.ts | 132 +++++++++++------- packages/api/src/research-guides/fetcher.ts | 4 +- .../research-guides/index.integration.test.ts | 6 +- .../api/src/research-guides/rdf-helpers.ts | 2 +- 4 files changed, 90 insertions(+), 54 deletions(-) diff --git a/packages/api/src/research-guides/fetcher.integration.test.ts b/packages/api/src/research-guides/fetcher.integration.test.ts index 7772a903..f58a6507 100644 --- a/packages/api/src/research-guides/fetcher.integration.test.ts +++ b/packages/api/src/research-guides/fetcher.integration.test.ts @@ -17,7 +17,7 @@ describe('getTopLevels', () => { // The sorting order is undefined and can change - don't use toStrictEqual() expect(researchGuides).toMatchObject([ { - id: 'https://guides.example.org/top-set', + id: 'https://guides.example.org/topset', name: 'Digital research guide', abstract: 'Research aides for conducting provenance research into colonial collections', @@ -25,82 +25,118 @@ describe('getTopLevels', () => { encodingFormat: 'text/markdown', seeAlso: [ { - id: 'https://guides.example.org/sub-set-2', - name: 'Name 2', + id: 'https://guides.example.org/subset1', + name: '1. Name', seeAlso: [ { - id: 'https://guides.example.org/sub-set-2a', - name: 'Military and navy', + id: 'https://guides.example.org/guide3', + name: 'Sources', seeAlso: [ { - id: 'https://guides.example.org/sub-set-3a', - name: 'Royal Cabinet of Curiosities', + id: 'https://guides.example.org/guide5', + name: 'Trade', + seeAlso: [ + { + id: 'https://guides.example.org/guide7', + name: 'Kunsthandel Van Lier', + }, + ], }, ], }, { - id: 'https://guides.example.org/sub-set-2c', - name: 'Trade', + id: 'https://guides.example.org/guide1', + name: 'Doing research', seeAlso: [ { - id: 'https://guides.example.org/sub-set-3c', - name: 'Kunsthandel Van Lier', + id: 'https://guides.example.org/guide4', + name: 'Military and navy', + seeAlso: [ + { + id: 'https://guides.example.org/guide6', + name: 'Royal Cabinet of Curiosities', + }, + ], }, ], }, + { + id: 'https://guides.example.org/guide2', + name: 'How can I use the data hub for my research?', + }, ], }, { - id: 'https://guides.example.org/sub-set-3', - name: 'Name 3', + id: 'https://guides.example.org/subset2', + name: '2. Name', seeAlso: [ { - id: 'https://guides.example.org/sub-set-3c', - name: 'Kunsthandel Van Lier', + id: 'https://guides.example.org/guide4', + name: 'Military and navy', seeAlso: [ { - id: 'https://guides.example.org/sub-set-2a', - name: 'Military and navy', + id: 'https://guides.example.org/guide6', + name: 'Royal Cabinet of Curiosities', + seeAlso: [ + { + id: 'https://guides.example.org/guide5', + name: 'Trade', + }, + ], }, ], }, { - id: 'https://guides.example.org/sub-set-3a', - name: 'Royal Cabinet of Curiosities', + id: 'https://guides.example.org/guide5', + name: 'Trade', seeAlso: [ { - id: 'https://guides.example.org/sub-set-2c', - name: 'Trade', + id: 'https://guides.example.org/guide7', + name: 'Kunsthandel Van Lier', + seeAlso: [ + { + id: 'https://guides.example.org/guide4', + name: 'Military and navy', + }, + ], }, ], }, ], }, { - id: 'https://guides.example.org/sub-set-1', - name: 'Name 1', + id: 'https://guides.example.org/subset3', + name: '3. Name', seeAlso: [ { - id: 'https://guides.example.org/sub-set-1b', - name: 'How can I use the data hub for my research?', - }, - { - id: 'https://guides.example.org/sub-set-1c', - name: 'Sources', + id: 'https://guides.example.org/guide7', + name: 'Kunsthandel Van Lier', seeAlso: [ { - id: 'https://guides.example.org/sub-set-2c', - name: 'Trade', + id: 'https://guides.example.org/guide4', + name: 'Military and navy', + seeAlso: [ + { + id: 'https://guides.example.org/guide6', + name: 'Royal Cabinet of Curiosities', + }, + ], }, ], }, { - id: 'https://guides.example.org/sub-set-1a', - name: 'Doing research', + id: 'https://guides.example.org/guide6', + name: 'Royal Cabinet of Curiosities', seeAlso: [ { - id: 'https://guides.example.org/sub-set-2a', - name: 'Military and navy', + id: 'https://guides.example.org/guide5', + name: 'Trade', + seeAlso: [ + { + id: 'https://guides.example.org/guide7', + name: 'Kunsthandel Van Lier', + }, + ], }, ], }, @@ -130,17 +166,17 @@ describe('getByIds', () => { it('returns the research guides that match the IDs', async () => { const researchGuides = await researchGuideFetcher.getByIds({ ids: [ - 'https://guides.example.org/sub-set-1a', - 'https://guides.example.org/sub-set-2a', + 'https://guides.example.org/guide1', + 'https://guides.example.org/guide4', ], }); expect(researchGuides).toMatchObject([ { - id: 'https://guides.example.org/sub-set-1a', + id: 'https://guides.example.org/guide1', }, { - id: 'https://guides.example.org/sub-set-2a', + id: 'https://guides.example.org/guide4', }, ]); }); @@ -165,11 +201,11 @@ describe('getById', () => { it('returns the research guide that matches the ID', async () => { const researchGuide = await researchGuideFetcher.getById({ - id: 'https://guides.example.org/sub-set-2a', + id: 'https://guides.example.org/guide4', }); expect(researchGuide).toStrictEqual({ - id: 'https://guides.example.org/sub-set-2a', + id: 'https://guides.example.org/guide4', name: 'Military and navy', alternateName: 'Navy', abstract: @@ -192,7 +228,7 @@ describe('getById', () => { ], seeAlso: expect.arrayContaining([ { - id: 'https://guides.example.org/sub-set-3a', + id: 'https://guides.example.org/guide6', name: 'Royal Cabinet of Curiosities', }, ]), @@ -232,12 +268,12 @@ describe('getById', () => { describe('get with localized names', () => { it('returns a research guide with English names', async () => { const researchGuide = await researchGuideFetcher.getById({ - id: 'https://guides.example.org/sub-set-2a', + id: 'https://guides.example.org/guide4', locale: 'en', }); expect(researchGuide).toMatchObject({ - id: 'https://guides.example.org/sub-set-2a', + id: 'https://guides.example.org/guide4', name: 'Military and navy', alternateName: 'Navy', abstract: @@ -245,7 +281,7 @@ describe('get with localized names', () => { text: 'Dutch authority in the [Dutch East Indies](https://www.geonames.org/1643084/republic-of-indonesia.html), [Suriname](https://www.geonames.org/3382998/republic-of-suriname.html) and on the [Caribbean Islands](https://www.geonames.org/8505032/netherlands-antilles.html) relied heavily on the use of the military...', seeAlso: expect.arrayContaining([ { - id: 'https://guides.example.org/sub-set-3a', + id: 'https://guides.example.org/guide6', name: 'Royal Cabinet of Curiosities', }, ]), @@ -271,12 +307,12 @@ describe('get with localized names', () => { it('returns a research guide with Dutch names', async () => { const researchGuide = await researchGuideFetcher.getById({ - id: 'https://guides.example.org/sub-set-2a', + id: 'https://guides.example.org/guide4', locale: 'nl', }); expect(researchGuide).toMatchObject({ - id: 'https://guides.example.org/sub-set-2a', + id: 'https://guides.example.org/guide4', name: 'Leger en Marine', alternateName: 'Marine', abstract: @@ -284,7 +320,7 @@ describe('get with localized names', () => { text: 'Het Nederlandse gezag in [Nederlands-Indië](https://www.geonames.org/1643084/republic-of-indonesia.html), [Suriname](https://www.geonames.org/3382998/republic-of-suriname.html) en op de [Caribische eilanden](https://www.geonames.org/8505032/netherlands-antilles.html) steunde in belangrijke mate op de inzet van het leger.', seeAlso: expect.arrayContaining([ { - id: 'https://guides.example.org/sub-set-3a', + id: 'https://guides.example.org/guide6', name: 'Koninklijk Kabinet van Zeldzaamheden', }, ]), diff --git a/packages/api/src/research-guides/fetcher.ts b/packages/api/src/research-guides/fetcher.ts index 4b4743b7..353b77ab 100644 --- a/packages/api/src/research-guides/fetcher.ts +++ b/packages/api/src/research-guides/fetcher.ts @@ -196,8 +196,8 @@ export class ResearchGuideFetcher { ex:url ?citationUrl . ?contentReferenceTime a ex:Event ; - ex:startDate ?contentReferenceTimeStartDate ; - ex:endDate ?contentReferenceTimeEndDate . + ex:startDate ?contentReferenceTimeStartDate ; + ex:endDate ?contentReferenceTimeEndDate . } WHERE { VALUES ?this { diff --git a/packages/api/src/research-guides/index.integration.test.ts b/packages/api/src/research-guides/index.integration.test.ts index cecba100..3d2e3ed6 100644 --- a/packages/api/src/research-guides/index.integration.test.ts +++ b/packages/api/src/research-guides/index.integration.test.ts @@ -26,8 +26,8 @@ describe('getByIds', () => { it('returns the research guides', async () => { const results = await researchGuides.getByIds({ ids: [ - 'https://guides.example.org/sub-set-1a', - 'https://guides.example.org/sub-set-2a', + 'https://guides.example.org/guide1', + 'https://guides.example.org/guide4', ], }); @@ -38,7 +38,7 @@ describe('getByIds', () => { describe('getById', () => { it('returns the research guide', async () => { const researchGuide = await researchGuides.getById({ - id: 'https://guides.example.org/sub-set-1a', + id: 'https://guides.example.org/guide1', }); expect(researchGuide).not.toBeUndefined(); diff --git a/packages/api/src/research-guides/rdf-helpers.ts b/packages/api/src/research-guides/rdf-helpers.ts index ee173c67..eb2c28f1 100644 --- a/packages/api/src/research-guides/rdf-helpers.ts +++ b/packages/api/src/research-guides/rdf-helpers.ts @@ -84,7 +84,7 @@ export function createResearchGuide( let seeAlso: ResearchGuide[] | undefined = undefined; // Prevent infinite recursion - if (stackSize < 4) { + if (stackSize < 5) { seeAlso = createResearchGuides( researchGuideResource, 'ex:seeAlso', From e862e865001aa17f7f0bbc34073da12440b6f4ad Mon Sep 17 00:00:00 2001 From: sdevalk Date: Sun, 1 Dec 2024 06:59:41 +0100 Subject: [PATCH 5/9] harmonze tests a little bit --- .../research-guides/fetcher.integration.test.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/api/src/research-guides/fetcher.integration.test.ts b/packages/api/src/research-guides/fetcher.integration.test.ts index f58a6507..2a319cc3 100644 --- a/packages/api/src/research-guides/fetcher.integration.test.ts +++ b/packages/api/src/research-guides/fetcher.integration.test.ts @@ -212,7 +212,7 @@ describe('getById', () => { 'Army and Navy personnel who operated in colonized territories collected objects in various ways during the colonial era.', text: 'Dutch authority in the [Dutch East Indies](https://www.geonames.org/1643084/republic-of-indonesia.html), [Suriname](https://www.geonames.org/3382998/republic-of-suriname.html) and on the [Caribbean Islands](https://www.geonames.org/8505032/netherlands-antilles.html) relied heavily on the use of the military...', encodingFormat: 'text/markdown', - contentReferenceTimes: [ + contentReferenceTimes: expect.arrayContaining([ { id: expect.stringContaining( 'https://data.colonialcollections.nl/.well-known/genid/' @@ -225,14 +225,14 @@ describe('getById', () => { endDate: new Date('1996-12-31T23:59:59.999Z'), }, }, - ], + ]), seeAlso: expect.arrayContaining([ { id: 'https://guides.example.org/guide6', name: 'Royal Cabinet of Curiosities', }, ]), - contentLocations: [ + contentLocations: expect.arrayContaining([ { id: expect.stringContaining( 'https://data.colonialcollections.nl/.well-known/genid/' @@ -240,8 +240,8 @@ describe('getById', () => { name: 'Netherlands Antilles', sameAs: 'https://www.geonames.org/8505032/netherlands-antilles.html', }, - ], - keywords: [ + ]), + keywords: expect.arrayContaining([ { id: expect.stringContaining( 'https://data.colonialcollections.nl/.well-known/genid/' @@ -249,8 +249,8 @@ describe('getById', () => { name: 'Midshipman', sameAs: 'https://www.wikidata.org/wiki/Q11141137', }, - ], - citations: [ + ]), + citations: expect.arrayContaining([ { id: expect.stringContaining( 'https://data.colonialcollections.nl/.well-known/genid/' @@ -260,7 +260,7 @@ describe('getById', () => { 'Via Delpher, the editions can be found by selecting the title', url: 'https://www.delpher.nl/', }, - ], + ]), }); }); }); From e583972661456169c9436e4e4c1615f48e28ce57 Mon Sep 17 00:00:00 2001 From: sdevalk Date: Mon, 2 Dec 2024 10:56:03 +0100 Subject: [PATCH 6/9] fix: reference to related guide --- packages/api/src/research-guides/fetcher.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/api/src/research-guides/fetcher.ts b/packages/api/src/research-guides/fetcher.ts index 353b77ab..e9ca0225 100644 --- a/packages/api/src/research-guides/fetcher.ts +++ b/packages/api/src/research-guides/fetcher.ts @@ -78,7 +78,7 @@ export class ResearchGuideFetcher { ex:seeAlso ?relatedGuide . ?relatedGuide a ex:CreativeWork ; - ex:name ?subGuideName . + ex:name ?relatedGuideName . } WHERE { VALUES ?topSet { From 97fcb911ef1bbc3ed7aece2f804e9ae585c479df Mon Sep 17 00:00:00 2001 From: sdevalk Date: Tue, 3 Dec 2024 08:43:14 +0100 Subject: [PATCH 7/9] fix: make dates optional --- packages/api/src/research-guides/fetcher.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/api/src/research-guides/fetcher.ts b/packages/api/src/research-guides/fetcher.ts index e9ca0225..d77c6edc 100644 --- a/packages/api/src/research-guides/fetcher.ts +++ b/packages/api/src/research-guides/fetcher.ts @@ -284,8 +284,14 @@ export class ResearchGuideFetcher { OPTIONAL { ?this schema:contentReferenceTime ?contentReferenceTime . - ?contentReferenceTime schema:startDate ?contentReferenceTimeStartDate ; - schema:endDate ?contentReferenceTimeEndDate . + + OPTIONAL { + ?contentReferenceTime schema:startDate ?contentReferenceTimeStartDate + } + + OPTIONAL { + ?contentReferenceTime schema:endDate ?contentReferenceTimeEndDate + } } } `; From 98bc7d6b934a24c5e43a57c86e0c9a21fbe71b2b Mon Sep 17 00:00:00 2001 From: sdevalk Date: Tue, 3 Dec 2024 15:33:38 +0100 Subject: [PATCH 8/9] fix: allow more than one alternate name; improve integration tests --- packages/api/src/objects/fetcher.ts | 2 + .../api/src/research-guides/definitions.ts | 2 +- .../fetcher.integration.test.ts | 112 +++++++++++------- .../src/research-guides/rdf-helpers.test.ts | 4 +- .../api/src/research-guides/rdf-helpers.ts | 7 +- 5 files changed, 80 insertions(+), 47 deletions(-) diff --git a/packages/api/src/objects/fetcher.ts b/packages/api/src/objects/fetcher.ts index 4484f6ca..ea43d9b8 100644 --- a/packages/api/src/objects/fetcher.ts +++ b/packages/api/src/objects/fetcher.ts @@ -173,6 +173,7 @@ export class HeritageObjectFetcher { FILTER(LANG(?typeName) = "${options.locale}") } + # For BC: data providers ought to use the same thesauri OPTIONAL { ?type rdfs:label ?typeName FILTER(LANG(?typeName) = "" || LANG(?typeName) = "${options.locale}") @@ -215,6 +216,7 @@ export class HeritageObjectFetcher { FILTER(LANG(?materialName) = "${options.locale}") } + # For BC: data providers ought to use the same thesauri OPTIONAL { ?material rdfs:label ?materialName FILTER(LANG(?materialName) = "" || LANG(?materialName) = "${options.locale}") diff --git a/packages/api/src/research-guides/definitions.ts b/packages/api/src/research-guides/definitions.ts index 29d0bcb9..7f793363 100644 --- a/packages/api/src/research-guides/definitions.ts +++ b/packages/api/src/research-guides/definitions.ts @@ -3,7 +3,7 @@ import {Event, Place, Term, Thing} from '../definitions'; export type Citation = Thing & {url?: string}; export type ResearchGuide = Thing & { - alternateName?: string; + alternateNames?: string[]; abstract?: string; text?: string; encodingFormat?: string; diff --git a/packages/api/src/research-guides/fetcher.integration.test.ts b/packages/api/src/research-guides/fetcher.integration.test.ts index 2a319cc3..9413ee33 100644 --- a/packages/api/src/research-guides/fetcher.integration.test.ts +++ b/packages/api/src/research-guides/fetcher.integration.test.ts @@ -25,12 +25,12 @@ describe('getTopLevels', () => { encodingFormat: 'text/markdown', seeAlso: [ { - id: 'https://guides.example.org/subset1', - name: '1. Name', + id: 'https://guides.example.org/subset3', + name: '3. Name', seeAlso: [ { - id: 'https://guides.example.org/guide3', - name: 'Sources', + id: 'https://guides.example.org/guide6', + name: 'Royal Cabinet of Curiosities', seeAlso: [ { id: 'https://guides.example.org/guide5', @@ -45,13 +45,17 @@ describe('getTopLevels', () => { ], }, { - id: 'https://guides.example.org/guide1', - name: 'Doing research', + id: 'https://guides.example.org/guide7', + name: 'Kunsthandel Van Lier', seeAlso: [ { id: 'https://guides.example.org/guide4', name: 'Military and navy', seeAlso: [ + { + id: 'https://guides.example.org/guide1', + name: 'Doing research', + }, { id: 'https://guides.example.org/guide6', name: 'Royal Cabinet of Curiosities', @@ -60,43 +64,47 @@ describe('getTopLevels', () => { }, ], }, - { - id: 'https://guides.example.org/guide2', - name: 'How can I use the data hub for my research?', - }, ], }, { - id: 'https://guides.example.org/subset2', - name: '2. Name', + id: 'https://guides.example.org/subset1', + name: '1. Name', seeAlso: [ { - id: 'https://guides.example.org/guide4', - name: 'Military and navy', + id: 'https://guides.example.org/guide1', + name: 'Doing research', seeAlso: [ { - id: 'https://guides.example.org/guide6', - name: 'Royal Cabinet of Curiosities', + id: 'https://guides.example.org/guide4', + name: 'Military and navy', seeAlso: [ { - id: 'https://guides.example.org/guide5', - name: 'Trade', + id: 'https://guides.example.org/guide1', + name: 'Doing research', + }, + { + id: 'https://guides.example.org/guide6', + name: 'Royal Cabinet of Curiosities', }, ], }, ], }, { - id: 'https://guides.example.org/guide5', - name: 'Trade', + id: 'https://guides.example.org/guide2', + name: 'How can I use the data hub for my research?', + }, + { + id: 'https://guides.example.org/guide3', + name: 'Sources', seeAlso: [ { - id: 'https://guides.example.org/guide7', - name: 'Kunsthandel Van Lier', + id: 'https://guides.example.org/guide5', + name: 'Trade', seeAlso: [ { - id: 'https://guides.example.org/guide4', - name: 'Military and navy', + id: 'https://guides.example.org/guide7', + name: 'Kunsthandel Van Lier', }, ], }, @@ -105,36 +113,46 @@ describe('getTopLevels', () => { ], }, { - id: 'https://guides.example.org/subset3', - name: '3. Name', + id: 'https://guides.example.org/subset2', + name: '2. Name', seeAlso: [ { - id: 'https://guides.example.org/guide7', - name: 'Kunsthandel Van Lier', + id: 'https://guides.example.org/guide4', + name: 'Military and navy', seeAlso: [ { - id: 'https://guides.example.org/guide4', - name: 'Military and navy', + id: 'https://guides.example.org/guide1', + name: 'Doing research', seeAlso: [ { - id: 'https://guides.example.org/guide6', - name: 'Royal Cabinet of Curiosities', + id: 'https://guides.example.org/guide4', + name: 'Military and navy', + }, + ], + }, + { + id: 'https://guides.example.org/guide6', + name: 'Royal Cabinet of Curiosities', + seeAlso: [ + { + id: 'https://guides.example.org/guide5', + name: 'Trade', }, ], }, ], }, { - id: 'https://guides.example.org/guide6', - name: 'Royal Cabinet of Curiosities', + id: 'https://guides.example.org/guide5', + name: 'Trade', seeAlso: [ { - id: 'https://guides.example.org/guide5', - name: 'Trade', + id: 'https://guides.example.org/guide7', + name: 'Kunsthandel Van Lier', seeAlso: [ { - id: 'https://guides.example.org/guide7', - name: 'Kunsthandel Van Lier', + id: 'https://guides.example.org/guide4', + name: 'Military and navy', }, ], }, @@ -207,7 +225,7 @@ describe('getById', () => { expect(researchGuide).toStrictEqual({ id: 'https://guides.example.org/guide4', name: 'Military and navy', - alternateName: 'Navy', + alternateNames: ['Navy'], abstract: 'Army and Navy personnel who operated in colonized territories collected objects in various ways during the colonial era.', text: 'Dutch authority in the [Dutch East Indies](https://www.geonames.org/1643084/republic-of-indonesia.html), [Suriname](https://www.geonames.org/3382998/republic-of-suriname.html) and on the [Caribbean Islands](https://www.geonames.org/8505032/netherlands-antilles.html) relied heavily on the use of the military...', @@ -231,6 +249,10 @@ describe('getById', () => { id: 'https://guides.example.org/guide6', name: 'Royal Cabinet of Curiosities', }, + { + id: 'https://guides.example.org/guide1', + name: 'Doing research', + }, ]), contentLocations: expect.arrayContaining([ { @@ -275,7 +297,7 @@ describe('get with localized names', () => { expect(researchGuide).toMatchObject({ id: 'https://guides.example.org/guide4', name: 'Military and navy', - alternateName: 'Navy', + alternateNames: expect.arrayContaining(['Navy']), abstract: 'Army and Navy personnel who operated in colonized territories collected objects in various ways during the colonial era.', text: 'Dutch authority in the [Dutch East Indies](https://www.geonames.org/1643084/republic-of-indonesia.html), [Suriname](https://www.geonames.org/3382998/republic-of-suriname.html) and on the [Caribbean Islands](https://www.geonames.org/8505032/netherlands-antilles.html) relied heavily on the use of the military...', @@ -284,6 +306,10 @@ describe('get with localized names', () => { id: 'https://guides.example.org/guide6', name: 'Royal Cabinet of Curiosities', }, + { + id: 'https://guides.example.org/guide1', + name: 'Doing research', + }, ]), contentLocations: [ { @@ -314,7 +340,7 @@ describe('get with localized names', () => { expect(researchGuide).toMatchObject({ id: 'https://guides.example.org/guide4', name: 'Leger en Marine', - alternateName: 'Marine', + alternateNames: expect.arrayContaining(['Marine', 'Zeemacht']), abstract: 'Leger- en marinepersoneel dat actief was in gekoloniseerde gebieden, verzamelde op verschillende manieren objecten tijdens het koloniale tijdperk.', text: 'Het Nederlandse gezag in [Nederlands-Indië](https://www.geonames.org/1643084/republic-of-indonesia.html), [Suriname](https://www.geonames.org/3382998/republic-of-suriname.html) en op de [Caribische eilanden](https://www.geonames.org/8505032/netherlands-antilles.html) steunde in belangrijke mate op de inzet van het leger.', @@ -323,6 +349,10 @@ describe('get with localized names', () => { id: 'https://guides.example.org/guide6', name: 'Koninklijk Kabinet van Zeldzaamheden', }, + { + id: 'https://guides.example.org/guide1', + name: 'Onderzoeken', + }, ]), contentLocations: [ { diff --git a/packages/api/src/research-guides/rdf-helpers.test.ts b/packages/api/src/research-guides/rdf-helpers.test.ts index b5b82191..ef04b277 100644 --- a/packages/api/src/research-guides/rdf-helpers.test.ts +++ b/packages/api/src/research-guides/rdf-helpers.test.ts @@ -24,7 +24,7 @@ beforeAll(async () => { ex:researchGuide2 a ex:CreativeWork ; ex:name "Name 2" ; - ex:alternateName "Alternate name 2" ; + ex:alternateName "Alternate name 2", "Alternate name 3" ; ex:abstract "Abstract 2" ; ex:text "Text" ; ex:encodingFormat "text/html" ; @@ -148,7 +148,7 @@ describe('createResearchGuide', () => { expect(researchGuide).toStrictEqual({ id: 'https://example.org/researchGuide2', name: 'Name 2', - alternateName: 'Alternate name 2', + alternateNames: ['Alternate name 2', 'Alternate name 3'], abstract: 'Abstract 2', text: 'Text', encodingFormat: 'text/html', diff --git a/packages/api/src/research-guides/rdf-helpers.ts b/packages/api/src/research-guides/rdf-helpers.ts index eb2c28f1..32e0050b 100644 --- a/packages/api/src/research-guides/rdf-helpers.ts +++ b/packages/api/src/research-guides/rdf-helpers.ts @@ -70,8 +70,9 @@ export function createResearchGuide( stackSize = 1 ) { const name = onlyOne(getPropertyValues(researchGuideResource, 'ex:name')); - const alternateName = onlyOne( - getPropertyValues(researchGuideResource, 'ex:alternateName') + const alternateNames = getPropertyValues( + researchGuideResource, + 'ex:alternateName' ); const abstract = onlyOne( getPropertyValues(researchGuideResource, 'ex:abstract') @@ -106,7 +107,7 @@ export function createResearchGuide( const researchGuideWithUndefinedValues: ResearchGuide = { id: researchGuideResource.value, name, - alternateName, + alternateNames, abstract, text, encodingFormat, From 8a0ba646703eb9bf1134c0c5b76c0a0dcad0fdba Mon Sep 17 00:00:00 2001 From: sdevalk Date: Thu, 5 Dec 2024 12:29:53 +0100 Subject: [PATCH 9/9] reexport definitions --- packages/api/src/research-guides/index.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/api/src/research-guides/index.ts b/packages/api/src/research-guides/index.ts index d87fc498..21273b9f 100644 --- a/packages/api/src/research-guides/index.ts +++ b/packages/api/src/research-guides/index.ts @@ -6,6 +6,9 @@ import { ResearchGuideFetcher, } from './fetcher'; +// Re-export definitions for ease of use in consuming apps +export * from './definitions'; + const constructorOptionsSchema = z.object({ sparqlEndpointUrl: z.string(), });