Skip to content

Commit

Permalink
fix: top level default values for deep objects (#586)
Browse files Browse the repository at this point in the history
  • Loading branch information
cdimascio committed Apr 18, 2021
1 parent 117d54b commit ca16b42
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 23 deletions.
25 changes: 21 additions & 4 deletions src/middlewares/parsers/req.parameter.mutator.ts
Expand Up @@ -103,22 +103,39 @@ export class RequestParameterMutator {
});
}

private handleDeepObject(req: Request, qs: string, name: string, schema: SchemaObject): void {
private handleDeepObject(
req: Request,
qs: string,
name: string,
schema: SchemaObject,
): void {
const getDefaultSchemaValue = () => {
let defaultValue;

if (schema.default !== undefined) {
defaultValue = schema.default
defaultValue = schema.default;
} else if (schema.properties) {
Object.entries(schema.properties).forEach(([k, v]) => {
// Handle recursive objects
defaultValue ??= {};
if (v['default']) {
defaultValue[k] = v['default'];
}
});
} else {
['allOf', 'oneOf', 'anyOf'].forEach((key) => {
if (schema[key]) {
schema[key].forEach((s) => {
if (s.$ref) {
const compiledSchema = this.ajv.getSchema(s.$ref);
// as any -> https://stackoverflow.com/a/23553128
defaultValue = defaultValue === undefined ? (compiledSchema.schema as any).default : defaultValue;
defaultValue =
defaultValue === undefined
? (compiledSchema.schema as any).default
: defaultValue;
} else {
defaultValue = defaultValue === undefined ? s.default : defaultValue;
defaultValue =
defaultValue === undefined ? s.default : defaultValue;
}
});
}
Expand Down
54 changes: 39 additions & 15 deletions test/resources/serialized-deep-object.objects.yaml
Expand Up @@ -40,23 +40,47 @@ paths:
responses:
"200":
description: the object
/deep_object_2:
get:
parameters:
- $ref: '#/components/parameters/pedestrian'
responses:
"200":
description: the object

components:
schemas:
Deep:
Pedestrian:
type: object
properties:
tag_ids:
type: array
items:
type: integer
minimum: 0
minItems: 1
state:
type: string
enum: ["default", "validated", "pending"]
default: "default"
description: "Filter the tags by their validity. The default value ('default') stands for no filtering."
greeting:
type: string
default: "hello"
speed:
type: number
format: double
minimum: 0.5
maximum: 2
default: 1
# Deep:
# type: object
# properties:
# tag_ids:
# type: array
# items:
# type: integer
# minimum: 0
# minItems: 1
# state:
# type: string
# enum: ["default", "validated", "pending"]
# default: "default"
# description: "Filter the tags by their validity. The default value ('default') stands for no filtering."
# greeting:
# type: string
# default: "hello"

parameters:
pedestrian:
name: pedestrian
in: query
style: deepObject
schema:
$ref: '#/components/schemas/Pedestrian'
28 changes: 24 additions & 4 deletions test/serialized-deep-object.objects.spec.ts
Expand Up @@ -10,13 +10,18 @@ describe(packageJson.name, () => {

before(async () => {
// Set up the express app
const apiSpec = path.join('test', 'resources', 'serialized-deep-object.objects.yaml');
const apiSpec = path.join(
'test',
'resources',
'serialized-deep-object.objects.yaml',
);
app = await createApp({ apiSpec }, 3005, (app) =>
app.use(
`${app.basePath}`,
express
.Router()
.get(`/deep_object`, (req, res) => res.json(req.query))
.get(`/deep_object_2`, (req, res) => res.json(req.query)),
),
);
});
Expand All @@ -25,6 +30,16 @@ describe(packageJson.name, () => {
app.server.close();
});

it('should explode deepObject and set default', async () =>
request(app)
.get(`${app.basePath}/deep_object_2`)
.expect(200)
.then((r) => {
expect(r.body).to.deep.equals({
pedestrian: { speed: 1 },
});
}));

it('should explode deepObject query params', async () =>
request(app)
.get(`${app.basePath}/deep_object?settings[state]=default`)
Expand All @@ -33,8 +48,8 @@ describe(packageJson.name, () => {
const expected = {
settings: {
greeting: 'hello',
state: 'default'
}
state: 'default',
},
};
expect(r.body).to.deep.equals(expected);
}));
Expand All @@ -45,6 +60,11 @@ describe(packageJson.name, () => {
.expect(200)
.then((r) => {
const expected = {};
expect(r.body).to.deep.equals(expected);
expect(r.body).to.deep.equals({
settings: {
greeting: 'hello',
state: 'default',
},
});
}));
});

0 comments on commit ca16b42

Please sign in to comment.