- Updated test cases

- Fixed capture of error body in Angular
This commit is contained in:
Ferdi Koomen 2022-01-28 10:32:50 +01:00
parent 8915770ad9
commit 16cc25bf1e
19 changed files with 460 additions and 326 deletions

View File

@ -2,7 +2,7 @@
import { HttpClient, HttpHeaders } from '@angular/common/http';
import type { HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { catchError, forkJoin, map, mergeMap, of, throwError } from 'rxjs';
import { catchError, forkJoin, map, switchMap, of, throwError } from 'rxjs';
import type { Observable } from 'rxjs';
import { ApiError } from './ApiError';
@ -72,7 +72,7 @@ export const request = <T>(config: OpenAPIConfig, http: HttpClient, options: Api
const body = getRequestBody(options);
return getHeaders(config, options).pipe(
mergeMap(headers => {
switchMap(headers => {
return sendRequest<T>(config, options, http, url, formData, body, headers);
}),
map(response => {
@ -88,14 +88,14 @@ export const request = <T>(config: OpenAPIConfig, http: HttpClient, options: Api
}),
catchError((error: HttpErrorResponse) => {
if (!error.status) {
return throwError(() => error);
return throwError(error);
}
return of({
url,
ok: error.ok,
status: error.status,
statusText: error.statusText,
body: error.statusText,
body: error.error ?? error.statusText,
} as ApiResult);
}),
map(result => {
@ -103,7 +103,7 @@ export const request = <T>(config: OpenAPIConfig, http: HttpClient, options: Api
return result.body as T;
}),
catchError((error: ApiError) => {
return throwError(() => error);
return throwError(error);
}),
);
};

View File

@ -3,7 +3,7 @@ import { compileWithTypescript } from './scripts/compileWithTypescript';
import { generateClient } from './scripts/generateClient';
import server from './scripts/server';
describe('v3.node', () => {
describe('client.node', () => {
beforeAll(async () => {
cleanup('client/axios');
await generateClient('client/axios', 'v3', 'axios', false, false, 'AppClient');
@ -83,4 +83,68 @@ describe('v3.node', () => {
}
expect(error).toContain('Request aborted');
});
it('should throw known error (500)', async () => {
let error;
try {
const { AppClient } = require('./generated/client/axios/index.js');
const client = new AppClient();
await client.error.testErrorCode(500);
} catch (e) {
const err = e as any;
error = JSON.stringify({
name: err.name,
message: err.message,
url: err.url,
status: err.status,
statusText: err.statusText,
body: err.body,
});
}
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Custom message: Internal Server Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
status: 500,
statusText: 'Internal Server Error',
body: {
status: 500,
message: 'hello world',
},
})
);
});
it('should throw unknown error (409)', async () => {
let error;
try {
const { AppClient } = require('./generated/client/axios/index.js');
const client = new AppClient();
await client.error.testErrorCode(409);
} catch (e) {
const err = e as any;
error = JSON.stringify({
name: err.name,
message: err.message,
url: err.url,
status: err.status,
statusText: err.statusText,
body: err.body,
});
}
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Generic Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
status: 409,
statusText: 'Conflict',
body: {
status: 409,
message: 'hello world',
},
})
);
});
});

View File

@ -5,7 +5,7 @@ import { copyAsset } from './scripts/copyAsset';
import { generateClient } from './scripts/generateClient';
import server from './scripts/server';
describe('v3.babel', () => {
describe('client.babel', () => {
beforeAll(async () => {
cleanup('client/babel');
await generateClient('client/babel', 'v3', 'fetch', true, true, 'AppClient');
@ -53,13 +53,123 @@ describe('v3.babel', () => {
const { AppClient } = (window as any).api;
const client = new AppClient();
return await client.complex.complexTypes({
first: {
second: {
third: 'Hello World!',
parameterObject: {
first: {
second: {
third: 'Hello World!',
},
},
},
});
});
expect(result).toBeDefined();
});
it('support form data', async () => {
const result = await browser.evaluate(async () => {
const { AppClient } = (window as any).api;
const client = new AppClient();
return await client.parameters.callWithParameters({
parameterHeader: 'valueHeader',
parameterQuery: 'valueQuery',
parameterForm: 'valueForm',
parameterCookie: 'valueCookie',
parameterPath: 'valuePath',
requestBody: {
prop: 'valueBody',
},
});
});
expect(result).toBeDefined();
});
it('can abort the request', async () => {
let error;
try {
await browser.evaluate(async () => {
const { AppClient } = (window as any).api;
const client = new AppClient();
const promise = client.simple.getCallWithoutParametersAndResponse();
setTimeout(() => {
promise.cancel();
}, 10);
await promise;
});
} catch (e) {
error = (e as Error).message;
}
expect(error).toContain('CancelError: Request aborted');
});
it('should throw known error (500)', async () => {
const error = await browser.evaluate(async () => {
try {
const { AppClient } = (window as any).api;
const client = new AppClient();
await client.error.testErrorCode({
status: 500,
});
} catch (e) {
const error = e as any;
return JSON.stringify({
name: error.name,
message: error.message,
url: error.url,
status: error.status,
statusText: error.statusText,
body: error.body,
});
}
return;
});
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Custom message: Internal Server Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
status: 500,
statusText: 'Internal Server Error',
body: {
status: 500,
message: 'hello world',
},
})
);
});
it('should throw unknown error (409)', async () => {
const error = await browser.evaluate(async () => {
try {
const { AppClient } = (window as any).api;
const client = new AppClient();
await client.error.testErrorCode({
status: 409,
});
} catch (e) {
const error = e as any;
return JSON.stringify({
name: error.name,
message: error.message,
url: error.url,
status: error.status,
statusText: error.statusText,
body: error.body,
});
}
return;
});
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Generic Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
status: 409,
statusText: 'Conflict',
body: {
status: 409,
message: 'hello world',
},
})
);
});
});

