Skip to content

Commit

Permalink
[#175017856] Handle exclusiveMaximum and exclusiveMinimum (#207)
Browse files Browse the repository at this point in the history
  • Loading branch information
infantesimone authored Oct 21, 2020
1 parent 6fcf9c5 commit 1d05f9c
Show file tree
Hide file tree
Showing 3 changed files with 218 additions and 12 deletions.
38 changes: 38 additions & 0 deletions __mocks__/api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,44 @@ definitions:
type: number
minimum: 0
maximum: 10
WithinRangeExclusiveMinimumNumberTest:
title: WithinRangeExclusiveMinimumNumberTest
type: number
minimum: 0
exclusiveMinimum: true
maximum: 10
WithinRangeExclusiveMaximumNumberTest:
title: WithinRangeExclusiveMaximumNumberTest
type: number
minimum: 0
maximum: 10
exclusiveMaximum: true
WithinRangeExclusiveMinMaxNumberTest:
title: WithinRangeExclusiveMinMaxNumberTest
type: number
minimum: 0
exclusiveMinimum: true
maximum: 10
exclusiveMaximum: true
WithinRangeExclusiveMinimumIntegerTest:
title: WithinRangeExclusiveMinimumIntegerTest
type: integer
minimum: 0
exclusiveMinimum: true
maximum: 10
WithinRangeExclusiveMaximumIntegerTest:
title: WithinRangeExclusiveMaximumIntegerTest
type: integer
minimum: 0
maximum: 10
exclusiveMaximum: true
WithinRangeExclusiveMinMaxIntegerTest:
title: WithinRangeExclusiveMinMaxIntegerTest
type: number
minimum: 0
exclusiveMinimum: true
maximum: 10
exclusiveMaximum: true
InlinePropertyTest:
type: object
properties:
Expand Down
133 changes: 127 additions & 6 deletions e2e/src/__tests__/test-api/definitions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,17 @@ import {
IWithinRangeIntegerTag,
IWithinRangeNumberTag
} from "italia-ts-commons/lib/numbers";
import { readableReport } from "italia-ts-commons/lib/reporters";
import { WithinRangeString } from "italia-ts-commons/lib/strings";
import { WithinRangeExclusiveMaximumIntegerTest } from "../../generated/testapi/WithinRangeExclusiveMaximumIntegerTest";
import { WithinRangeExclusiveMaximumNumberTest } from "../../generated/testapi/WithinRangeExclusiveMaximumNumberTest";
import { WithinRangeExclusiveMinimumIntegerTest } from "../../generated/testapi/WithinRangeExclusiveMinimumIntegerTest";
import { WithinRangeExclusiveMinimumNumberTest } from "../../generated/testapi/WithinRangeExclusiveMinimumNumberTest";
import { WithinRangeExclusiveMinMaxNumberTest } from "../../generated/testapi/WithinRangeExclusiveMinMaxNumberTest";

import { WithinRangeIntegerTest } from "../../generated/testapi/WithinRangeIntegerTest";
import { WithinRangeNumberTest } from "../../generated/testapi/WithinRangeNumberTest";
import { WithinRangeStringTest } from "../../generated/testapi/WithinRangeStringTest";
import { WithinRangeString } from "italia-ts-commons/lib/strings";
import { readableReport } from "italia-ts-commons/lib/reporters";

const { generatedFilesDir, isSpecEnabled } = config.specs.testapi;

Expand Down Expand Up @@ -93,7 +99,7 @@ describe("Profile defintion", () => {
});

describe("WithinRangeIntegerTest defintion", () => {
//WithinRangeIntegerTest is defined min=0 max=10 in the spec
// WithinRangeIntegerTest is defined min=0 max=10 in the spec
it.each`
value | expected
${0} | ${true /* lower bound */}
Expand All @@ -115,7 +121,7 @@ describe("WithinRangeIntegerTest defintion", () => {
});

describe("WithinRangeNumberTest defintion", () => {
//WithinRangeNumberTest is defined min=0 max=10 in the spec
// WithinRangeNumberTest is defined min=0 max=10 in the spec
it.each`
value | expected
${0} | ${true /* lower bound */}
Expand All @@ -135,7 +141,78 @@ describe("WithinRangeNumberTest defintion", () => {
}
);

/* it("should have correct ts types", () => {
describe("WithinRangeExclusiveMinimumNumberTest definition", () => {
// WithinRangeExclusiveMinimumNumberTest is defined min=0 max=10 exclusiveMinimum: true in the spec
it.each`
value | expected
${-1} | ${false}
${0} | ${false}
${0.1} | ${true}
${0.5} | ${true}
${1} | ${true}
${9.9999999} | ${true}
${10} | ${true /* upper bound */}
${10.000001} | ${false}
${11} | ${false}
${100} | ${false}
${undefined} | ${false}
`(
"should decode $value with WithinRangeExclusiveMinimumNumberTest",
({ value, expected }) => {
const result = WithinRangeExclusiveMinimumNumberTest.decode(value);
expect(result.isRight()).toEqual(expected);
}
);
});
describe("WithinRangeExclusiveMaximumNumberTest definition", () => {
// WithinRangeExclusiveMaximumNumberTest is defined min=0 max=10 exclusiveMaximum: true in the spec
it.each`
value | expected
${-1} | ${false}
${0} | ${true /* lower bound */}
${1.5} | ${true}
${5.5} | ${true}
${9} | ${true}
${9.5} | ${true}
${9.999} | ${true}
${10} | ${false}
${11} | ${false}
${100} | ${false}
${undefined} | ${false}
`(
"should decode $value with WithinRangeExclusiveMaximumNumberTest",
({ value, expected }) => {
const result = WithinRangeExclusiveMaximumNumberTest.decode(value);
expect(result.isRight()).toEqual(expected);
}
);
});

describe("WithinRangeExclusiveMinMaxNumberTest definition", () => {
// WithinRangeExclusiveMinMaxNumberTest is defined min=0 max=10 exclusiveMaximum: true exclusiveMinimum: true in the spec
it.each`
value | expected
${-1} | ${false}
${0} | ${false}
${0.1} | ${true}
${1.5} | ${true}
${5.5} | ${true}
${9} | ${true}
${9.5} | ${true}
${9.999} | ${true}
${10} | ${false}
${11} | ${false}
${100} | ${false}
${undefined} | ${false}
`(
"should decode $value with WithinRangeExclusiveMinMaxNumberTest",
({ value, expected }) => {
const result = WithinRangeExclusiveMinMaxNumberTest.decode(value);
expect(result.isRight()).toEqual(expected);
}
);
});
/* it("should have correct ts types", () => {
// value is actually "any"
const value1: WithinRangeNumberTest = WithinRangeNumberTest.decode(10).getOrElseL(err => {
throw new Error(readableReport(err))
Expand All @@ -149,8 +226,52 @@ describe("WithinRangeNumberTest defintion", () => {
}) */
});

describe("WithinRangeExclusiveMinimumIntegerTest definition", () => {
// WithinRangeExclusiveMinimumIntegerTest is defined min=0 max=10 exclusiveMinimum: true in the spec
it.each`
value | expected
${0} | ${false}
${-1} | ${false}
${1} | ${true /* lower bound */}
${5} | ${true}
${9} | ${true}
${10} | ${true /* upper bound */}
${11} | ${false}
${100} | ${false}
${undefined} | ${false}
`(
"should decode $value with WithinRangeExclusiveMinimumIntegerTest",
({ value, expected }) => {
const result = WithinRangeExclusiveMinimumIntegerTest.decode(value);
expect(result.isRight()).toEqual(expected);
}
);
});

describe("WithinRangeExclusiveMaximumIntegerTest definition", () => {
// WithinRangeExclusiveMaximumIntegerTest is defined min=0 max=10 exclusiveMaximum: true in the spec
it.each`
value | expected
${0} | ${true /* lower bound */}
${-1} | ${false}
${1} | ${true}
${5} | ${true}
${9} | ${true}
${10} | ${false /* upper bound */}
${11} | ${false}
${100} | ${false}
${undefined} | ${false}
`(
"should decode $value with WithinRangeExclusiveMaximumIntegerTest",
({ value, expected }) => {
const result = WithinRangeExclusiveMaximumIntegerTest.decode(value);
expect(result.isRight()).toEqual(expected);
}
);
});

describe("WithinRangeStringTest defintion", () => {
//WithinRangeStringTest is defined min=8 max=10 in the spec
// WithinRangeStringTest is defined min=8 max=10 in the spec
it.each`
value | expected
${"a".repeat(7)} | ${false}
Expand Down
59 changes: 53 additions & 6 deletions templates/macros.njk
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,55 @@
{% macro defineNumber(definitionName, definition, inline = false) -%}
{% if definition.minimum != undefined and definition.maximum != undefined %}
{{- 'import { IWithinRangeNumberTag, WithinRangeNumber } from "italia-ts-commons/lib/numbers";' | addImport -}}
{% set typedef %}t.union([
WithinRangeNumber<{{ definition.minimum }}, {{ definition.maximum }}, IWithinRangeNumberTag<{{ definition.minimum }}, {{ definition.maximum }}>>({{ definition.minimum }}, {{ definition.maximum }}),
t.literal({{ definition.maximum }})
]){% endset %}
{% if definition.minimum != undefined and definition.maximum != undefined %}
{## [R,L) #}
{% if definition.exclusiveMaximum and not definition.exclusiveMinimum %}
{% set typedef %}
WithinRangeNumber<{{ definition.minimum }}, {{ definition.maximum }}, IWithinRangeNumberTag<{{ definition.minimum }}, {{ definition.maximum }}>>({{ definition.minimum }}, {{ definition.maximum }})
{% endset %}
{## (R,L] #}
{% elif definition.exclusiveMinimum and not definition.exclusiveMaximum %}
{% set typedef %}const WithoutExclusive = t.union([
WithinRangeNumber<{{ definition.minimum }}, {{ definition.maximum }}, IWithinRangeNumberTag<{{ definition.minimum }}, {{ definition.maximum }}>>({{ definition.minimum }}, {{ definition.maximum }}),
t.literal({{ definition.maximum }})
]){% endset %}
{{ defineConst(undefined, 'WithoutExclusive', typedef, false, true) }}
{% set typedef %}
t.brand(
WithoutExclusive,
(
n
): n is t.Branded<
t.TypeOf<typeof WithoutExclusive>,
{ readonly {{ definitionName }}: symbol }
> => n != {{ definition.minimum }},
"{{definitionName}}"
);
{% endset %}
{## (R,L) #}
{% elif definition.exclusiveMaximum and definition.exclusiveMinimum %}
{% set typedef %}const WithoutExclusive = WithinRangeNumber<{{ definition.minimum }}, {{ definition.maximum }}, IWithinRangeNumberTag<{{ definition.minimum }}, {{ definition.maximum }}>>({{ definition.minimum }}, {{ definition.maximum }}){% endset %}
{{ defineConst(undefined, 'WithoutExclusive', typedef, false, true) }}
{% set typedef %}
t.brand(
WithoutExclusive,
(
n
): n is t.Branded<
t.TypeOf<typeof WithoutExclusive>,
{ readonly {{ definitionName }}: symbol }
> => n != {{ definition.minimum }},
"{{definitionName}}"
);
{% endset %}
{## [R,L] #}
{% else %}
{% set typedef %}t.union([
WithinRangeNumber<{{ definition.minimum }}, {{ definition.maximum }}, IWithinRangeNumberTag<{{ definition.minimum }}, {{ definition.maximum }}>>({{ definition.minimum }}, {{ definition.maximum }}),
t.literal({{ definition.maximum }})
]){% endset %}
{% endif %}
{% endif %}
{% elif definition.minimum == "0" %}
{{- 'import { NonNegativeNumber } from "italia-ts-commons/lib/numbers";' | addImport -}}
{% set typedef %}NonNegativeNumber{% endset %}
Expand All @@ -89,10 +134,12 @@
#}
{% macro defineInteger(definitionName, definition, inline = false) -%}
{% if definition.minimum != undefined and definition.maximum != undefined %}
{% set minimum = definition.minimum + 1 if definition.exclusiveMinimum else definition.minimum %}
{% set maximum = definition.maximum - 1 if definition.exclusiveMaximum else definition.maximum %}
{{- 'import { IWithinRangeIntegerTag, WithinRangeInteger } from "italia-ts-commons/lib/numbers";' | addImport -}}
{% set typedef %}t.union([
WithinRangeInteger<{{ definition.minimum }}, {{ definition.maximum }}, IWithinRangeIntegerTag<{{ definition.minimum }}, {{ definition.maximum }}>>({{ definition.minimum }}, {{ definition.maximum }}),
t.literal({{ definition.maximum }})
WithinRangeInteger<{{ minimum }}, {{ maximum }}, IWithinRangeIntegerTag<{{ minimum }}, {{ maximum }}>>({{ minimum }}, {{ maximum }}),
t.literal({{ maximum }})
]){% endset %}
{% elif definition.minimum == "0" %}
{{- 'import { NonNegativeInteger } from "italia-ts-commons/lib/numbers";' | addImport -}}
Expand Down

0 comments on commit 1d05f9c

Please sign in to comment.