-
Notifications
You must be signed in to change notification settings - Fork 307
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update Grunt task #813
Update Grunt task #813
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,46 @@ | ||
import global from '@dojo/shim/global'; | ||
import { assign } from '@dojo/core/lang'; | ||
|
||
import Node from '../lib/executors/Node'; | ||
import { Config } from '../lib/executors/Executor'; | ||
import { getConfig } from '../lib/node/util'; | ||
|
||
interface TaskOptions extends grunt.task.ITaskOptions, Partial<Config> { | ||
[key: string]: any; | ||
} | ||
|
||
function configure(options: TaskOptions): Promise<{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
config: Partial<Config>; | ||
options: TaskOptions; | ||
}> { | ||
if (options.config) { | ||
return getConfig(options.config, []).then(({ config }) => { | ||
delete options.config; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of deleting config from the passed-in options, it'd be nicer to return a new object that didn't have the config property (since we're returning options anyway). |
||
|
||
return { config, options }; | ||
}); | ||
} | ||
|
||
return Promise.resolve({ config: {}, options }); | ||
} | ||
|
||
export = function(grunt: IGrunt) { | ||
grunt.registerMultiTask('intern', function() { | ||
const done = this.async(); | ||
const config = this.options<TaskOptions>({}); | ||
const options = assign({}, this.options<TaskOptions>({})); | ||
|
||
// Force colored output for istanbul report | ||
process.env.FORCE_COLOR = 'true'; | ||
|
||
const intern = (global.intern = new Node(config)); | ||
intern.run().then(finish, finish); | ||
configure(options).then(({ config, options }) => { | ||
const intern = (global.intern = new Node()); | ||
intern.configure(config); | ||
intern.configure(options); | ||
|
||
return intern.run(); | ||
}).then(finish, finish); | ||
|
||
function finish(error?: any) { | ||
// Remove the global intern object when we're done; this will allow | ||
// Intern to be run again in the same process | ||
global.intern = null; | ||
done(error); | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,36 @@ | ||
import { spy, stub } from 'sinon'; | ||
import * as sinon from 'sinon'; | ||
import _gruntTask from 'src/tasks/intern'; | ||
|
||
const mockRequire = intern.getPlugin<mocking.MockRequire>('mockRequire'); | ||
|
||
registerSuite('tasks/intern', function() { | ||
const mockDone = stub(); | ||
const sandbox = sinon.sandbox.create(); | ||
|
||
let mockDone: sinon.SinonSpy; | ||
|
||
function setupDone() { | ||
return new Promise(resolve => { | ||
mockDone = sinon.spy(() => resolve()); | ||
}); | ||
} | ||
|
||
const mockGrunt = { | ||
registerMultiTask: spy(() => {}), | ||
async: spy(() => mockDone), | ||
options: spy(() => { | ||
return { foo: 'bar' }; | ||
}) | ||
registerMultiTask: sandbox.stub(), | ||
async: sandbox.spy(() => mockDone), | ||
options: sandbox.stub() | ||
}; | ||
|
||
const mockRun = stub(); | ||
const mockRun = sandbox.stub(); | ||
const mockConfigure = sandbox.stub(); | ||
|
||
const mockGetConfig = sandbox.stub(); | ||
class MockNode { | ||
config: any; | ||
run: Function; | ||
constructor(config: any) { | ||
configure: Function; | ||
constructor() { | ||
executors.push(this); | ||
this.config = config; | ||
this.run = mockRun; | ||
this.configure = mockConfigure; | ||
} | ||
} | ||
|
||
|
@@ -34,7 +42,8 @@ registerSuite('tasks/intern', function() { | |
before() { | ||
return mockRequire(require, 'src/tasks/intern', { | ||
'src/lib/executors/Node': { default: MockNode }, | ||
'@dojo/shim/global': { default: {} } | ||
'@dojo/shim/global': { default: {} }, | ||
'src/lib/node/util': { getConfig: mockGetConfig } | ||
}).then(handle => { | ||
removeMocks = handle.remove; | ||
gruntTask = handle.module; | ||
|
@@ -46,15 +55,15 @@ registerSuite('tasks/intern', function() { | |
}, | ||
|
||
beforeEach() { | ||
mockRun.reset(); | ||
sandbox.reset(); | ||
mockRun.resolves(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we made There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are a few other stubs I've set up that need to be reset every time |
||
mockDone.reset(); | ||
executors = []; | ||
}, | ||
|
||
tests: { | ||
'task registration'() { | ||
gruntTask(<any>mockGrunt); | ||
|
||
assert.equal( | ||
mockGrunt.registerMultiTask.callCount, | ||
1, | ||
|
@@ -67,55 +76,110 @@ registerSuite('tasks/intern', function() { | |
); | ||
}, | ||
|
||
'run task'() { | ||
const dfd = this.async(); | ||
gruntTask(<any>mockGrunt); | ||
const callback = mockGrunt.registerMultiTask.getCall(0).args[1]; | ||
callback.call(mockGrunt); | ||
assert.lengthOf( | ||
executors, | ||
1, | ||
'1 executor should have been created' | ||
); | ||
assert.equal( | ||
mockRun.callCount, | ||
1, | ||
'intern should have been run' | ||
); | ||
assert.deepEqual(executors[0].config, { foo: 'bar' }); | ||
setTimeout( | ||
dfd.callback(() => { | ||
'run task': { | ||
'config'() { | ||
mockGrunt.registerMultiTask.callsArgOn(1, mockGrunt); | ||
mockGrunt.options.returns({ | ||
config: '@coverage', | ||
foo: 'bar' | ||
}); | ||
mockGetConfig.resolves({ | ||
config: { | ||
spam: 'ham' | ||
} | ||
}); | ||
const done = setupDone(); | ||
|
||
gruntTask(<any>mockGrunt); | ||
|
||
return done.then(() => { | ||
assert.lengthOf( | ||
executors, | ||
1, | ||
'1 executor should have been created' | ||
); | ||
assert.equal( | ||
mockRun.callCount, | ||
1, | ||
'intern should have been run' | ||
); | ||
assert.equal(mockGetConfig.callCount, 1); | ||
assert.equal( | ||
mockGetConfig.getCall(0).args[0], | ||
'@coverage' | ||
); | ||
assert.equal(mockConfigure.callCount, 2); | ||
assert.deepEqual(mockConfigure.getCall(0).args[0], { | ||
spam: 'ham' | ||
}); | ||
assert.deepEqual(mockConfigure.getCall(1).args[0], { | ||
foo: 'bar' | ||
}); | ||
assert.equal(mockDone.callCount, 1); | ||
// First arg is an error, so it should be undefined here | ||
assert.isUndefined(mockDone.getCall(0).args[0]); | ||
}) | ||
); | ||
}); | ||
}, | ||
|
||
'no config'() { | ||
mockGrunt.registerMultiTask.callsArgOn(1, mockGrunt); | ||
mockGrunt.options.returns({ | ||
foo: 'bar' | ||
}); | ||
const done = setupDone(); | ||
|
||
gruntTask(<any>mockGrunt); | ||
|
||
return done.then(() => { | ||
assert.lengthOf( | ||
executors, | ||
1, | ||
'1 executor should have been created' | ||
); | ||
assert.equal( | ||
mockRun.callCount, | ||
1, | ||
'intern should have been run' | ||
); | ||
assert.equal(mockGetConfig.callCount, 0); | ||
assert.equal(mockConfigure.callCount, 2); | ||
assert.deepEqual(mockConfigure.getCall(0).args[0], {}); | ||
assert.deepEqual(mockConfigure.getCall(1).args[0], { | ||
foo: 'bar' | ||
}); | ||
assert.equal(mockDone.callCount, 1); | ||
// First arg is an error, so it should be undefined here | ||
assert.isUndefined(mockDone.getCall(0).args[0]); | ||
}); | ||
} | ||
}, | ||
|
||
error() { | ||
const dfd = this.async(); | ||
gruntTask(<any>mockGrunt); | ||
const callback = mockGrunt.registerMultiTask.getCall(0).args[1]; | ||
mockGrunt.registerMultiTask.callsArgOn(1, mockGrunt); | ||
mockGrunt.options.returns({ | ||
foo: 'bar' | ||
}); | ||
const error = new Error('bad'); | ||
mockRun.rejects(error); | ||
callback.call(mockGrunt); | ||
assert.lengthOf( | ||
executors, | ||
1, | ||
'1 executor should have been created' | ||
); | ||
assert.equal( | ||
mockRun.callCount, | ||
1, | ||
'intern should have been run' | ||
); | ||
assert.deepEqual(executors[0].config, { foo: 'bar' }); | ||
setTimeout( | ||
dfd.callback(() => { | ||
assert.equal(mockDone.callCount, 1); | ||
assert.equal(mockDone.getCall(0).args[0], error); | ||
}) | ||
); | ||
|
||
const done = setupDone(); | ||
|
||
gruntTask(<any>mockGrunt); | ||
|
||
return done.then(() => { | ||
assert.lengthOf( | ||
executors, | ||
1, | ||
'1 executor should have been created' | ||
); | ||
assert.equal( | ||
mockRun.callCount, | ||
1, | ||
'intern should have been run' | ||
); | ||
assert.equal(mockDone.callCount, 1); | ||
assert.equal(mockDone.getCall(0).args[0], error); | ||
}); | ||
} | ||
} | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't need the
string[]
type since it can be inferred from the default arg. Also, should we have an overload that takes just anargv
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It'd also be nice to add typedoc @param comments so we can point out that
argv
args should at position 2.