-
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.
test(repository): add tests for hasManyThrough helpers
- Loading branch information
Agnes Lin
committed
May 7, 2020
1 parent
806cdf0
commit f0a435c
Showing
1 changed file
with
189 additions
and
0 deletions.
There are no files selected for viewing
189 changes: 189 additions & 0 deletions
189
...c/__tests__/unit/repositories/relations-helpers/resolve-has-many-through-metadata.unit.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,189 @@ | ||
// Copyright IBM Corp. 2019. All Rights Reserved. | ||
// Node module: @loopback/repository | ||
// This file is licensed under the MIT License. | ||
// License text available at https://opensource.org/licenses/MIT | ||
|
||
import {expect} from '@loopback/testlab'; | ||
import { | ||
Entity, | ||
HasManyDefinition, | ||
ModelDefinition, | ||
RelationType, | ||
} from '../../../..'; | ||
import {resolveHasManyThroughMetadata} from '../../../../relations/has-many/has-many-through.helper'; | ||
|
||
describe.only('resolveHasManyThroughMetadata', () => { | ||
it('throws if the wrong metadata type is used', async () => { | ||
const metadata: unknown = { | ||
name: 'category', | ||
type: RelationType.hasOne, | ||
targetsMany: false, | ||
source: Category, | ||
target: () => Category, | ||
}; | ||
|
||
expect(() => { | ||
resolveHasManyThroughMetadata(metadata as HasManyDefinition); | ||
}).to.throw( | ||
/Invalid hasOne definition for Category#category: relation type must be HasMany/, | ||
); | ||
}); | ||
|
||
it('throws if the through is not resolvable', async () => { | ||
const metadata: unknown = { | ||
name: 'category', | ||
type: RelationType.hasMany, | ||
targetsMany: true, | ||
source: Category, | ||
through: {model: 'random'}, | ||
target: () => Category, | ||
}; | ||
|
||
expect(() => { | ||
resolveHasManyThroughMetadata(metadata as HasManyDefinition); | ||
}).to.throw( | ||
/Invalid hasMany definition for Category#category: through.model must be a type resolver/, | ||
); | ||
}); | ||
|
||
describe('resolves through.keyTo/keyFrom', () => { | ||
it('resolves metadata with complete hasManyThrough definition', () => { | ||
const metadata = { | ||
name: 'products', | ||
type: RelationType.hasMany, | ||
targetsMany: true, | ||
source: Category, | ||
keyFrom: 'id', | ||
target: () => Product, | ||
keyTo: 'categoryId', | ||
|
||
through: { | ||
model: () => CategoryProductLink, | ||
keyFrom: 'categoryId', | ||
keyTo: 'productId', | ||
}, | ||
}; | ||
const meta = resolveHasManyThroughMetadata(metadata as HasManyDefinition); | ||
|
||
expect(meta).to.eql(resolvedMetadata); | ||
}); | ||
|
||
it('infers through.keyFrom if it is not provided', () => { | ||
const metadata = { | ||
name: 'products', | ||
type: RelationType.hasMany, | ||
targetsMany: true, | ||
source: Category, | ||
keyFrom: 'id', | ||
target: () => Product, | ||
keyTo: 'categoryId', | ||
|
||
through: { | ||
model: () => CategoryProductLink, | ||
// no through.keyFrom | ||
keyTo: 'productId', | ||
}, | ||
}; | ||
const meta = resolveHasManyThroughMetadata(metadata as HasManyDefinition); | ||
|
||
expect(meta).to.eql(resolvedMetadata); | ||
}); | ||
|
||
it('infers through.keyTo if it is not provided', () => { | ||
const metadata = { | ||
name: 'products', | ||
type: RelationType.hasMany, | ||
targetsMany: true, | ||
source: Category, | ||
keyFrom: 'id', | ||
target: () => Product, | ||
keyTo: 'categoryId', | ||
|
||
through: { | ||
model: () => CategoryProductLink, | ||
keyFrom: 'categoryId', | ||
// no through.keyTo | ||
}, | ||
}; | ||
|
||
const meta = resolveHasManyThroughMetadata(metadata as HasManyDefinition); | ||
|
||
expect(meta).to.eql(resolvedMetadata); | ||
}); | ||
|
||
it('throws if through.keyFrom, through.keyTo, and default foreign key name are not provided in through', async () => { | ||
const metadata = { | ||
name: 'categories', | ||
type: RelationType.hasMany, | ||
targetsMany: true, | ||
source: Category, | ||
keyFrom: 'id', | ||
target: () => Product, | ||
keyTo: 'categoryId', | ||
|
||
through: { | ||
model: () => InvalidThrough, | ||
keyTo: 'productId', | ||
}, | ||
}; | ||
|
||
expect(() => { | ||
resolveHasManyThroughMetadata(metadata as HasManyDefinition); | ||
}).to.throw( | ||
/Invalid hasMany definition for Category#categories: through model InvalidThrough is missing definition of source foreign key/, | ||
); | ||
}); | ||
}); | ||
/****** HELPERS *******/ | ||
|
||
class Category extends Entity {} | ||
Category.definition = new ModelDefinition('Category').addProperty('id', { | ||
type: 'number', | ||
id: true, | ||
required: true, | ||
}); | ||
|
||
class Product extends Entity {} | ||
Product.definition = new ModelDefinition('Product') | ||
.addProperty('id', { | ||
type: 'number', | ||
id: true, | ||
required: true, | ||
}) | ||
.addProperty('categoryId', {type: 'number'}); | ||
|
||
class CategoryProductLink extends Entity {} | ||
CategoryProductLink.definition = new ModelDefinition('CategoryProductLink') | ||
.addProperty('id', { | ||
type: 'number', | ||
id: true, | ||
required: true, | ||
}) | ||
.addProperty('categoryId', {type: 'number'}) | ||
.addProperty('productId', {type: 'number'}); | ||
|
||
const resolvedMetadata = { | ||
name: 'products', | ||
type: 'hasMany', | ||
targetsMany: true, | ||
source: Category, | ||
keyFrom: 'id', | ||
target: () => Product, | ||
keyTo: 'categoryId', | ||
through: { | ||
model: () => CategoryProductLink, | ||
keyFrom: 'categoryId', | ||
keyTo: 'productId', | ||
}, | ||
}; | ||
|
||
class InvalidThrough extends Entity {} | ||
InvalidThrough.definition = new ModelDefinition('InvalidThrough') | ||
.addProperty('id', { | ||
type: 'number', | ||
id: true, | ||
required: true, | ||
}) | ||
// lack through.keyFrom | ||
.addProperty('productId', {type: 'number'}); | ||
}); |