fix: Convert TemplateEngine to AsyncHandlers

This commit is contained in:
Wannes Kerckhove
2022-06-30 11:36:19 +02:00
committed by Joachim Van Herwegen
parent a3c7baf6d3
commit cf74ce3d2a
43 changed files with 484 additions and 321 deletions

View File

@@ -4,13 +4,20 @@ import type { TemplateEngine } from '../../../../src/util/templates/TemplateEngi
describe('A ChainedTemplateEngine', (): void => {
const contents = { title: 'myTitle' };
const template = { templateFile: '/template.tmpl' };
const input = { contents, template };
let engines: jest.Mocked<TemplateEngine>[];
let engine: ChainedTemplateEngine;
beforeEach(async(): Promise<void> => {
engines = [
{ render: jest.fn().mockResolvedValue('body1') },
{ render: jest.fn().mockResolvedValue('body2') },
{
canHandle: jest.fn(),
handle: jest.fn().mockResolvedValue('body1'),
} as any,
{
canHandle: jest.fn(),
handleSafe: jest.fn().mockResolvedValue('body2'),
} as any,
];
engine = new ChainedTemplateEngine(engines);
@@ -21,19 +28,19 @@ describe('A ChainedTemplateEngine', (): void => {
});
it('chains the engines.', async(): Promise<void> => {
await expect(engine.render(contents, template)).resolves.toBe('body2');
expect(engines[0].render).toHaveBeenCalledTimes(1);
expect(engines[0].render).toHaveBeenLastCalledWith(contents, template);
expect(engines[1].render).toHaveBeenCalledTimes(1);
expect(engines[1].render).toHaveBeenLastCalledWith({ ...contents, body: 'body1' });
await expect(engine.handleSafe(input)).resolves.toBe('body2');
expect(engines[0].handle).toHaveBeenCalledTimes(1);
expect(engines[0].handle).toHaveBeenLastCalledWith(input);
expect(engines[1].handleSafe).toHaveBeenCalledTimes(1);
expect(engines[1].handleSafe).toHaveBeenLastCalledWith({ contents: { ...contents, body: 'body1' }});
});
it('can use a different field to pass along the body.', async(): Promise<void> => {
engine = new ChainedTemplateEngine(engines, 'different');
await expect(engine.render(contents, template)).resolves.toBe('body2');
expect(engines[0].render).toHaveBeenCalledTimes(1);
expect(engines[0].render).toHaveBeenLastCalledWith(contents, template);
expect(engines[1].render).toHaveBeenCalledTimes(1);
expect(engines[1].render).toHaveBeenLastCalledWith({ ...contents, different: 'body1' });
await expect(engine.handleSafe(input)).resolves.toBe('body2');
expect(engines[0].handle).toHaveBeenCalledTimes(1);
expect(engines[0].handle).toHaveBeenLastCalledWith(input);
expect(engines[1].handleSafe).toHaveBeenCalledTimes(1);
expect(engines[1].handleSafe).toHaveBeenLastCalledWith({ contents: { ...contents, different: 'body1' }});
});
});

View File

@@ -1,24 +1,31 @@
import { NotImplementedHttpError } from '../../../../src/util/errors/NotImplementedHttpError';
import { EjsTemplateEngine } from '../../../../src/util/templates/EjsTemplateEngine';
jest.mock('../../../../src/util/templates/TemplateEngine', (): any => ({
getTemplateFilePath: jest.fn((): string => `filename`),
readTemplate: jest.fn(async({ templateString }): Promise<string> => `${templateString}: <%= detail %>`),
jest.mock('../../../../src/util/templates/TemplateUtil', (): any => ({
getTemplateFilePath: jest.fn((template): string => template),
readTemplate: jest.fn(async(): Promise<string> => `<%= detail %>`),
}));
describe('A EjsTemplateEngine', (): void => {
const defaultTemplate = { templateString: 'xyz' };
const contents = { detail: 'a&b' };
let templateEngine: EjsTemplateEngine;
beforeEach((): void => {
templateEngine = new EjsTemplateEngine('http://localhost:3000', defaultTemplate);
});
it('uses the default template when no template was passed.', async(): Promise<void> => {
await expect(templateEngine.render(contents)).resolves.toBe('xyz: a&amp;b');
templateEngine = new EjsTemplateEngine('http://localhost:3000');
});
it('uses the passed template.', async(): Promise<void> => {
await expect(templateEngine.render(contents, { templateString: 'my' })).resolves.toBe('my: a&amp;b');
await expect(templateEngine.handleSafe({ contents, template: 'someTemplate.ejs' }))
.resolves.toBe('a&amp;b');
});
it('throws an exception for unsupported template files.', async(): Promise<void> => {
await expect(templateEngine.handleSafe({ contents, template: 'someTemplate.txt' }))
.rejects.toThrow(NotImplementedHttpError);
});
it('throws an exception if no template was passed.', async(): Promise<void> => {
await expect(templateEngine.handleSafe({ contents }))
.rejects.toThrow(NotImplementedHttpError);
});
});

View File

@@ -1,23 +1,31 @@
import { NotImplementedHttpError } from '../../../../src';
import { HandlebarsTemplateEngine } from '../../../../src/util/templates/HandlebarsTemplateEngine';
jest.mock('../../../../src/util/templates/TemplateEngine', (): any => ({
readTemplate: jest.fn(async({ templateString }): Promise<string> => `${templateString}: {{detail}}`),
jest.mock('../../../../src/util/templates/TemplateUtil', (): any => ({
getTemplateFilePath: jest.fn((template): string => template),
readTemplate: jest.fn(async(): Promise<string> => `{{detail}}`),
}));
describe('A HandlebarsTemplateEngine', (): void => {
const template = { templateString: 'xyz' };
const contents = { detail: 'a&b' };
let templateEngine: HandlebarsTemplateEngine;
beforeEach((): void => {
templateEngine = new HandlebarsTemplateEngine('http://localhost:3000/', template);
});
it('uses the default template when no template was passed.', async(): Promise<void> => {
await expect(templateEngine.render(contents)).resolves.toBe('xyz: a&amp;b');
templateEngine = new HandlebarsTemplateEngine('http://localhost:3000/');
});
it('uses the passed template.', async(): Promise<void> => {
await expect(templateEngine.render(contents, { templateString: 'my' })).resolves.toBe('my: a&amp;b');
await expect(templateEngine.handleSafe({ contents, template: 'someTemplate.hbs' }))
.resolves.toBe('a&amp;b');
});
it('throws an exception for unsupported template files.', async(): Promise<void> => {
await expect(templateEngine.handleSafe({ contents, template: 'someTemplate.txt' }))
.rejects.toThrow(NotImplementedHttpError);
});
it('throws an exception if no template was passed.', async(): Promise<void> => {
await expect(templateEngine.handleSafe({ contents }))
.rejects.toThrow(NotImplementedHttpError);
});
});

View File

@@ -0,0 +1,47 @@
import { StaticTemplateEngine, NotFoundHttpError } from '../../../../src';
import type { AsyncHandler, TemplateEngineInput } from '../../../../src';
import Dict = NodeJS.Dict;
describe('A StaticTemplateEngine', (): void => {
let templateEngine: jest.Mocked<AsyncHandler<TemplateEngineInput<Dict<any>>, string>>;
it('forwards calls to the handle method of the provided templateEngine, adding the template as an argument.',
async(): Promise<void> => {
templateEngine = {
canHandle: jest.fn(),
handle: jest.fn().mockResolvedValue(''),
} as any;
const input = { contents: {}};
const engine = new StaticTemplateEngine(templateEngine, 'template');
await expect(engine.handleSafe(input)).resolves.toBe('');
expect(templateEngine.canHandle).toHaveBeenCalledTimes(1);
expect(templateEngine.canHandle).toHaveBeenLastCalledWith({ contents: {}, template: 'template' });
expect(templateEngine.handle).toHaveBeenCalledTimes(1);
expect(templateEngine.handle).toHaveBeenLastCalledWith({ contents: {}, template: 'template' });
});
it('propagates errors that occur in the handle method of the provided handler.', async(): Promise<void> => {
templateEngine = {
canHandle: jest.fn(),
handle: jest.fn().mockRejectedValue(new NotFoundHttpError()),
} as any;
const input = { contents: {}};
const engine = new StaticTemplateEngine(templateEngine, 'template');
await expect(engine.handleSafe(input)).rejects.toThrow(NotFoundHttpError);
expect(templateEngine.canHandle).toHaveBeenCalledTimes(1);
expect(templateEngine.canHandle).toHaveBeenLastCalledWith({ contents: input.contents, template: 'template' });
expect(templateEngine.handle).toHaveBeenCalledTimes(1);
expect(templateEngine.handle).toHaveBeenLastCalledWith({ contents: input.contents, template: 'template' });
});
it('results in an error when calling handle with template defined.', async(): Promise<void> => {
templateEngine = {
canHandle: jest.fn(),
handle: jest.fn().mockResolvedValue(''),
} as any;
const input = { contents: {}, template: 'template2' };
const engine = new StaticTemplateEngine(templateEngine, 'template1');
await expect(engine.handleSafe(input)).rejects
.toThrow('StaticTemplateEngine does not support template as handle input');
});
});

View File

@@ -1,10 +1,10 @@
import { resolveAssetPath } from '../../../../src/util/PathUtil';
import { getTemplateFilePath, readTemplate } from '../../../../src/util/templates/TemplateEngine';
import { getTemplateFilePath, readTemplate } from '../../../../src/util/templates/TemplateUtil';
import { mockFileSystem } from '../../../util/Util';
jest.mock('fs');
describe('TemplateEngine', (): void => {
describe('TemplateUtil', (): void => {
describe('#getTemplateFilePath', (): void => {
const templateFile = 'template.xyz';
const templatePath = 'other';