Skip to content

Commit

Permalink
feat: add multiple xor
Browse files Browse the repository at this point in the history
  • Loading branch information
JeanArhancet committed Apr 25, 2024
1 parent 300ac00 commit a9ed47a
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 21 deletions.
34 changes: 21 additions & 13 deletions packages/functions/src/__tests__/xor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,24 @@ describe('Core Functions / Xor', () => {
]);
});

it('given multiple properties that do not match, should return an error message', async () => {
expect(
await runXor(
{
version: '1.0.0',
title: 'Swagger Petstore',
termsOfService: 'http://swagger.io/terms/',
},
{ properties: ['yada-yada', 'whatever', 'foo'] },
),
).toEqual([
{
message: '"yada-yada", "whatever" and "foo" must not be both defined or both undefined',
path: [],
},
]);
});

it('given both properties, should return an error message', async () => {
expect(
await runXor(
Expand Down Expand Up @@ -99,22 +117,12 @@ describe('Core Functions / Xor', () => {
]),
],
],
[
{ properties: ['foo', 'bar', 'baz'] },
[
new RulesetValidationError(
'invalid-function-options',
'"xor" and its "properties" option support 2-item tuples, i.e. ["id", "name"]',
['rules', 'my-rule', 'then', 'functionOptions', 'properties'],
),
],
],
[
{ properties: ['foo', {}] },
[
new RulesetValidationError(
'invalid-function-options',
'"xor" and its "properties" option support 2-item tuples, i.e. ["id", "name"]',
'"xor" and its "properties" option require at least 2-item tuples, i.e. ["id", "name"]',
['rules', 'my-rule', 'then', 'functionOptions', 'properties'],
),
],
Expand All @@ -124,7 +132,7 @@ describe('Core Functions / Xor', () => {
[
new RulesetValidationError(
'invalid-function-options',
'"xor" and its "properties" option support 2-item tuples, i.e. ["id", "name"]',
'"xor" and its "properties" option require at least 2-item tuples, i.e. ["id", "name"]',
['rules', 'my-rule', 'then', 'functionOptions', 'properties'],
),
],
Expand All @@ -134,7 +142,7 @@ describe('Core Functions / Xor', () => {
[
new RulesetValidationError(
'invalid-function-options',
'"xor" and its "properties" option support 2-item tuples, i.e. ["id", "name"]',
'"xor" and its "properties" option require at least 2-item tuples, i.e. ["id", "name"]',
['rules', 'my-rule', 'then', 'functionOptions', 'properties'],
),
],
Expand Down
3 changes: 1 addition & 2 deletions packages/functions/src/optionSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,7 @@ export const optionSchemas: Record<string, CustomFunctionOptionsSchema> = {
type: 'string',
},
minItems: 2,
maxItems: 2,
errorMessage: `"xor" and its "properties" option support 2-item tuples, i.e. ["id", "name"]`,
errorMessage: `"xor" and its "properties" option require at least 2-item tuples, i.e. ["id", "name"]`,
description: 'The properties to check.',
},
},
Expand Down
22 changes: 16 additions & 6 deletions packages/functions/src/xor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,26 @@ export default createRulesetFunction<Record<string, unknown>, Options>(
options: optionSchemas.xor,
},
function xor(targetVal, { properties }) {
if (properties.length !== 2) return;

const results: IFunctionResult[] = [];

const intersection = Object.keys(targetVal).filter(value => -1 !== properties.indexOf(value));
const intersection = Object.keys(targetVal).filter(key => properties.includes(key));

if (intersection.length !== 1) {
const formattedProperties = properties.map(prop => printValue(prop));
// If more than one, join with commas and "and"
let message = '';
if (formattedProperties.length > 1) {
const lastProperty = formattedProperties.pop();
message = formattedProperties.join(', ') + (lastProperty != undefined ? ` and ${lastProperty}` : '');
} else {
// If only one property or none
message = formattedProperties.join('');
}

message += ' must not be both defined or both undefined';

results.push({
message: `${printValue(properties[0])} and ${printValue(
properties[1],
)} must not be both defined or both undefined`,
message,
});
}

Expand Down

0 comments on commit a9ed47a

Please sign in to comment.