Skip to content

Commit

Permalink
test(@nestjs) update unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kamilmysliwiec committed Mar 22, 2018
1 parent 852ce08 commit 11b397a
Show file tree
Hide file tree
Showing 52 changed files with 1,739 additions and 504 deletions.
Binary file modified .DS_Store
Binary file not shown.
435 changes: 140 additions & 295 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
"reflect-metadata": "^0.1.10",
"rxjs": "^5.5.6",
"rxjs-grpc": "^0.1.6",
"socket.io": "^2.0.3",
"socket.io": "^2.0.4",
"trouter": "^1.0.0"
},
"devDependencies": {
Expand All @@ -69,7 +69,7 @@
"@types/redis": "^0.12.36",
"@types/reflect-metadata": "0.0.5",
"@types/sinon": "^1.16.36",
"@types/socket.io": "^1.4.29",
"@types/socket.io": "^1.4.32",
"awesome-typescript-loader": "^3.0.0-beta.18",
"body-parser": "^1.17.2",
"chai": "^3.5.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { Observable } from 'rxjs/Observable';

export interface WebSocketAdapter {
create(port: number);
createWithNamespace?(port: number, namespace: string, server?);
create(port: number, options?: any & { namespace?: string; server?: any });
bindClientConnect(server, callback: (...args) => void);
bindClientDisconnect?(client, callback: (...args) => void);
bindMessageHandlers(
client,
handler: {
message: string;
callback: (...args) => Observable<any> | Promise<any> | void;
message: any;
callback: (...args) => Observable<any> | Promise<any> | any;
}[],
process: (data) => Observable<any>,
);
bindMiddleware?(server, middleware: (socket, next) => void);
}
12 changes: 12 additions & 0 deletions src/common/test/interceptors/files.interceptor.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,17 @@ describe('FilesInterceptor', () => {
expect(arraySpy.called).to.be.true;
expect(arraySpy.calledWith(fieldName, maxCount)).to.be.true;
});
it('should transform exception', async () => {
const fieldName = 'file';
const target = new (FilesInterceptor(fieldName));
const err = {};
const callback = (req, res, next) => next(err);

(target as any).upload = {
array: () => callback,
};
const req = {};
expect(target.intercept(req, null, stream$)).to.eventually.throw();
});
});
});
9 changes: 9 additions & 0 deletions src/core/errors/exceptions/circular-dependency.exception.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { RuntimeException } from './runtime.exception';

export class CircularDependencyException extends RuntimeException {
constructor(context: string) {
super(
`A circular dependency has been detected inside ${context}. Please, make sure that each side of a bidirectional relationships are decorated with "forwardRef()".`,
);
}
}
16 changes: 10 additions & 6 deletions src/core/scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import { Type } from '@nestjs/common/interfaces/type.interface';
import { MetadataScanner } from '../core/metadata-scanner';
import { DynamicModule } from '@nestjs/common';
import { ApplicationConfig } from './application-config';
import { isNil } from '@nestjs/common/utils/shared.utils';
import { isNil, isUndefined } from '@nestjs/common/utils/shared.utils';
import { APP_INTERCEPTOR, APP_PIPE, APP_GUARD, APP_FILTER } from './constants';
import { CircularDependencyException } from './errors/exceptions/circular-dependency.exception';