View File

@ -5,7 +5,7 @@ import { copyAsset } from './scripts/copyAsset';
import { generateClient } from './scripts/generateClient';
import server from './scripts/server';
describe('v3.fetch', () => {
describe('client.fetch', () => {
beforeAll(async () => {
cleanup('client/fetch');
await generateClient('client/fetch', 'v3', 'fetch', false, false, 'AppClient');
@ -126,7 +126,10 @@ describe('v3.fetch', () => {
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
status: 500,
statusText: 'Internal Server Error',
body: 'Internal Server Error',
body: {
status: 500,
message: 'hello world',
},
})
);
});
@ -157,7 +160,10 @@ describe('v3.fetch', () => {
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
status: 409,
statusText: 'Conflict',
body: 'Conflict',
body: {
status: 409,
message: 'hello world',
},
})
);
});

View File

@ -3,7 +3,7 @@ import { compileWithTypescript } from './scripts/compileWithTypescript';
import { generateClient } from './scripts/generateClient';
import server from './scripts/server';
describe('v3.node', () => {
describe('client.node', () => {
beforeAll(async () => {
cleanup('client/node');
await generateClient('client/node', 'v3', 'node', false, false, 'AppClient');
@ -108,7 +108,10 @@ describe('v3.node', () => {
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
status: 500,
statusText: 'Internal Server Error',
body: 'Internal Server Error',
body: {
status: 500,
message: 'hello world',
},
})
);
});
@ -137,7 +140,10 @@ describe('v3.node', () => {
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
status: 409,
statusText: 'Conflict',
body: 'Conflict',
body: {
status: 409,
message: 'hello world',
},
})
);
});

View File

