From 7e6800b2b88d20942b0a3058a3d16cbab5f9bca7 Mon Sep 17 00:00:00 2001 From: Hannah Wolfe Date: Mon, 5 Jul 2021 20:02:22 +0100 Subject: [PATCH] Improved dev tooling (#13118) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit achieves a few things: - ☑️ No longer having to remember whether a command is yarn something or grunt something - ☑️ Simplification of tools hopefully making them easier to remember and use - ☑️ Complete removal of the need for grunt from our test tooling Several of the tools still use grunt under the hood, but the **entrypoint** should aways be `yarn xxx`. - `grunt main` -> `yarn main` - `grunt dev` -> `yarn dev` - `grunt build` -> `yarn build` - `grunt test:file-or-folder` -> `yarn test file-or-folder` - `grunt test-unit` -> `yarn test:unit` - `grunt test-acceptance` -> `yarn test:acceptance` - `grunt test-regression` -> `yarn test:regression` - `grunt validate` -> removed due to lack of use There is now also `yarn test:all` to run all 3 classes of tests This PR also reorders & restructures the Gruntfile extensively so that: - The remaining useful commands are all at the top of the file - Config and other blah happens after all the useful commands - All release-only config happens in the release task at the very end of the file --- DONE: * Removed all references to npm/bower * Removed all references to lint / deprecated command * Moved debug to yarn dev:debug * Removed all references to travis * Removed broken help task + useless comment * Removed unused knex-migrator and clean:test setup tasks * Added new test commands, removed grunt validate * Moved stubClientFiles to test utility and use in the few tests that need it * Used mocha in yarn directly except grunt test:x * Swapped grunt test for yarn test * extensive cleanup and reshuffling --- .github/workflows/test.yml | 6 +- Gruntfile.js | 486 +++++------------- package.json | 15 +- test/regression/api/admin_spec.js | 3 + .../regression/site/parent_app_vhosts_spec.js | 2 + test/utils/acceptance-utils.js | 2 - test/utils/admin-utils.js | 17 + test/utils/overrides.js | 3 + 8 files changed, 156 insertions(+), 378 deletions(-) create mode 100644 test/utils/admin-utils.js create mode 100644 test/utils/overrides.js diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index d47b865e30..c65fb7fb11 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -104,11 +104,11 @@ jobs: mysql root password: 'root' - run: yarn - - run: grunt test-acceptance --verbose + - run: yarn test:acceptance env: database__connection__filename: /dev/shm/ghost-test.db - - run: grunt test-unit --verbose - - run: grunt test-regression --verbose + - run: yarn test:unit + - run: yarn test:regression env: database__connection__filename: /dev/shm/ghost-test.db diff --git a/Gruntfile.js b/Gruntfile.js index 396093dd15..ddfa4c4123 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,24 +1,8 @@ -// # Task automation for Ghost -// -// Run various tasks when developing for and working with Ghost. -// -// **Usage instructions:** can be found in the [Custom Tasks](#custom%20tasks) section or by running `grunt --help`. -// -// **Debug tip:** If you have any problems with any Grunt tasks, try running them with the `--verbose` command const config = require('./core/shared/config'); -const _ = require('lodash'); const fs = require('fs-extra'); -const KnexMigrator = require('knex-migrator'); -const knexMigrator = new KnexMigrator({ - knexMigratorFilePath: config.get('paths:appRoot') -}); - const path = require('path'); -const escapeChar = process.platform.match(/^win/) ? '^' : '\\'; -const cwd = process.cwd().replace(/( |\(|\))/g, escapeChar + '$1'); -const buildDirectory = path.resolve(cwd, '.build'); -const distDirectory = path.resolve(cwd, '.dist'); +// Utility for outputting messages indicating that the admin is building, as it can take a while. let hasBuiltClient = false; const logBuildingClient = function (grunt) { if (!hasBuiltClient) { @@ -27,56 +11,53 @@ const logBuildingClient = function (grunt) { } }; -// ## Grunt configuration -const configureGrunt = function (grunt) { - // #### Load all grunt tasks - grunt.loadNpmTasks('@lodder/grunt-postcss'); - grunt.loadNpmTasks('grunt-bg-shell'); - grunt.loadNpmTasks('grunt-contrib-clean'); - grunt.loadNpmTasks('grunt-contrib-compress'); - grunt.loadNpmTasks('grunt-contrib-copy'); - grunt.loadNpmTasks('grunt-contrib-symlink'); - grunt.loadNpmTasks('grunt-contrib-watch'); - grunt.loadNpmTasks('grunt-express-server'); - grunt.loadNpmTasks('grunt-mocha-cli'); - grunt.loadNpmTasks('grunt-shell'); - grunt.loadNpmTasks('grunt-subgrunt'); - grunt.loadNpmTasks('grunt-update-submodules'); +module.exports = function (grunt) { + // grunt dev - use yarn dev instead! + // - Start a server & build assets on the fly whilst developing + grunt.registerTask('dev', 'Dev Mode; watch files and restart server on changes', function () { + if (grunt.option('client')) { + grunt.task.run(['clean:built', 'bgShell:client']); + } else if (grunt.option('server')) { + grunt.task.run(['express:dev', 'watch']); + } else { + grunt.task.run(['clean:built', 'bgShell:client', 'express:dev', 'watch']); + } + }); - /** This little bit of weirdness gives the express server chance to shutdown properly */ - const waitBeforeExit = () => { - setTimeout(() => { - process.exit(0); - }, 1000); - }; + // grunt build -- use yarn build instead! + // - Builds the client without a watch task + grunt.registerTask('build', 'Build client app in development mode', + ['subgrunt:init', 'clean:tmp', 'ember']); - process.on('SIGINT', waitBeforeExit); - process.on('SIGTERM', waitBeforeExit); + // Helpers for common deprecated tasks + grunt.registerTask('main', function () { + grunt.log.error('@deprecated: Run `yarn main` instead'); + }); + grunt.registerTask('validate', function () { + grunt.log.error('@deprecated: Run `yarn test` instead'); + }); + + // --- Sub Commands + // Used to make other commands work + + // Updates submodules, then installs and builds the client for you + grunt.registerTask('init', 'Prepare the project for development', + ['update_submodules:pinned', 'build']); + + // Runs ember dev + grunt.registerTask('ember', 'Build JS & templates for development', + ['subgrunt:dev']); + + // Production asset build + grunt.registerTask('prod', 'Build JS & templates for production', + ['subgrunt:prod', 'postcss:prod']); + + // --- Configuration const cfg = { - // #### Common paths used by tasks - paths: { - build: buildDirectory, - releaseBuild: path.join(buildDirectory, 'release'), - dist: distDirectory, - releaseDist: path.join(distDirectory, 'release') - }, - // Standard build type, for when we have nightlies again. - buildType: 'Build', - // Load package.json so that we can create correctly versioned releases. - pkg: grunt.file.readJSON('package.json'), - - clientFiles: [ - 'server/web/admin/views/default.html', - 'built/assets/ghost.js', - 'built/assets/ghost.css', - 'built/assets/vendor.js', - 'built/assets/vendor.css' - ], - - // ### grunt-contrib-watch + // grunt-contrib-watch // Watch files and livereload in the browser during development. - // See the [grunt dev](#live%20reload) task for how this is used. + // See the grunt dev task for how this is used. watch: grunt.option('no-server-watch') ? {files: []} : { livereload: { files: [ @@ -107,58 +88,19 @@ const configureGrunt = function (grunt) { } }, - // ### grunt-express-server + // grunt-express-server // Start a Ghost express server for use in development and testing express: { - options: { - script: 'index.js', - output: 'Ghost is running' - }, - dev: { - options: {} - }, - test: { options: { - node_env: 'testing' + script: 'index.js', + output: 'Ghost is running' } } }, - // ### grunt-mocha-cli - mochacli: { - options: { - ui: 'bdd', - reporter: grunt.option('reporter') || 'spec', - timeout: '60000', - require: ['core/server/overrides'], - flags: ['--trace-warnings'], - exit: true - }, - - unit: { - src: [ - 'test/unit/**/*_spec.js' - ] - }, - - acceptance: { - src: [ - 'test/api-acceptance/**/*_spec.js', - 'test/frontend-acceptance/**/*_spec.js' - ] - }, - - regression: { - src: [ - 'test/regression/**/*_spec.js' - ] - }, - - // #### Run single test (src is set dynamically, see grunt task 'test') - single: {} - }, - + // grunt-bg-shell + // Tools for building the client bgShell: { client: { cmd: function () { @@ -205,12 +147,9 @@ const configureGrunt = function (grunt) { } }, - // ### grunt-shell + // grunt-shell // Command line tools where it's easier to run a command directly than configure a grunt plugin shell: { - lint: { - command: 'yarn lint' - }, main: { command: function () { const upstream = grunt.option('upstream') || process.env.GHOST_UPSTREAM || 'upstream'; @@ -247,7 +186,7 @@ const configureGrunt = function (grunt) { } }, - // ### grunt-contrib-clean + // grunt-contrib-clean // Clean up files as part of other tasks clean: { built: { @@ -255,34 +194,12 @@ const configureGrunt = function (grunt) { 'core/built/**' ] }, - release: { - src: ['<%= paths.releaseBuild %>/**'] - }, - test: { - src: ['content/data/ghost-test.db'] - }, tmp: { src: ['.tmp/**'] - }, - dependencies: { - src: ['node_modules/**', 'core/client/bower_components/**', 'core/client/node_modules/**'] } }, - // ### grunt-contrib-compress - // Zip up files for builds / releases - compress: { - release: { - options: { - archive: '<%= paths.releaseDist %>/Ghost-<%= pkg.version %>.zip' - }, - expand: true, - cwd: '<%= paths.releaseBuild %>/', - src: ['**'] - } - }, - - // ### grunt-update-submodules + // grunt-update-submodules // Grunt task to update git submodules update_submodules: { pinned: { @@ -292,6 +209,8 @@ const configureGrunt = function (grunt) { } }, + // @lodder/grunt-postcss + // Generate processed, minified css files postcss: { prod: { options: { @@ -305,7 +224,7 @@ const configureGrunt = function (grunt) { } }, - // ### grunt-subgrunt + // grunt-subgrunt // Run grunt tasks in submodule Gruntfiles subgrunt: { options: { @@ -337,7 +256,7 @@ const configureGrunt = function (grunt) { } }, - // ### grunt-contrib-symlink + // grunt-contrib-symlink // Create symlink for git hooks symlink: { githooks: { @@ -354,251 +273,69 @@ const configureGrunt = function (grunt) { } }; + // --- Grunt Initialisation + + // Load all grunt tasks + grunt.loadNpmTasks('@lodder/grunt-postcss'); + grunt.loadNpmTasks('grunt-bg-shell'); + grunt.loadNpmTasks('grunt-contrib-clean'); + grunt.loadNpmTasks('grunt-contrib-compress'); + grunt.loadNpmTasks('grunt-contrib-copy'); + grunt.loadNpmTasks('grunt-contrib-symlink'); + grunt.loadNpmTasks('grunt-contrib-watch'); + grunt.loadNpmTasks('grunt-express-server'); + grunt.loadNpmTasks('grunt-mocha-cli'); + grunt.loadNpmTasks('grunt-shell'); + grunt.loadNpmTasks('grunt-subgrunt'); + grunt.loadNpmTasks('grunt-update-submodules'); + + // This little bit of weirdness gives the express server chance to shutdown properly + const waitBeforeExit = () => { + setTimeout(() => { + process.exit(0); + }, 1000); + }; + + process.on('SIGINT', waitBeforeExit); + process.on('SIGTERM', waitBeforeExit); + // Load the configuration grunt.initConfig(cfg); - // # Custom Tasks + // --- Release Tooling - // Ghost has a number of useful tasks that we use every day in development. Tasks marked as *Utility* are used - // by grunt to perform current actions, but isn't useful to developers. - // - // Skip ahead to the section on: - // - // * [Building assets](#building%20assets): - // `grunt init`, `grunt` & `grunt prod` or live reload with `grunt dev` - // * [Testing](#testing): - // `grunt validate`, the `grunt test-*` sub-tasks. - - // ### Help - // Run `grunt help` on the commandline to get a print out of the available tasks and details of - // what each one does along with any available options. This is an alias for `grunt --help` - grunt.registerTask('help', - 'Outputs help information if you type `grunt help` instead of `grunt --help`', - function () { - grunt.log.writeln('Type `grunt --help` to get the details of available grunt tasks.'); - }); - - // ## Testing - - // Ghost has an extensive set of test suites. The following section documents the various types of tests - // and how to run them. - // - // TLDR; run `grunt validate` - - // #### Set Test Env *(Utility Task)* - // Set the NODE_ENV to 'testing' unless the environment is already set to TRAVIS. - // This ensures that the tests get run under the correct environment, using the correct database, and - // that they work as expected. Trying to run tests with no ENV set will throw an error to do with `client`. - grunt.registerTask('setTestEnv', - 'Use "testing" Ghost config; unless we are running on travis (then show queries for debugging)', - function () { - process.env.NODE_ENV = process.env.NODE_ENV || 'testing'; - cfg.express.test.options.node_env = process.env.NODE_ENV; - }); - - // ### Test - // **Testing utility** - // - // `grunt test:unit/apps_spec.js` will run just the tests inside the apps_spec.js file - // - // It works for any path relative to the /test/ folder. It will also run all the tests in a single directory - // You can also run a test with grunt test:test/unit/... to get bash autocompletion - // - // `grunt test:regression/api` - runs the api regression tests - grunt.registerTask('test', 'Run a particular spec file from the /test/ directory e.g. `grunt test:unit/apps_spec.js`', function (test) { - if (!test) { - grunt.fail.fatal('No test provided. `grunt test` expects a filename. e.g.: `grunt test:unit/apps_spec.js`. Did you mean `npm test` or `grunt validate`?'); - } - - if (!test.match(/test\//) && !test.match(/core\/server/)) { - test = 'test/' + test; - } - - // CASE: execute folder - if (!test.match(/.js/)) { - test += '/**'; - } else if (!fs.existsSync(test)) { - grunt.fail.fatal('This file does not exist!'); - } - - cfg.mochacli.single.src = [test]; - grunt.initConfig(cfg); - grunt.task.run('test-setup', 'mochacli:single'); - }); - - // #### Stub out ghost files *(Utility Task)* - // Creates stub files in the built directory and the views directory - // so that the test environments do not need to build out the client files - grunt.registerTask('stubClientFiles', function () { - _.each(cfg.clientFiles, function (file) { - const filePath = path.resolve(cwd + '/core/' + file); - fs.ensureFileSync(filePath); - }); - }); - - /** - * Ensures the target database get's automatically created. - */ - grunt.registerTask('knex-migrator', function () { - return knexMigrator.init({noScripts: true}); - }); - - // ### Validate - // **Main testing task** - // - // `grunt validate` will either run all tests or run linting - // `grunt validate` is called by `yarn test` and is used by Travis. - grunt.registerTask('validate', 'Run tests', function () { - grunt.task.run(['test-unit', 'test-acceptance']); - }); - - grunt.registerTask('test-all', 'Run all server tests', - ['test-unit', 'test-acceptance', 'test-regression']); - - // ### Lint - // - // `grunt lint` will run the linter - grunt.registerTask('lint', 'Run the code style checks for server & tests', - ['shell:lint'] - ); - - // ### test-setup *(utility)( - // `grunt test-setup` will run all the setup tasks required for running tests - grunt.registerTask('test-setup', 'Setup ready to run tests', - ['knex-migrator', 'clean:test', 'setTestEnv', 'stubClientFiles'] - ); - - // ### Unit Tests *(sub task)* - // `grunt test-unit` will run just the unit tests - // - // If you need to run an individual unit test file, you can use the `grunt test:` task: - // - // `grunt test:unit/config_spec.js` - // - // This also works for folders (although it isn't recursive), E.g. - // - // `grunt test:unit/helpers` - // - // Unit tests are run with [mocha](http://mochajs.org/) using - // [should](https://github.com/visionmedia/should.js) to describe the tests in a highly readable style. - // Unit tests do **not** touch the database. - grunt.registerTask('test-unit', 'Run unit tests (mocha)', - ['test-setup', 'mochacli:unit'] - ); - - grunt.registerTask('test-regression', 'Run regression tests.', - ['test-setup', 'mochacli:regression'] - ); - - grunt.registerTask('test-acceptance', 'Run acceptance tests', - ['test-setup', 'mochacli:acceptance'] - ); - - // ## Building assets - // - // Ghost's GitHub repository contains the un-built source code for Ghost. If you're looking for the already - // built release zips, you can get these from the [release page](https://github.com/TryGhost/Ghost/releases) on - // GitHub or from https://ghost.org/docs/install/. These zip files are created using the [grunt release](#release) - // task. - // - // If you want to work on Ghost core, or you want to use the source files from GitHub, then you have to build - // the Ghost assets in order to make them work. - // - // There are a number of grunt tasks available to help with this. Firstly after fetching an updated version of - // the Ghost codebase, after running `yarn install`, you will need to run [grunt init](#init%20assets). - // - // For production blogs you will need to run [grunt prod](#production%20assets). - // - // For updating assets during development, the tasks [grunt](#default%20asset%20build) and - // [grunt dev](#live%20reload) are available. - - // ### Init assets - // `grunt init` - will run an initial asset build for you - // - // Grunt init runs `yarn install && bower install` inside `core/client` as well as the standard asset build - // tasks which occur when you run just `grunt`. This fetches the latest client-side dependencies. - // - // This task is very important, and should always be run when fetching down an updated code base just after - // running `yarn install`. - // - // `bower` does have some quirks, such as not running as root. If you have problems please try running - // `grunt init --verbose` to see if there are any errors. - grunt.registerTask('init', 'Prepare the project for development', - ['update_submodules:pinned', 'subgrunt:init', 'clean:tmp', 'default']); - - // ### Build assets - // `grunt build` - will build client assets (without updating the submodule) - // - // This task is identical to `grunt init`, except it does not build client dependencies - grunt.registerTask('build', 'Build client app', - ['subgrunt:init', 'clean:tmp', 'default']); - - // ### Default asset build - // `grunt` - default grunt task - // - // Build assets and dev version of the admin app. - grunt.registerTask('default', 'Build JS & templates for development', - ['subgrunt:dev']); - - // ### Production assets - // `grunt prod` - will build the minified assets used in production. - // - // It is otherwise the same as running `grunt`, but is only used when running Ghost in the `production` env. - grunt.registerTask('prod', 'Build JS & templates for production', - ['subgrunt:prod', 'postcss:prod']); - - // ### Live reload - // `grunt dev` - build assets on the fly whilst developing - // - // If you want Ghost to live reload for you whilst you're developing, you can do this by running `grunt dev`. - // This works hand-in-hand with the [livereload](http://livereload.com/) chrome extension. - // - // `grunt dev` manages starting an express server and restarting the server whenever core files change (which - // require a server restart for the changes to take effect) and also manage reloading the browser whenever - // frontend code changes. - // - // Note that the current implementation of watch only works with casper, not other themes. - grunt.registerTask('dev', 'Dev Mode; watch files and restart server on changes', function () { - if (grunt.option('client')) { - grunt.task.run(['clean:built', 'bgShell:client']); - } else if (grunt.option('server')) { - grunt.task.run(['express:dev', 'watch']); - } else { - grunt.task.run(['clean:built', 'bgShell:client', 'express:dev', 'watch']); - } - }); - - // ### grunt main - // This command helps you to bring your working directory back to current main. - // It will also update your dependencies to main and shows you if your database is healthy. - // It won't build the client! - // - // `grunt main` [`upstream` is the default upstream to pull from] - // `grunt main --upstream=parent` - grunt.registerTask('main', 'Update your current working folder to latest main.', - ['shell:main', 'subgrunt:init'] - ); - - grunt.registerTask('master', 'Backwards compatible alias for `grunt main`.', 'main'); - - // ### Release - // Run `grunt release` to create a Ghost release zip file. + // grunt release + // - create a Ghost release zip file. // Uses the files specified by `.npmignore` to know what should and should not be included. // Runs the asset generation tasks for production and duplicates default-prod.html to default.html - // so it can be run in either production or development, and packages all the files up into a zip. grunt.registerTask('release', 'Release task - creates a final built zip\n' + ' - Do our standard build steps \n' + ' - Copy files to release-folder/#/#{version} directory\n' + - ' - Clean out unnecessary files (travis, .git*, etc)\n' + + ' - Clean out unnecessary files (.git*, etc)\n' + ' - Zip files in release-folder to dist-folder/#{version} directory', function () { + const escapeChar = process.platform.match(/^win/) ? '^' : '\\'; + const cwd = process.cwd().replace(/( |\(|\))/g, escapeChar + '$1'); + const buildDirectory = path.resolve(cwd, '.build'); + const distDirectory = path.resolve(cwd, '.dist'); + + // Common paths used by release + grunt.config.set('paths', { + build: buildDirectory, + releaseBuild: path.join(buildDirectory, 'release'), + dist: distDirectory, + releaseDist: path.join(distDirectory, 'release') + }); + + // Load package.json so that we can create correctly versioned releases. + grunt.config.set('pkg', grunt.file.readJSON('package.json')); + + // grunt-contrib-copy grunt.config.set('copy.release', { expand: true, - // #### Build File Patterns // A list of files and patterns to include when creating a release zip. - // This is read from the `.npmignore` file and all patterns are inverted as the `.npmignore` - // file defines what to ignore, whereas we want to define what to include. + // This is read from the `.npmignore` file and all patterns are inverted as we want to define what to include src: fs.readFileSync('.npmignore', 'utf8').split('\n').filter(Boolean).map(function (pattern) { return pattern[0] === '!' ? pattern.substr(1) : '!' + pattern; }), @@ -613,6 +350,21 @@ const configureGrunt = function (grunt) { }] }); + // grunt-contrib-compress + grunt.config.set('compress.release', { + options: { + archive: '<%= paths.releaseDist %>/Ghost-<%= pkg.version %>.zip' + }, + expand: true, + cwd: '<%= paths.releaseBuild %>/', + src: ['**'] + }); + + // grunt-contrib-clean + grunt.config.set('clean.release', { + src: ['<%= paths.releaseBuild %>/**'] + }); + if (!grunt.option('skip-update')) { grunt.task .run('update_submodules:pinned') @@ -630,5 +382,3 @@ const configureGrunt = function (grunt) { } ); }; - -module.exports = configureGrunt; diff --git a/package.json b/package.json index c6ff7f9a7a..ff8eb01351 100644 --- a/package.json +++ b/package.json @@ -21,12 +21,17 @@ "license": "MIT", "scripts": { "start": "node index", - "dev": "DEBUG=ghost:* grunt dev", - "test": "grunt validate", - "test:slow": "grunt validate --reporter=mocha-slow-test-reporter", - "ci": "grunt validate --verbose", - "ci:regression": "grunt test-regression --verbose", + "dev": "grunt", + "dev:debug": "DEBUG=ghost:* grunt", "setup": "yarn install && knex-migrator init && grunt symlink && grunt init || (exit 0)", + "main": "grunt shell:main && grunt subgrunt:init", + "build": "grunt build", + "test": "mocha --require=test/utils/overrides.js --exit --trace-warnings --recursive --timeout=60000", + "test:all": "yarn test:unit && yarn test:acceptance && yarn test:regression", + "test:unit": "mocha --require=test/utils/overrides.js --exit --trace-warnings './test/unit/**/*_spec.js' --timeout=7000", + "test:acceptance": "mocha --require=test/utils/overrides.js --exit --trace-warnings './test/api-acceptance/**/*_spec.js' './test/frontend-acceptance/**/*_spec.js' --timeout=10000", + "test:regression": "mocha --require=test/utils/overrides.js --exit --trace-warnings './test/regression/**/*_spec.js' --timeout=60000", + "test:slow": "yarn test:unit --reporter=mocha-slow-test-reporter && yarn test:acceptance --reporter=mocha-slow-test-reporter", "lint:server": "eslint --ignore-path .eslintignore 'core/server/**/*.js' 'core/*.js' '*.js'", "lint:shared": "eslint --ignore-path .eslintignore 'core/shared/**/*.js'", "lint:frontend": "eslint --ignore-path .eslintignore 'core/frontend/**/*.js'", diff --git a/test/regression/api/admin_spec.js b/test/regression/api/admin_spec.js index 4e153642e7..4b270e169e 100644 --- a/test/regression/api/admin_spec.js +++ b/test/regression/api/admin_spec.js @@ -9,6 +9,7 @@ const supertest = require('supertest'); const testUtils = require('../../utils'); const configUtils = require('../../utils/configUtils'); const urlUtils = require('../../utils/urlUtils'); +const adminUtils = require('../../utils/admin-utils'); const ghost = testUtils.startGhost; const i18n = require('../../../core/shared/i18n'); const config = require('../../../core/shared/config'); @@ -44,6 +45,8 @@ describe('Admin Routing', function () { } before(function () { + adminUtils.stubClientFiles(); + return ghost() .then(function () { request = supertest.agent(config.get('url')); diff --git a/test/regression/site/parent_app_vhosts_spec.js b/test/regression/site/parent_app_vhosts_spec.js index deded1c5bb..d37f6e96f0 100644 --- a/test/regression/site/parent_app_vhosts_spec.js +++ b/test/regression/site/parent_app_vhosts_spec.js @@ -2,6 +2,7 @@ const should = require('should'); const sinon = require('sinon'); const _ = require('lodash'); const testUtils = require('../../utils'); +const adminUtils = require('../../utils/admin-utils'); const mockUtils = require('../../utils/mocks'); const configUtils = require('../../utils/configUtils'); const urlUtils = require('../../utils/urlUtils'); @@ -15,6 +16,7 @@ describe('Integration - Web - vhosts', function () { before(testUtils.integrationTesting.urlService.resetGenerators); before(testUtils.teardownDb); before(testUtils.setup('users:roles', 'posts')); + before(adminUtils.stubClientFiles); after(function () { configUtils.restore(); diff --git a/test/utils/acceptance-utils.js b/test/utils/acceptance-utils.js index bd5566e67b..638270f139 100644 --- a/test/utils/acceptance-utils.js +++ b/test/utils/acceptance-utils.js @@ -1,5 +1,3 @@ -require('../../core/server/overrides'); - // Utility Packages const Promise = require('bluebird'); const _ = require('lodash'); diff --git a/test/utils/admin-utils.js b/test/utils/admin-utils.js new file mode 100644 index 0000000000..51aa271983 --- /dev/null +++ b/test/utils/admin-utils.js @@ -0,0 +1,17 @@ +const fs = require('fs-extra'); +const path = require('path'); + +const clientFiles = [ + 'server/web/admin/views/default.html', + 'built/assets/ghost.js', + 'built/assets/ghost.css', + 'built/assets/vendor.js', + 'built/assets/vendor.css' +]; + +module.exports.stubClientFiles = () => { + clientFiles.forEach((file) => { + const filePath = path.resolve(__dirname, '../../core/', file); + fs.ensureFileSync(filePath); + }); +}; diff --git a/test/utils/overrides.js b/test/utils/overrides.js new file mode 100644 index 0000000000..322fb637fc --- /dev/null +++ b/test/utils/overrides.js @@ -0,0 +1,3 @@ +process.env.NODE_ENV = process.env.NODE_ENV || 'testing'; + +require('../../core/server/overrides');