Setup tests. Add basic GenericRestClient tests
This commit is contained in:
Родитель
7b11a60ff0
Коммит
8a36fb9d22
|
@ -0,0 +1 @@
|
|||
module.exports = require('./karma/karma.config');
|
|
@ -0,0 +1,50 @@
|
|||
const webpack = require('./webpack.test');
|
||||
|
||||
module.exports = config => (
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine-ajax', 'jasmine'],
|
||||
reporters: ['spec', 'kjhtml'],
|
||||
browsers: [
|
||||
process.env.TRAVIS
|
||||
? 'ChromeHeadlessNoSandbox'
|
||||
: 'Chrome',
|
||||
],
|
||||
plugins: [
|
||||
'karma-jasmine-html-reporter',
|
||||
'karma-sourcemap-loader',
|
||||
'karma-chrome-launcher',
|
||||
'karma-spec-reporter',
|
||||
'karma-jasmine-ajax',
|
||||
'karma-jasmine',
|
||||
'karma-webpack',
|
||||
],
|
||||
|
||||
customLaunchers: {
|
||||
ChromeHeadlessNoSandbox: {
|
||||
base: 'ChromeHeadless',
|
||||
flags: ['--no-sandbox'],
|
||||
}
|
||||
},
|
||||
|
||||
preprocessors: {
|
||||
'./karma/karma.entry.js': ['webpack', 'sourcemap'],
|
||||
},
|
||||
|
||||
files: [
|
||||
{ pattern: './karma/karma.entry.js', watched: false },
|
||||
],
|
||||
|
||||
logLevel: config.LOG_INFO,
|
||||
colors: true,
|
||||
mime: {
|
||||
'text/x-typescript': ['ts'],
|
||||
},
|
||||
|
||||
webpack,
|
||||
|
||||
webpackMiddleware: {
|
||||
stats: 'errors-only',
|
||||
}
|
||||
})
|
||||
);
|
|
@ -0,0 +1,6 @@
|
|||
const context = require
|
||||
.context('../test/', true, /\.spec\.ts$/);
|
||||
|
||||
context
|
||||
.keys()
|
||||
.forEach(context);
|
|
@ -0,0 +1,30 @@
|
|||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
const path = require('path');
|
||||
const ROOT_PATH = path.resolve(__dirname, '..');
|
||||
const CONFIG_PATH = path.resolve(ROOT_PATH, 'tsconfig.test.json');
|
||||
|
||||
module.exports = {
|
||||
devtool: 'inline-source-map',
|
||||
mode: 'development',
|
||||
|
||||
resolve: {
|
||||
extensions: ['.js', '.ts']
|
||||
},
|
||||
|
||||
module: {
|
||||
rules: [{
|
||||
test: /\.ts$/,
|
||||
loader: 'ts-loader',
|
||||
options: {
|
||||
transpileOnly: true,
|
||||
configFile: CONFIG_PATH,
|
||||
context: ROOT_PATH,
|
||||
},
|
||||
exclude: /node_modules/
|
||||
}]
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new ForkTsCheckerWebpackPlugin({ tsconfig: CONFIG_PATH }),
|
||||
]
|
||||
};
|
39
package.json
39
package.json
|
@ -4,20 +4,41 @@
|
|||
"description": "A library of components for accessing RESTful services with javascript/typescript.",
|
||||
"author": "David de Regt <David.de.Regt@microsoft.com>",
|
||||
"scripts": {
|
||||
"prepublish": "tsc",
|
||||
"prepare": "tsc",
|
||||
"clean": "rimraf dist",
|
||||
"build": "npm run tslint && tsc",
|
||||
"tslint": "tslint --project tsconfig.json -r tslint.json --fix || true"
|
||||
"tslint": "tslint --project tsconfig.json -r tslint.json --fix || true",
|
||||
"test": "npm run clean && karma start --singleRun",
|
||||
"test:watch": "npm run clean && karma start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@types/lodash": "^4.14.62",
|
||||
"assert": "^1.4.1",
|
||||
"lodash": "4.x",
|
||||
"synctasks": "^0.3.0"
|
||||
"@types/lodash": "4.14.107",
|
||||
"assert": "1.4.1",
|
||||
"lodash": "4.17.5",
|
||||
"synctasks": "0.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"tslint": "5.4.3",
|
||||
"tslint-microsoft-contrib": "5.0.0",
|
||||
"typescript": "^2.6.0"
|
||||
"@types/faker": "4.1.2",
|
||||
"@types/jasmine": "2.8.6",
|
||||
"@types/jasmine-ajax": "3.1.37",
|
||||
"faker": "4.1.0",
|
||||
"fork-ts-checker-webpack-plugin": "0.4.1",
|
||||
"jasmine": "3.1.0",
|
||||
"jasmine-core": "3.1.0",
|
||||
"karma": "2.0.0",
|
||||
"karma-chrome-launcher": "2.2.0",
|
||||
"karma-jasmine": "1.1.1",
|
||||
"karma-jasmine-ajax": "0.1.13",
|
||||
"karma-jasmine-html-reporter": "1.0.0",
|
||||
"karma-sourcemap-loader": "0.3.7",
|
||||
"karma-spec-reporter": "0.0.32",
|
||||
"karma-webpack": "4.0.0-beta.0",
|
||||
"rimraf": "2.6.2",
|
||||
"ts-loader": "4.1.0",
|
||||
"tslint": "5.9.1",
|
||||
"tslint-microsoft-contrib": "5.0.3",
|
||||
"typescript": "2.8.1",
|
||||
"webpack": "4.5.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
|
|
@ -69,7 +69,7 @@ export class GenericRestClient {
|
|||
}
|
||||
options.augmentHeaders['If-None-Match'] = options.eTag;
|
||||
}
|
||||
|
||||
|
||||
if (!options.contentType) {
|
||||
options.contentType = _.isString(options.sendData) ? 'form' : 'json';
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
// @TODO
|
|
@ -0,0 +1,373 @@
|
|||
import * as faker from 'faker';
|
||||
import { GenericRestClient, ApiCallOptions } from '../src/GenericRestClient';
|
||||
import { DETAILED_RESPONSE, REQUEST_OPTIONS } from './helpers';
|
||||
|
||||
class RestClient extends GenericRestClient { }
|
||||
const BASE_URL = faker.internet.url();
|
||||
const http = new RestClient(BASE_URL);
|
||||
|
||||
describe('GenericRestClient', () => {
|
||||
beforeEach(() => jasmine.Ajax.install());
|
||||
afterEach(() => jasmine.Ajax.uninstall());
|
||||
|
||||
it('performs GET request with performApiGet', () => {
|
||||
const id = faker.random.uuid();
|
||||
const statusCode = 200;
|
||||
const onSuccess = jasmine.createSpy('onSuccess');
|
||||
const method = 'GET';
|
||||
const body = {
|
||||
title: faker.name.title(),
|
||||
text: faker.lorem.text(),
|
||||
id,
|
||||
};
|
||||
const path = `/get/${id}`;
|
||||
const url = BASE_URL + path;
|
||||
|
||||
http.performApiGet(path)
|
||||
.then(onSuccess);
|
||||
|
||||
const request = jasmine.Ajax.requests.mostRecent();
|
||||
request.respondWith({
|
||||
responseText: JSON.stringify(body),
|
||||
status: statusCode,
|
||||
});
|
||||
|
||||
expect(request.url).toEqual(url);
|
||||
expect(request.method).toEqual(method);
|
||||
expect(request.status).toEqual(statusCode);
|
||||
expect(onSuccess).toHaveBeenCalledWith(body);
|
||||
});
|
||||
|
||||
it('performs GET request with performApiGetDetailed', () => {
|
||||
const id = faker.random.uuid();
|
||||
const statusCode = 200;
|
||||
const onSuccess = jasmine.createSpy('onSuccess');
|
||||
const method = 'GET';
|
||||
const body = {
|
||||
title: faker.name.title(),
|
||||
text: faker.lorem.text(),
|
||||
id,
|
||||
};
|
||||
const path = `/get/${id}`;
|
||||
const url = BASE_URL + path;
|
||||
const response = {
|
||||
...DETAILED_RESPONSE,
|
||||
requestHeaders: { 'Accept': 'application/json' },
|
||||
statusCode,
|
||||
method,
|
||||
body,
|
||||
url
|
||||
};
|
||||
|
||||
http.performApiGetDetailed(path, { contentType: 'json' })
|
||||
.then(onSuccess);
|
||||
|
||||
const request = jasmine.Ajax.requests.mostRecent();
|
||||
request.respondWith({
|
||||
responseText: JSON.stringify(body),
|
||||
status: statusCode,
|
||||
});
|
||||
|
||||
expect(request.url).toEqual(url);
|
||||
expect(request.method).toEqual(method);
|
||||
expect(onSuccess).toHaveBeenCalledWith(response);
|
||||
});
|
||||
|
||||
it('performs POST request with performApiPost', () => {
|
||||
const statusCode = 201;
|
||||
const onSuccess = jasmine.createSpy('onSuccess');
|
||||
const method = 'POST';
|
||||
const sendData = {
|
||||
title: faker.name.title(),
|
||||
text: faker.lorem.text(),
|
||||
};
|
||||
const body = { ...sendData, id: faker.random.uuid() };
|
||||
const path = '/post';
|
||||
const url = BASE_URL + path;
|
||||
|
||||
http.performApiPost(path, sendData, { contentType: 'json' })
|
||||
.then(onSuccess);
|
||||
|
||||
const request = jasmine.Ajax.requests.mostRecent();
|
||||
request.respondWith({
|
||||
responseText: JSON.stringify(body),
|
||||
status: statusCode,
|
||||
});
|
||||
|
||||
expect(request.url).toEqual(url);
|
||||
expect(request.method).toEqual(method);
|
||||
expect(request.status).toEqual(statusCode);
|
||||
expect(request.data() as any).toEqual(sendData);
|
||||
expect(onSuccess).toHaveBeenCalledWith(body);
|
||||
});
|
||||
|
||||
it('performs POST request with performApiPostDetailed', () => {
|
||||
const statusCode = 201;
|
||||
const onSuccess = jasmine.createSpy('onSuccess');
|
||||
const sendData = {
|
||||
title: faker.name.title(),
|
||||
text: faker.lorem.text(),
|
||||
};
|
||||
const method = 'POST';
|
||||
const body = { ...sendData, id: faker.random.uuid() };
|
||||
const path = '/post';
|
||||
const url = BASE_URL + path;
|
||||
const response = {
|
||||
...DETAILED_RESPONSE,
|
||||
requestOptions: { ...REQUEST_OPTIONS, sendData },
|
||||
statusCode,
|
||||
method,
|
||||
body,
|
||||
url
|
||||
};
|
||||
|
||||
http.performApiPostDetailed(path, sendData, { contentType: 'json' })
|
||||
.then(onSuccess);
|
||||
|
||||
const request = jasmine.Ajax.requests.mostRecent();
|
||||
request.respondWith({
|
||||
responseText: JSON.stringify(body),
|
||||
status: statusCode,
|
||||
});
|
||||
|
||||
expect(request.url).toEqual(url);
|
||||
expect(request.method).toEqual(method);
|
||||
expect(request.status).toEqual(statusCode);
|
||||
expect(onSuccess).toHaveBeenCalledWith(response);
|
||||
});
|
||||
|
||||
it('performs PUT request with performApiPut', () => {
|
||||
const id = faker.random.uuid();
|
||||
const statusCode = 200;
|
||||
const onSuccess = jasmine.createSpy('onSuccess');
|
||||
const sendData = { title: faker.name.title() };
|
||||
const method = 'PUT';
|
||||
const body = { ...sendData, id };
|
||||
const path = '/put/' + id;
|
||||
const url = BASE_URL + path;
|
||||
|
||||
http.performApiPut(path, sendData, { contentType: 'json' })
|
||||
.then(onSuccess);
|
||||
|
||||
const request = jasmine.Ajax.requests.mostRecent();
|
||||
request.respondWith({
|
||||
responseText: JSON.stringify(body),
|
||||
status: statusCode,
|
||||
});
|
||||
|
||||
expect(request.url).toEqual(url);
|
||||
expect(request.method).toEqual(method);
|
||||
expect(request.status).toEqual(statusCode);
|
||||
expect(request.data() as any).toEqual(sendData);
|
||||
expect(onSuccess).toHaveBeenCalledWith(body);
|
||||
});
|
||||
|
||||
it('performs PUT request with performApiPutDetailed', () => {
|
||||
const id = faker.random.uuid();
|
||||
const statusCode = 200;
|
||||
const onSuccess = jasmine.createSpy('onSuccess');
|
||||
const sendData = { title: faker.name.title() };
|
||||
const method = 'PUT';
|
||||
const body = { ...sendData, id: faker.random.uuid() };
|
||||
const path = `/patch/${id}`;
|
||||
const url = BASE_URL + path;
|
||||
const response = {
|
||||
...DETAILED_RESPONSE,
|
||||
requestOptions: { ...REQUEST_OPTIONS, sendData },
|
||||
statusCode,
|
||||
method,
|
||||
body,
|
||||
url
|
||||
};
|
||||
|
||||
http.performApiPutDetailed(path, sendData, { contentType: 'json' })
|
||||
.then(onSuccess);
|
||||
|
||||
const request = jasmine.Ajax.requests.mostRecent();
|
||||
request.respondWith({
|
||||
responseText: JSON.stringify(body),
|
||||
status: statusCode,
|
||||
});
|
||||
|
||||
expect(request.url).toEqual(url);
|
||||
expect(request.method).toEqual(method);
|
||||
expect(request.status).toEqual(statusCode);
|
||||
expect(request.data() as any).toEqual(sendData);
|
||||
expect(onSuccess).toHaveBeenCalledWith(response);
|
||||
});
|
||||
|
||||
it('performs PATCH request with performApiPatch', () => {
|
||||
const id = faker.random.uuid();
|
||||
const statusCode = 200;
|
||||
const onSuccess = jasmine.createSpy('onSuccess');
|
||||
const method = 'PATCH';
|
||||
const sendData = {
|
||||
title: faker.name.title(),
|
||||
text: faker.lorem.text(),
|
||||
};
|
||||
const body = { ...sendData, text: faker.lorem.text(), id };
|
||||
const path = '/patch' + id;
|
||||
const url = BASE_URL + path;
|
||||
|
||||
http.performApiPatch(path, sendData, { contentType: 'json' })
|
||||
.then(onSuccess);
|
||||
|
||||
const request = jasmine.Ajax.requests.mostRecent();
|
||||
request.respondWith({
|
||||
responseText: JSON.stringify(body),
|
||||
status: statusCode,
|
||||
});
|
||||
|
||||
expect(request.url).toEqual(url);
|
||||
expect(request.method).toEqual(method);
|
||||
expect(request.status).toEqual(statusCode);
|
||||
expect(request.data() as any).toEqual(sendData);
|
||||
expect(onSuccess).toHaveBeenCalledWith(body);
|
||||
});
|
||||
|
||||
it('performs PATCH request with performApiPatchDetailed', () => {
|
||||
const id = faker.random.uuid();
|
||||
const statusCode = 200;
|
||||
const onSuccess = jasmine.createSpy('onSuccess');
|
||||
const sendData = {
|
||||
title: faker.name.title(),
|
||||
text: faker.lorem.text(),
|
||||
};
|
||||
const method = 'PATCH';
|
||||
const body = { ...sendData, id: faker.random.uuid() };
|
||||
const path = `/patch/${id}`;
|
||||
const url = BASE_URL + path;
|
||||
const response = {
|
||||
...DETAILED_RESPONSE,
|
||||
requestOptions: { ...REQUEST_OPTIONS, sendData },
|
||||
statusCode,
|
||||
method,
|
||||
body,
|
||||
url
|
||||
};
|
||||
|
||||
http.performApiPatchDetailed(path, sendData, { contentType: 'json' })
|
||||
.then(onSuccess);
|
||||
|
||||
const request = jasmine.Ajax.requests.mostRecent();
|
||||
request.respondWith({
|
||||
responseText: JSON.stringify(body),
|
||||
status: statusCode,
|
||||
});
|
||||
|
||||
expect(request.url).toEqual(url);
|
||||
expect(request.method).toEqual(method);
|
||||
expect(request.status).toEqual(statusCode);
|
||||
expect(request.data() as any).toEqual(sendData);
|
||||
expect(onSuccess).toHaveBeenCalledWith(response);
|
||||
});
|
||||
|
||||
it('performs DELETE request with performApiDelete', () => {
|
||||
const statusCode = 200;
|
||||
const onSuccess = jasmine.createSpy('onSuccess');
|
||||
const method = 'DELETE';
|
||||
const body = {};
|
||||
const path = `/delete/${faker.random.uuid()}`;
|
||||
const url = BASE_URL + path;
|
||||
|
||||
http.performApiDelete(path)
|
||||
.then(onSuccess);
|
||||
|
||||
const request = jasmine.Ajax.requests.mostRecent();
|
||||
request.respondWith({
|
||||
responseText: JSON.stringify(body),
|
||||
status: statusCode,
|
||||
});
|
||||
|
||||
expect(request.url).toEqual(url);
|
||||
expect(request.method).toEqual(method);
|
||||
expect(onSuccess).toHaveBeenCalledWith(body);
|
||||
});
|
||||
|
||||
it('performs DELETE request with performApiDeleteDetailed', () => {
|
||||
const id = faker.random.uuid();
|
||||
const statusCode = 200;
|
||||
const onSuccess = jasmine.createSpy('onSuccess');
|
||||
const sendData = { id };
|
||||
const method = 'DELETE';
|
||||
const body = {};
|
||||
const path = `/delete/${id}`;
|
||||
const url = BASE_URL + path;
|
||||
const response = {
|
||||
...DETAILED_RESPONSE,
|
||||
requestOptions: { ...REQUEST_OPTIONS, sendData },
|
||||
statusCode,
|
||||
method,
|
||||
body,
|
||||
url,
|
||||
};
|
||||
|
||||
http.performApiDeleteDetailed(path, sendData, { contentType: 'json' })
|
||||
.then(onSuccess);
|
||||
|
||||
const request = jasmine.Ajax.requests.mostRecent();
|
||||
request.respondWith({
|
||||
responseText: JSON.stringify(body),
|
||||
status: statusCode,
|
||||
});
|
||||
|
||||
expect(request.url).toEqual(url);
|
||||
expect(request.method).toEqual(method);
|
||||
expect(request.data() as any).toEqual(sendData);
|
||||
expect(onSuccess).toHaveBeenCalledWith(response);
|
||||
});
|
||||
|
||||
it('performs request with custum headers', () => {
|
||||
const headers = {
|
||||
'Authorization': `Barrier ${faker.random.uuid()}`,
|
||||
};
|
||||
|
||||
class Http extends GenericRestClient {
|
||||
protected _getHeaders(options: ApiCallOptions): { [header: string]: string } {
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
const statusCode = 200;
|
||||
const onSuccess = jasmine.createSpy('onSuccess');
|
||||
const http = new Http(BASE_URL);
|
||||
const path = '/auth';
|
||||
|
||||
http.performApiGet(path)
|
||||
.then(onSuccess);
|
||||
|
||||
const request = jasmine.Ajax.requests.mostRecent();
|
||||
request.respondWith({ status: statusCode });
|
||||
|
||||
expect(request.requestHeaders['Authorization']).toEqual(headers['Authorization']);
|
||||
expect(onSuccess).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('overrides response', () => {
|
||||
class Http extends GenericRestClient {
|
||||
protected _processSuccessResponse<T>(resp: any): void {
|
||||
resp.body = resp.body.map((str: string) => str.trim());
|
||||
}
|
||||
}
|
||||
const statusCode = 200;
|
||||
const onSuccess = jasmine.createSpy('onSuccess');
|
||||
const method = 'GET';
|
||||
const http = new Http(BASE_URL);
|
||||
const path = '/get';
|
||||
const body = [' x ', ' y ', ' z '];
|
||||
const url = BASE_URL + path;
|
||||
|
||||
http.performApiGet<string[]>(path)
|
||||
.then(onSuccess);
|
||||
|
||||
const request = jasmine.Ajax.requests.mostRecent();
|
||||
request.respondWith({
|
||||
responseText: JSON.stringify(body),
|
||||
status: statusCode,
|
||||
});
|
||||
|
||||
expect(request.url).toEqual(url);
|
||||
expect(request.method).toEqual(method);
|
||||
expect(request.status).toEqual(statusCode);
|
||||
expect(onSuccess).toHaveBeenCalledWith(body.map((str: string) => str.trim()));
|
||||
});
|
||||
});
|
|
@ -0,0 +1 @@
|
|||
// @TODO
|
|
@ -0,0 +1,24 @@
|
|||
export const REQUEST_OPTIONS = {
|
||||
excludeEndpointUrl: false,
|
||||
withCredentials: false,
|
||||
contentType: 'json',
|
||||
priority: 2,
|
||||
retries: 0,
|
||||
};
|
||||
|
||||
export const REQUEST_HEADERS = {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
};
|
||||
|
||||
export const DETAILED_RESPONSE = {
|
||||
requestOptions: REQUEST_OPTIONS,
|
||||
requestHeaders: REQUEST_HEADERS,
|
||||
statusCode: 200,
|
||||
statusText: undefined,
|
||||
headers: {
|
||||
'content-type': 'application/json',
|
||||
},
|
||||
body: '',
|
||||
url: '',
|
||||
};
|
|
@ -1,20 +1,20 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noImplicitReturns": true,
|
||||
"strictNullChecks": true,
|
||||
"noImplicitAny": true,
|
||||
"noImplicitThis": true,
|
||||
"noUnusedLocals": true,
|
||||
"declaration": true,
|
||||
"noResolve": false,
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"outDir": "dist/",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
"noImplicitThis": true,
|
||||
"noUnusedLocals": true,
|
||||
"strictNullChecks": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
"outDir": "dist",
|
||||
},
|
||||
|
||||
"filesGlob": [
|
||||
"src/**/*{ts,tsx}"
|
||||
"include": [
|
||||
"src/**/*"
|
||||
],
|
||||
|
||||
"exclude": [
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"extends": "./tsconfig",
|
||||
"compilerOptions": {
|
||||
"sourceMap": true
|
||||
},
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"test/**/*"
|
||||
]
|
||||
}
|
Загрузка…
Ссылка в новой задаче