Skip to content

Commit

Permalink
test(crud): fixed serialize feature coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelyali committed Dec 18, 2019
1 parent 8eeab37 commit 765341d
Show file tree
Hide file tree
Showing 27 changed files with 450 additions and 82 deletions.
28 changes: 0 additions & 28 deletions packages/crud-typeorm/src/typeorm-crud.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -745,34 +745,6 @@ export class TypeOrmCrudService<T> extends CrudService<T> {
return select;
}

protected getSkip(query: ParsedRequestParams, take: number): number | null {
return query.page && take
? take * (query.page - 1)
: query.offset
? query.offset
: null;
}

protected getTake(query: ParsedRequestParams, options: QueryOptions): number | null {
if (query.limit) {
return options.maxLimit
? query.limit <= options.maxLimit
? query.limit
: options.maxLimit
: query.limit;
}
/* istanbul ignore if */
if (options.limit) {
return options.maxLimit
? options.limit <= options.maxLimit
? options.limit
: options.maxLimit
: options.limit;
}

return options.maxLimit ? options.maxLimit : null;
}

protected getSort(query: ParsedRequestParams, options: QueryOptions) {
return query.sort && query.sort.length
? this.mapSort(query.sort)
Expand Down
7 changes: 5 additions & 2 deletions packages/crud/src/crud/crud-routes.factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,11 +463,14 @@ export class CrudRoutesFactory {

private setSwaggerResponseOk(name: BaseRouteName) {
const metadata = Swagger.getResponseOk(this.targetProto[name]);
const metadataToAdd = Swagger.createResponseMeta(name, this.options) || {};
const metadataToAdd =
Swagger.createResponseMeta(name, this.options) || /* istanbul ignore next */ {};
Swagger.setResponseOk({ ...metadata, ...metadataToAdd }, this.targetProto[name]);
}

private routeNameAction(name: BaseRouteName): string {
return name.split('OneBase')[0] || name.split('ManyBase')[0];
return (
name.split('OneBase')[0] || /* istanbul ignore next */ name.split('ManyBase')[0]
);
}
}
5 changes: 1 addition & 4 deletions packages/crud/src/crud/serialize.helper.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
import { Type, Transform, classToPlainFromExist, classToPlain } from 'class-transformer';
import { GetManyDefaultResponse } from '../interfaces';
import { safeRequire } from '../util';
import { ApiProperty } from './swagger.helper';

const transformer = safeRequire('class-transformer');

export class SerializeHelper {
static createGetManyDto(dto: any, resourceName: string): any {
const { Type } = transformer;

class GetManyResponseDto implements GetManyDefaultResponse<any> {
@ApiProperty({ type: dto, isArray: true })
@Type(() => dto)
Expand Down
55 changes: 35 additions & 20 deletions packages/crud/src/crud/swagger.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export class Swagger {
}

static setExtraModels(options: MergedCrudOptions) {
/* istanbul ignore else */
if (swaggerConst) {
const { serialize } = options;
const meta = Swagger.getExtraModels(serialize.get);
Expand Down Expand Up @@ -70,6 +71,7 @@ export class Swagger {
}

static getExtraModels(target: any): any[] {
/* istanbul ignore next */
return swaggerConst ? R.get(swaggerConst.API_EXTRA_MODELS, target) || [] : [];
}

Expand All @@ -79,6 +81,7 @@ export class Swagger {
}

static createResponseMeta(name: BaseRouteName, options: MergedCrudOptions): any {
/* istanbul ignore else */
if (swagger) {
const { routes, serialize, query } = options;

Expand Down Expand Up @@ -109,12 +112,16 @@ export class Swagger {
};
case 'createManyBase':
return {
[HttpStatus.CREATED]: {
schema: {
type: 'array',
items: { $ref: swagger.getSchemaPath(serialize.create.name) },
},
},
[HttpStatus.CREATED]: serialize.createMany
? {
schema: { $ref: swagger.getSchemaPath(serialize.createMany.name) },
}
: {
schema: {
type: 'array',
items: { $ref: swagger.getSchemaPath(serialize.create.name) },
},
},
};
case 'deleteOneBase':
return {
Expand All @@ -130,9 +137,9 @@ export class Swagger {
},
};
}
} else {
return {};
}

return {};
}

static createPathParasmMeta(options: ParamsOptions): any[] {
Expand Down Expand Up @@ -177,7 +184,7 @@ export class Swagger {
in: 'query',
};
const fieldsMeta = oldVersion
? {
? /* istanbul ignore next */ {
...fieldsMetaBase,
type: 'array',
items: {
Expand All @@ -204,7 +211,7 @@ export class Swagger {
in: 'query',
};
const searchMeta = oldVersion
? { ...searchMetaBase, type: 'string' }
? /* istanbul ignore next */ { ...searchMetaBase, type: 'string' }
: { ...searchMetaBase, schema: { type: 'string' } };

const filterMetaBase = {
Expand All @@ -214,7 +221,7 @@ export class Swagger {
in: 'query',
};
const filterMeta = oldVersion
? {
? /* istanbul ignore next */ {
...filterMetaBase,
items: {
type: 'string',
Expand All @@ -240,7 +247,7 @@ export class Swagger {
in: 'query',
};
const orMeta = oldVersion
? {
? /* istanbul ignore next */ {
...orMetaBase,
items: {
type: 'string',
Expand All @@ -266,7 +273,7 @@ export class Swagger {
in: 'query',
};
const sortMeta = oldVersion
? {
? /* istanbul ignore next */ {
...sortMetaBase,
items: {
type: 'string',
Expand All @@ -292,7 +299,7 @@ export class Swagger {
in: 'query',
};
const joinMeta = oldVersion
? {
? /* istanbul ignore next */ {
...joinMetaBase,
items: {
type: 'string',
Expand All @@ -318,7 +325,7 @@ export class Swagger {
in: 'query',
};
const limitMeta = oldVersion
? { ...limitMetaBase, type: 'integer' }
? /* istanbul ignore next */ { ...limitMetaBase, type: 'integer' }
: { ...limitMetaBase, schema: { type: 'integer' } };

const offsetMetaBase = {
Expand All @@ -328,7 +335,7 @@ export class Swagger {
in: 'query',
};
const offsetMeta = oldVersion
? { ...offsetMetaBase, type: 'integer' }
? /* istanbul ignore next */ { ...offsetMetaBase, type: 'integer' }
: { ...offsetMetaBase, schema: { type: 'integer' } };

const pageMetaBase = {
Expand All @@ -338,7 +345,7 @@ export class Swagger {
in: 'query',
};
const pageMeta = oldVersion
? { ...pageMetaBase, type: 'integer' }
? /* istanbul ignore next */ { ...pageMetaBase, type: 'integer' }
: { ...pageMetaBase, schema: { type: 'integer' } };

const cacheMetaBase = {
Expand All @@ -348,7 +355,12 @@ export class Swagger {
in: 'query',
};
const cacheMeta = oldVersion
? { ...cacheMetaBase, type: 'integer', minimum: 0, maximum: 1 }
? /* istanbul ignore next */ {
...cacheMetaBase,
type: 'integer',
minimum: 0,
maximum: 1,
}
: { ...cacheMetaBase, schema: { type: 'integer', minimum: 0, maximum: 1 } };

switch (name) {
Expand Down Expand Up @@ -396,7 +408,9 @@ export class Swagger {
}

private static getSwaggerVersion(): number {
return swaggerPkgJson ? parseInt(swaggerPkgJson.version[0], 10) : 3;
return swaggerPkgJson
? parseInt(swaggerPkgJson.version[0], 10)
: /* istanbul ignore next */ 3;
}
}

Expand All @@ -406,7 +420,8 @@ export function ApiProperty(options?: any): PropertyDecorator {
/* istanbul ignore else */
if (swagger) {
// tslint:disable-next-line
const ApiPropertyDecorator = swagger.ApiProperty || swagger.ApiModelProperty;
const ApiPropertyDecorator =
swagger.ApiProperty || /* istanbul ignore next */ swagger.ApiModelProperty;
// tslint:disable-next-line
ApiPropertyDecorator(options)(target, propertyKey);
}
Expand Down
17 changes: 13 additions & 4 deletions packages/crud/src/interceptors/crud-response.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
Injectable,
NestInterceptor,
} from '@nestjs/common';
import { isNil } from '@nestjsx/util';
import { classToPlain, classToPlainFromExist } from 'class-transformer';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
Expand All @@ -16,7 +17,7 @@ const actionToDtoNameMap: {
} = {
[CrudActions.ReadAll]: 'getMany',
[CrudActions.ReadOne]: 'get',
[CrudActions.CreateMany]: 'create',
[CrudActions.CreateMany]: 'createMany',
[CrudActions.CreateOne]: 'create',
[CrudActions.UpdateOne]: 'update',
[CrudActions.ReplaceOne]: 'replace',
Expand All @@ -31,8 +32,8 @@ export class CrudResponseInterceptor extends CrudBaseInterceptor
return next.handle().pipe(map((data) => this.serialize(context, data)));
}

protected transform(dto: any, data: any) {
if (!(dto && data && data.constructor !== Object)) {
protected transform(dto: any, data: any, forced = false) {
if (!(dto && data && data.constructor !== Object) && !forced) {
return data;
}

Expand All @@ -49,9 +50,17 @@ export class CrudResponseInterceptor extends CrudBaseInterceptor

switch (action) {
case CrudActions.ReadAll:
const defaultPaginated =
!isNil(data) &&
!isNil(data.data) &&
!isNil(data.count) &&
!isNil(data.total) &&
!isNil(data.page) &&
!isNil(data.pageCount);

return isArray
? (data as any[]).map((item) => this.transform(serialize.get, item))
: this.transform(dto, data);
: this.transform(dto, data, defaultPaginated);
case CrudActions.CreateMany:
return isArray
? (data as any[]).map((item) => this.transform(dto, item))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export interface SerializeOptions {
getMany?: any;
get?: any;
create?: any;
createMany?: any;
update?: any;
replace?: any;
delete?: any;
Expand Down
53 changes: 48 additions & 5 deletions packages/crud/src/services/crud-service.abstract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
CrudRequest,
CrudRequestOptions,
GetManyDefaultResponse,
QueryOptions,
} from '../interfaces';

export abstract class CrudService<T> {
Expand Down Expand Up @@ -34,12 +35,13 @@ export abstract class CrudService<T> {
/**
* Wrap page into page-info
* override this method to create custom page-info response
* or set custom `serialize.getMany` dto in the controller's CrudOption
* @param data
* @param total
* @param limit
* @param offset
*/
public createPageInfo(
createPageInfo(
data: T[],
total: number,
limit: number,
Expand All @@ -63,8 +65,49 @@ export abstract class CrudService<T> {
* @param parsed
* @param options
*/
abstract decidePagination(
parsed: ParsedRequestParams,
options: CrudRequestOptions,
): boolean;
decidePagination(parsed: ParsedRequestParams, options: CrudRequestOptions): boolean {
return (
options.query.alwaysPaginate ||
((Number.isFinite(parsed.page) || Number.isFinite(parsed.offset)) &&
!!this.getTake(parsed, options.query))
);
}

/**
* Get number of resources to be fetched
* @param query
* @param options
*/
getTake(query: ParsedRequestParams, options: QueryOptions): number | null {
if (query.limit) {
return options.maxLimit
? query.limit <= options.maxLimit
? query.limit
: options.maxLimit
: query.limit;
}
/* istanbul ignore if */
if (options.limit) {
return options.maxLimit
? options.limit <= options.maxLimit
? options.limit
: options.maxLimit
: options.limit;
}

return options.maxLimit ? options.maxLimit : null;
}

/**
* Get number of resources to be skipped
* @param query
* @param take
*/
getSkip(query: ParsedRequestParams, take: number): number | null {
return query.page && take
? take * (query.page - 1)
: query.offset
? query.offset
: null;
}
}
3 changes: 3 additions & 0 deletions packages/crud/test/__fixture__/models/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './test.model';
export * from './test-serialize.model';
export * from './test-serialize-2.model';
17 changes: 17 additions & 0 deletions packages/crud/test/__fixture__/models/test-serialize-2.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Exclude } from 'class-transformer';

import { TestSerializeModel } from './test-serialize.model';

export class TestSerialize2Model extends TestSerializeModel {
id: number;
name: string;
email: string;

@Exclude()
isActive: boolean;

constructor(partial: Partial<TestSerialize2Model>) {
super(partial);
Object.assign(this, partial);
}
}
Loading

0 comments on commit 765341d

Please sign in to comment.