Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement functions that checks the passed http status code value is in the expected range #306

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions packages/http-helper/src/http_status_code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,3 +276,73 @@ export const HTTP_VERSION_NOT_SUPPORTED_505 = 505;
* - https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/511
*/
export const NETWORK_AUTHENTICATION_REQUIRED_511 = 511;

/**
* @param code
* The http status code.
* @returns
* This will be `true` if the _code_ is in the range of [1xx][1xx].
* Otherwise, return `false`.
*
* [1xx]: https://httpwg.org/specs/rfc9110.html#status.1xx
*/
export function isInformational1xx(code: number): boolean {
const ok = 100 <= code && code < 200;
return ok;
}

/**
* @param code
* The http status code.
* @returns
* This will be `true` if the _code_ is in the range of [2xx][2xx].
* Otherwise, return `false`.
*
* [2xx]: https://httpwg.org/specs/rfc9110.html#status.2xx
*/
export function isSuccessful2xx(code: number): boolean {
const ok = 200 <= code && code < 300;
return ok;
}

/**
* @param code
* The http status code.
* @returns
* This will be `true` if the _code_ is in the range of [3xx][3xx].
* Otherwise, return `false`.
*
* [3xx]: https://httpwg.org/specs/rfc9110.html#status.3xx
*/
export function isRedirection3xx(code: number): boolean {
const ok = 300 <= code && code < 400;
return ok;
}

/**
* @param code
* The http status code.
* @returns
* This will be `true` if the _code_ is in the range of [4xx][4xx].
* Otherwise, return `false`.
*
* [4xx]: https://httpwg.org/specs/rfc9110.html#status.4xx
*/
export function isClientError4xx(code: number): boolean {
const ok = 400 <= code && code < 500;
return ok;
}

