1 |
|
2 | var _, abs_path, each_sub_mod, esprima, fs, get, if_assignment_statement, if_variable_declaration, internal_modules, load, matches_module, mock, parse_private_modules, path, resolve, rewire, set;
|
3 |
|
4 | path = require("path");
|
5 |
|
6 | resolve = require("resolve");
|
7 |
|
8 | fs = require("fs");
|
9 |
|
10 | rewire = require("rewire");
|
11 |
|
12 | _ = require("lodash");
|
13 |
|
14 | esprima = require("esprima");
|
15 |
|
16 | mock = require("./mock");
|
17 |
|
18 | set = function(wired, path, value) {
|
19 | return wired.__set__(path, value);
|
20 | };
|
21 |
|
22 | get = function(wired, path) {
|
23 | return wired.__get__(path);
|
24 | };
|
25 |
|
26 | if_variable_declaration = function(node, base, list) {
|
27 | if (!node || node.type !== "VariableDeclaration") {
|
28 | return;
|
29 | }
|
30 | return _.each(node.declarations, function(declare) {
|
31 | var mod_loc, statement, statement_args;
|
32 | statement = declare && declare.type === "VariableDeclarator" && declare.init;
|
33 | if (!statement) {
|
34 | return;
|
35 | }
|
36 | if (statement.callee && statement.callee.name === "require") {
|
37 | statement_args = statement["arguments"] && statement["arguments"].length > 0;
|
38 | mod_loc = statement_args ? statement["arguments"][0].value : void 0;
|
39 | return list.push({
|
40 | name: declare.id ? declare.id.name : void 0,
|
41 | path: mod_loc
|
42 | });
|
43 | }
|
44 | });
|
45 | };
|
46 |
|
47 | if_assignment_statement = function(node, base, list) {
|
48 | var exp, mod_loc, name, right_args;
|
49 | exp = node && node.type === "ExpressionStatement" && node.expression;
|
50 | if (exp.type === "AssignmentExpression" && exp.right && exp.left && exp.right.type === "CallExpression" && exp.right.callee.name === "require") {
|
51 | name = (function() {
|
52 | switch (false) {
|
53 | case exp.left.type !== "Identifier":
|
54 | return exp.left.name;
|
55 | default:
|
56 | return name = exp.left.object.name + "." + exp.left.property.name;
|
57 | }
|
58 | })();
|
59 | right_args = exp.right["arguments"] && exp.right["arguments"].length > 0;
|
60 | mod_loc = right_args ? exp.right["arguments"][0].value : void 0;
|
61 | return list.push({
|
62 | name: name,
|
63 | path: mod_loc
|
64 | });
|
65 | }
|
66 | };
|
67 |
|
68 | internal_modules = function(ast, base, list) {
|
69 | if (!list) {
|
70 | list = [];
|
71 | }
|
72 | if (!ast || !ast.body) {
|
73 | return list;
|
74 | }
|
75 | _.each(ast.body, function(node) {
|
76 | if_variable_declaration(node, base, list);
|
77 | if_assignment_statement(node, base, list);
|
78 | return internal_modules(node, base, list);
|
79 | });
|
80 | return list;
|
81 | };
|
82 |
|
83 | abs_path = function(loc, base) {
|
84 | return resolve.sync(loc, {
|
85 | basedir: base || ""
|
86 | });
|
87 | };
|
88 |
|
89 | each_sub_mod = function(file) {
|
90 | var ast, base, data, mods;
|
91 | base = path.dirname(file);
|
92 | mods = null;
|
93 | if (fs.existsSync(file)) {
|
94 | data = fs.readFileSync(file, "utf-8");
|
95 | if (data) {
|
96 | ast = esprima.parse(data);
|
97 | mods = internal_modules(ast, base);
|
98 | }
|
99 | }
|
100 | return mods || [];
|
101 | };
|
102 |
|
103 | matches_module = function(mod, base) {
|
104 | return function(compare) {
|
105 | return compare === mod.path;
|
106 | };
|
107 | };
|
108 |
|
109 | parse_private_modules = function(module_path, wired, accept) {
|
110 | return each_sub_mod(module_path).forEach(function(mod) {
|
111 | var obj;
|
112 | if (!accept.some(matches_module(mod, module_path))) {
|
113 | return;
|
114 | }
|
115 | obj = get(wired, mod.name);
|
116 | _.each(Object.keys(obj), function(key) {
|
117 | if (typeof obj[key] !== "function") {
|
118 | return;
|
119 | }
|
120 | return obj[key] = mock.stub(obj, key);
|
121 | });
|
122 | if (typeof obj === "function") {
|
123 | return set(wired, mod.name, _.extend(mock.stub(), obj));
|
124 | }
|
125 | });
|
126 | };
|
127 |
|
128 | load = function(module_path, base, accept) {
|
129 | var full_path, wired;
|
130 | if (accept == null) {
|
131 | accept = [];
|
132 | }
|
133 | full_path = abs_path(module_path, base);
|
134 | wired = rewire(full_path);
|
135 | parse_private_modules(full_path, wired, accept);
|
136 | return wired;
|
137 | };
|
138 |
|
139 | module.exports = {
|
140 | set: set,
|
141 | get: get,
|
142 | load: load
|
143 | };
|