Skip to content

Commit

Permalink
refactor: move unexpectedhttperrorlogger to testlab
Browse files Browse the repository at this point in the history
  • Loading branch information
nabdelgadir committed May 7, 2019
1 parent f8ecd49 commit 798c416
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ import {
ParameterObject,
ResponseObject,
} from '@loopback/openapi-v3-types';
import {Client, createClientForHandler, expect} from '@loopback/testlab';
import {
Client,
createClientForHandler,
createUnexpectedHttpErrorLogger,
expect,
} from '@loopback/testlab';
import {
ControllerClass,
ControllerInstance,
Expand All @@ -28,7 +33,6 @@ import {
RestServer,
SequenceActions,
} from '../../..';
import {createUnexpectedHttpErrorLogger} from '../../helpers';

/* # Feature: Routing
* - In order to build REST APIs
Expand Down
22 changes: 0 additions & 22 deletions packages/rest/src/__tests__/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,8 @@ import {
RequestBodyObject,
SchemaObject,
} from '@loopback/openapi-v3-types';
import {IncomingMessage} from 'http';
import {LogError} from '..';
import {RestServerConfig, RestServerResolvedConfig} from '../rest.server';

export function createUnexpectedHttpErrorLogger(
expectedStatusCode: number = 0,
): LogError {
return function logUnexpectedHttpError(
err: Error,
statusCode: number,
req: IncomingMessage,
) {
if (statusCode === expectedStatusCode) return;

console.error(
'Unhandled error in %s %s: %s %s',
req.method,
req.url,
statusCode,
err.stack || err,
);
};
}

/**
* Create an OpenAPI request body spec with the given content
* @param schema The schema object
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ import {Context} from '@loopback/context';
import {anOpenApiSpec, anOperationSpec} from '@loopback/openapi-spec-builder';
import {ControllerSpec, get} from '@loopback/openapi-v3';
import {ParameterObject, RequestBodyObject} from '@loopback/openapi-v3-types';
import {Client, createClientForHandler, expect} from '@loopback/testlab';
import {
Client,
createClientForHandler,
createUnexpectedHttpErrorLogger,
expect,
} from '@loopback/testlab';
import * as express from 'express';
import * as HttpErrors from 'http-errors';
import {is} from 'type-is';
Expand All @@ -30,7 +35,7 @@ import {
UrlEncodedBodyParser,
writeResultToResponse,
} from '../..';
import {createUnexpectedHttpErrorLogger, aRestServerConfig} from '../helpers';
import {aRestServerConfig} from '../helpers';

const SequenceActions = RestBindings.SequenceActions;

Expand Down
42 changes: 42 additions & 0 deletions packages/testlab/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ Table of contents:
- [httpGetAsync](#httpgetasync) - Async wrapper for HTTP GET requests.
- [httpsGetAsync](#httpsgetasync) - Async wrapper for HTTPS GET requests.
- [toJSON](#toJSON) - A helper to obtain JSON data representing a given object.
- [createUnexpectedHttpErrorLogger](#createUnexpectedHttpErrorLogger) - An error
logger that only logs errors for unexpected HTTP statuses.

### `expect`

Expand Down Expand Up @@ -287,6 +289,46 @@ describe('MyApp', () => {
});
```

### `createUnexpectedHttpErrorLogger`

An error logger that logs the error only when the HTTP status code is not the
expected HTTP status code. This is useful when writing tests for error
responses:

- When we don't want any error messages printed to the console when the server
responds with the expected error and the test passes.

- When something else goes wrong and the server returns an unexpected error
status code, and we do want an error message to be printed to the console so
that we have enough information to troubleshoot the failing test.

```ts
import {createUnexpectedHttpErrorLogger} from '@loopback/testlab';
import {RestApplication} from '@loopback/rest';

describe('MyApp', () => {
it('does not log a known 401 error to console', async () => {
const app = new RestApplication();
const errorLogger = createUnexpectedHttpErrorLogger(401);

const spec = {
responses: {
/*...*/
},
};
function throwUnauthorizedError() {
throw new HttpErrors.Unauthorized('Unauthorized!');
}

app.route('get', '/', spec, throwUnauthorizedError);

// binds the custom error logger
app.bind(SequenceActions.LOG_ERROR).to(errorLogger);
await app.start();
});
});
```

## Related resources

For more info about `supertest`, please refer to
Expand Down
35 changes: 35 additions & 0 deletions packages/testlab/src/http-error-logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright IBM Corp. 2019. All Rights Reserved.
// Node module: @loopback/testlab
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {Request} from 'express';
import {IncomingMessage} from 'http';

/**
* Creates a Logger that logs an Error if the HTTP status code is not expected
*
* @param expectedStatusCode HTTP status code that is expected
*/
export function createUnexpectedHttpErrorLogger(
expectedStatusCode?: number,
): LogError {
return function logUnexpectedHttpError(
err: Error,
statusCode: number,
req: IncomingMessage,
) {
if (statusCode === expectedStatusCode) return;

/* istanbul ignore next */
console.error(
'Unhandled error in %s %s: %s %s',
req.method,
req.url,
statusCode,
err.stack || err,
);
};
}

type LogError = (err: Error, statusCode: number, request: Request) => void;
13 changes: 7 additions & 6 deletions packages/testlab/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

export * from './expect';
export * from './sinon';
export * from './client';
export * from './expect';
export * from './http-error-logger';
export * from './http-server-config';
export * from './request';
export * from './shot';
export * from './validate-api-spec';
export * from './test-sandbox';
export * from './sinon';
export * from './skip-travis';
export * from './request';
export * from './http-server-config';
export * from './test-sandbox';
export * from './to-json';
export * from './validate-api-spec';

0 comments on commit 798c416

Please sign in to comment.