Add custom routes to pages router (#7231)
* added custom routes * fixed docs typos * added page.customRoutes config validation * added 404 response if missing custom route response * added docs * minor README formatting * added CHANGELOG entry * fixed bug in definitions builder that did not recognize array of custom type * added missing route handler definition * fixed custom routes definition
This commit is contained in:
@@ -252,6 +252,9 @@ describe('Pages Router', () => {
|
||||
expect(Config.get(Parse.applicationId).pages.customUrls).toBe(
|
||||
Definitions.PagesOptions.customUrls.default
|
||||
);
|
||||
expect(Config.get(Parse.applicationId).pages.customRoutes).toBe(
|
||||
Definitions.PagesOptions.customRoutes.default
|
||||
);
|
||||
});
|
||||
|
||||
it('throws on invalid configuration', async () => {
|
||||
@@ -296,6 +299,10 @@ describe('Pages Router', () => {
|
||||
{ localizationFallbackLocale: 0 },
|
||||
{ localizationFallbackLocale: {} },
|
||||
{ localizationFallbackLocale: [] },
|
||||
{ customRoutes: true },
|
||||
{ customRoutes: 0 },
|
||||
{ customRoutes: 'a' },
|
||||
{ customRoutes: {} },
|
||||
];
|
||||
for (const option of options) {
|
||||
await expectAsync(reconfigureServerWithPagesConfig(option)).toBeRejected();
|
||||
@@ -972,6 +979,153 @@ describe('Pages Router', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('custom route', () => {
|
||||
it('handles custom route with GET', async () => {
|
||||
config.pages.customRoutes = [
|
||||
{
|
||||
method: 'GET',
|
||||
path: 'custom_page',
|
||||
handler: async req => {
|
||||
expect(req).toBeDefined();
|
||||
expect(req.method).toBe('GET');
|
||||
return { file: 'custom_page.html' };
|
||||
},
|
||||
},
|
||||
];
|
||||
await reconfigureServer(config);
|
||||
const handlerSpy = spyOn(config.pages.customRoutes[0], 'handler').and.callThrough();
|
||||
|
||||
const url = `${config.publicServerURL}/apps/${config.appId}/custom_page`;
|
||||
const response = await request({
|
||||
url: url,
|
||||
followRedirects: false,
|
||||
}).catch(e => e);
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.text).toMatch(config.appName);
|
||||
expect(handlerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('handles custom route with POST', async () => {
|
||||
config.pages.customRoutes = [
|
||||
{
|
||||
method: 'POST',
|
||||
path: 'custom_page',
|
||||
handler: async req => {
|
||||
expect(req).toBeDefined();
|
||||
expect(req.method).toBe('POST');
|
||||
return { file: 'custom_page.html' };
|
||||
},
|
||||
},
|
||||
];
|
||||
const handlerSpy = spyOn(config.pages.customRoutes[0], 'handler').and.callThrough();
|
||||
await reconfigureServer(config);
|
||||
|
||||
const url = `${config.publicServerURL}/apps/${config.appId}/custom_page`;
|
||||
const response = await request({
|
||||
url: url,
|
||||
followRedirects: false,
|
||||
method: 'POST',
|
||||
}).catch(e => e);
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.text).toMatch(config.appName);
|
||||
expect(handlerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('handles multiple custom routes', async () => {
|
||||
config.pages.customRoutes = [
|
||||
{
|
||||
method: 'GET',
|
||||
path: 'custom_page',
|
||||
handler: async req => {
|
||||
expect(req).toBeDefined();
|
||||
expect(req.method).toBe('GET');
|
||||
return { file: 'custom_page.html' };
|
||||
},
|
||||
},
|
||||
{
|
||||
method: 'POST',
|
||||
path: 'custom_page',
|
||||
handler: async req => {
|
||||
expect(req).toBeDefined();
|
||||
expect(req.method).toBe('POST');
|
||||
return { file: 'custom_page.html' };
|
||||
},
|
||||
},
|
||||
];
|
||||
const getHandlerSpy = spyOn(config.pages.customRoutes[0], 'handler').and.callThrough();
|
||||
const postHandlerSpy = spyOn(config.pages.customRoutes[1], 'handler').and.callThrough();
|
||||
await reconfigureServer(config);
|
||||
|
||||
const url = `${config.publicServerURL}/apps/${config.appId}/custom_page`;
|
||||
const getResponse = await request({
|
||||
url: url,
|
||||
followRedirects: false,
|
||||
method: 'GET',
|
||||
}).catch(e => e);
|
||||
expect(getResponse.status).toBe(200);
|
||||
expect(getResponse.text).toMatch(config.appName);
|
||||
expect(getHandlerSpy).toHaveBeenCalled();
|
||||
|
||||
const postResponse = await request({
|
||||
url: url,
|
||||
followRedirects: false,
|
||||
method: 'POST',
|
||||
}).catch(e => e);
|
||||
expect(postResponse.status).toBe(200);
|
||||
expect(postResponse.text).toMatch(config.appName);
|
||||
expect(postHandlerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('handles custom route with async handler', async () => {
|
||||
config.pages.customRoutes = [
|
||||
{
|
||||
method: 'GET',
|
||||
path: 'custom_page',
|
||||
handler: async req => {
|
||||
expect(req).toBeDefined();
|
||||
expect(req.method).toBe('GET');
|
||||
const file = await new Promise(resolve =>
|
||||
setTimeout(resolve('custom_page.html'), 1000)
|
||||
);
|
||||
return { file };
|
||||
},
|
||||
},
|
||||
];
|
||||
await reconfigureServer(config);
|
||||
const handlerSpy = spyOn(config.pages.customRoutes[0], 'handler').and.callThrough();
|
||||
|
||||
const url = `${config.publicServerURL}/apps/${config.appId}/custom_page`;
|
||||
const response = await request({
|
||||
url: url,
|
||||
followRedirects: false,
|
||||
}).catch(e => e);
|
||||
expect(response.status).toBe(200);
|
||||
expect(response.text).toMatch(config.appName);
|
||||
expect(handlerSpy).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('returns 404 if custom route does not return page', async () => {
|
||||
config.pages.customRoutes = [
|
||||
{
|
||||
method: 'GET',
|
||||
path: 'custom_page',
|
||||
handler: async () => {},
|
||||
},
|
||||
];
|
||||
await reconfigureServer(config);
|
||||
const handlerSpy = spyOn(config.pages.customRoutes[0], 'handler').and.callThrough();
|
||||
|
||||
const url = `${config.publicServerURL}/apps/${config.appId}/custom_page`;
|
||||
const response = await request({
|
||||
url: url,
|
||||
followRedirects: false,
|
||||
}).catch(e => e);
|
||||
expect(response.status).toBe(404);
|
||||
expect(response.text).toMatch('Not found');
|
||||
expect(handlerSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('custom endpoint', () => {
|
||||
it('password reset works with custom endpoint', async () => {
|
||||
config.pages.pagesEndpoint = 'customEndpoint';
|
||||
|
||||
Reference in New Issue
Block a user