mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-09-06 20:54:26 +08:00
ci(spectron): Add support to execute spectron/chrome-driver tests
Summary: - Sets up spectron test suite inside its own directory and with its own dependencies (must run on a build of the app) - Sets up dummy test - Adds `run-spectron-specs` grunt task, and adds it to cibuild task - Cleans up spec tasks code Test Plan: - Run specs Reviewers: evan, bengotow Reviewed By: bengotow Differential Revision: https://phab.nylas.com/D2256
This commit is contained in:
parent
338dc5284f
commit
c6b4adbcd1
6 changed files with 104 additions and 157 deletions
|
@ -104,6 +104,7 @@ module.exports = (grunt) ->
|
||||||
installDir ?= process.env.INSTALL_PREFIX ? '/usr/local'
|
installDir ?= process.env.INSTALL_PREFIX ? '/usr/local'
|
||||||
killCommand = 'pkill -9 nylas'
|
killCommand = 'pkill -9 nylas'
|
||||||
|
|
||||||
|
grunt.option('appDir', appDir)
|
||||||
installDir = path.resolve(installDir)
|
installDir = path.resolve(installDir)
|
||||||
|
|
||||||
cjsxConfig =
|
cjsxConfig =
|
||||||
|
@ -359,7 +360,7 @@ module.exports = (grunt) ->
|
||||||
|
|
||||||
grunt.registerTask('compile', ['coffee', 'cjsx', 'babel', 'prebuild-less', 'cson', 'peg'])
|
grunt.registerTask('compile', ['coffee', 'cjsx', 'babel', 'prebuild-less', 'cson', 'peg'])
|
||||||
grunt.registerTask('lint', ['coffeelint', 'csslint', 'lesslint', 'nylaslint', 'eslint'])
|
grunt.registerTask('lint', ['coffeelint', 'csslint', 'lesslint', 'nylaslint', 'eslint'])
|
||||||
grunt.registerTask('test', ['shell:kill-n1', 'run-edgehill-specs'])
|
grunt.registerTask('test', ['shell:kill-n1', 'run-edgehill-specs', 'run-spectron-specs'])
|
||||||
grunt.registerTask('docs', ['build-docs', 'render-docs'])
|
grunt.registerTask('docs', ['build-docs', 'render-docs'])
|
||||||
|
|
||||||
ciTasks = ['output-disk-space', 'download-electron', 'build']
|
ciTasks = ['output-disk-space', 'download-electron', 'build']
|
||||||
|
|
|
@ -1,144 +1,12 @@
|
||||||
fs = require 'fs'
|
fs = require 'fs'
|
||||||
path = require 'path'
|
path = require 'path'
|
||||||
|
|
||||||
_ = require 'underscore'
|
|
||||||
async = require 'async'
|
|
||||||
request = require 'request'
|
request = require 'request'
|
||||||
|
proc = require 'child_process'
|
||||||
|
|
||||||
concurrency = 2
|
executeTests = (test, grunt, done) ->
|
||||||
|
|
||||||
module.exports = (grunt) ->
|
|
||||||
{isNylasPackage, spawn} = require('./task-helpers')(grunt)
|
|
||||||
|
|
||||||
packageSpecQueue = null
|
|
||||||
|
|
||||||
logDeprecations = (label, {stderr}={}) ->
|
|
||||||
return unless process.env.JANKY_SHA1
|
|
||||||
stderr ?= ''
|
|
||||||
deprecatedStart = stderr.indexOf('Calls to deprecated functions')
|
|
||||||
return if deprecatedStart is -1
|
|
||||||
|
|
||||||
grunt.log.error(label)
|
|
||||||
stderr = stderr.substring(deprecatedStart)
|
|
||||||
stderr = stderr.replace(/^\s*\[[^\]]+\]\s+/gm, '')
|
|
||||||
stderr = stderr.replace(/source: .*$/gm, '')
|
|
||||||
stderr = stderr.replace(/^"/gm, '')
|
|
||||||
stderr = stderr.replace(/",\s*$/gm, '')
|
|
||||||
grunt.log.error(stderr)
|
|
||||||
|
|
||||||
getAppPath = ->
|
|
||||||
contentsDir = grunt.config.get('nylasGruntConfig.contentsDir')
|
|
||||||
switch process.platform
|
|
||||||
when 'darwin'
|
|
||||||
path.join(contentsDir, 'MacOS', 'Edgehill')
|
|
||||||
when 'linux'
|
|
||||||
path.join(contentsDir, 'edgehill')
|
|
||||||
when 'win32'
|
|
||||||
path.join(contentsDir, 'edgehill.exe')
|
|
||||||
|
|
||||||
runPackageSpecs = (callback) ->
|
|
||||||
failedPackages = []
|
|
||||||
rootDir = grunt.config.get('nylasGruntConfig.shellAppDir')
|
|
||||||
resourcePath = process.cwd()
|
|
||||||
appPath = getAppPath()
|
|
||||||
|
|
||||||
# Ensure application is executable on Linux
|
|
||||||
fs.chmodSync(appPath, '755') if process.platform is 'linux'
|
|
||||||
|
|
||||||
packageSpecQueue = async.queue (packagePath, callback) ->
|
|
||||||
if process.platform in ['darwin', 'linux']
|
|
||||||
options =
|
|
||||||
cmd: appPath
|
|
||||||
args: ['--test', "--resource-path=#{resourcePath}", "--spec-directory=#{path.join(packagePath, 'spec')}"]
|
|
||||||
opts:
|
|
||||||
cwd: packagePath
|
|
||||||
env: _.extend({}, process.env, ATOM_SHELL_PATH: rootDir)
|
|
||||||
else if process.platform is 'win32'
|
|
||||||
options =
|
|
||||||
cmd: process.env.comspec
|
|
||||||
args: ['/c', appPath, '--test', "--resource-path=#{resourcePath}", "--spec-directory=#{path.join(packagePath, 'spec')}", "--log-file=ci.log"]
|
|
||||||
opts:
|
|
||||||
cwd: packagePath
|
|
||||||
env: _.extend({}, process.env, ATOM_SHELL_PATH: rootDir)
|
|
||||||
|
|
||||||
grunt.verbose.writeln "Launching #{path.basename(packagePath)} specs."
|
|
||||||
spawn options, (error, results, code) ->
|
|
||||||
if process.platform is 'win32'
|
|
||||||
if error
|
|
||||||
process.stderr.write(fs.readFileSync(path.join(packagePath, 'ci.log')))
|
|
||||||
fs.unlinkSync(path.join(packagePath, 'ci.log'))
|
|
||||||
|
|
||||||
failedPackages.push path.basename(packagePath) if error
|
|
||||||
logDeprecations("#{path.basename(packagePath)} Specs", results)
|
|
||||||
callback()
|
|
||||||
|
|
||||||
modulesDirectory = path.resolve('node_modules')
|
|
||||||
for packageDirectory in fs.readdirSync(modulesDirectory)
|
|
||||||
packagePath = path.join(modulesDirectory, packageDirectory)
|
|
||||||
continue unless grunt.file.isDir(path.join(packagePath, 'spec'))
|
|
||||||
continue unless isNylasPackage(packagePath)
|
|
||||||
packageSpecQueue.push(packagePath)
|
|
||||||
|
|
||||||
packageSpecQueue.concurrency = concurrency - 1
|
|
||||||
packageSpecQueue.drain = -> callback(null, failedPackages)
|
|
||||||
|
|
||||||
runCoreSpecs = (callback) ->
|
|
||||||
appPath = getAppPath()
|
|
||||||
resourcePath = process.cwd()
|
|
||||||
coreSpecsPath = path.resolve('spec')
|
|
||||||
|
|
||||||
if process.platform in ['darwin', 'linux']
|
|
||||||
options =
|
|
||||||
cmd: appPath
|
|
||||||
args: ['--test', "--resource-path=#{resourcePath}", "--spec-directory=#{coreSpecsPath}"]
|
|
||||||
else if process.platform is 'win32'
|
|
||||||
options =
|
|
||||||
cmd: process.env.comspec
|
|
||||||
args: ['/c', appPath, '--test', "--resource-path=#{resourcePath}", "--spec-directory=#{coreSpecsPath}", "--log-file=ci.log"]
|
|
||||||
|
|
||||||
spawn options, (error, results, code) ->
|
|
||||||
if process.platform is 'win32'
|
|
||||||
process.stderr.write(fs.readFileSync('ci.log')) if error
|
|
||||||
fs.unlinkSync('ci.log')
|
|
||||||
else
|
|
||||||
# TODO: Restore concurrency on Windows
|
|
||||||
packageSpecQueue.concurrency = concurrency
|
|
||||||
logDeprecations('Core Specs', results)
|
|
||||||
|
|
||||||
callback(null, error)
|
|
||||||
|
|
||||||
grunt.registerTask 'run-specs', 'Run the specs', ->
|
|
||||||
done = @async()
|
|
||||||
startTime = Date.now()
|
|
||||||
|
|
||||||
# TODO: This should really be parallel on both platforms, however our
|
|
||||||
# fixtures step on each others toes currently.
|
|
||||||
if process.platform in ['darwin', 'linux']
|
|
||||||
method = async.parallel
|
|
||||||
else if process.platform is 'win32'
|
|
||||||
method = async.series
|
|
||||||
|
|
||||||
method [runCoreSpecs, runPackageSpecs], (error, results) ->
|
|
||||||
[coreSpecFailed, failedPackages] = results
|
|
||||||
elapsedTime = Math.round((Date.now() - startTime) / 100) / 10
|
|
||||||
grunt.log.ok("Total spec time: #{elapsedTime}s using #{concurrency} cores")
|
|
||||||
failures = failedPackages
|
|
||||||
failures.push "N1 core" if coreSpecFailed
|
|
||||||
|
|
||||||
grunt.log.error("[Error]".red + " #{failures.join(', ')} spec(s) failed") if failures.length > 0
|
|
||||||
|
|
||||||
if process.platform is 'win32' and process.env.JANKY_SHA1
|
|
||||||
done()
|
|
||||||
else
|
|
||||||
done(!coreSpecFailed and failedPackages.length == 0)
|
|
||||||
|
|
||||||
grunt.registerTask 'run-edgehill-specs', 'Run the specs', ->
|
|
||||||
proc = require 'child_process'
|
|
||||||
done = @async()
|
|
||||||
testSucceeded = false
|
testSucceeded = false
|
||||||
testOutput = ""
|
testOutput = ""
|
||||||
testProc = proc.spawn("./N1.sh", ["--test"])
|
testProc = proc.spawn(test.cmd, test.args)
|
||||||
|
|
||||||
testProc.stdout.on 'data', (data) ->
|
testProc.stdout.on 'data', (data) ->
|
||||||
str = data.toString()
|
str = data.toString()
|
||||||
testOutput += str
|
testOutput += str
|
||||||
|
@ -155,7 +23,7 @@ module.exports = (grunt) ->
|
||||||
grunt.log.error("Process error: #{err}")
|
grunt.log.error("Process error: #{err}")
|
||||||
|
|
||||||
testProc.on 'close', (exitCode, signal) ->
|
testProc.on 'close', (exitCode, signal) ->
|
||||||
if testSucceeded
|
if testSucceeded and exitCode is 0
|
||||||
done()
|
done()
|
||||||
else
|
else
|
||||||
testOutput = testOutput.replace(/\x1b\[[^m]+m/g, '')
|
testOutput = testOutput.replace(/\x1b\[[^m]+m/g, '')
|
||||||
|
@ -167,3 +35,29 @@ module.exports = (grunt) ->
|
||||||
text: "Aghhh somebody broke the build. ```#{testOutput}```"
|
text: "Aghhh somebody broke the build. ```#{testOutput}```"
|
||||||
, (err, httpResponse, body) ->
|
, (err, httpResponse, body) ->
|
||||||
done(false)
|
done(false)
|
||||||
|
|
||||||
|
module.exports = (grunt) ->
|
||||||
|
|
||||||
|
grunt.registerTask 'run-spectron-specs', 'Run spectron specs', ->
|
||||||
|
appPath = path.resolve('./N1.sh')
|
||||||
|
done = @async()
|
||||||
|
npmPath = path.resolve "./build/node_modules/.bin/npm"
|
||||||
|
grunt.log.writeln 'App exists: ' + fs.existsSync(appPath)
|
||||||
|
|
||||||
|
process.chdir('./spectron')
|
||||||
|
grunt.log.writeln "Current dir: #{process.cwd()}"
|
||||||
|
installProc = proc.exec "#{npmPath} install", (error) ->
|
||||||
|
if error?
|
||||||
|
process.chdir('..')
|
||||||
|
grunt.log.error('Failed while running npm install in spectron folder')
|
||||||
|
grunt.fail.warn(error)
|
||||||
|
done(false)
|
||||||
|
else
|
||||||
|
executeTests cmd: npmPath, args: ['test', "APP_PATH=#{appPath}"], grunt, (succeeded) ->
|
||||||
|
process.chdir('..')
|
||||||
|
done(succeeded)
|
||||||
|
|
||||||
|
|
||||||
|
grunt.registerTask 'run-edgehill-specs', 'Run the specs', ->
|
||||||
|
done = @async()
|
||||||
|
executeTests cmd: './N1.sh', args: ['--test'], grunt, done
|
||||||
|
|
23
spectron/app-spec.es6
Normal file
23
spectron/app-spec.es6
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
import {Application} from 'spectron';
|
||||||
|
|
||||||
|
describe('Nylas', ()=> {
|
||||||
|
beforeEach((done)=>{
|
||||||
|
this.app = new Application({
|
||||||
|
path: jasmine.APP_PATH,
|
||||||
|
});
|
||||||
|
this.app.start().then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach((done)=> {
|
||||||
|
if (this.app && this.app.isRunning()) {
|
||||||
|
this.app.stop().then(done);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows an initial window', ()=> {
|
||||||
|
this.app.client.getWindowCount().then((count)=> {
|
||||||
|
expect(count).toEqual(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
4
spectron/bootstrap.js
vendored
Normal file
4
spectron/bootstrap.js
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
var babelOptions = require('../static/babelrc.json');
|
||||||
|
require('babel-core/register')(babelOptions);
|
||||||
|
jasmine.APP_PATH = process.argv.slice(3)[0].split('APP_PATH=')[1];
|
||||||
|
jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000;
|
9
spectron/config.json
Normal file
9
spectron/config.json
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"spec_dir": ".",
|
||||||
|
"spec_files": [
|
||||||
|
"**/*-spec.{js,es6,es,jsx}"
|
||||||
|
],
|
||||||
|
"helpers": [
|
||||||
|
"bootstrap.js"
|
||||||
|
]
|
||||||
|
}
|
16
spectron/package.json
Normal file
16
spectron/package.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"name": "nylas-spectron",
|
||||||
|
"description": "N1 Spectron Test Suite",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/nylas/N1.git"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "jasmine JASMINE_CONFIG_PATH=./config.json"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"babel-core": "^5.8.21",
|
||||||
|
"jasmine": "^2.3.2",
|
||||||
|
"spectron": "^0.34.1"
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue