-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(repository-tests): move relation tests to repository-tests p…
…ackage Move these tests to repository-tests package so that they would be tested against real databases such as MongoDB and MySQL. Introduce a new type MixedIdType to CrudFeatures to solve the different usage of id types in different databases. Co-authored-by: Nora <[email protected]>
- Loading branch information
Showing
29 changed files
with
1,159 additions
and
822 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
107 changes: 107 additions & 0 deletions
107
packages/repository-tests/src/crud/nested-model-properties.suite.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// Copyright IBM Corp. 2019. All Rights Reserved. | ||
// Node module: @loopback/repository-tests | ||
// This file is licensed under the MIT License. | ||
// License text available at https://opensource.org/licenses/MIT | ||
|
||
import { | ||
DefaultCrudRepository, | ||
Entity, | ||
EntityCrudRepository, | ||
juggler, | ||
model, | ||
property, | ||
} from '@loopback/repository'; | ||
import {expect, toJSON} from '@loopback/testlab'; | ||
import { | ||
deleteAllModelsInDefaultDataSource, | ||
withCrudCtx, | ||
MixedIdType, | ||
} from '../helpers.repository-tests'; | ||
import { | ||
CrudFeatures, | ||
CrudRepositoryCtor, | ||
CrudTestContext, | ||
DataSourceOptions, | ||
} from '../types.repository-tests'; | ||
|
||
export function nestedModelsPropertiesSuite( | ||
dataSourceOptions: DataSourceOptions, | ||
repositoryClass: CrudRepositoryCtor, | ||
features: CrudFeatures, | ||
) { | ||
describe('Nested models properties', () => { | ||
let db: juggler.DataSource; | ||
let userRepo: EntityCrudRepository<User, typeof User.prototype.id>; | ||
|
||
before(deleteAllModelsInDefaultDataSource); | ||
|
||
before( | ||
withCrudCtx(async function setupRepository(ctx: CrudTestContext) { | ||
db = ctx.dataSource; | ||
userRepo = new DefaultCrudRepository<User, typeof User.prototype.id>( | ||
User, | ||
db, | ||
); | ||
const models = [User]; | ||
await db.automigrate(models.map(m => m.name)); | ||
}), | ||
); | ||
beforeEach(async function resetDatabase() { | ||
await userRepo.deleteAll(); | ||
}); | ||
|
||
it('allows models to allow a singel nested model property', async () => { | ||
const user = { | ||
name: 'foo', | ||
roles: [], | ||
address: {street: 'backstreet'}, | ||
}; | ||
const created = await userRepo.create(user); | ||
|
||
const stored = await userRepo.findById(created.id); | ||
expect(toJSON(stored)).to.containDeep(toJSON(user)); | ||
}); | ||
|
||
it('allows models to allow multiple nested model properties in an array', async () => { | ||
const user = { | ||
name: 'foo', | ||
roles: [{name: 'admin'}, {name: 'user'}], | ||
address: {street: 'backstreet'}, | ||
}; | ||
const created = await userRepo.create(user); | ||
|
||
const stored = await userRepo.findById(created.id); | ||
expect(toJSON(stored)).to.containDeep(toJSON(user)); | ||
}); | ||
|
||
@model() | ||
class Role extends Entity { | ||
@property() | ||
name: string; | ||
} | ||
|
||
@model() | ||
class Address extends Entity { | ||
@property() | ||
street: string; | ||
} | ||
|
||
@model() | ||
class User extends Entity { | ||
@property({ | ||
id: true, | ||
generated: true, | ||
}) | ||
id: MixedIdType; | ||
|
||
@property({type: 'string'}) | ||
name: string; | ||
|
||
@property.array(Role) | ||
roles: Role[]; | ||
|
||
@property() | ||
address: Address; | ||
} | ||
}); | ||
} |
114 changes: 114 additions & 0 deletions
114
packages/repository-tests/src/crud/relations/acceptance/belongs-to.relation.acceptance.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// Copyright IBM Corp. 2019. All Rights Reserved. | ||
// Node module: @loopback/repository-tests | ||
// This file is licensed under the MIT License. | ||
// License text available at https://opensource.org/licenses/MIT | ||
|
||
import { | ||
BelongsToAccessor, | ||
BelongsToDefinition, | ||
createBelongsToAccessor, | ||
EntityNotFoundError, | ||
Getter, | ||
} from '@loopback/repository'; | ||
import {expect, toJSON} from '@loopback/testlab'; | ||
import { | ||
deleteAllModelsInDefaultDataSource, | ||
withCrudCtx, | ||
} from '../../../helpers.repository-tests'; | ||
import { | ||
CrudFeatures, | ||
CrudRepositoryCtor, | ||
CrudTestContext, | ||
DataSourceOptions, | ||
} from '../../../types.repository-tests'; | ||
import { | ||
Customer, | ||
CustomerRepository, | ||
Order, | ||
OrderRepository, | ||
Shipment, | ||
ShipmentRepository, | ||
} from '../fixtures/models'; | ||
import {givenBoundCrudRepositories} from '../helpers'; | ||
|
||
export function belongsToRelationAcceptance( | ||
dataSourceOptions: DataSourceOptions, | ||
repositoryClass: CrudRepositoryCtor, | ||
features: CrudFeatures, | ||
) { | ||
describe('BelongsTo relation (acceptance)', () => { | ||
before(deleteAllModelsInDefaultDataSource); | ||
|
||
let findCustomerOfOrder: BelongsToAccessor< | ||
Customer, | ||
typeof Order.prototype.id | ||
>; | ||
let customerRepo: CustomerRepository; | ||
let orderRepo: OrderRepository; | ||
let shipmentRepo: ShipmentRepository; | ||
|
||
before( | ||
withCrudCtx(async function setupRepository(ctx: CrudTestContext) { | ||
({customerRepo, orderRepo, shipmentRepo} = givenBoundCrudRepositories( | ||
ctx.dataSource, | ||
repositoryClass, | ||
)); | ||
const models = [Customer, Order, Shipment]; | ||
await ctx.dataSource.automigrate(models.map(m => m.name)); | ||
}), | ||
); | ||
before(givenAccessor); | ||
beforeEach(async () => { | ||
await orderRepo.deleteAll(); | ||
}); | ||
|
||
it('can find customer of order', async () => { | ||
const customer = await customerRepo.create({ | ||
name: 'Order McForder', | ||
}); | ||
const order = await orderRepo.create({ | ||
customerId: customer.id, | ||
description: 'Order from Order McForder, the hoarder of Mordor', | ||
}); | ||
|
||
const result = await orderRepo.customer(order.id); | ||
// adding parentId to customer so MySQL doesn't complain about null vs | ||
// undefined | ||
expect(toJSON(result)).to.deepEqual( | ||
toJSON({...customer, parentId: features.emptyValue}), | ||
); | ||
}); | ||
|
||
it('can find shipment of order with a custom foreign key name', async () => { | ||
const shipment = await shipmentRepo.create({ | ||
name: 'Tuesday morning shipment', | ||
}); | ||
const order = await orderRepo.create({ | ||
// eslint-disable-next-line @typescript-eslint/camelcase | ||
shipment_id: shipment.id, | ||
description: 'Order that is shipped Tuesday morning', | ||
}); | ||
const result = await orderRepo.shipment(order.id); | ||
expect(result).to.deepEqual(shipment); | ||
}); | ||
|
||
it('throws EntityNotFound error when the related model does not exist', async () => { | ||
const order = await orderRepo.create({ | ||
customerId: 999, // does not exist | ||
description: 'Order of a fictional customer', | ||
}); | ||
|
||
await expect(findCustomerOfOrder(order.id)).to.be.rejectedWith( | ||
EntityNotFoundError, | ||
); | ||
}); | ||
// helpers | ||
function givenAccessor() { | ||
findCustomerOfOrder = createBelongsToAccessor( | ||
Order.definition.relations.customer as BelongsToDefinition, | ||
Getter.fromValue(customerRepo), | ||
orderRepo, | ||
); | ||
} | ||
}); | ||
} |
Oops, something went wrong.