Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// 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 {BelongsToDefinition, Entity, RelationType} from '../../..';
import {resolveBelongsToMetadata} from '../../../relations/belongs-to/belongs-to.helpers';

describe('resolveBelongsToMetadata', () => {
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(() => {
resolveBelongsToMetadata(metadata as BelongsToDefinition);
}).to.throw(
/Invalid hasOne definition for Category#category: relation type must be BelongsTo/,
);
});

/****** HELPERS *******/
class Category extends Entity {}
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,142 +12,157 @@ import {
} from '../../..';
import {resolveHasManyMetadata} from '../../../relations/has-many/has-many.helpers';

describe('keyTo and keyFrom with resolveHasManyMetadata', () => {
it('resolves metadata using keyTo and keyFrom', () => {
const meta = resolveHasManyMetadata(Category.definition.relations[
'products'
] as HasManyDefinition);

expect(meta).to.eql({
name: 'products',
type: 'hasMany',
targetsMany: true,
describe('resolveHasManyMetadata', () => {
it('throws if the wrong metadata type is used', async () => {
const metadata: unknown = {
name: 'category',
type: RelationType.hasOne,
targetsMany: false,
source: Category,
keyFrom: 'id',
target: () => Product,
keyTo: 'categoryId',
});
});

it('infers keyFrom if it is not provided', () => {
const meta = resolveHasManyMetadata(Category.definition.relations[
'items'
] as HasManyDefinition);
target: () => Category,
};

expect(meta).to.eql({
name: 'items',
type: 'hasMany',
targetsMany: true,
source: Category,
keyFrom: 'id',
target: () => Item,
keyTo: 'categoryId',
});
expect(() => {
resolveHasManyMetadata(metadata as HasManyDefinition);
}).to.throw(
/Invalid hasOne definition for Category#category: relation type must be HasMany/,
);
});

it('infers keyTo if it is not provided', () => {
const meta = resolveHasManyMetadata(Category.definition.relations[
'things'
] as HasManyDefinition);

expect(meta).to.eql({
name: 'things',
type: 'hasMany',
targetsMany: true,
source: Category,
keyFrom: 'id',
target: () => Thing,
keyTo: 'categoryId',
describe('keyTo and keyFrom with resolveHasManyMetadata', () => {
it('resolves metadata using keyTo and keyFrom', () => {
const metadata = {
name: 'products',
type: RelationType.hasMany,
targetsMany: true,

source: Category,
keyFrom: 'id',

target: () => Product,
keyTo: 'categoryId',
};
const meta = resolveHasManyMetadata(metadata as HasManyDefinition);

expect(meta).to.eql({
name: 'products',
type: 'hasMany',
targetsMany: true,
source: Category,
keyFrom: 'id',
target: () => Product,
keyTo: 'categoryId',
});
});
});

it('throws if keyFrom, keyTo, and default foreign key name are not provided', async () => {
let error;
it('infers keyFrom if it is not provided', () => {
const metadata = {
name: 'products',
type: RelationType.hasMany,
targetsMany: true,

source: Category,
// no keyFrom

target: () => Product,
keyTo: 'categoryId',
};
const meta = resolveHasManyMetadata(metadata as HasManyDefinition);

expect(meta).to.eql({
name: 'products',
type: 'hasMany',
targetsMany: true,
source: Category,
keyFrom: 'id',
target: () => Product,
keyTo: 'categoryId',
});
});

try {
resolveHasManyMetadata(Category.definition.relations[
'categories'
] as HasManyDefinition);
} catch (err) {
error = err;
}
it('infers keyTo if it is not provided', () => {
const metadata = {
name: 'products',
type: RelationType.hasMany,
targetsMany: true,

source: Category,
keyFrom: 'id',

target: () => Product,
// no keyTo
};

const meta = resolveHasManyMetadata(metadata as HasManyDefinition);

expect(meta).to.eql({
name: 'products',
type: 'hasMany',
targetsMany: true,
source: Category,
keyFrom: 'id',
target: () => Product,
keyTo: 'categoryId',
});
});

expect(error.message).to.eql(
'Invalid hasMany definition for Category#categories: target model ' +
'Category is missing definition of foreign key categoryId',
);
it('throws if keyFrom, keyTo, and default foreign key name are not provided', async () => {
const metadata = {
name: 'categories',
type: RelationType.hasMany,
targetsMany: true,

expect(error.code).to.eql('INVALID_RELATION_DEFINITION');
});
source: Category,
// no keyFrom

it('resolves metadata if keyTo and keyFrom are not provided, but default foreign key is', async () => {
Category.definition.addProperty('categoryId', {type: 'number'});
target: () => Category,
// no keyTo
};

const meta = resolveHasManyMetadata(Category.definition.relations[
'categories'
] as HasManyDefinition);

expect(meta).to.eql({
name: 'categories',
type: 'hasMany',
targetsMany: true,
source: Category,
keyFrom: 'id',
target: () => Category,
keyTo: 'categoryId',
expect(() => {
resolveHasManyMetadata(metadata as HasManyDefinition);
}).to.throw(
/Invalid hasMany definition for Category#categories: target model Category is missing definition of foreign key categoryId/,
);
});
});

/****** HELPERS *******/
it('resolves metadata if keyTo and keyFrom are not provided, but default foreign key is', async () => {
Category.definition.addProperty('categoryId', {type: 'number'});

class Category extends Entity {}
const metadata = {
name: 'category',
type: RelationType.hasMany,
targetsMany: true,

Category.definition = new ModelDefinition('Category')
.addProperty('id', {type: 'number', id: true, required: true})
.addRelation(<HasManyDefinition>{
name: 'products',
type: RelationType.hasMany,
targetsMany: true,
source: Category,
// no keyFrom

source: Category,
keyFrom: 'id',
target: () => Category,
// no keyTo
};

target: () => Product,
keyTo: 'categoryId',
})
.addRelation(<HasManyDefinition>{
name: 'items',
type: RelationType.hasMany,
targetsMany: true,

source: Category,
// no keyFrom
const meta = resolveHasManyMetadata(metadata as HasManyDefinition);

target: () => Item,
keyTo: 'categoryId',
})
.addRelation(<HasManyDefinition>{
name: 'things',
type: RelationType.hasMany,
targetsMany: true,

source: Category,
keyFrom: 'id',

target: () => Thing,
// no keyTo
})
.addRelation(<HasManyDefinition>{
name: 'categories',
type: RelationType.hasMany,
targetsMany: true,
expect(meta).to.eql({
name: 'category',
type: 'hasMany',
targetsMany: true,
source: Category,
keyFrom: 'id',
target: () => Category,
keyTo: 'categoryId',
});
});
});
/****** HELPERS *******/

source: Category,
// no keyFrom
class Category extends Entity {}

target: () => Category,
// no keyTo
});
Category.definition = new ModelDefinition('Category').addProperty('id', {
type: 'number',
id: true,
required: true,
});

class Product extends Entity {}

Expand All @@ -158,24 +173,4 @@ describe('keyTo and keyFrom with resolveHasManyMetadata', () => {
required: true,
})
.addProperty('categoryId', {type: 'number'});

class Item extends Entity {}

Item.definition = new ModelDefinition('Item')
.addProperty('id', {
type: 'number',
id: true,
required: true,
})
.addProperty('categoryId', {type: 'number'});

class Thing extends Entity {}

Thing.definition = new ModelDefinition('Thing')
.addProperty('id', {
type: 'number',
id: true,
required: true,
})
.addProperty('categoryId', {type: 'number'});
});
Loading