Commit 4593a6ad authored by Diegodlh's avatar Diegodlh
Browse files

Fix T302024: update the TemplateFieldOutput type

* translation field info now includes field validity (because it is no longer redundant with field output)
* the TemplateField's translate method now always returns an unvalidated field output, with the separate "valid" property indicating whether it is valid or not
* the TemplateField's validate method now returns a boolean, rather than a validated output
parent 38ef330f
......@@ -214,6 +214,7 @@ export class Domain {
required: fieldOutput.required,
procedures,
output: fieldOutput.output,
valid: fieldOutput.valid,
applicable: fieldOutput.applicable,
};
return fieldInfo;
......@@ -323,7 +324,8 @@ type FieldInfo = {
transformations: Array<TransformationDefinition & { output: StepOutput }>;
output: StepOutput;
}[];
output: Array<string | null>; // this is a validated output; no need to have separate valid property
output: StepOutput;
valid: boolean;
applicable: boolean;
};
......
......@@ -116,6 +116,23 @@ it("marks empty outputs as invalid", async () => {
expect(fieldOutput.valid).toBe(false);
});
it("always returns field output, even if invalid", async () => {
const field = new TemplateField({
fieldname: "itemType",
required: true,
procedures: [
{
selections: [{ type: "fixed", config: "invalidType" }],
transformations: [],
},
],
});
const target = new Webpage("https://example.com/target");
const output = await field.translate(target);
expect(output.output).toEqual(["invalidType"]);
expect(output.valid).toBe(false);
});
it("constructor optionally skips invalid procedure definitions", () => {
const warnSpy = jest.spyOn(log, "warn").mockImplementation();
const definition: unknown = {
......
......@@ -5,7 +5,6 @@ import { MediaWikiBaseFieldCitation, MediaWikiCreator } from "../citoid";
import {
TemplateFieldDefinition,
TemplateFieldOutput,
ProcedureOutput,
ProcedureDefinition,
} from "../types";
import log from "loglevel";
......@@ -77,16 +76,24 @@ export class TemplateField extends TranslationField {
const procedureOutputs = await Promise.all(
this.procedures.map((procedure) => procedure.translate(target))
);
const combinedOutput = ([] as string[]).concat(
let combinedOutput = ([] as string[]).concat(
...procedureOutputs.map((output) => output.output.procedure)
);
const output = this.validate(combinedOutput);
const valid = output.length > 0 && output.every((value) => value !== null);
// if field does not expect an array for output, join output values
if (!this.isArray && combinedOutput.length > 0) {
combinedOutput = [combinedOutput.join()];
}
combinedOutput = combinedOutput.map((value) => value.trim());
const valid = this.validate(combinedOutput);
const fieldOutput: TemplateFieldOutput = {
fieldname: this.name,
required: this.required,
procedureOutputs: procedureOutputs,
output,
output: combinedOutput,
valid,
applicable: valid || !this.required,
control: this.isControl,
......@@ -102,20 +109,10 @@ export class TemplateField extends TranslationField {
};
}
private validate(
output: ProcedureOutput["output"]["procedure"]
): Array<string | null> {
if (!this.isArray && output.length) {
// alternatively, consider:
// a. keep first element only
// b. return [null] (invalid)
output = [output.join()];
}
const validatedOutput = output.map((output) => {
output = output.trim();
return this.pattern.test(output) ? output : null;
});
return validatedOutput;
private validate(output: TemplateFieldOutput["output"]): boolean {
const valid =
output.length > 0 && output.every((value) => this.pattern.test(value));
return valid;
}
}
......@@ -140,11 +137,6 @@ export function outputToCitation(
// ignore invalid and control fields
if (field.valid && !field.control) {
const fieldName = field.fieldname;
// fixme: reconsider whether field output should accept null values
// see T302024
if (field.output.some((value) => value === null)) {
throw new Error(`Unexpected non-string value in valid field output`);
}
fields.set(fieldName, field.output as string[]);
}
}
......
......@@ -178,8 +178,8 @@ export type TemplateOutput = {
export type TemplateFieldOutput = {
fieldname: FieldName;
procedureOutputs: ProcedureOutput[];
output: Array<string | null>; // todo: change Array<string>, see T302024
valid: boolean; // todo: remove, see T302024
output: StepOutput;
valid: boolean;
required: boolean;
applicable: boolean; // valid || !required
control: boolean;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment