diff --git a/packages/repository/src/__tests__/integration/repositories/resolve-belongs-to-metadata.integration.ts b/packages/repository/src/__tests__/integration/repositories/resolve-belongs-to-metadata.integration.ts new file mode 100644 index 000000000000..8687c0dc6806 --- /dev/null +++ b/packages/repository/src/__tests__/integration/repositories/resolve-belongs-to-metadata.integration.ts @@ -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 {} +}); diff --git a/packages/repository/src/__tests__/integration/repositories/resolve-has-many-metadata.integration.ts b/packages/repository/src/__tests__/integration/repositories/resolve-has-many-metadata.integration.ts index bcf494ca11ac..12f04b76adb6 100644 --- a/packages/repository/src/__tests__/integration/repositories/resolve-has-many-metadata.integration.ts +++ b/packages/repository/src/__tests__/integration/repositories/resolve-has-many-metadata.integration.ts @@ -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({ - name: 'products', - type: RelationType.hasMany, - targetsMany: true, + source: Category, + // no keyFrom - source: Category, - keyFrom: 'id', + target: () => Category, + // no keyTo + }; - target: () => Product, - keyTo: 'categoryId', - }) - .addRelation({ - name: 'items', - type: RelationType.hasMany, - targetsMany: true, - - source: Category, - // no keyFrom + const meta = resolveHasManyMetadata(metadata as HasManyDefinition); - target: () => Item, - keyTo: 'categoryId', - }) - .addRelation({ - name: 'things', - type: RelationType.hasMany, - targetsMany: true, - - source: Category, - keyFrom: 'id', - - target: () => Thing, - // no keyTo - }) - .addRelation({ - 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 {} @@ -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'}); }); diff --git a/packages/repository/src/__tests__/integration/repositories/resolve-has-one-metadata.integration.ts b/packages/repository/src/__tests__/integration/repositories/resolve-has-one-metadata.integration.ts index 3db13b0d66b4..dd22965f1c79 100644 --- a/packages/repository/src/__tests__/integration/repositories/resolve-has-one-metadata.integration.ts +++ b/packages/repository/src/__tests__/integration/repositories/resolve-has-one-metadata.integration.ts @@ -12,89 +12,146 @@ import { } from '../../..'; import {resolveHasOneMetadata} from '../../../relations/has-one/has-one.helpers'; -describe('keyTo and keyFrom with resolveHasOneMetadata', () => { - it('resolves metadata using keyTo and keyFrom', () => { - const meta = resolveHasOneMetadata(Category.definition.relations[ - 'product' - ] as HasOneDefinition); - - expect(meta).to.eql({ - name: 'product', - type: 'hasOne', - targetsMany: false, - source: Category, - keyFrom: 'id', - target: () => Product, - keyTo: 'categoryId', - }); +describe('resolveHasOneMetadata', () => { + it('throws if the wrong metadata type is used', async () => { + const metadata: unknown = { + name: 'category', + type: RelationType.hasMany, + targetsMany: true, + source: Product, + target: () => Category, + }; + + expect(() => { + resolveHasOneMetadata(metadata as HasOneDefinition); + }).to.throw( + /Invalid hasMany definition for Product#category: relation type must be HasOne/, + ); }); - it('infers keyFrom if it is not provided', () => { - const meta = resolveHasOneMetadata(Category.definition.relations[ - 'item' - ] as HasOneDefinition); - - expect(meta).to.eql({ - name: 'item', - type: 'hasOne', - targetsMany: false, - source: Category, - keyFrom: 'id', - target: () => Item, - keyTo: 'categoryId', + describe('keyTo and keyFrom with resolveHasOneMetadata', () => { + it('resolves metadata using keyTo and keyFrom', () => { + const metadata = { + name: 'category', + type: RelationType.hasOne, + targetsMany: false, + + source: Product, + keyFrom: 'id', + + target: () => Category, + keyTo: 'productId', + }; + const meta = resolveHasOneMetadata(metadata as HasOneDefinition); + + expect(meta).to.eql({ + name: 'category', + type: 'hasOne', + targetsMany: false, + source: Product, + keyFrom: 'id', + target: () => Category, + keyTo: 'productId', + }); }); - }); - it('infers keyTo if it is not provided', () => { - const meta = resolveHasOneMetadata(Category.definition.relations[ - 'thing' - ] as HasOneDefinition); - - expect(meta).to.eql({ - name: 'thing', - type: 'hasOne', - targetsMany: false, - source: Category, - keyFrom: 'id', - target: () => Thing, - keyTo: 'categoryId', + it('infers keyFrom if it is not provided', () => { + const metadata = { + name: 'category', + type: 'hasOne', + targetsMany: false, + + source: Product, + // no keyFrom + + target: () => Category, + keyTo: 'productId', + }; + const meta = resolveHasOneMetadata(metadata as HasOneDefinition); + + expect(meta).to.eql({ + name: 'category', + type: 'hasOne', + targetsMany: false, + source: Product, + keyFrom: 'id', + target: () => Category, + keyTo: 'productId', + }); }); - }); - it('throws if keyFrom, keyTo, and default foreign key name are not provided', async () => { - let error; + it('infers keyTo if it is not provided', () => { + const metadata = { + name: 'category', + type: RelationType.hasOne, + targetsMany: false, + + source: Product, + keyFrom: 'id', + + target: () => Category, + // no keyTo + }; + + const meta = resolveHasOneMetadata(metadata as HasOneDefinition); + + expect(meta).to.eql({ + name: 'category', + type: 'hasOne', + targetsMany: false, + source: Product, + keyFrom: 'id', + target: () => Category, + keyTo: 'productId', + }); + }); - try { - resolveHasOneMetadata(Category.definition.relations[ - 'category' - ] as HasOneDefinition); - } catch (err) { - error = err; - } + it('throws if keyFrom, keyTo, and default foreign key name are not provided', async () => { + const metadata = { + name: 'category', + type: RelationType.hasOne, + targetsMany: false, - expect(error.message).to.eql( - 'Invalid hasOne definition for Category#category: target model Category' + - ' is missing definition of foreign key categoryId', - ); + source: Category, + // no keyFrom - expect(error.code).to.eql('INVALID_RELATION_DEFINITION'); - }); + target: () => Category, + // no keyTo + }; - it('resolves metadata if keyTo and keyFrom are not provided, but default foreign key is', async () => { - Category.definition.addProperty('categoryId', {type: 'number'}); + expect(() => { + resolveHasOneMetadata(metadata as HasOneDefinition); + }).to.throw( + /Invalid hasOne definition for Category#category: target model Category is missing definition of foreign key categoryId/, + ); + }); - const meta = resolveHasOneMetadata(Category.definition.relations[ - 'category' - ] as HasOneDefinition); + it('resolves metadata if keyTo and keyFrom are not provided, but default foreign key is', async () => { + Category.definition.addProperty('categoryId', {type: 'number'}); - expect(meta).to.eql({ - name: 'category', - type: 'hasOne', - targetsMany: false, - source: Category, - keyFrom: 'id', - target: () => Category, - keyTo: 'categoryId', + const metadata = { + name: 'category', + type: RelationType.hasOne, + targetsMany: false, + + source: Category, + // no keyFrom + + target: () => Category, + // no keyTo + }; + + const meta = resolveHasOneMetadata(metadata as HasOneDefinition); + + expect(meta).to.eql({ + name: 'category', + type: 'hasOne', + targetsMany: false, + source: Category, + keyFrom: 'id', + target: () => Category, + keyTo: 'categoryId', + }); }); }); @@ -104,78 +161,13 @@ describe('keyTo and keyFrom with resolveHasOneMetadata', () => { Category.definition = new ModelDefinition('Category') .addProperty('id', {type: 'number', id: true, required: true}) - .addRelation({ - name: 'product', - type: RelationType.hasOne, - targetsMany: false, - - source: Category, - keyFrom: 'id', - - target: () => Product, - keyTo: 'categoryId', - }) - .addRelation({ - name: 'item', - type: RelationType.hasOne, - targetsMany: false, - - source: Category, - // no keyFrom - - target: () => Item, - keyTo: 'categoryId', - }) - .addRelation({ - name: 'thing', - type: RelationType.hasOne, - targetsMany: false, - - source: Category, - keyFrom: 'id', - - target: () => Thing, - // no keyTo - }) - .addRelation({ - name: 'category', - type: RelationType.hasOne, - targetsMany: false, - - source: Category, - // no keyFrom - - target: () => Category, - // no keyTo - }); + .addProperty('productId', {type: 'number', required: true}); class Product extends Entity {} - Product.definition = new ModelDefinition('Product') - .addProperty('id', { - type: 'number', - id: true, - 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'}); + Product.definition = new ModelDefinition('Product').addProperty('id', { + type: 'number', + id: true, + required: true, + }); });