Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions cypress/integration/validation.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (C) 2020-2021 The Software Heritage developers
* Copyright (C) 2020-2025 The Software Heritage developers
* See the AUTHORS file at the top-level directory of this distribution
* License: GNU Affero General Public License version 3, or any later version
* See top-level LICENSE file for more information
Expand Down Expand Up @@ -105,7 +105,7 @@ describe('Document validation', function() {
cy.get('#errorMessage').should('have.text', 'Unknown field "foobar".');
});

it('errors when both "type" and "@type" are present', function() {
it('errors on having both "type" and "@type"', function() {
cy.get('#codemetaText').then((elem) =>
elem.text(JSON.stringify({
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
Expand Down Expand Up @@ -317,6 +317,42 @@ describe('Things or URLs validation', function() {
cy.get('#errorMessage').should('have.text', '"license" must be an URL or a CreativeWork/SoftwareSourceCode/SoftwareApplication object, not: "Copyright 2021 Myself"');
});

it('errors on having both "id" and "@id"', function () {
cy.get('#codemetaText').then((elem) =>
elem.text(JSON.stringify({
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
"@type": "SoftwareSourceCode",
"author": {
"id": "http://example.org/~jdoe",
"@id": "http://example.org/~jdoe",
"@type": "Person",
"name": "Jane Doe",
},
}))
);
cy.get('#validateCodemeta').click();

cy.get('#errorMessage').should('have.text', '"author" must use either "id" or "@id", not both.');
});

it('errors on having both "type" and "@type"', function () {
cy.get('#codemetaText').then((elem) =>
elem.text(JSON.stringify({
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
"@type": "SoftwareSourceCode",
"author": {
"id": "http://example.org/~jdoe",
"type": "Person",
"@type": "Person",
"name": "Jane Doe",
},
}))
);
cy.get('#validateCodemeta').click();

cy.get('#errorMessage').should('have.text', '"author" must use either "type" or "@type", not both.');
});

it('errors on wrong type', function() {
cy.get('#codemetaText').then((elem) =>
elem.text(JSON.stringify({
Expand Down
2 changes: 1 addition & 1 deletion js/validation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function validateDocument(doc) {
// TODO: validate id/@id

// Ensure either "type" or "@type" is used, but not both
const typeKeys = ['type', '@type'];
const typeKeys = ["type", "@type"];
if (typeKeys.filter(k => Object.prototype.hasOwnProperty.call(doc, k)).length > 1) {
setError(`Document must use either "type" or "@type", not both.`);
return false;
Expand Down
19 changes: 15 additions & 4 deletions js/validation/things.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright (C) 2020-2021 The Software Heritage developers
* Copyright (C) 2020-2025 The Software Heritage developers
* See the AUTHORS file at the top-level directory of this distribution
* License: GNU Affero General Public License version 3, or any later version
* See top-level LICENSE file for more information
Expand Down Expand Up @@ -67,8 +67,19 @@ function validateThingOrId(parentFieldName, typeFieldValidators, doc) {
//
// typeFieldValidators is a map: {type => {fieldName => fieldValidator}}
function validateThing(parentFieldName, typeFieldValidators, doc) {
// TODO: check there is either id or @id but not both
// TODO: check there is either type or @type but not both
// Ensure either "id" or "@id" is used, but not both
const idKeys = ["id", "@id"];
if (idKeys.filter(k => Object.prototype.hasOwnProperty.call(doc, k)).length > 1) {
setError(`"${parentFieldName}" must use either "id" or "@id", not both.`);
return false;
}

// Ensure either "type" or "@type" is used, but not both
const typeKeys = ["type", "@type"];
if (typeKeys.filter(k => Object.prototype.hasOwnProperty.call(doc, k)).length > 1) {
setError(`"${parentFieldName}" must use either "type" or "@type", not both.`);
return false;
}

var acceptedTypesString = Object.keys(typeFieldValidators).join('/');

Expand Down Expand Up @@ -196,6 +207,7 @@ function validateReview(fieldName, doc) {
return validateThingOrId(fieldName, {"Review": reviewFieldValidators}, doc);
}

// Define validators for each field of each type of Thing

var softwareFieldValidators = {
"@id": validateUrl,
Expand Down Expand Up @@ -323,7 +335,6 @@ var personFieldValidators = {
"url": validateUrls,
};


var organizationFieldValidators = {
"@id": validateUrl,
"id": validateUrl,
Expand Down