@ -5,7 +5,7 @@ import { copyAsset } from './scripts/copyAsset';
import { generateClient } from './scripts/generateClient';
import server from './scripts/server';
describe('v3.xhr', () => {
describe('client.xhr', () => {
beforeAll(async () => {
cleanup('client/xhr');
await generateClient('client/xhr', 'v3', 'xhr', false, false, 'AppClient');
@ -63,6 +63,24 @@ describe('v3.xhr', () => {
expect(result).toBeDefined();
});
it('support form data', async () => {
const result = await browser.evaluate(async () => {
const { AppClient } = (window as any).api;
const client = new AppClient();
return await client.parameters.callWithParameters(
'valueHeader',
'valueQuery',
'valueForm',
'valueCookie',
'valuePath',
{
prop: 'valueBody',
}
);
});
expect(result).toBeDefined();
});
it('can abort the request', async () => {
let error;
try {
@ -107,7 +125,10 @@ describe('v3.xhr', () => {
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
status: 500,
statusText: 'Internal Server Error',
body: 'Internal Server Error',
body: {
status: 500,
message: 'hello world',
},
})
);
});
@ -138,7 +159,10 @@ describe('v3.xhr', () => {
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
status: 409,
statusText: 'Conflict',
body: 'Conflict',
body: {
status: 409,
message: 'hello world',
},
})
);
});

View File

@ -56,7 +56,10 @@ const start = async (dir: string) => {
// See the spec files for more information.
_app.all('/base/api/v1.0/error', (req, res) => {
const status = parseInt(String(req.query.status));
res.sendStatus(status);
res.status(status).json({
status,
message: 'hello world',
});
});
// Register an 'echo' server that just returns all data from the API calls.

View File

@ -51,68 +51,4 @@ describe('v2.angular', () => {
});
expect(result).toBeDefined();
});
it('should throw known error (500)', async () => {
const error = await browser.evaluate(async () => {
try {
await new Promise<any>((resolve, reject) => {
const { ErrorService } = (window as any).api;
ErrorService.testErrorCode(500).subscribe(resolve, reject);
});
} catch (e) {
const error = e as any;
return JSON.stringify({
name: error.name,
message: error.message,
url: error.url,
status: error.status,
statusText: error.statusText,
body: error.body,
});
}
return;
});
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Custom message: Internal Server Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
status: 500,
statusText: 'Internal Server Error',
body: 'Internal Server Error',
})
);
});
it('should throw unknown error (409)', async () => {
const error = await browser.evaluate(async () => {
try {
await new Promise<any>((resolve, reject) => {
const { ErrorService } = (window as any).api;
ErrorService.testErrorCode(409).subscribe(resolve, reject);
});
} catch (e) {
const error = e as any;
return JSON.stringify({
name: error.name,
message: error.message,
url: error.url,
status: error.status,
statusText: error.statusText,
body: error.body,
});
}
return;
});
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Generic Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
status: 409,
statusText: 'Conflict',
body: 'Conflict',
})
);
});
});

View File

@ -35,19 +35,4 @@ describe('v2.node', () => {
});
expect(result).toBeDefined();
});
it('can abort the request', async () => {
let error;
try {
const { SimpleService } = require('./generated/v2/axios/index.js');
const promise = SimpleService.getCallWithoutParametersAndResponse();
setTimeout(() => {
promise.cancel();
}, 10);
await promise;
} catch (e) {
error = (e as Error).message;
}
expect(error).toContain('Request aborted');
});
});

View File

@ -35,9 +35,11 @@ describe('v2.babel', () => {
const result = await browser.evaluate(async () => {
const { ComplexService } = (window as any).api;
return await ComplexService.complexTypes({
first: {
second: {
third: 'Hello World!',
parameterObject: {
first: {
second: {
third: 'Hello World!',
},
},
},
});

View File

@ -44,82 +44,4 @@ describe('v2.fetch', () => {
});
expect(result).toBeDefined();
});
it('can abort the request', async () => {
let error;
try {
await browser.evaluate(async () => {
const { SimpleService } = (window as any).api;
const promise = SimpleService.getCallWithoutParametersAndResponse();
setTimeout(() => {
promise.cancel();
}, 10);
await promise;
});
} catch (e) {
error = (e as Error).message;
}
expect(error).toContain('CancelError: Request aborted');
});
it('should throw known error (500)', async () => {
const error = await browser.evaluate(async () => {
try {
const { ErrorService } = (window as any).api;
await ErrorService.testErrorCode(500);
} catch (e) {
const error = e as any;
return JSON.stringify({
name: error.name,
message: error.message,
url: error.url,
status: error.status,
statusText: error.statusText,
body: error.body,
});
}
return;
});
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Custom message: Internal Server Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
status: 500,
statusText: 'Internal Server Error',
body: 'Internal Server Error',
})
);
});
it('should throw unknown error (409)', async () => {
const error = await browser.evaluate(async () => {
try {
const { ErrorService } = (window as any).api;
await ErrorService.testErrorCode(409);
} catch (e) {
const error = e as any;
return JSON.stringify({
name: error.name,
message: error.message,
url: error.url,
status: error.status,
statusText: error.statusText,
body: error.body,
});
}
return;
});
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Generic Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
status: 409,
statusText: 'Conflict',
body: 'Conflict',
})
);
});
});

View File