interface ApplicationProviderWrapper {
moduleToken: string;
Expand Down Expand Up @@ -58,14 +59,14 @@ export class DependenciesScanner {
const modules = this.container.getModules();

modules.forEach(({ metatype }, token) => {
this.reflectRelatedModules(metatype, token);
this.reflectRelatedModules(metatype, token, metatype.name);
this.reflectComponents(metatype, token);
this.reflectControllers(metatype, token);
this.reflectExports(metatype, token);
});
}

public reflectRelatedModules(module: Type<any>, token: string) {
public reflectRelatedModules(module: Type<any>, token: string, context: string) {
const modules = [
...this.reflectMetadata(module, metadata.MODULES),
...this.container.getDynamicMetadataByToken(
Expand All @@ -77,7 +78,7 @@ export class DependenciesScanner {
metadata.IMPORTS as 'imports',
),
];
modules.map(related => this.storeRelatedModule(related, token));
modules.map(related => this.storeRelatedModule(related, token, context));
}

public reflectComponents(module: Type<any>, token: string) {
Expand Down Expand Up @@ -189,8 +190,11 @@ export class DependenciesScanner {
return descriptor ? Reflect.getMetadata(key, descriptor.value) : undefined;
}

public storeRelatedModule(related: any, token: string) {
if (related.forwardRef) {
public storeRelatedModule(related: any, token: string, context: string) {
if (isUndefined(related)) {
throw new CircularDependencyException(context);
}
if (related && related.forwardRef) {
return this.container.addRelatedModule(related.forwardRef(), token);
}
this.container.addRelatedModule(related, token);
Expand Down
2 changes: 1 addition & 1 deletion src/core/test/scanner.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ describe('DependenciesScanner', () => {
const module = { forwardRef: sinon.stub().returns({}) };

sinon.stub(container, 'addRelatedModule').returns({});
scanner.storeRelatedModule(module as any, [] as any);
scanner.storeRelatedModule(module as any, [] as any, 'test');
expect(module.forwardRef.called).to.be.true;
});
});
Expand Down
Binary file added src/microservices/.DS_Store
Binary file not shown.
17 changes: 14 additions & 3 deletions src/microservices/client/client-grpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { ClientGrpc } from './../interfaces';
import { Observable } from 'rxjs/Observable';
import { InvalidGrpcServiceException } from '../exceptions/invalid-grpc-service.exception';
import { InvalidGrpcPackageException } from '../exceptions/invalid-grpc-package.exception';
import { InvalidProtoDefinitionException } from '../exceptions/invalid-proto-definition.exception';

export interface GrpcService {
[name: string]: (...args: any[]) => Observable<any>;
Expand Down Expand Up @@ -84,9 +85,7 @@ export class ClientGrpcProxy extends ClientProxy implements ClientGrpc {
}

public createClient(): any {
const grpcContext = grpc.load(
this.getOptionsProp<GrpcOptions>(this.options, 'protoPath'),
);
const grpcContext = this.loadProto();
const packageName = this.getOptionsProp<GrpcOptions>(
this.options,
'package',
Expand All @@ -98,6 +97,18 @@ export class ClientGrpcProxy extends ClientProxy implements ClientGrpc {
return grpcPackage;
}

public loadProto(): grpc.GrpcObject {
try {
const context = grpc.load(
this.getOptionsProp<GrpcOptions>(this.options, 'protoPath'),
);
return context;
}
catch (e) {
throw new InvalidProtoDefinitionException();
}
}

public lookupPackage(root: any, packageName: string) {
/** Reference: https://github.com/kondi/rxjs-grpc */
let pkg = root;
Expand Down
2 changes: 1 addition & 1 deletion src/microservices/client/client-mqtt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class ClientMqtt extends ClientProxy {
this.getOptionsProp<MqttOptions>(this.options, 'url') || MQTT_DEFAULT_URL;
}

protected async publish(
protected publish(
partialPacket: ReadPacket,
callback: (packet: WritePacket) => any,
) {
Expand Down
44 changes: 25 additions & 19 deletions src/microservices/client/client-nats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,12 @@ import { ClientProxy } from './client-proxy';
import { Logger } from '@nestjs/common/services/logger.service';
import { ClientOptions } from '../interfaces/client-metadata.interface';
import { NATS_DEFAULT_URL, ERROR_EVENT, CONNECT_EVENT } from './../constants';
import { WritePacket, NatsOptions } from './../interfaces';
import { ReadPacket, PacketId } from 'src/microservices';
import {
WritePacket,
NatsOptions,
ReadPacket,
PacketId,
} from './../interfaces';

export class ClientNats extends ClientProxy {
private readonly logger = new Logger(ClientProxy.name);
Expand All @@ -28,28 +32,30 @@ export class ClientNats extends ClientProxy {
const pattern = JSON.stringify(partialPacket.pattern);
const responseChannel = this.getResPatternName(pattern);

const subscriptionId = this.natsClient.subscribe(
responseChannel,
(message: WritePacket & PacketId) => {
if (message.id !== packet.id) {
return void 0;
}
const { err, response, isDisposed } = message;
if (isDisposed || err) {
callback({
err,
response: null,
isDisposed: true,
});
return this.natsClient.unsubscribe(subscriptionId);
}
const subscriptionHandler = (message: WritePacket & PacketId) => {
if (message.id !== packet.id) {
return void 0;
}
const { err, response, isDisposed } = message;
if (isDisposed || err) {
callback({
err,
response,
response: null,
isDisposed: true,
});
},
return this.natsClient.unsubscribe(subscriptionId);
}
callback({
err,
response,
});
};
const subscriptionId = this.natsClient.subscribe(
responseChannel,
subscriptionHandler,
);
this.natsClient.publish(this.getAckPatternName(pattern), packet as any);
return subscriptionHandler;
}

public getAckPatternName(pattern: string): string {
Expand Down
19 changes: 12 additions & 7 deletions src/microservices/client/client-redis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ export class ClientRedis extends ClientProxy {

constructor(private readonly options: ClientOptions) {
super();
this.url = this.getOptionsProp<RedisOptions>(options, 'url') || REDIS_DEFAULT_URL;
this.url =
this.getOptionsProp<RedisOptions>(options, 'url') || REDIS_DEFAULT_URL;
}

protected async publish(
Expand Down Expand Up @@ -62,12 +63,16 @@ export class ClientRedis extends ClientProxy {
};
this.subClient.on(MESSAGE_EVENT, responseCallback);
this.subClient.subscribe(responseChannel);
await new Promise(resolve =>
this.subClient.on(
SUBSCRIBE,
channel => channel === responseChannel && resolve(),
),
);
await new Promise(resolve => {
const handler = channel => {
if (channel && channel !== responseChannel) {
return void 0;
}
this.subClient.removeListener(SUBSCRIBE, handler);
resolve();
};
this.subClient.on(SUBSCRIBE, handler);
});

this.pubClient.publish(
this.getAckPatternName(pattern),
Expand Down
3 changes: 1 addition & 2 deletions src/microservices/client/client-tcp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ import {
ERROR_EVENT,
CLOSE_EVENT,
} from './../constants';
import { WritePacket } from './../interfaces';
import { ReadPacket, PacketId } from 'src/microservices';
import { WritePacket, ReadPacket, PacketId } from './../interfaces';

export class ClientTCP extends ClientProxy {
private readonly logger = new Logger(ClientTCP.name);
Expand Down
2 changes: 1 addition & 1 deletion src/microservices/context/rpc-context-creator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export class RpcContextCreator {
instance: Controller,
callback: (data) => Observable<any>,
module,
): (data) => Promise<Observable<any>> {
): (...args) => Promise<Observable<any>> {
const exceptionHandler = this.exceptionFiltersContext.create(
instance,
callback,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { RuntimeException } from '@nestjs/core/errors/exceptions/runtime.exception';

export class InvalidProtoDefinitionException extends RuntimeException {
constructor() {
super('Invalid .proto definition (file not found?)');
}
}
4 changes: 2 additions & 2 deletions src/microservices/server/server-grpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ export class ServerGrpc extends Server implements CustomTransportStrategy {
}

public async start(callback?: () => void) {
await this.bindEvents(this.grpcClient);
await this.bindEvents();
this.grpcClient.start();
callback();
}

public async bindEvents(client: any) {
public async bindEvents() {
const grpcContext = grpc.load(
this.getOptionsProp<GrpcOptions>(this.options, 'protoPath'),
);
Expand Down
10 changes: 5 additions & 5 deletions src/microservices/server/server-tcp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ export class ServerTCP extends Server implements CustomTransportStrategy {
private isExplicitlyTerminated = false;
private retryAttemptsCount = 0;

constructor(private readonly config: MicroserviceOptions) {
constructor(private readonly options: MicroserviceOptions) {
super();
this.port =
this.getOptionsProp<TcpOptions>(config, 'port') ||
this.getOptionsProp<TcpOptions>(options, 'port') ||
TCP_DEFAULT_PORT;
this.init();
}
Expand Down Expand Up @@ -71,12 +71,12 @@ export class ServerTCP extends Server implements CustomTransportStrategy {
if (
this.isExplicitlyTerminated ||
!this.getOptionsProp<TcpOptions>(
this.config,
this.options,
'retryAttempts',
) ||
this.retryAttemptsCount >=
this.getOptionsProp<TcpOptions>(
this.config,
this.options,
'retryAttempts',
)
) {
Expand All @@ -86,7 +86,7 @@ export class ServerTCP extends Server implements CustomTransportStrategy {
return setTimeout(
() => this.server.listen(this.port),
this.getOptionsProp<TcpOptions>(
this.config,
this.options,
'retryDelay',
) || 0,
);
Expand Down
Loading

0 comments on commit 11b397a

Please sign in to comment.