Skip to content

Commit

Permalink
fix: handle wrong value in BaseRecord#populated
Browse files Browse the repository at this point in the history
in JS users can put to BaseRecord.populate some arbitrary
value. This commit simply omits toJSON conversion for
such cases
  • Loading branch information
wojtek-krysiak authored and RiledUpCrow committed Nov 13, 2020
1 parent 9e42e8e commit 5c8bc5c
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 1 deletion.
42 changes: 42 additions & 0 deletions src/backend/adapters/record/base-record.spec.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import chai, { expect } from 'chai'
import chaiChange from 'chai-change'
import sinon from 'sinon'
import sinonChai from 'sinon-chai'
import chaiAsPromised from 'chai-as-promised'
import { ParamsType } from './params.type'

import BaseRecord from './base-record'
import BaseResource from '../resource/base-resource'
import BaseProperty from '../property/base-property'
import ValidationError, { PropertyErrors } from '../../utils/errors/validation-error'
import { ActionDecorator, ResourceDecorator } from '../../decorators'

chai.use(chaiAsPromised)
chai.use(chaiChange)
chai.use(sinonChai)

describe('Record', function () {
let record: BaseRecord
Expand Down Expand Up @@ -223,4 +226,43 @@ describe('Record', function () {
}).to.alter(() => record.populated.value, { from: 'something', to: undefined })
})
})

describe('#toJSON', () => {
const param = 'populatedProperty'
let resource: BaseResource

beforeEach(() => {
resource = sinon.createStubInstance(BaseResource, {
properties: sinon.stub<[], BaseProperty[]>().returns([]),
decorate: sinon.stub<[], ResourceDecorator>().returns(
sinon.createStubInstance(ResourceDecorator, {
recordActions: sinon.stub<[BaseRecord], ActionDecorator[]>().returns([]),
bulkActions: sinon.stub<[BaseRecord], ActionDecorator[]>().returns([]),
}) as unknown as ResourceDecorator,
),
})
record = new BaseRecord(params, resource)
})

it('changes populated records to JSON', () => {
const refRecord = sinon.createStubInstance(BaseRecord, {
toJSON: sinon.stub(),
})
record.populate(param, refRecord)
sinon.stub(record, 'id').returns('1')

record.toJSON()

expect(refRecord.toJSON).to.have.been.calledOnce
})

it('does not changes to JSON when in populated there is something else than BaseRecord', () => {
record.populate(param, 'something else' as unknown as BaseRecord)
sinon.stub(record, 'id').returns('1')

expect(() => {
record.toJSON()
}).not.to.throw()
})
})
})
8 changes: 7 additions & 1 deletion src/backend/adapters/record/base-record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,13 @@ class BaseRecord {
*/
toJSON(currentAdmin?: CurrentAdmin): RecordJSON {
const populated = Object.keys(this.populated).reduce((m, key) => {
m[key] = this.populated[key].toJSON(currentAdmin)
// sometimes user can add some arbitrary element to populated object. In such case
// we should omit toJSON call.
if ((this.populated[key] as any).toJSON) {
m[key] = this.populated[key].toJSON(currentAdmin)
} else {
m[key] = this.populated[key]
}

return m
}, {})
Expand Down

0 comments on commit 5c8bc5c

Please sign in to comment.