Skip to content

Commit

Permalink
feat(repository-tests): test replaceById, verify plain data handling
Browse files Browse the repository at this point in the history
Signed-off-by: Miroslav Bajtoš <mbajtoss@gmail.com>
  • Loading branch information
bajtos committed Jul 26, 2019
1 parent 146e1b1 commit ea52f1b
Show file tree
Hide file tree
Showing 5 changed files with 131 additions and 0 deletions.
Expand Up @@ -20,4 +20,5 @@ export const MYSQL_CONFIG: DataSourceOptions = {
export const MYSQL_FEATURES: Partial<CrudFeatures> = {
idType: 'number',
freeFormProperties: false,
emptyValue: null,
};
1 change: 1 addition & 0 deletions packages/repository-tests/src/crud-test-suite.ts
Expand Up @@ -31,6 +31,7 @@ export function crudRepositoryTestSuite(
const features: CrudFeatures = {
idType: 'string',
freeFormProperties: true,
emptyValue: undefined,
...partialFeatures,
};

Expand Down
10 changes: 10 additions & 0 deletions packages/repository-tests/src/crud/create-retrieve.suite.ts
Expand Up @@ -4,6 +4,7 @@
// License text available at https://opensource.org/licenses/MIT

import {
AnyObject,
Entity,
EntityCrudRepository,
model,
Expand Down Expand Up @@ -65,5 +66,14 @@ export function createRetrieveSuite(
const found = await repo.findById(created.id);
expect(toJSON(created)).to.deepEqual(toJSON(found));
});

it('retrieves a newly created model when id was transformed via JSON', async () => {
const created = await repo.create({name: 'Pen'});
expect(created.id).to.be.ok();

const id = (toJSON(created) as AnyObject).id;
const found = await repo.findById(id);
expect(toJSON(created)).to.deepEqual(toJSON(found));
});
});
}
111 changes: 111 additions & 0 deletions packages/repository-tests/src/crud/replace-by-id.suite.ts
@@ -0,0 +1,111 @@
// 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 {Entity, model, property} from '@loopback/repository';
import {AnyObject, EntityCrudRepository} from '@loopback/repository/src';
import {expect, toJSON} from '@loopback/testlab';
import {
deleteAllModelsInDefaultDataSource,
withCrudCtx,
} from '../helpers.repository-tests';
import {
CrudFeatures,
CrudRepositoryCtor,
CrudTestContext,
DataSourceOptions,
} from '../types.repository-tests';

// Tests for `replaceById` method.
export function createSuiteForReplaceById(
dataSourceOptions: DataSourceOptions,
repositoryClass: CrudRepositoryCtor,
features: CrudFeatures,
) {
@model()
class Product extends Entity {
@property({
type: features.idType,
id: true,
generated: true,
description: 'The unique identifier for a product',
})
id: number | string;

@property({type: 'string', required: true})
name: string;

@property({type: 'string', required: false})
description?: string;

constructor(data?: Partial<Product>) {
super(data);
}
}

describe('replaceById', () => {
before(deleteAllModelsInDefaultDataSource);

let repo: EntityCrudRepository<Product, typeof Product.prototype.id>;
before(
withCrudCtx(async function setupRepository(ctx: CrudTestContext) {
repo = new repositoryClass(Product, ctx.dataSource);
await ctx.dataSource.automigrate(Product.name);
}),
);

it('replaces all model properties (using model instance as data)', async () => {
const created = await repo.create({
name: 'Pencil',
description: 'some description',
});
expect(created.id).to.be.ok();

created.name = 'new name';
// This important! Not all databases allow `patchById` to set
// properties to "undefined", `replaceById` must always work.
created.description = undefined;

await repo.replaceById(created.id, created);

const found = await repo.findById(created.id);
expect(toJSON(found)).to.deepEqual(
toJSON({
id: created.id,
name: 'new name',
description: features.emptyValue,
}),
);
});

// This test simulates REST API scenario, where data returned from
// the database is converted to JSON and client sends plain data object
// encoded as JSON.
it('replaces all model properties (using plain data object)', async () => {
const created = toJSON(
await repo.create({
name: 'Pencil',
description: 'some description',
}),
) as AnyObject;
expect(created.id).to.be.ok();

created.name = 'new name';
// This important! Not all databases allow `patchById` to set
// properties to "undefined", `replaceById` must always work.
created.description = undefined;

await repo.replaceById(created.id, created);

const found = await repo.findById(created.id);
expect(toJSON(found)).to.deepEqual(
toJSON({
id: created.id,
name: 'new name',
description: features.emptyValue,
}),
);
});
});
}
8 changes: 8 additions & 0 deletions packages/repository-tests/src/types.repository-tests.ts
Expand Up @@ -38,6 +38,14 @@ export interface CrudFeatures {
* Default: `true`
*/
freeFormProperties: boolean;

/**
* The value used by the database to store properties set to `undefined`.
* Typically, SQL databases store both `undefined` and `null` as `null`.
*
* Default: `undefined`
*/
emptyValue: undefined | null;
}

/**
Expand Down

0 comments on commit ea52f1b

Please sign in to comment.