Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ var exec = require('child_process').exec;
var jsxTask = require('./grunt/tasks/jsx');
var browserifyTask = require('./grunt/tasks/browserify');
var wrapupTask = require('./grunt/tasks/wrapup');
var populistTask = require('./grunt/tasks/populist');
var phantomTask = require('./grunt/tasks/phantom');
var npmTask = require('./grunt/tasks/npm');
var releaseTasks = require('./grunt/tasks/release');
Expand All @@ -16,6 +17,7 @@ module.exports = function(grunt) {
jsx: require('./grunt/config/jsx/jsx'),
browserify: require('./grunt/config/browserify'),
wrapup: require('./grunt/config/wrapup'),
populist: require('./grunt/config/populist'),
phantom: require('./grunt/config/phantom'),
npm: require('./grunt/config/npm'),
clean: ['./build', './*.gem', './docs/_site', './examples/shared/*.js'],
Expand Down Expand Up @@ -44,6 +46,8 @@ module.exports = function(grunt) {
// defines global variables instead of using require.
grunt.registerMultiTask('wrapup', wrapupTask);

grunt.registerMultiTask('populist', populistTask);

grunt.registerMultiTask('phantom', phantomTask);

grunt.registerMultiTask('npm', npmTask);
Expand All @@ -52,11 +56,10 @@ module.exports = function(grunt) {
grunt.registerTask('build:transformer', ['jsx:debug', 'browserify:transformer']);
grunt.registerTask('build:min', ['jsx:release', 'browserify:min']);
grunt.registerTask('build:test', [
'jsx:debug',
'jsx:jasmine',
'jsx:test',
'browserify:jasmine',
'browserify:test'
'populist:test'
]);

grunt.registerTask('test', ['build:test', 'phantom:run']);
Expand Down
20 changes: 19 additions & 1 deletion bin/jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,23 @@ require("commoner").resolve(function(id) {

// Constant propagation means removing any obviously dead code after
// replacing constant expressions with literal (boolean) values.
return propagate(constants, source);
source = propagate(constants, source);

if (context.config.mocking) {
// Make sure there is exactly one newline at the end of the module.
source = source.replace(/\s+$/m, "\n");

return context.getProvidedP().then(function(idToPath) {
if (id !== "mock-modules" &&
id !== "mocks" &&
idToPath.hasOwnProperty("mock-modules")) {
return source + '\nrequire("mock-modules").register(' +
JSON.stringify(id) + ', module);\n';
}

return source;
});
}

return source;
});
2 changes: 1 addition & 1 deletion grunt/config/jsx/jsx.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ var test = {
"test/all.js",
"**/__tests__/*.js"
]),
configFile: debug.configFile,
configFile: "grunt/config/jsx/test.json",
sourceDir: "src",
outputDir: "build/modules"
};
Expand Down
7 changes: 7 additions & 0 deletions grunt/config/jsx/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"debug": true,
"mocking": true,
"constants": {
"__DEV__": true
}
}
13 changes: 13 additions & 0 deletions grunt/config/populist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';

var test = {
args: ["test/all:"],
requires: [
"**/__tests__/*-test.js"
],
outfile: './build/react-test.js'
};

module.exports = {
test: test
};
28 changes: 28 additions & 0 deletions grunt/tasks/populist.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
'use strict';

var grunt = require('grunt');

