Skip to content

Commit

Permalink
feat: (strf-8740) cover StencilStart.assembleTemplates() with tests
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxGenash committed Oct 13, 2020
1 parent f2e2724 commit 0adf1f8
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 35 deletions.
60 changes: 25 additions & 35 deletions lib/stencil-start.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
require('colors');
const browserSyncInstance = require('browser-sync').create();
const recursiveRead = require('recursive-readdir');
const async = require('async');
const { promisify } = require('util');
const fetchModule = require('node-fetch');
const fsModule = require('fs');
const path = require('path');
Expand Down Expand Up @@ -29,6 +28,7 @@ class StencilStart {
buildConfigManger = buildConfigManagerInstance,
templateAssembler = templateAssemblerModule,
CyclesDetector = Cycles,
logger = console,
} = {}) {
this.browserSync = browserSync;
this.fetch = fetch;
Expand All @@ -39,6 +39,7 @@ class StencilStart {
this.buildConfigManger = buildConfigManger;
this.templateAssembler = templateAssembler;
this.CyclesDetector = CyclesDetector;
this.logger = logger;
}

async run(cliOptions, dotStencilFilePath, stencilCliVersion) {
Expand Down Expand Up @@ -70,7 +71,7 @@ class StencilStart {

await this.startLocalServer(cliOptions, updatedStencilConfig);

console.log(this.getStartUpInfo(updatedStencilConfig, dotStencilFilePath));
this.logger.log(this.getStartUpInfo(updatedStencilConfig, dotStencilFilePath));

await this.startBrowserSync(cliOptions, updatedStencilConfig, browserSyncPort);
}
Expand Down Expand Up @@ -186,7 +187,7 @@ class StencilStart {
const storefrontConfigPath = path.join(themePath, '.config/storefront.json');
this.browserSync.watch(storefrontConfigPath, (event, file) => {
if (event === 'change') {
console.log('storefront.json changed');
this.logger.log('storefront.json changed');
this.browserSync.emitter.emit('storefront_config_file:changed', {
event,
path: file,
Expand All @@ -197,19 +198,13 @@ class StencilStart {
});

const templatesPath = path.join(themePath, 'templates');
this.browserSync.watch(templatesPath, { ignoreInitial: true }, () => {
this.assembleTemplates(templatesPath, (err, results) => {
if (err) {
console.error(err);
return;
}

try {
new this.CyclesDetector(results).detect();
} catch (e) {
console.error(e);
}
});
this.browserSync.watch(templatesPath, { ignoreInitial: true }, async () => {
try {
const results = await this.assembleTemplates(templatesPath);
new this.CyclesDetector(results).detect();
} catch (e) {
this.logger.error(e);
}
});

// tunnel value should be true/false or a string with name
Expand Down Expand Up @@ -256,26 +251,21 @@ class StencilStart {

/**
* Assembles all the needed templates and resolves their partials.
*
* @param {string} templatesPath
* @param {function} callback
* @returns {object[]}
*/
assembleTemplates(templatesPath, callback) {
recursiveRead(templatesPath, ['!*.html'], (err, files) => {
const templateNames = files.map((file) =>
file.replace(templatesPath + path.sep, '').replace('.html', ''),
);

async.map(
templateNames,
this.templateAssembler.assemble.bind(null, templatesPath),
(err2, results) => {
if (err2) {
callback(err2);
}
callback(null, results);
},
);
});
async assembleTemplates(templatesPath) {
const filesPaths = await this.fsUtils.recursiveReadDir(templatesPath, ['!*.html']);
const templateNames = filesPaths.map((file) =>
file.replace(templatesPath + path.sep, '').replace('.html', ''),
);

return Promise.all(
templateNames.map(async (templateName) =>
promisify(this.templateAssembler.assemble)(templatesPath, templateName),
),
);
}

/**
Expand Down
123 changes: 123 additions & 0 deletions lib/stencil-start.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
const fetchMockModule = require('fetch-mock-jest');
const path = require('path');

const StencilStart = require('./stencil-start');

afterAll(() => jest.restoreAllMocks());

describe('StencilStart unit tests', () => {
const getBrowserSyncStub = () => ({
watch: jest.fn(),
init: jest.fn(),
});
const getFetchStub = () => fetchMockModule.sandbox();
const getFsStub = () => ({
existsSync: jest.fn(),
});
const getFsUtilsStub = () => ({
parseJsonFile: jest.fn(),
recursiveReadDir: jest.fn(),
});
const getCliCommonStub = () => ({
checkNodeVersion: jest.fn(),
});
const getThemeConfigManagerStub = () => ({});
const getBuildConfigMangerStub = () => ({});
const getTemplateAssemblerStub = () => ({});
const getCyclesDetectorConstructorStub = () => jest.fn();
const getLoggerStub = () => ({
log: jest.fn(),
error: jest.fn(),
});

const createStencilStartInstance = ({
browserSync,
fetch,
fs,
fsUtils,
cliCommon,
themeConfigManager,
buildConfigManger,
templateAssembler,
CyclesDetector,
logger,
} = {}) => {
const passedArgs = {
browserSync: browserSync || getBrowserSyncStub(),
fetch: fetch || getFetchStub(),
fs: fs || getFsStub(),
fsUtils: fsUtils || getFsUtilsStub(),
cliCommon: cliCommon || getCliCommonStub(),
themeConfigManager: themeConfigManager || getThemeConfigManagerStub(),
buildConfigManger: buildConfigManger || getBuildConfigMangerStub(),
templateAssembler: templateAssembler || getTemplateAssemblerStub(),
CyclesDetector: CyclesDetector || getCyclesDetectorConstructorStub(),
logger: logger || getLoggerStub(),
};
const instance = new StencilStart(passedArgs);

return {
passedArgs,
instance,
};
};

describe('constructor', () => {
it('should create an instance of StencilStart without options parameters passed', async () => {
const instance = new StencilStart();

expect(instance).toBeInstanceOf(StencilStart);
});

it('should create an instance of StencilStart with all options parameters passed', async () => {
const { instance } = createStencilStartInstance();

expect(instance).toBeInstanceOf(StencilStart);
});
});

describe('assembleTemplates method', () => {
it('should obtain names of all templates in the passed templatesPath and return results of call templateAssembler.assemble for each template name', async () => {
const templatesPath = '/some/absolute/templates/path';
const templateNamesMock = ['layout/base', 'pages/page1'];
const filesPathsMock = [
templatesPath + path.sep + templateNamesMock[0] + '.html',
templatesPath + path.sep + templateNamesMock[1] + '.html',
];
const templateAssemblerResults = [
{
[templateNamesMock[0]]: 'html file content 1',
},
{
[templateNamesMock[0]]: 'html file content 1',
[templateNamesMock[1]]: 'html file content 2',
},
];
const fsUtilsStub = {
recursiveReadDir: jest.fn().mockResolvedValue(filesPathsMock),
};
const templateAssemblerStub = {
assemble: jest
.fn()
.mockImplementationOnce((p, n, cb) => cb(null, templateAssemblerResults[0]))
.mockImplementationOnce((p, n, cb) => cb(null, templateAssemblerResults[1])),
};

const { instance } = createStencilStartInstance({
fsUtils: fsUtilsStub,
templateAssembler: templateAssemblerStub,
});
const result = await instance.assembleTemplates(templatesPath);

expect(fsUtilsStub.recursiveReadDir).toHaveBeenCalledTimes(1);
expect(fsUtilsStub.recursiveReadDir).toHaveBeenCalledWith(templatesPath, ['!*.html']);

expect(templateAssemblerStub.assemble.mock.calls).toEqual([
[templatesPath, templateNamesMock[0], expect.any(Function)],
[templatesPath, templateNamesMock[1], expect.any(Function)],
]);

expect(result).toStrictEqual(templateAssemblerResults);
});
});
});

0 comments on commit 0adf1f8

Please sign in to comment.