diff --git a/__tests__/ResourceValidator.test.js b/__tests__/ResourceValidator.test.js index 877ba08d7..fd9de27e7 100644 --- a/__tests__/ResourceValidator.test.js +++ b/__tests__/ResourceValidator.test.js @@ -123,4 +123,30 @@ describe('validate()', () => { expect(results[1]).toEqual([{ message: 'Required', path: ['Instance', 'Barcode', 'Barcode', 'Barcode'], reduxPath: ['resource', 'resourceTemplate:Monograph:Instance', 'http://id.loc.gov/ontologies/bibframe/itemPortion', 'abcdCode', 'resourceTemplate:bf2:Identifiers:Barcode', 'http://www.w3.org/1999/02/22-rdf-syntax-ns#value'] }]) }) + + it('when a resourceTemplate is not found', () => { + const resource = { + 'rt:fooched': {}, + } + const rt = { + 'rt:fooched': { + resourceLabel: 'borked', + propertyTemplates: [ + { + propertyURI: 'http://examples.org/bogusOntologies/lookup1', + propertyLabel: 'lookup type with valueTemplateRefs', + type: 'lookup', + valueConstraint: { + valueTemplateRefs: [ + 'resourceTemplate:bf2:Note', + ], + }, + }, + ], + }, + } + const results = new Validator({ resource, entities: { rt } }).validate() + + expect(results[0].resource['rt:fooched'].errors[0]).toMatch('unable to retrieve rt:fooched from local store') + }) }) diff --git a/__tests__/__fixtures__/lookupWithValueTemplateRefs.json b/__tests__/__fixtures__/lookupWithValueTemplateRefs.json new file mode 100644 index 000000000..a9b26f129 --- /dev/null +++ b/__tests__/__fixtures__/lookupWithValueTemplateRefs.json @@ -0,0 +1,40 @@ +{ + "id": "Sinopia:RT:Fixture:LookupWithValueTemplateRefs", + "resourceURI": "http://examples.org/bogusOntologies/Resource", + "remark": "This is a sample Resource Template, content is meaningless", + "resourceLabel": "test lookup type misconfigured with valueTemplateRefs", + "author": "surrogate for Nancy Lorimer", + "schema": "https://ld4p.github.io/sinopia/schemas/0.0.9/resource-template.json", + "propertyTemplates": [ + { + "mandatory": "false", + "repeatable": "true", + "type": "lookup", + "valueConstraint": { + "defaults": [], + "useValuesFrom": [], + "valueDataType": {}, + "valueTemplateRefs": [ + "resourceTemplate:bf2:Note" + ] + }, + "propertyLabel": "lookup type with valueTemplateRefs", + "propertyURI": "http://examples.org/bogusOntologies/lookup1" + }, + { + "mandatory": "false", + "repeatable": "true", + "type": "resource", + "valueConstraint": { + "defaults": [], + "useValuesFrom": [], + "valueDataType": {}, + "valueTemplateRefs": [ + "resourceTemplate:bf2:Title:Note" + ] + }, + "propertyLabel": "resource type with valueTemplateRefs", + "propertyURI": "http://examples.org/bogusOntologies/lookup2" + } + ] +} diff --git a/__tests__/fixtureLoaderHelper.js b/__tests__/fixtureLoaderHelper.js index 2beba9253..afd7fff5e 100644 --- a/__tests__/fixtureLoaderHelper.js +++ b/__tests__/fixtureLoaderHelper.js @@ -53,6 +53,7 @@ const rtFileNames = [ 'literalRepeatDefaultLiteralNonEnglish.json', 'literalRepeatDefaultLiteralOnly.json', 'literalRepeatNoDefault.json', + 'lookupWithValueTemplateRefs.json', 'propertyURIRepeated.json', 'rdaItemMonograph.json', ] diff --git a/__tests__/integration/propertyTemplateMisconfigured.test.js b/__tests__/integration/propertyTemplateMisconfigured.test.js new file mode 100644 index 000000000..ddad4b846 --- /dev/null +++ b/__tests__/integration/propertyTemplateMisconfigured.test.js @@ -0,0 +1,22 @@ +// Copyright 2019 Stanford University see LICENSE for license + +import pupExpect from 'expect-puppeteer' +import { testUserLogin } from './loginHelper' + +describe('Errors with Misconfigured Property Templates', () => { + beforeAll(async () => { + await testUserLogin() + }) + + beforeEach(async () => { + await page.goto('http://127.0.0.1:8888/templates') + await page.waitForSelector('.react-bootstrap-table') + }) + + it('lookup type misconfigured with valueTemplateRefs', async () => { + // expect.assertions(3) + await pupExpect(page).toClick('a[href="/editor"]', { text: 'test lookup type misconfigured with valueTemplateRefs' }) + await pupExpect(page).toClick('button.btn-add[data-id="lookup1"]') + await pupExpect(page).toMatch('This propertyTemplate should not be of type lookup.') + }) +}) diff --git a/src/ResourceValidator.js b/src/ResourceValidator.js index 5aed2fc13..5032eceb4 100644 --- a/src/ResourceValidator.js +++ b/src/ResourceValidator.js @@ -35,16 +35,22 @@ export default class Validator { validateResource(reduxPath, labelPath) { const resourceTemplateId = reduxPath.slice(-1)[0] const resourceTemplate = getResourceTemplate({ selectorReducer: this.selectorReducer }, resourceTemplateId) - resourceTemplate.propertyTemplates.forEach((propertyTemplate) => { - const newReduxPath = [...reduxPath, propertyTemplate.propertyURI] - const newLabelPath = [...labelPath, resourceTemplate.resourceLabel, propertyTemplate.propertyLabel] - if (propertyTemplate.mandatory === 'true') { - this.validateMandatoryProperty(newReduxPath, newLabelPath) - } - if (!_.isEmpty(propertyTemplate.valueConstraint?.valueTemplateRefs)) { - this.validateNestedResourceProperty(newReduxPath, newLabelPath, propertyTemplate) - } - }) + if (resourceTemplate) { + resourceTemplate.propertyTemplates.forEach((propertyTemplate) => { + const newReduxPath = [...reduxPath, propertyTemplate.propertyURI] + const newLabelPath = [...labelPath, resourceTemplate.resourceLabel, propertyTemplate.propertyLabel] + if (propertyTemplate.mandatory === 'true') { + this.validateMandatoryProperty(newReduxPath, newLabelPath) + } + if (!_.isEmpty(propertyTemplate.valueConstraint?.valueTemplateRefs)) { + this.validateNestedResourceProperty(newReduxPath, newLabelPath, propertyTemplate) + } + }) + } else { + // not sure this error is ever surfaced anywhere, but we do need to trap for undefined resourceTemplate + // possibly will be surfaced when issue #1148 is addressed + this.addError(reduxPath, labelPath, `unable to retrieve ${resourceTemplateId} from local store`) + } } validateMandatoryProperty(reduxPath, labelPath) { diff --git a/src/components/editor/property/PropertyComponent.jsx b/src/components/editor/property/PropertyComponent.jsx index 707890a54..efb94eb7c 100644 --- a/src/components/editor/property/PropertyComponent.jsx +++ b/src/components/editor/property/PropertyComponent.jsx @@ -10,6 +10,19 @@ import { getTagNameForPropertyTemplate } from 'utilities/propertyTemplates' const PropertyComponent = (props) => { const tag = getTagNameForPropertyTemplate(props.propertyTemplate) + if (!tag) { + return ( +
+
+
+ + This propertyTemplate should not be of type {props.propertyTemplate.type}. +
+
+
+ ) + } + const TagName = React.lazy(() => import(`./${tag}`)) return ( Loading...}> diff --git a/src/utilities/propertyTemplates.js b/src/utilities/propertyTemplates.js index 74ac6a379..22ef3ea55 100644 --- a/src/utilities/propertyTemplates.js +++ b/src/utilities/propertyTemplates.js @@ -32,7 +32,7 @@ const textFieldType = (config, propertyTemplate) => { case 'resource': return 'InputURI' default: - console.error(`Unknown propertyTemplate type (component=${config}, type=${propertyTemplate.type})`) + // error case handled by caller return null } }