fix: emit "type: 'object'," for schema definitions#3828
Conversation
| if (meta.description) { | ||
| result.description = meta.description; | ||
| } | ||
| result.type = 'object'; |
There was a problem hiding this comment.
Isn't the type default to object if properties is present?
There was a problem hiding this comment.
I am not sure, but the test fails when the element is not present so the validation does not work as expected.
|
@noels Please also fix https://travis-ci.com/strongloop/loopback-next/jobs/239863212 |
bajtos
left a comment
There was a problem hiding this comment.
Thank you for the pull request. Please add a new test to verify the scenario you have described in PR description:
- Loopback generated JSON Schema omits this declaration. build-schema.ts:353.
- Omitting this declaration causes ajv validation to pass when a required element (which is a reference to a different object) is set to null.
- Adding the declaration: "type: 'object'" to generated schemas enables ajv validation to correctly fail when a required referenced property is present but the value set to null.
This test should fail with a descriptive error message on the current master and pass with your changes in place.
Please can you give me some guidance as to where the test would be required. The framework tests the validation of the body in the Rest package tests (which I have now updated to work with my changes), but the schema is supplied to the validation requests as a test fixture. If I added a test there I think I would just be testing something that should already be covered in the ajv test suite. I have added tests that test for the presence of the 'type: "object" in the generated schema to the repository-json-schema package. If you can point me to where there are currently tests that verify that the generated JSONSchema works correctly with ajv validation I can add a new test there to ensure the behaviour is correct. |
|
@noels thanks for asking. I was thinking about adding a new test to If I understand your scenario correctly, then you want to reject requests when a required property is set to Alternatively, you can create a new |
- JSON Schema makes provision for structuring a complex schema into re-usable elements. - Loopback makes use of reference schema re-use through the '$ref' keyword. - in the JSON Schema documentation for complex schemas https://json-schema.org/understanding-json-schema/structuring.html the complex schema definitions are declared as type: 'object'. - Loopback generated JSON Schema omits this declaration. build-schema.ts:353. - Omitting this declaration causes ajv validation to pass when a required element (which is a reference to a different object) is set to null. - Adding the declaration: "type: 'object'" to generated schemas enables ajv validation to correctly fail when a required referenced property is present but the value set to null. - fix failing failing tests. - Add a category to to product in rest acceptance tests in order to test complex schema functionaly.
|
Thanks for the guidance. I have added an acceptance test to test for an object property being passed a null value. I have now fixed the prettier and commit message issues, and squashed the previous commits into a single commit for clarity. |
bajtos
left a comment
There was a problem hiding this comment.
Thank you @noels for the update. AFAICT, you have updated the tests to verify the "happy path" when the user provided data for the nested object property. Now you also need to add a test to verify that a request setting such property to null is rejected. See your own description of the problem:
Omitting this declaration causes ajv validation to pass when a required element (which is a reference to a different object) is set to null.
|
It seems I forgot to include the new test when I copied everything over to a single commit. I've added the test. Please see if that's what you wanted. |
bajtos
left a comment
There was a problem hiding this comment.
I am afraid the new test is not good enough, see my comment below.
Let's build a better understanding of the problem and come up with an improved test that better describes and verifies the bug you want to fix.
| .type('json') | ||
| .send(DATA) | ||
| .expect(422); | ||
| }); |
There was a problem hiding this comment.
I am afraid this test is passing on the current master too. Here is the error reported:
{
statusCode: 422,
name: 'UnprocessableEntityError',
message: 'The request body is invalid. See error object `details` property for more info.',
code: 'VALIDATION_FAILED',
details: [
{
path: '',
code: 'additionalProperties',
message: 'should NOT have additional properties',
info: [Object]
}
]
}@noels PTAL.
We need a test that fails on the current master and thus reproduces the bug you are trying to fix. Without such test, we have very little confidence that your changes are actually achieving the desired goal, plus it's easy to introduce unwanted regressions in the future.
There was a problem hiding this comment.
HI @bajtos Thanks for having a look. I reset my local copy to the upstream master, replaced the validation.acceptance.ts file with the one from my branch, then ran mocha in loopback-next/packages/rest
and got:
Error: expected 422 "Unprocessable Entity", got 200 "OK"
at Test._assertStatus (/home/noels/Documents/workspace/ho/GEFEAPI/loopback-next/packages/testlab/node_modules/supertest/lib/test.js:268:12)
at Test._assertFunction (/home/noels/Documents/workspace/ho/GEFEAPI/loopback-next/packages/testlab/node_modules/supertest/lib/test.js:283:11)
at Test.assert (/home/noels/Documents/workspace/ho/GEFEAPI/loopback-next/packages/testlab/node_modules/supertest/lib/test.js:173:18)
at localAssert (/home/noels/Documents/workspace/ho/GEFEAPI/loopback-next/packages/testlab/node_modules/supertest/lib/test.js:131:12)
at /home/noels/Documents/workspace/ho/GEFEAPI/loopback-next/packages/testlab/node_modules/supertest/lib/test.js:128:5
at Test.Request.callback (/home/noels/Documents/workspace/ho/GEFEAPI/loopback-next/packages/testlab/node_modules/superagent/lib/node/index.js:716:12)
at parser (/home/noels/Documents/workspace/ho/GEFEAPI/loopback-next/packages/testlab/node_modules/superagent/lib/node/index.js:916:18)
at IncomingMessage.res.on (/home/noels/Documents/workspace/ho/GEFEAPI/loopback-next/packages/testlab/node_modules/superagent/lib/node/parsers/json.js:19:7)
at endReadableNT (_stream_readable.js:1059:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9)
Did you npm run build before running the test? Am I missing something?
There was a problem hiding this comment.
I created a feature branch based on the current master (as of today morning), adding your commit with the test (b44cac5).
You can find the feature branch here:
https://github.com/strongloop/loopback-next/tree/test-pr-3828
When I run npm it (install & test), all tests are green.
I think the change in behavior may be caused by #3895, where we started to add additionalProperties: false to schema emitted for models in strict mode (which is the default).
When I change the definition of Product model in the acceptance test and disable strict mode, then your new test fails as expected. (Unfortunately, there is one more test that fails too.)
diff --git a/packages/rest/src/__tests__/acceptance/validation/validation.acceptance.ts b/packages/rest/src/__tests__/acceptance/validation/validation.acceptance.ts
index 19697b83f..9070273fa 100644
--- a/packages/rest/src/__tests__/acceptance/validation/validation.acceptance.ts
+++ b/packages/rest/src/__tests__/acceptance/validation/validation.acceptance.ts
@@ -28,7 +28,7 @@ describe('Validation at REST level', () => {
let app: RestApplication;
let client: Client;
- @model()
+ @model({settings: {strict: false}})
class Product {
@property()
id: number;Obviously, we don't want to change all existing tests to start testing the scenario with strict: false and no longer test the default setup with strict: true. To support non-strict mode, we need to create a new group of tests in validation.acceptance.ts that will use a new model with strict: false.
Let me ask you a question: how are your models configured? Do you use the default "strict" model behavior, or are you disabling it via model settings? If you are using strict mode, then I think you should be find a this pull request is not needed for your app.
|
@noels Last but not least, please rebase your patch on top of the latest |
|
@noels what's the status of this pull request? Are you still keen to continue working on this improvement? |
|
This issue has been closed due to continued inactivity. Thank you for your understanding. If you believe this to be in error, please contact one of the code owners, listed in the |
Checklist
👉 Read and sign the CLA (Contributor License Agreement) 👈
npm testpasses on your machinepackages/cliwere updatedexamples/*were updated👉 Check out how to submit a PR 👈