@ -50,60 +50,4 @@ describe('v2.node', () => {
}
expect(error).toContain('Request aborted');
});
it('should throw known error (500)', async () => {
let error;
try {
const { ErrorService } = require('./generated/v2/node/index.js');
await ErrorService.testErrorCode(500);
} catch (e) {
const err = e as any;
error = JSON.stringify({
name: err.name,
message: err.message,
url: err.url,
status: err.status,
statusText: err.statusText,
body: err.body,
});
}
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Custom message: Internal Server Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
status: 500,
statusText: 'Internal Server Error',
body: 'Internal Server Error',
})
);
});
it('should throw unknown error (409)', async () => {
let error;
try {
const { ErrorService } = require('./generated/v2/node/index.js');
await ErrorService.testErrorCode(409);
} catch (e) {
const err = e as any;
error = JSON.stringify({
name: err.name,
message: err.message,
url: err.url,
status: err.status,
statusText: err.statusText,
body: err.body,
});
}
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Generic Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
status: 409,
statusText: 'Conflict',
body: 'Conflict',
})
);
});
});

View File

@ -44,82 +44,4 @@ describe('v2.xhr', () => {
});
expect(result).toBeDefined();
});
it('can abort the request', async () => {
let error;
try {
await browser.evaluate(async () => {
const { SimpleService } = (window as any).api;
const promise = SimpleService.getCallWithoutParametersAndResponse();
setTimeout(() => {
promise.cancel();
}, 10);
await promise;
});
} catch (e) {
error = (e as Error).message;
}
expect(error).toContain('CancelError: Request aborted');
});
it('should throw known error (500)', async () => {
const error = await browser.evaluate(async () => {
try {
const { ErrorService } = (window as any).api;
await ErrorService.testErrorCode(500);
} catch (e) {
const error = e as any;
return JSON.stringify({
name: error.name,
message: error.message,
url: error.url,
status: error.status,
statusText: error.statusText,
body: error.body,
});
}
return;
});
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Custom message: Internal Server Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
status: 500,
statusText: 'Internal Server Error',
body: 'Internal Server Error',
})
);
});
it('should throw unknown error (409)', async () => {
const error = await browser.evaluate(async () => {
try {
const { ErrorService } = (window as any).api;
await ErrorService.testErrorCode(409);
} catch (e) {
const error = e as any;
return JSON.stringify({
name: error.name,
message: error.message,
url: error.url,
status: error.status,
statusText: error.statusText,
body: error.body,
});
}
return;
});
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Generic Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
status: 409,
statusText: 'Conflict',
body: 'Conflict',
})
);
});
});

View File

@ -111,7 +111,10 @@ describe('v3.angular', () => {
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
status: 500,
statusText: 'Internal Server Error',
body: 'Internal Server Error',
body: {
status: 500,
message: 'hello world',
},
})
);
});
@ -145,7 +148,10 @@ describe('v3.angular', () => {
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
status: 409,
statusText: 'Conflict',
body: 'Conflict',
body: {
status: 409,
message: 'hello world',
},
})
);
});

View File

@ -3,7 +3,7 @@ import { compileWithTypescript } from './scripts/compileWithTypescript';
import { generateClient } from './scripts/generateClient';
import server from './scripts/server';
describe('v3.node', () => {
describe('v3.axios', () => {
beforeAll(async () => {
cleanup('v3/axios');
await generateClient('v3/axios', 'v3', 'axios');
@ -76,4 +76,66 @@ describe('v3.node', () => {
}
expect(error).toContain('Request aborted');
});
it('should throw known error (500)', async () => {
let error;
try {
const { ErrorService } = require('./generated/v3/axios/index.js');
await ErrorService.testErrorCode(500);
} catch (e) {
const err = e as any;
error = JSON.stringify({
name: err.name,
message: err.message,
url: err.url,
status: err.status,
statusText: err.statusText,
body: err.body,
});
}
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Custom message: Internal Server Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
status: 500,
statusText: 'Internal Server Error',
body: {
status: 500,
message: 'hello world',
},
})
);
});
it('should throw unknown error (409)', async () => {
let error;
try {
const { ErrorService } = require('./generated/v3/axios/index.js');
await ErrorService.testErrorCode(409);
} catch (e) {
const err = e as any;
error = JSON.stringify({
name: err.name,
message: err.message,
url: err.url,
status: err.status,
statusText: err.statusText,
body: err.body,
});
}
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Generic Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
status: 409,
statusText: 'Conflict',
body: {
status: 409,
message: 'hello world',
},
})
);
});
});

View File