module.exports = function() {
var config = this.data;
var done = this.async();

// create the bundle we'll work with
var args = config.args;

// Make sure the things that need to be exposed are.
var requires = config.requires || {};
grunt.file.expand({
nonull: true, // Keep IDs that don't expand to anything.
cwd: "src"
}, requires).forEach(function(name) {
args.push(name.replace(/\.js$/i, ""));
});

require("populist").buildP({
rootDirectory: "build/modules",
args: args
}).then(function(output) {
grunt.file.write(config.outfile, output);
done();
});
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
"devDependencies": {
"browserify": "~2.24.1",
"wrapup": "~0.12.0",
"populist": "~0.1.2",
"grunt-cli": "~0.1.9",
"grunt": "~0.4.1",
"grunt-contrib-copy": "~0.4.1",
Expand Down
3 changes: 3 additions & 0 deletions src/test/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ var Ap = Array.prototype;
var slice = Ap.slice;
var Fp = Function.prototype;

var global = Function("return this")();
global.require = require;

if (!Fp.bind) {
// PhantomJS doesn't support Function.prototype.bind natively, so
// polyfill it whenever this module is required.
Expand Down
95 changes: 86 additions & 9 deletions src/test/mock-modules.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,95 @@
* @providesModule mock-modules
*/

var global = Function("return this")();
require('test/mock-timers').installMockTimers(global);
var mocks = require("mocks");
var exportsRegistry = {};
var hasOwn = exportsRegistry.hasOwnProperty;
var explicitMockMap = {};

exports.dumpCache = function() {
require("mocks").clear();
function getMock(exports) {
try {
return mocks.generateFromMetadata(mocks.getMetadata(exports));
} catch (err) {
console.warn(err);
return exports;
};
}
}

exports.dontMock = function() {
return exports;
// This function should be called at the bottom of any module that might
// need to be mocked, after the final value of module.exports is known.
exports.register = function(id, module) {
exportsRegistry[id] = {
module: module,
actual: module.exports,
mocked: null // Filled in lazily later.
};

// If doMock or doNotMock was called earlier, before the module was
// registered, then the choice should have been recorded in
// explicitMockMap. Now that the module is registered, we can finally
// fulfill the request.
if (hasOwn.call(explicitMockMap, id)) {
if (explicitMockMap[id]) {
doMock(id);
} else {
doNotMock(id);
}
}

return exports;
};

exports.mock = function() {
return exports;
function resetEntry(id) {
if (hasOwn.call(exportsRegistry, id)) {
delete exportsRegistry[id].module.exports;
delete exportsRegistry[id];
}
}

exports.dumpCache = function() {
require("mocks").clear();

// Deleting module.exports will cause the module to be lazily
// reevaluated the next time it is required.
for (var id in exportsRegistry) {
resetEntry(id);
}

return exports;
};

// Call this function to ensure that require(id) returns the actual
// exports object created by the module.
function doNotMock(id) {
explicitMockMap[id] = false;

var entry = exportsRegistry[id];
if (entry && entry.module && entry.actual) {
entry.module.exports = entry.actual;
}

return exports;
}

// Call this function to ensure that require(id) returns a mock exports
// object based on the actual exports object created by the module.
function doMock(id) {
explicitMockMap[id] = true;

var entry = exportsRegistry[id];
if (entry && entry.module && entry.actual) {
// Because mocking can be expensive, create the mock exports object on
// demand, the first time doMock is called.
entry.mocked || (entry.mocked = getMock(entry.actual));
entry.module.exports = entry.mocked;
}

return exports;
}

var global = Function("return this")();
require('test/mock-timers').installMockTimers(global);

// Exported names are different for backwards compatibility.
exports.dontMock = doNotMock;
exports.mock = doMock;
9 changes: 5 additions & 4 deletions src/test/mocks.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ function makeComponent(metadata) {
metadata.members.prototype.members) || {};

var f = function() {
dirtyMocks.push(f);
global.dirtyMocks.push(f);

instances.push(this);
calls.push(Array.prototype.slice.call(arguments));
Expand Down Expand Up @@ -305,16 +305,17 @@ function removeUnusedRefs(metadata) {
});
}

var dirtyMocks = [];
var global = Function("return this")();
global.dirtyMocks = global.dirtyMocks || [];

module.exports = {
/**
* Invokes the .mockClear method of all function mocks that have been
* called since the last time clear was called.
*/
clear: function() {
var old = dirtyMocks;
dirtyMocks = [];
var old = global.dirtyMocks;
global.dirtyMocks = [];
old.forEach(function(mock) {
mock.mockClear();
});
Expand Down