Skip to content

Commit af3410e

Browse files
author
Agnes Lin
committed
fix: feedback applied
1 parent 8a7f78d commit af3410e

File tree

4 files changed

+109
-88
lines changed

4 files changed

+109
-88
lines changed

packages/repository-tests/src/crud/relations/acceptance/has-many-inclusion-resolver.relation.acceptance.ts

+78-76
Original file line numberDiff line numberDiff line change
@@ -187,84 +187,86 @@ export function hasManyInclusionResolverAcceptance(
187187
expect(toJSON(result)).to.deepEqual(toJSON(expected));
188188
});
189189

190-
describe('checks save() and replaceById()', () => {
191-
/* istanbul ignore next */
192-
(features.hasRevisionToken ? it.skip : it)(
193-
'skips the tests for Cloudant as it needs the token',
194-
async () => {
195-
it('returns inclusions after running save() operation', async () => {
196-
// this shows save() works well with func ensurePersistable and ObjectId
197-
const thor = await customerRepo.create({name: 'Thor'});
198-
const odin = await customerRepo.create({name: 'Odin'});
199-
200-
const thorOrder = await orderRepo.create({
201-
customerId: thor.id,
202-
description: 'Pizza',
203-
});
204-
205-
const pizza = await orderRepo.findById(thorOrder.id);
206-
pizza.customerId = odin.id;
207-
208-
await orderRepo.save(pizza);
209-
const odinPizza = await orderRepo.findById(thorOrder.id);
210-
211-
const result = await customerRepo.findById(odin.id, {
212-
include: [{relation: 'orders'}],
213-
});
214-
const expected = {
215-
...odin,
216-
parentId: features.emptyValue,
217-
orders: [
218-
{
219-
...odinPizza,
220-
isShipped: features.emptyValue,
221-
// eslint-disable-next-line @typescript-eslint/camelcase
222-
shipment_id: features.emptyValue,
223-
},
224-
],
225-
};
226-
expect(toJSON(result)).to.containEql(toJSON(expected));
227-
});
228-
229-
it('returns inclusions after running replaceById() operation', async () => {
230-
// this shows replaceById() works well with func ensurePersistable and ObjectId
231-
const thor = await customerRepo.create({name: 'Thor'});
232-
const odin = await customerRepo.create({name: 'Odin'});
233-
234-
const thorOrder = await orderRepo.create({
235-
customerId: thor.id,
236-
description: 'Pizza',
237-
});
238-
239-
const pizza = await orderRepo.findById(thorOrder.id);
240-
pizza.customerId = odin.id;
241-
242-
await orderRepo.replaceById(thorOrder.id, pizza);
243-
const odinPizza = await orderRepo.findById(thorOrder.id);
244-
245-
const result = await customerRepo.find({
246-
include: [{relation: 'orders'}],
247-
});
248-
const expected = [
249-
{...thor, parentId: features.emptyValue},
190+
skipIf(
191+
!features.hasRevisionToken,
192+
it,
193+
'returns inclusions after running save() operation',
194+
async () => {
195+
// this shows save() works well with func ensurePersistable and ObjectId
196+
const thor = await customerRepo.create({name: 'Thor'});
197+
const odin = await customerRepo.create({name: 'Odin'});
198+
199+
const thorOrder = await orderRepo.create({
200+
customerId: thor.id,
201+
description: 'Pizza',
202+
});
203+
204+
const pizza = await orderRepo.findById(thorOrder.id);
205+
pizza.customerId = odin.id;
206+
207+
await orderRepo.save(pizza);
208+
const odinPizza = await orderRepo.findById(thorOrder.id);
209+
210+
const result = await customerRepo.findById(odin.id, {
211+
include: [{relation: 'orders'}],
212+
});
213+
const expected = {
214+
...odin,
215+
parentId: features.emptyValue,
216+
orders: [
217+
{
218+
...odinPizza,
219+
isShipped: features.emptyValue,
220+
// eslint-disable-next-line @typescript-eslint/camelcase
221+
shipment_id: features.emptyValue,
222+
},
223+
],
224+
};
225+
expect(toJSON(result)).to.containEql(toJSON(expected));
226+
},
227+
);
228+
229+
skipIf(
230+
!features.hasRevisionToken,
231+
it,
232+
'returns inclusions after running replaceById() operation',
233+
async () => {
234+
// this shows replaceById() works well with func ensurePersistable and ObjectId
235+
const thor = await customerRepo.create({name: 'Thor'});
236+
const odin = await customerRepo.create({name: 'Odin'});
237+
238+
const thorOrder = await orderRepo.create({
239+
customerId: thor.id,
240+
description: 'Pizza',
241+
});
242+
243+
const pizza = await orderRepo.findById(thorOrder.id.toString());
244+
pizza.customerId = odin.id;
245+
246+
await orderRepo.replaceById(thorOrder.id, pizza);
247+
const odinPizza = await orderRepo.findById(thorOrder.id);
248+
249+
const result = await customerRepo.find({
250+
include: [{relation: 'orders'}],
251+
});
252+
const expected = [
253+
{...thor, parentId: features.emptyValue},
254+
{
255+
...odin,
256+
parentId: features.emptyValue,
257+
orders: [
250258
{
251-
...odin,
252-
parentId: features.emptyValue,
253-
orders: [
254-
{
255-
...odinPizza,
256-
isShipped: features.emptyValue,
257-
// eslint-disable-next-line @typescript-eslint/camelcase
258-
shipment_id: features.emptyValue,
259-
},
260-
],
259+
...odinPizza,
260+
isShipped: features.emptyValue,
261+
// eslint-disable-next-line @typescript-eslint/camelcase
262+
shipment_id: features.emptyValue,
261263
},
262-
];
263-
expect(toJSON(result)).to.deepEqual(toJSON(expected));
264-
});
265-
},
266-
);
267-
});
264+
],
265+
},
266+
];
267+
expect(toJSON(result)).to.deepEqual(toJSON(expected));
268+
},
269+
);
268270

