From e4ab3d3a40b8bafdd4f6cbb11b9d9d3888310830 Mon Sep 17 00:00:00 2001 From: Alexandre Bodin Date: Mon, 6 May 2019 11:54:15 +0200 Subject: [PATCH] Test strapiFS --- .../package.json | 1 + .../services/ContentTypeBuilder.js | 8 +- .../controllers/Documentation.js | 10 +-- .../strapi-plugin-documentation/package.json | 1 + .../strapi/lib/core/__mocks__/fs-extra.js | 4 + packages/strapi/lib/core/__tests__/fs.test.js | 75 +++++++++++++++++++ packages/strapi/lib/core/fs.js | 51 +++++++------ 7 files changed, 117 insertions(+), 33 deletions(-) create mode 100644 packages/strapi/lib/core/__mocks__/fs-extra.js create mode 100644 packages/strapi/lib/core/__tests__/fs.test.js diff --git a/packages/strapi-plugin-content-type-builder/package.json b/packages/strapi-plugin-content-type-builder/package.json index dc3e62f7804..300ec2d23b6 100644 --- a/packages/strapi-plugin-content-type-builder/package.json +++ b/packages/strapi-plugin-content-type-builder/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "classnames": "^2.2.6", + "fs-extra": "^7.0.0", "immutable": "^3.8.2", "invariant": "^2.2.1", "lodash": "^4.17.11", diff --git a/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js b/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js index 93aaa1c5e6c..3cb4177bc95 100644 --- a/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js +++ b/packages/strapi-plugin-content-type-builder/services/ContentTypeBuilder.js @@ -1,7 +1,7 @@ 'use strict'; const path = require('path'); -const fs = require('fs'); +const fs = require('fs-extra'); const _ = require('lodash'); const generator = require('strapi-generate'); const { fromJS, List, Map } = require('immutable'); @@ -268,14 +268,14 @@ module.exports = { const filepath = this.getModelPath(name, { api, plugin }); const content = JSON.stringify(data, null, 2); - strapi.fs.ensureFileSync(filepath); - return strapi.fs.writeFileSync(filepath, content); + fs.ensureFileSync(filepath); + return fs.writeFileSync(filepath, content); }, readModel(name, { api, plugin } = {}) { const filepath = this.getModelPath(name, { api, plugin }); - if (plugin && !strapi.fs.pathExistsSync(filepath)) { + if (plugin && !fs.pathExistsSync(filepath)) { return _.cloneDeep( _.pick(strapi.plugins[plugin].models[name], [ 'collectionName', diff --git a/packages/strapi-plugin-documentation/controllers/Documentation.js b/packages/strapi-plugin-documentation/controllers/Documentation.js index 5f854777508..70951eaf54f 100755 --- a/packages/strapi-plugin-documentation/controllers/Documentation.js +++ b/packages/strapi-plugin-documentation/controllers/Documentation.js @@ -10,7 +10,7 @@ const path = require('path'); // Public dependencies. -const fs = require('fs'); +const fs = require('fs-extra'); const cheerio = require('cheerio'); const _ = require('lodash'); @@ -79,8 +79,8 @@ module.exports = { // Write the layout with the new Swagger configuration. // fs.writeFileSync(layoutPath, $.html()); const layoutPath = path.resolve(strapi.config.appPath, 'extensions', 'documentation', 'public', 'index.html'); - await strapi.fs.ensureFile(layoutPath); - await strapi.fs.writeFile(layoutPath, $.html()); + await fs.ensureFile(layoutPath); + await fs.writeFile(layoutPath, $.html()); // Serve the file. ctx.url = path.basename(`${ctx.url}/index.html`); @@ -114,8 +114,8 @@ module.exports = { try { const layoutPath = path.resolve(strapi.config.appPath, 'extensions', 'documentation', 'public', 'login.html'); - await strapi.fs.ensureFile(layoutPath); - await strapi.fs.writeFile(layoutPath, $.html()); + await fs.ensureFile(layoutPath); + await fs.writeFile(layoutPath, $.html()); ctx.url = path.basename(`${ctx.url}/login.html`); diff --git a/packages/strapi-plugin-documentation/package.json b/packages/strapi-plugin-documentation/package.json index 47c5b4525d0..af202ef0532 100755 --- a/packages/strapi-plugin-documentation/package.json +++ b/packages/strapi-plugin-documentation/package.json @@ -18,6 +18,7 @@ "lodash": "^4.17.11", "moment": "^2.22.2", "path-to-regexp": "^2.4.0", + "fs-extra": "^7.0.0", "react": "^16.0.0", "react-copy-to-clipboard": "^5.0.1", "react-dom": "^16.0.0", diff --git a/packages/strapi/lib/core/__mocks__/fs-extra.js b/packages/strapi/lib/core/__mocks__/fs-extra.js new file mode 100644 index 00000000000..70ce7d75b60 --- /dev/null +++ b/packages/strapi/lib/core/__mocks__/fs-extra.js @@ -0,0 +1,4 @@ +module.exports = { + ensureFile: jest.fn(() => Promise.resolve()), + writeFile: jest.fn(() => Promise.resolve()), +}; diff --git a/packages/strapi/lib/core/__tests__/fs.test.js b/packages/strapi/lib/core/__tests__/fs.test.js new file mode 100644 index 00000000000..55e60298229 --- /dev/null +++ b/packages/strapi/lib/core/__tests__/fs.test.js @@ -0,0 +1,75 @@ +const fs = require('../fs'); +jest.mock('fs-extra'); +const fsExtra = require('fs-extra'); + +describe('Strapi fs utils', () => { + const strapi = { + dir: '/tmp', + }; + + test('Provides new functions', () => { + const strapiFS = fs(strapi); + + expect(strapiFS.writeAppFile).toBeInstanceOf(Function); + expect(strapiFS.writePluginFile).toBeInstanceOf(Function); + }); + + describe('Write App File', () => { + test('Makes sure the path exists and writes', async () => { + const strapiFS = fs(strapi); + + const content = ''; + + await strapiFS.writeAppFile('test', content); + + expect(fsExtra.ensureFile).toHaveBeenCalledWith('/tmp/test'); + expect(fsExtra.writeFile).toHaveBeenCalledWith('/tmp/test', content); + }); + + test('Normalize the path to avoid relative access to folders in parent directories', async () => { + const strapiFS = fs(strapi); + + const content = ''; + + await strapiFS.writeAppFile('../../test', content); + + expect(fsExtra.ensureFile).toHaveBeenCalledWith('/tmp/test'); + expect(fsExtra.writeFile).toHaveBeenCalledWith('/tmp/test', content); + }); + + test('Works with array path', async () => { + const strapiFS = fs(strapi); + + const content = ''; + + await strapiFS.writeAppFile(['test', 'sub', 'path'], content); + + expect(fsExtra.ensureFile).toHaveBeenCalledWith('/tmp/test/sub/path'); + expect(fsExtra.writeFile).toHaveBeenCalledWith( + '/tmp/test/sub/path', + content + ); + }); + }); + + describe('Write Plugin File', () => { + test('Scopes the writes in the extensions folder', async () => { + const strapiFS = fs(strapi); + + const content = ''; + + strapiFS.writeAppFile = jest.fn(() => Promise.resolve()); + + await strapiFS.writePluginFile( + 'users-permissions', + ['test', 'sub', 'path'], + content + ); + + expect(strapiFS.writeAppFile).toHaveBeenCalledWith( + 'extensions/users-permissions/test/sub/path', + content + ); + }); + }); +}); diff --git a/packages/strapi/lib/core/fs.js b/packages/strapi/lib/core/fs.js index 7f963feaa12..331594a110c 100644 --- a/packages/strapi/lib/core/fs.js +++ b/packages/strapi/lib/core/fs.js @@ -1,3 +1,5 @@ +'use strict'; + const path = require('path'); const fs = require('fs-extra'); @@ -5,34 +7,35 @@ const fs = require('fs-extra'); * create strapi fs layer */ module.exports = strapi => { - /** - * Writes a file in a strapi app - * @param {Array|string} optPath - file path - * @param {string} data - content - */ - const writeAppFile = (optPath, data) => { - const filePath = Array.isArray(optPath) ? optPath.join('/') : optPath; + const strapiFS = { + /** + * Writes a file in a strapi app + * @param {Array|string} optPath - file path + * @param {string} data - content + */ + writeAppFile(optPath, data) { + const filePath = Array.isArray(optPath) ? optPath.join('/') : optPath; - const normalizedPath = path.normalize(filePath).replace(/^(\/?\.\.?)+/, ''); + const normalizedPath = path + .normalize(filePath) + .replace(/^(\/?\.\.?)+/, ''); - const writePath = path.join(strapi.config.appPath, normalizedPath); + const writePath = path.join(strapi.dir, normalizedPath); - return fs.ensureFile(writePath).then(() => fs.writeFile(writePath, data)); - }; + return fs.ensureFile(writePath).then(() => fs.writeFile(writePath, data)); + }, - /** - * Writes a file in a plugin extensions folder - * @param {string} plugin - plugin name - * @param {Array|string} optPath - path to file - * @param {string} data - content - */ - const writePluginFile = (plugin, optPath, data) => { - const newPath = ['extensions', plugin].concat(optPath).join('/'); - return writeAppFile(newPath, data); + /** + * Writes a file in a plugin extensions folder + * @param {string} plugin - plugin name + * @param {Array|string} optPath - path to file + * @param {string} data - content + */ + writePluginFile(plugin, optPath, data) { + const newPath = ['extensions', plugin].concat(optPath).join('/'); + return strapiFS.writeAppFile(newPath, data); + }, }; - return Object.assign(fs, { - writeAppFile, - writePluginFile, - }); + return strapiFS; };