From 8115cae3dbbe59e83ff3c3af5828f903a08c6739 Mon Sep 17 00:00:00 2001 From: Sam Lee-Lindsay Date: Wed, 11 Dec 2024 14:49:10 +1100 Subject: [PATCH] Fix(SCIMMY.Types.SchemaDefinition): presence filtering of complex multi-value attributes --- src/lib/types/definition.js | 9 ++++++--- test/lib/types/definition.js | 6 ++++-- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/lib/types/definition.js b/src/lib/types/definition.js index 53f6bd6..e583461 100644 --- a/src/lib/types/definition.js +++ b/src/lib/types/definition.js @@ -417,11 +417,14 @@ export class SchemaDefinition { // If the attribute is always returned, add it to the result if (returned === "always") target[key] = data[key]; // Otherwise, if the attribute was requested and ~can~ be returned, process it - else if (![false, "never"].includes(returned)) { + else if (![false, "never"].includes(returned) && !exclusions.includes(key)) { // If there's a filter for a complex attribute, evaluate it... if (key in filter && type === "complex") { - // ...either using Filter instance match method, or by recursing into this filter method to get specified attributes - const value = Array.isArray(filter[key]) ? new Filter(filter[key].filter((expr) => Object.getPrototypeOf(expr).constructor === Object)).match(data[key]) : SchemaDefinition.#filter(definition, filter[key], data[key], key); + const value = Array.isArray(filter[key]) ? !filter[key].some((expr) => typeof expr === "object") ? data[key] : + // ...either using Filter instance match method for complex expressions... + new Filter(filter[key].filter((expr) => Object.getPrototypeOf(expr).constructor === Object)).match(data[key]) : + // ...or by recursing into this filter method to get specified attributes + SchemaDefinition.#filter(definition, filter[key], data[key], key); // Only set the value if it isn't empty if ((!multiValued && value !== undefined) || (Array.isArray(value) && value.length)) diff --git a/test/lib/types/definition.js b/test/lib/types/definition.js index f061963..b6bbb42 100644 --- a/test/lib/types/definition.js +++ b/test/lib/types/definition.js @@ -594,8 +594,10 @@ describe("SCIMMY.Types.SchemaDefinition", () => { for (let [target, outcome, unexpected, expected, filter, multiValued] of [ ["complex attributes", "filtered positively", "unexpectedly included", {test: {value: "False"}}, "test.value pr"], ["complex attributes", "filtered negatively", "unexpectedly excluded", {test: {name: "Test"}}, "test.value np"], - ["complex multi-value attributes", "filtered positively", "unexpectedly included", {test: [{name: "Test"}]}, "test.name pr", true], - ["complex multi-value attributes", "filtered negatively", "unexpectedly excluded", {test: [{value: "Test"}, {value: "False"}]}, "test.name np", true], + ["complex multi-value attributes", "filtered positively", "unexpectedly included", {test: [{name: "Test", value: "Test"}, {name: undefined, value: "False"}]}, "test pr", true], + ["complex multi-value attributes", "filtered negatively", "unexpectedly excluded", {}, "test np", true], + ["nested complex multi-value attributes", "filtered positively", "unexpectedly included", {test: [{name: "Test"}]}, "test.name pr", true], + ["nested complex multi-value attributes", "filtered negatively", "unexpectedly excluded", {test: [{value: "Test"}, {value: "False"}]}, "test.name np", true], ["complex multi-value attributes", "matched against filter expressions", "unexpectedly excluded", {test: [{name: "Test", value: "Test"}]}, "test[name eq \"Test\"] pr", true] ]) it(`should expect ${target} to be ${outcome}`, () => { const source = {test: multiValued ? [{name: "Test", value: "Test"}, {value: "False"}] : {name: "Test", value: "False"}};