/**
* @param code
* The http status code.
* @returns
* This will be `true` if the _code_ is in the range of [5xx][5xx].
* Otherwise, return `false`.
*
* [5xx]: https://httpwg.org/specs/rfc9110.html#status.5xx
*/
export function isServerError5xx(code: number): boolean {
const ok = 500 <= code && code < 600;
return ok;
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,5 +50,10 @@ exports[`HttpStatus exported items 1`] = `
"UPGRADE_REQUIRED_426": 426,
"URI_TOO_LONG_414": 414,
"USE_PROXY_305": 305,
"isClientError4xx": [Function],
"isInformational1xx": [Function],
"isRedirection3xx": [Function],
"isServerError5xx": [Function],
"isSuccessful2xx": [Function],
}
`;
46 changes: 46 additions & 0 deletions packages/unittests/__tests__/http_status_code/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { assert } from 'vitest';

export function assertNoOverlap(a: ReadonlySet<number>, b: ReadonlySet<number>): void {
const ok = a.isDisjointFrom(b);
if (!ok) {
// we want to avoid to iterate sets multiple times....
const overlapping = a.intersection(b);
assert(false, `test cases have overlap point. They are: ${Array.from(overlapping)}`);
}
}

const RANGE_BEGIN = 0;
// We believe the community does not inroduce new status code range over 999.
const RANGE_END = 999;

export function assertNoLackPatterns(...ranges: Array<ReadonlySet<number>>): void {
const base = new Set(testRange(RANGE_BEGIN, RANGE_END));
let differ = base;
for (const range of ranges) {
differ = differ.difference(range);
}
const noDifference = differ.size === 0;
if (!noDifference) {
assert(false, `There are missing spans: ${Array.from(differ)}`);
}
}

function* testRange(begin: number, end: number): Generator<number> {
assert(begin <= end);

for (let i = begin; i <= end; ++i) {
yield i;
}
}

export function* validRange(begin: number, end: number): Generator<number> {
yield* testRange(begin, end);
}

export function* invalidRangeFrom0To(end: number): Generator<number> {
yield* testRange(RANGE_BEGIN, end);
}

export function* invalidRangeToEndFrom(begin: number): Generator<number> {
yield* testRange(begin, RANGE_END);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { test, expect, beforeAll } from 'vitest';

import { HttpStatus } from '@nikkei/http-helper';
import {
assertNoLackPatterns,
assertNoOverlap,
invalidRangeFrom0To,
invalidRangeToEndFrom,
validRange,
} from './helper.js';

const TRUE_RANGE: ReadonlySet<number> = new Set([
// @prettier-ignore
...validRange(400, 499),
]);

const FALSE_RANGE: ReadonlySet<number> = new Set([
// @prettier-ignore
...invalidRangeFrom0To(399),
...invalidRangeToEndFrom(500),
]);

beforeAll(() => {
assertNoOverlap(TRUE_RANGE, FALSE_RANGE);
assertNoLackPatterns(TRUE_RANGE, FALSE_RANGE);
});

for (const input of TRUE_RANGE) {
test(`isClientError4xx(): input is \`${String(input)}\``, () => {
expect(HttpStatus.isClientError4xx(input)).toEqual(true);
});
}

for (const input of FALSE_RANGE) {
test(`isClientError4xx(): input is \`${String(input)}\``, () => {
expect(HttpStatus.isClientError4xx(input)).toEqual(false);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { test, expect, beforeAll } from 'vitest';

import { HttpStatus } from '@nikkei/http-helper';
import {
assertNoLackPatterns,
assertNoOverlap,
invalidRangeFrom0To,
invalidRangeToEndFrom,
validRange,
} from './helper.js';

const TRUE_RANGE: ReadonlySet<number> = new Set([
// @prettier-ignore
...validRange(100, 199),
]);

const FALSE_RANGE: ReadonlySet<number> = new Set([
// @prettier-ignore
...invalidRangeFrom0To(99),
...invalidRangeToEndFrom(200),
]);

beforeAll(() => {
assertNoOverlap(TRUE_RANGE, FALSE_RANGE);
assertNoLackPatterns(TRUE_RANGE, FALSE_RANGE);
});

for (const input of TRUE_RANGE) {
test(`isInformational1xx(): input is \`${String(input)}\``, () => {
expect(HttpStatus.isInformational1xx(input)).toEqual(true);
});
}

for (const input of FALSE_RANGE) {
test(`isInformational1xx(): input is \`${String(input)}\``, () => {
expect(HttpStatus.isInformational1xx(input)).toEqual(false);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { test, expect, beforeAll } from 'vitest';

import { HttpStatus } from '@nikkei/http-helper';
import {
assertNoLackPatterns,
assertNoOverlap,
invalidRangeFrom0To,
invalidRangeToEndFrom,
validRange,
} from './helper.js';

const TRUE_RANGE: ReadonlySet<number> = new Set([
// @prettier-ignore
...validRange(300, 399),
]);

const FALSE_RANGE: ReadonlySet<number> = new Set([
// @prettier-ignore
...invalidRangeFrom0To(299),
...invalidRangeToEndFrom(400),
]);

beforeAll(() => {
assertNoOverlap(TRUE_RANGE, FALSE_RANGE);
assertNoLackPatterns(TRUE_RANGE, FALSE_RANGE);
});

for (const input of TRUE_RANGE) {
test(`isRedirection3xx(): input is \`${String(input)}\``, () => {
expect(HttpStatus.isRedirection3xx(input)).toEqual(true);
});
}

for (const input of FALSE_RANGE) {
test(`isRedirection3xx(): input is \`${String(input)}\``, () => {
expect(HttpStatus.isRedirection3xx(input)).toEqual(false);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { test, expect, beforeAll } from 'vitest';

import { HttpStatus } from '@nikkei/http-helper';
import {
assertNoLackPatterns,
assertNoOverlap,
invalidRangeFrom0To,
invalidRangeToEndFrom,
validRange,
} from './helper.js';

const TRUE_RANGE: ReadonlySet<number> = new Set([
// @prettier-ignore
...validRange(500, 599),
]);

const FALSE_RANGE: ReadonlySet<number> = new Set([
// @prettier-ignore
...invalidRangeFrom0To(499),
...invalidRangeToEndFrom(600),
]);

beforeAll(() => {
assertNoOverlap(TRUE_RANGE, FALSE_RANGE);
assertNoLackPatterns(TRUE_RANGE, FALSE_RANGE);
});

for (const input of TRUE_RANGE) {
test(`isServerError5xx(): input is \`${String(input)}\``, () => {
expect(HttpStatus.isServerError5xx(input)).toEqual(true);
});
}

for (const input of FALSE_RANGE) {
test(`isServerError5xx(): input is \`${String(input)}\``, () => {
expect(HttpStatus.isServerError5xx(input)).toEqual(false);
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { test, expect, beforeAll } from 'vitest';

import { HttpStatus } from '@nikkei/http-helper';
import {
assertNoLackPatterns,
assertNoOverlap,
invalidRangeFrom0To,
invalidRangeToEndFrom,
validRange,
} from './helper.js';

const TRUE_RANGE: ReadonlySet<number> = new Set([
// @prettier-ignore
...validRange(200, 299),
]);

const FALSE_RANGE: ReadonlySet<number> = new Set([
// @prettier-ignore
...invalidRangeFrom0To(199),
...invalidRangeToEndFrom(300),
]);

beforeAll(() => {
assertNoOverlap(TRUE_RANGE, FALSE_RANGE);
assertNoLackPatterns(TRUE_RANGE, FALSE_RANGE);
});

for (const input of TRUE_RANGE) {
test(`isSuccessful2xx(): input is \`${String(input)}\``, () => {
expect(HttpStatus.isSuccessful2xx(input)).toEqual(true);
});
}

for (const input of FALSE_RANGE) {
test(`isSuccessful2xx(): input is \`${String(input)}\``, () => {
expect(HttpStatus.isSuccessful2xx(input)).toEqual(false);
});
}
1 change: 1 addition & 0 deletions packages/unittests/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"extends": "../../tsconfig.base.project_reference.json",
"compilerOptions": {
"lib": ["ESNext"],
"noEmit": true,
"outDir": "./__obj"
},
Expand Down