269271
it('throws when navigational properties are present when updating model instance with save()', async () => {
270272
// save() calls replaceById so the result will be the same for replaceById

packages/repository-tests/src/crud/relations/acceptance/has-many.relation.acceptance.ts

+17
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,23 @@ export function hasManyRelationAcceptance(
247247
).to.be.rejectedWith(/Navigational properties are not allowed.*"orders"/);
248248
});
249249

250+
it('throws when the instance contains navigational property when operates delete()', async () => {
251+
const customer = await customerRepo.create({name: 'customer'});
252+
253+
await orderRepo.create({
254+
description: 'pizza',
255+
customerId: customer.id,
256+
});
257+
258+
const found = await customerRepo.findById(customer.id, {
259+
include: [{relation: 'orders'}],
260+
});
261+
262+
await expect(customerRepo.delete(found)).to.be.rejectedWith(
263+
'Navigational properties are not allowed in model data (model "Customer" property "orders")',
264+
);
265+
});
266+
250267
context('when targeting the source model', () => {
251268
it('gets the parent entity through the child entity', async () => {
252269
const parent = await customerRepo.create({name: 'parent customer'});

packages/repository-tests/src/crud/relations/helpers.ts

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ export function givenBoundCrudRepositories(
3030
Order.definition.properties.id.type = features.idType;
3131
Address.definition.properties.id.type = features.idType;
3232
Customer.definition.properties.id.type = features.idType;
33+
Customer.definition.properties.id.mongodb = {
34+
dataType: 'ObjectID',
35+
};
3336
Shipment.definition.properties.id.type = features.idType;
3437
// when running the test suite on MongoDB, we don't really need to setup
3538
// this config for mongo connector to pass the test.

packages/repository/src/repositories/legacy-juggler-bridge.ts

+11-12
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,8 @@ export class DefaultCrudRepository<
420420
return this.updateById(entity.getId(), entity, options);
421421
}
422422

423-
delete(entity: T, options?: Options): Promise<void> {
423+
async delete(entity: T, options?: Options): Promise<void> {
424+
this.ensurePersistable(entity);
424425
return this.deleteById(entity.getId(), options);
425426
}
426427

@@ -456,7 +457,7 @@ export class DefaultCrudRepository<
456457
options?: Options,
457458
): Promise<void> {
458459
try {
459-
const payload = this.ensurePersistable(data, {replacement: true});
460+
const payload = this.ensurePersistable(data);
460461
await ensurePromise(this.modelClass.replaceById(id, payload, options));
461462
} catch (err) {
462463
if (err.statusCode === 404) {
@@ -536,15 +537,13 @@ export class DefaultCrudRepository<
536537

537538
/** Converts an entity object to a JSON object to check if it contains navigational property.
538539
* Throws an error if `entity` contains navigational property.
539-
* Also removed id property for replaceById operation (mongo use case).
540540
*
541541
* @param entity
542-
* @param options when attributw replacement is set to true, delete the id property to operate
543-
* replaceById method.
542+
* @param options
544543
*/
545544
protected ensurePersistable<R extends T>(
546545
entity: R | DataObject<R>,
547-
options: {replacement?: boolean; idProperty?: string} = {},
546+
options: {},
548547
): legacy.ModelData<legacy.PersistedModel> {
549548
// FIXME(bajtos) Ideally, we should call toJSON() to convert R to data object
550549
// Unfortunately that breaks replaceById for MongoDB connector, where we
@@ -569,12 +568,12 @@ export class DefaultCrudRepository<
569568
);
570569
}
571570
}
572-
if (options.replacement === true) {
573-
const idProperty = this.entityClass.getIdProperties()[0];
574-
if (idProperty) {
575-
delete data[idProperty];
576-
}
577-
}
571+
// if (options.replacement === true) {
572+
// const idProperty = this.entityClass.getIdProperties()[0];
573+
// if (!data[idProperty] === undefined) {
574+
// throw new Error(`id property should not be included in ${data}`);
575+
// }
576+
// }
578577
return data;
579578
}
580579

0 commit comments

Comments
 (0)