From ded680888cc2038c3c82e55b43b7b396eda84075 Mon Sep 17 00:00:00 2001 From: Abdi Mo Date: Wed, 4 Feb 2026 14:36:45 +0100 Subject: [PATCH 1/5] preventing numerical metadata values from being incorrectly formatted as dates --- .../metadata-view/metadata-view.component.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts b/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts index ffdcef447..84824f2cc 100644 --- a/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts +++ b/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts @@ -240,8 +240,8 @@ export class MetadataViewComponent implements OnInit, OnChanges { isDate(scientificMetadata: ScientificMetadataTableData): boolean { // NOTE: If the type is date, we expect the value to be in ISO format. - if (scientificMetadata.type === "date") { - return true; + if (scientificMetadata.type) { + return scientificMetadata.type === "date"; } const isValidDate = @@ -249,11 +249,7 @@ export class MetadataViewComponent implements OnInit, OnChanges { new Date(scientificMetadata.value).toString() !== "Invalid Date" && DateTime.fromISO(scientificMetadata.value).isValid; - if (isValidDate) { - return true; - } - - return false; + return isValidDate; } ngOnInit() { From fcc65172be19cbb4f16f91c767adf9624c169e47 Mon Sep 17 00:00:00 2001 From: Abdi Mo Date: Mon, 9 Feb 2026 12:57:44 +0100 Subject: [PATCH 2/5] validation now only accepts if date value has separators --- .../metadata-view/metadata-view.component.ts | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts b/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts index 84824f2cc..3f3e9af5c 100644 --- a/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts +++ b/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts @@ -240,16 +240,21 @@ export class MetadataViewComponent implements OnInit, OnChanges { isDate(scientificMetadata: ScientificMetadataTableData): boolean { // NOTE: If the type is date, we expect the value to be in ISO format. - if (scientificMetadata.type) { - return scientificMetadata.type === "date"; + if (scientificMetadata.type === "date") { + return true; } - const isValidDate = - typeof scientificMetadata.value !== "number" && - new Date(scientificMetadata.value).toString() !== "Invalid Date" && - DateTime.fromISO(scientificMetadata.value).isValid; + const stringValue = String(scientificMetadata.value); - return isValidDate; + const hasDateSeparators = /[-\/]/.test(stringValue); + + if (!hasDateSeparators) { + return false; + } + + const dateTime = DateTime.fromISO(stringValue); + + return dateTime.isValid; } ngOnInit() { From 815a1166a11bac4e69a3ef0c853b42fea88be42a Mon Sep 17 00:00:00 2001 From: Abdi Mo Date: Mon, 9 Feb 2026 14:05:05 +0100 Subject: [PATCH 3/5] eslint fix --- .../metadata-view/metadata-view.component.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts b/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts index 3f3e9af5c..96f5b800c 100644 --- a/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts +++ b/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts @@ -246,7 +246,7 @@ export class MetadataViewComponent implements OnInit, OnChanges { const stringValue = String(scientificMetadata.value); - const hasDateSeparators = /[-\/]/.test(stringValue); + const hasDateSeparators = /[-]/.test(stringValue); if (!hasDateSeparators) { return false; From 4a4b7708b2f9c4d3e68a1198b9b5b9889eeff687 Mon Sep 17 00:00:00 2001 From: Abdi Mo Date: Wed, 11 Feb 2026 16:57:29 +0100 Subject: [PATCH 4/5] removed isDate func --- .../metadata-view.component.spec.ts | 62 ------------------- .../metadata-view/metadata-view.component.ts | 23 +------ 2 files changed, 2 insertions(+), 83 deletions(-) diff --git a/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.spec.ts b/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.spec.ts index 34d9eed8d..9ede369ed 100644 --- a/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.spec.ts +++ b/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.spec.ts @@ -98,66 +98,4 @@ describe("MetadataViewComponent", () => { expect(metadataArray[0]["unit"]).toEqual(""); }); }); - - describe("#isDate()", () => { - it("should return false if scientificMetadata item is a quantity", () => { - const metadata = { - name: "wavelength", - value: 1024, - unit: "nanometers", - }; - - const isDate = component.isDate(metadata); - - expect(isDate).toEqual(false); - }); - - it("should return false if scientificMetadata value is a number", () => { - const metadata = { - name: "test", - value: 1024, - unit: "", - }; - - const isDate = component.isDate(metadata); - - expect(isDate).toEqual(false); - }); - - it("should return false if scientificMetadata value is a string", () => { - const metadata = { - name: "test", - value: "test value", - unit: "", - }; - - const isDate = component.isDate(metadata); - - expect(isDate).toEqual(false); - }); - - it("should return false if scientificMetadata value is a string of numbers", () => { - const metadata = { - name: "test", - value: "123", - unit: "", - }; - - const isDate = component.isDate(metadata); - - expect(isDate).toEqual(false); - }); - - it("should return true if scientificMetadata item is a date string", () => { - const metadata = { - name: "today", - value: new Date().toISOString(), - unit: "", - }; - - const isDate = component.isDate(metadata); - - expect(isDate).toEqual(true); - }); - }); }); diff --git a/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts b/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts index 96f5b800c..1c00866a6 100644 --- a/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts +++ b/src/app/shared/modules/scientific-metadata/metadata-view/metadata-view.component.ts @@ -107,7 +107,7 @@ export class MetadataViewComponent implements OnInit, OnChanges { name: "value", header: "Value", customRender: (column, row) => { - if (row.type === "date" || this.isDate(row)) { + if (row.type === "date") { return this.datePipe.transform(row[column.name]); } @@ -123,7 +123,7 @@ export class MetadataViewComponent implements OnInit, OnChanges { return row[column.name]; }, toExport: (column, row) => { - if (row.type === "date" || this.isDate(row)) { + if (row.type === "date") { return this.datePipe.transform(row[column.name]); } @@ -238,25 +238,6 @@ export class MetadataViewComponent implements OnInit, OnChanges { return metadataArray; } - isDate(scientificMetadata: ScientificMetadataTableData): boolean { - // NOTE: If the type is date, we expect the value to be in ISO format. - if (scientificMetadata.type === "date") { - return true; - } - - const stringValue = String(scientificMetadata.value); - - const hasDateSeparators = /[-]/.test(stringValue); - - if (!hasDateSeparators) { - return false; - } - - const dateTime = DateTime.fromISO(stringValue); - - return dateTime.isValid; - } - ngOnInit() { if (this.metadata) { this.tableData = this.createMetadataArray(this.metadata); From 277b6adf284dff1b00db33c0b1096302237a9504 Mon Sep 17 00:00:00 2001 From: Abdi Mo Date: Wed, 18 Feb 2026 15:37:26 +0100 Subject: [PATCH 5/5] added additional e2e tests for metadata types --- cypress/e2e/datasets/datasets-metadata.cy.js | 218 +++++++++++++++++++ 1 file changed, 218 insertions(+) diff --git a/cypress/e2e/datasets/datasets-metadata.cy.js b/cypress/e2e/datasets/datasets-metadata.cy.js index d74f41e99..7b7356a3c 100644 --- a/cypress/e2e/datasets/datasets-metadata.cy.js +++ b/cypress/e2e/datasets/datasets-metadata.cy.js @@ -769,6 +769,224 @@ describe("Datasets", () => { cy.contains(`unitSI: "${metadata.unitSI}"`).should("exist"); }); }); + + it("should be able to add a metadata entry with type 'number'", () => { + const newMetadataName = "Cypress dataset number metadata"; + const metadata = { + value: "2010", + name: "number_metadata", + human_name: "Number test", + type: "number", + }; + cy.createDataset({ + type: "raw", + dataFileSize: "small", + datasetName: newMetadataName, + }); + + cy.visit("/datasets"); + + cy.get(".dataset-table mat-table mat-header-row").should("exist"); + + cy.finishedLoading(); + + cy.get('[data-cy="text-search"]').clear().type(newMetadataName); + cy.get('[data-cy="search-button"]').click(); + + cy.isLoading(); + + cy.get("mat-row").contains(newMetadataName).first().click(); + + cy.wait("@fetch"); + + cy.finishedLoading(); + + cy.scrollTo("bottom"); + + cy.get('[role="tab"]').contains("Edit").click(); + + cy.get('[data-cy="add-new-row"]').click(); + + cy.get("mat-select[data-cy=field-type-input]").last().click(); + cy.get("mat-option") + .contains(metadata.type) + .then((option) => { + option[0].click(); + }); + + cy.get("[data-cy=metadata-name-input]") + .last() + .focus() + .type(`${metadata.name}{enter}`); + + cy.get("[data-cy=metadata-human-name-input]") + .last() + .focus() + .type(`${metadata.human_name}{enter}`); + + cy.get("[data-cy=metadata-value-input]") + .last() + .focus() + .type(`${metadata.value}{enter}`); + + cy.get("button[data-cy=save-changes-button]").click(); + + cy.finishedLoading(); + + cy.contains("[role='tab']", "View").click(); + + cy.contains("dynamic-mat-table mat-row", metadata.human_name); + cy.contains("dynamic-mat-table mat-row", metadata.value); + }); + + it("should be able to add a metadata entry with type 'quantity'", () => { + const newMetadataName = "Cypress dataset quantity metadata"; + const metadata = { + value: "2010", + name: "quantity_metadata", + human_name: "Quantity test", + type: "quantity", + unit: "cm", + valueSI: "20.1", + unitSI: "m", + }; + cy.createDataset({ + type: "raw", + dataFileSize: "small", + datasetName: newMetadataName, + }); + + cy.visit("/datasets"); + + cy.get(".dataset-table mat-table mat-header-row").should("exist"); + + cy.finishedLoading(); + + cy.get('[data-cy="text-search"]').clear().type(newMetadataName); + cy.get('[data-cy="search-button"]').click(); + + cy.isLoading(); + + cy.get("mat-row").contains(newMetadataName).first().click(); + + cy.wait("@fetch"); + + cy.finishedLoading(); + + cy.scrollTo("bottom"); + + cy.get('[role="tab"]').contains("Edit").click(); + + cy.get('[data-cy="add-new-row"]').click(); + + cy.get("mat-select[data-cy=field-type-input]").last().click(); + + cy.get("mat-option") + .contains(metadata.type) + .then((option) => { + option[0].click(); + }); + + cy.get("[data-cy=metadata-name-input]") + .last() + .focus() + .type(`${metadata.name}{enter}`); + + cy.get("[data-cy=metadata-human-name-input]") + .last() + .focus() + .type(`${metadata.human_name}{enter}`); + + cy.get("[data-cy=metadata-value-input]") + .last() + .focus() + .type(`${metadata.value}{enter}`); + + cy.get("[data-cy=metadata-unit-input]") + .last() + .focus() + .type(`${metadata.unit}{enter}`); + + cy.get("button[data-cy=save-changes-button]").click(); + + cy.finishedLoading(); + + cy.contains("[role='tab']", "View").click(); + + cy.contains("dynamic-mat-table mat-row", metadata.human_name); + cy.contains("dynamic-mat-table mat-row", metadata.value); + cy.contains("dynamic-mat-table mat-row", metadata.unit); + }); + + it("should be able to add a metadata entry with type 'string'", () => { + const newMetadataName = "Cypress dataset string metadata"; + const metadata = { + value: "2010", + name: "string_metadata", + human_name: "String test", + type: "string", + }; + cy.createDataset({ + type: "raw", + dataFileSize: "small", + datasetName: newMetadataName, + }); + + cy.visit("/datasets"); + + cy.get(".dataset-table mat-table mat-header-row").should("exist"); + + cy.finishedLoading(); + + cy.get('[data-cy="text-search"]').clear().type(newMetadataName); + cy.get('[data-cy="search-button"]').click(); + + cy.isLoading(); + + cy.get("mat-row").contains(newMetadataName).first().click(); + + cy.wait("@fetch"); + + cy.finishedLoading(); + + cy.scrollTo("bottom"); + + cy.get('[role="tab"]').contains("Edit").click(); + + cy.get('[data-cy="add-new-row"]').click(); + + cy.get("mat-select[data-cy=field-type-input]").last().click(); + + cy.get("mat-option") + .contains(metadata.type) + .then((option) => { + option[0].click(); + }); + + cy.get("[data-cy=metadata-name-input]") + .last() + .focus() + .type(`${metadata.name}{enter}`); + + cy.get("[data-cy=metadata-human-name-input]") + .last() + .focus() + .type(`${metadata.human_name}{enter}`); + + cy.get("[data-cy=metadata-value-input]") + .last() + .focus() + .type(`${metadata.value}{enter}`); + + cy.get("button[data-cy=save-changes-button]").click(); + + cy.finishedLoading(); + + cy.contains("[role='tab']", "View").click(); + + cy.contains("dynamic-mat-table mat-row", metadata.human_name); + cy.contains("dynamic-mat-table mat-row", metadata.value); + }); }); describe("Remove metadata item", () => {