From cb4f4a559ac049c3ba8acc7bf42f8a26b7fcc342 Mon Sep 17 00:00:00 2001 From: Johann Haaf Date: Mon, 16 Dec 2019 15:57:14 +0100 Subject: [PATCH 1/2] add test case for #57 --- test/integration/validations.test.ts | 72 +++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/test/integration/validations.test.ts b/test/integration/validations.test.ts index 7fb1a45..5df0bc7 100644 --- a/test/integration/validations.test.ts +++ b/test/integration/validations.test.ts @@ -25,7 +25,7 @@ const resetMocks = (mockErrors: any, status: number = 422) => { } let tempIdIndex = 0 -describe("validations (1/2)", () => { +describe("validations (1/3)", () => { const mockErrors = { firstName: { code: "unprocessable_entity", @@ -280,7 +280,7 @@ describe("validations (1/2)", () => { }) }) -describe("validations (2/2)", () => { +describe("validations (2/3)", () => { const mockErrors = { personDetailBase: { code: "unprocessable_entity", @@ -341,6 +341,74 @@ describe("validations (2/2)", () => { }) }) +describe("validations (3/3)", () => { + const mockErrors = { + bookTitle: { + code: "unprocessable_entity", + status: "422", + title: "Validation Error", + detail: "Title cannot be blank", + meta: { + relationship: { + id: "30", + // ["temp-id"]: "abc1", + name: "books", + type: "books", + attribute: "title", + message: "cannot be blank" + } + } + } + } as any + + let instance: Author + + beforeEach(() => { + resetMocks(mockErrors) + }) + + beforeEach(() => { + sinon.stub(tempId, "generate").callsFake(() => { + tempIdIndex++ + return `abc${tempIdIndex}` + }) + + const genre = new Genre({ id: "20", name: "Horror" }) + genre.isPersisted = true + const book1 = new Book({ id: "10", title: "The Shining", genre }) + book1.isPersisted = true + const book2 = new Book({ id: "30", title: "Pet Sematary", genre }) + book2.isPersisted = true + instance = new Author({ firstName: "Stephen", lastName: "King" }) + instance.id = "1" + instance.books = [book1, book2] + instance.specialBooks = [] + instance.isPersisted = true + }) + + afterEach(() => { + tempIdIndex = 0 + ;(tempId.generate).restore() + }) + + it("applies errors to objects other than the first in nested hasMany relationships", async () => { + instance.books[1].title = "" + const isSuccess = await instance.save({ with: { books: "genre" } }) + + expect(isSuccess).to.eq(false) + expect(instance.books[1].errors).to.deep.equal({ + title: { + title: "Validation Error", + attribute: "title", + code: "unprocessable_entity", + fullMessage: "Title cannot be blank", + message: "cannot be blank", + rawPayload: mockErrors.bookTitle + } + }) + }) +}) + describe("Errors without graphiti validation (1/2)", () => { const mockErrors = { noMeta: { From ea2b5a91449737ab04bc00c234801b53f9fe7d5e Mon Sep 17 00:00:00 2001 From: Johann Haaf Date: Mon, 16 Dec 2019 15:59:27 +0100 Subject: [PATCH 2/2] check for tempId existence fix #57 --- src/util/validation-error-builder.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/util/validation-error-builder.ts b/src/util/validation-error-builder.ts index 15b7bb7..d57c6c6 100644 --- a/src/util/validation-error-builder.ts +++ b/src/util/validation-error-builder.ts @@ -71,6 +71,7 @@ export class ValidationErrorBuilder { let relatedObject = model[model.klass.deserializeKey(meta.name)] if (Array.isArray(relatedObject)) { relatedObject = relatedObject.find(r => { + if (meta["temp-id"] === undefined) return r.id === meta.id return r.id === meta.id || r.temp_id === meta["temp-id"] }) }