Skip to content

Commit

Permalink
update tests with new types
Browse files Browse the repository at this point in the history
  • Loading branch information
brendarearden committed May 10, 2023
1 parent 6b17f89 commit 0c4b819
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,9 @@ describe('body params validation', () => {

expect(response.status).toBe(422);
return expect(response.json()).resolves.toMatchObject({
validation: [{ code: 'required', message: "Request body must have required property 'id'", severity: 'Error' }],
validation: [
{ code: 'required', message: "Request body must have required property 'id'", severity: 'Error' },
],
});
});
});
Expand Down Expand Up @@ -624,7 +626,8 @@ describe('body params validation', () => {
{
code: 'enum',
location: ['body', 'status'],
message: 'Request body property status must be equal to one of the allowed values: placed, approved, delivered',
message:
'Request body property status must be equal to one of the allowed values: placed, approved, delivered',
severity: 'Error',
},
],
Expand Down
2 changes: 1 addition & 1 deletion packages/http/src/router/__tests__/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { DeepNonNullable } from 'utility-types';
const httpMethods: HttpMethod[] = ['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace'];

export function pickOneHttpMethod(): HttpMethod {
return faker.random.arrayElement(httpMethods);
return faker.helpers.arrayElement(httpMethods);
}

export function pickSetOfHttpMethods(count = 2): HttpMethod[] {
Expand Down
100 changes: 49 additions & 51 deletions packages/http/src/validator/validators/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,60 +19,58 @@ export type Deps<Target> = {

const schemaCache = new WeakMap<IHttpParam[], JSONSchema>();

export const validateParams = <Target>(
target: Target,
specs: IHttpParam[],
bundle?: unknown
): RE.ReaderEither<Deps<Target>, NEA.NonEmptyArray<IPrismDiagnostic>, Target> => ({
deserializers,
prefix,
defaultStyle,
}) => {
const deprecatedWarnings = specs
.filter(spec => spec.deprecated && target[spec.name])
.map<IPrismDiagnostic>(spec => ({
path: [prefix, spec.name],
code: 'deprecated',
message: `${upperFirst(prefix)} param ${spec.name} is deprecated`,
severity: DiagnosticSeverity.Warning,
}));
export const validateParams =
<Target>(
target: Target,
specs: IHttpParam[],
bundle?: unknown
): RE.ReaderEither<Deps<Target>, NEA.NonEmptyArray<IPrismDiagnostic>, Target> =>
({ deserializers, prefix, defaultStyle }) => {
const deprecatedWarnings = specs
.filter(spec => spec.deprecated && target[spec.name])
.map<IPrismDiagnostic>(spec => ({
path: [prefix, spec.name],
code: 'deprecated',
message: `${upperFirst(prefix)} param ${spec.name} is deprecated`,
severity: DiagnosticSeverity.Warning,
}));

return pipe(
NEA.fromArray(specs),
O.map(specs => {
const schema = schemaCache.get(specs) ?? createJsonSchemaFromParams(specs);
if (!schemaCache.has(specs)) {
schemaCache.set(specs, schema);
}
return pipe(
NEA.fromArray(specs),
O.map(specs => {
const schema = schemaCache.get(specs) ?? createJsonSchemaFromParams(specs);
if (!schemaCache.has(specs)) {
schemaCache.set(specs, schema);
}

const parameterValues = pickBy(
mapValues(
keyBy(specs, s => s.name.toLowerCase()),
el => {
const resolvedStyle = el.style || defaultStyle;
const deserializer = deserializers[resolvedStyle];
const parameterValues = pickBy(
mapValues(
keyBy(specs, s => s.name.toLowerCase()),
el => {
const resolvedStyle = el.style || defaultStyle;
const deserializer = deserializers[resolvedStyle];

return deserializer
? deserializer(
el.name.toLowerCase(),
// @ts-ignore
mapKeys(target, (_value: unknown, key: string) => key.toLowerCase()),
schema.properties && (schema.properties[el.name.toLowerCase()] as JSONSchema4),
el.explode || false
)
: undefined;
}
)
);
return { parameterValues, schema };
}),
O.chain(({ parameterValues, schema }) => validateAgainstSchema(parameterValues, schema, true, prefix, bundle)),
O.map(schemaDiagnostic => NEA.concat(schemaDiagnostic, deprecatedWarnings)),
O.alt(() => NEA.fromArray(deprecatedWarnings)),
E.fromOption(() => target),
E.swap
);
};
return deserializer
? deserializer(
el.name.toLowerCase(),
// @ts-ignore
mapKeys(target, (_value: unknown, key: string) => key.toLowerCase()),
schema.properties && (schema.properties[el.name.toLowerCase()] as JSONSchema4),
el.explode || false
)
: undefined;
}
)
);
return { parameterValues, schema };
}),
O.chain(({ parameterValues, schema }) => validateAgainstSchema(parameterValues, schema, true, prefix, bundle)),
O.map(schemaDiagnostic => NEA.concat(schemaDiagnostic, deprecatedWarnings)),
O.alt(() => NEA.fromArray(deprecatedWarnings)),
E.fromOption(() => target),
E.swap
);
};

function createJsonSchemaFromParams(params: NEA.NonEmptyArray<IHttpParam>): JSONSchema {
return {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,15 @@ describe('validateSecurity', () => {

describe('when security scheme uses Basic authorization', () => {
const securityScheme: HttpSecurityScheme[][] = [
[{ id: faker.random.word(), scheme: 'basic', type: 'http', key: 'sec' }],
[
{
id: faker.random.word(),
scheme: 'basic',
type: 'http',
key: 'sec',
extensions: { 'x-test': faker.random.word() },
},
],
];

it('passes the validation', () => {
Expand Down Expand Up @@ -69,7 +77,15 @@ describe('validateSecurity', () => {

describe('when security scheme uses Digest authorization', () => {
const securityScheme: HttpSecurityScheme[][] = [
[{ id: faker.random.word(), scheme: 'digest', type: 'http', key: 'sec' }],
[
{
id: faker.random.word(),
scheme: 'digest',
type: 'http',
key: 'sec',
extensions: { 'x-test': faker.random.word() },
},
],
];

it('passes the validation', () => {
Expand Down Expand Up @@ -105,7 +121,15 @@ describe('validateSecurity', () => {

describe('when security scheme uses Bearer authorization', () => {
const securityScheme: HttpSecurityScheme[][] = [
[{ id: faker.random.word(), scheme: 'bearer', type: 'http', key: 'sec' }],
[
{
id: faker.random.word(),
scheme: 'bearer',
type: 'http',
key: 'sec',
extensions: { 'x-test': faker.random.word() },
},
],
];

it('passes the validation', () => {
Expand Down Expand Up @@ -138,7 +162,15 @@ describe('validateSecurity', () => {

describe('when security scheme uses OAuth2 authorization', () => {
const securityScheme: HttpSecurityScheme[][] = [
[{ id: faker.random.word(), type: 'oauth2', flows: {}, key: 'sec' }],
[
{
id: faker.random.word(),
type: 'oauth2',
flows: {},
key: 'sec',
extensions: { 'x-test': faker.random.word() },
},
],
];

it('it passes the validation', () => {
Expand Down Expand Up @@ -171,7 +203,15 @@ describe('validateSecurity', () => {

describe('when security scheme uses OpenID authorization', () => {
const securityScheme: HttpSecurityScheme[][] = [
[{ id: faker.random.word(), type: 'openIdConnect', openIdConnectUrl: 'https://google.it', key: 'sec' }],
[
{
id: faker.random.word(),
type: 'openIdConnect',
openIdConnectUrl: 'https://google.it',
key: 'sec',
extensions: { 'x-test': faker.random.word() },
},
],
];

it('passes the validation', () => {
Expand Down Expand Up @@ -211,8 +251,21 @@ describe('validateSecurity', () => {
resource: {
security: [
[
{ id: faker.random.word(), scheme: 'basic', type: 'http', key: 'sec' },
{ id: faker.random.word(), in: 'header', type: 'apiKey', name: 'x-api-key', key: 'sec' },
{
id: faker.random.word(),
scheme: 'basic',
type: 'http',
key: 'sec',
extensions: { 'x-test': faker.random.word() },
},
{
id: faker.random.word(),
in: 'header',
type: 'apiKey',
name: 'x-api-key',
key: 'sec',
extensions: { 'x-test': faker.random.word() },
},
],
],
},
Expand All @@ -232,7 +285,16 @@ describe('validateSecurity', () => {

describe('when api key is expected to be found in a header', () => {
const securityScheme: HttpSecurityScheme[][] = [
[{ id: faker.random.word(), in: 'header', type: 'apiKey', name: 'x-api-key', key: 'sec' }],
[
{
id: faker.random.word(),
in: 'header',
type: 'apiKey',
name: 'x-api-key',
key: 'sec',
extensions: { 'x-test': faker.random.word() },
},
],
];

it('passes the validation', () => {
Expand Down Expand Up @@ -262,7 +324,16 @@ describe('validateSecurity', () => {

describe('when api key is expected to be found in the query', () => {
const securityScheme: HttpSecurityScheme[][] = [
[{ id: faker.random.word(), in: 'query', type: 'apiKey', name: 'key', key: 'sec' }],
[
{
id: faker.random.word(),
in: 'query',
type: 'apiKey',
name: 'key',
key: 'sec',
extensions: { 'x-test': faker.random.word() },
},
],
];

it('passes the validation', () => {
Expand Down Expand Up @@ -290,7 +361,16 @@ describe('validateSecurity', () => {

describe('when api key is expected to be found in a cookie', () => {
const securityScheme: HttpSecurityScheme[][] = [
[{ id: faker.random.word(), in: 'cookie', type: 'apiKey', name: 'key', key: 'sec' }],
[
{
id: faker.random.word(),
in: 'cookie',
type: 'apiKey',
name: 'key',
key: 'sec',
extensions: { 'x-test': faker.random.word() },
},
],
];

it('passes the validation', () => {
Expand Down Expand Up @@ -319,8 +399,24 @@ describe('validateSecurity', () => {

describe('OR relation between security schemes', () => {
const securityScheme: HttpSecurityScheme[][] = [
[{ id: faker.random.word(), scheme: 'bearer', type: 'http', key: 'sec' }],
[{ id: faker.random.word(), scheme: 'basic', type: 'http', key: 'sec' }],
[
{
id: faker.random.word(),
scheme: 'bearer',
type: 'http',
key: 'sec',
extensions: { 'x-test': faker.random.word() },
},
],
[
{
id: faker.random.word(),
scheme: 'basic',
type: 'http',
key: 'sec',
extensions: { 'x-test': faker.random.word() },
},
],
];

it('fails with an invalid security scheme error', () => {
Expand Down Expand Up @@ -373,12 +469,22 @@ describe('validateSecurity', () => {
type: 'apiKey' as const,
name: 'x-api-key' as const,
key: 'sec' as const,
extensions: { 'x-test': 'test' },
};

describe('when 2 different security schemes are expected', () => {
describe('expecting oauth + apikey', () => {
const securityScheme: HttpSecurityScheme[][] = [
[headerScheme, { id: faker.random.word(), type: 'oauth2', flows: {}, key: 'sec' }],
[
headerScheme,
{
id: faker.random.word(),
type: 'oauth2',
flows: {},
key: 'sec',
extensions: { 'x-test': faker.random.word() },
},
],
];

it('fails with an invalid security scheme error', () => {
Expand Down Expand Up @@ -417,7 +523,13 @@ describe('validateSecurity', () => {
const securityScheme: HttpSecurityScheme[][] = [
[
headerScheme,
{ id: faker.random.word(), type: 'openIdConnect', openIdConnectUrl: 'https://google.it', key: 'sec' },
{
id: faker.random.word(),
type: 'openIdConnect',
openIdConnectUrl: 'https://google.it',
key: 'sec',
extensions: { 'x-test': faker.random.word() },
},
],
];

Expand Down Expand Up @@ -464,6 +576,7 @@ describe('validateSecurity', () => {
type: 'apiKey',
name: 'apiKey',
key: 'sec',
extensions: { 'x-test': faker.random.word() },
},
],
];
Expand Down
Loading

0 comments on commit 0c4b819

Please sign in to comment.