@ -48,13 +48,120 @@ describe('v3.babel', () => {
const result = await browser.evaluate(async () => {
const { ComplexService } = (window as any).api;
return await ComplexService.complexTypes({
first: {
second: {
third: 'Hello World!',
parameterObject: {
first: {
second: {
third: 'Hello World!',
},
},
},
});
});
expect(result).toBeDefined();
});
it('support form data', async () => {
const result = await browser.evaluate(async () => {
const { ParametersService } = (window as any).api;
return await ParametersService.callWithParameters({
parameterHeader: 'valueHeader',
parameterQuery: 'valueQuery',
parameterForm: 'valueForm',
parameterCookie: 'valueCookie',
parameterPath: 'valuePath',
requestBody: {
prop: 'valueBody',
},
});
});
expect(result).toBeDefined();
});
it('can abort the request', async () => {
let error;
try {
await browser.evaluate(async () => {
const { SimpleService } = (window as any).api;
const promise = SimpleService.getCallWithoutParametersAndResponse();
setTimeout(() => {
promise.cancel();
}, 10);
await promise;
});
} catch (e) {
error = (e as Error).message;
}
expect(error).toContain('CancelError: Request aborted');
});
it('should throw known error (500)', async () => {
const error = await browser.evaluate(async () => {
try {
const { ErrorService } = (window as any).api;
await ErrorService.testErrorCode({
status: 500,
});
} catch (e) {
const error = e as any;
return JSON.stringify({
name: error.name,
message: error.message,
url: error.url,
status: error.status,
statusText: error.statusText,
body: error.body,
});
}
return;
});
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Custom message: Internal Server Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
status: 500,
statusText: 'Internal Server Error',
body: {
status: 500,
message: 'hello world',
},
})
);
});
it('should throw unknown error (409)', async () => {
const error = await browser.evaluate(async () => {
try {
const { ErrorService } = (window as any).api;
await ErrorService.testErrorCode({
status: 409,
});
} catch (e) {
const error = e as any;
return JSON.stringify({
name: error.name,
message: error.message,
url: error.url,
status: error.status,
statusText: error.statusText,
body: error.body,
});
}
return;
});
expect(error).toBe(
JSON.stringify({
name: 'ApiError',
message: 'Generic Error',
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
status: 409,
statusText: 'Conflict',
body: {
status: 409,
message: 'hello world',
},
})
);
});
});

View File

@ -118,7 +118,10 @@ describe('v3.fetch', () => {
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
status: 500,
statusText: 'Internal Server Error',
body: 'Internal Server Error',
body: {
status: 500,
message: 'hello world',
},
})
);
});
@ -148,7 +151,10 @@ describe('v3.fetch', () => {
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
status: 409,
statusText: 'Conflict',
body: 'Conflict',
body: {
status: 409,
message: 'hello world',
},
})
);
});

View File

@ -100,7 +100,10 @@ describe('v3.node', () => {
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
status: 500,
statusText: 'Internal Server Error',
body: 'Internal Server Error',
body: {
status: 500,
message: 'hello world',
},
})
);
});
@ -128,7 +131,10 @@ describe('v3.node', () => {
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
status: 409,
statusText: 'Conflict',
body: 'Conflict',
body: {
status: 409,
message: 'hello world',
},
})
);
});

View File

@ -58,6 +58,23 @@ describe('v3.xhr', () => {
expect(result).toBeDefined();
});
it('support form data', async () => {
const result = await browser.evaluate(async () => {
const { ParametersService } = (window as any).api;
return await ParametersService.callWithParameters(
'valueHeader',
'valueQuery',
'valueForm',
'valueCookie',
'valuePath',
{
prop: 'valueBody',
}
);
});
expect(result).toBeDefined();
});
it('can abort the request', async () => {
let error;
try {
@ -100,7 +117,10 @@ describe('v3.xhr', () => {
url: 'http://localhost:3000/base/api/v1.0/error?status=500',
status: 500,
statusText: 'Internal Server Error',
body: 'Internal Server Error',
body: {
status: 500,
message: 'hello world',
},
})
);
});
@ -130,7 +150,10 @@ describe('v3.xhr', () => {
url: 'http://localhost:3000/base/api/v1.0/error?status=409',
status: 409,
statusText: 'Conflict',
body: 'Conflict',
body: {
status: 409,
message: 'hello world',
},
})
);
});