|
| 1 | +/* |
| 2 | + Speclj Runner |
| 3 | +
|
| 4 | + Usage: |
| 5 | + phantomjs resources/public/specs/speclj.js [auto] |
| 6 | +
|
| 7 | + auto: will only run specs updated after the last run. (default: false) |
| 8 | +
|
| 9 | + Each run produced/touches a timestamp file, .specljs-timestamp |
| 10 | + */ |
| 11 | + |
| 12 | +var outputDir = "target/cljs"; |
| 13 | +var nsPrefix = "speclj"; |
| 14 | +var runnerFile = "bin/specs.html"; |
| 15 | + |
| 16 | +var fs = require("fs"); |
| 17 | +var p = require('webpage').create(); |
| 18 | +var system = require('system'); |
| 19 | + |
| 20 | +String.prototype.endsWith = function (suffix) { |
| 21 | + return this.indexOf(suffix, this.length - suffix.length) !== -1; |
| 22 | +}; |
| 23 | +String.prototype.startsWith = function (str) { |
| 24 | + return this.slice(0, str.length) == str; |
| 25 | +}; |
| 26 | + |
| 27 | +p.onConsoleMessage = function (x) { |
| 28 | + fs.write("/dev/stdout", x, "w"); |
| 29 | +}; |
| 30 | + |
| 31 | +var timestampFile = ".specljs-timestamp"; |
| 32 | +writeTimestamp = function () { |
| 33 | + if(fs.lastModified(timestampFile) != null) |
| 34 | + fs.remove(timestampFile); |
| 35 | + fs.touch(timestampFile); |
| 36 | +}; |
| 37 | + |
| 38 | +readTimestamp = function () { |
| 39 | + return fs.lastModified(timestampFile); |
| 40 | +}; |
| 41 | + |
| 42 | +allSpecsFilter = function () { |
| 43 | + return true; |
| 44 | +}; |
| 45 | + |
| 46 | +var autoMode = function () { |
| 47 | + return system.args[1] == "auto" && readTimestamp() != null; |
| 48 | +}; |
| 49 | + |
| 50 | +var logList = function (title, list) { |
| 51 | + console.log(title + ":"); |
| 52 | + for(var i in list) |
| 53 | + console.log(i); |
| 54 | +}; |
| 55 | + |
| 56 | +var relativeRoot = outputDir + "/goog/"; |
| 57 | +findUpdatedSpecs = function (rdeps, deps) { |
| 58 | + var minMillis = readTimestamp().getTime(); |
| 59 | + var updated = {}; |
| 60 | + for(var ns in rdeps) { |
| 61 | + var file = deps.nameToPath[ns]; |
| 62 | + var path = relativeRoot + file; |
| 63 | + if(fs.lastModified(path).getTime() >= minMillis) { |
| 64 | + updated[ns] = true; |
| 65 | + } |
| 66 | + } |
| 67 | + return updated; |
| 68 | +}; |
| 69 | + |
| 70 | +buildReverseDeps = function (deps) { |
| 71 | + var rdeps = {}; |
| 72 | + for(var ns in deps.nameToPath) { |
| 73 | + if(ns.startsWith(nsPrefix)) { |
| 74 | + var file = deps.nameToPath[ns]; |
| 75 | + for(var rdep in deps.requires[file]) { |
| 76 | + if(rdep.startsWith(nsPrefix)) { |
| 77 | + if(!(rdep in rdeps)) { |
| 78 | + rdeps[rdep] = {} |
| 79 | + } |
| 80 | + rdeps[rdep][ns] = true; |
| 81 | + } |
| 82 | + } |
| 83 | + if(!(ns in rdeps)) { |
| 84 | + rdeps[ns] = {} |
| 85 | + } |
| 86 | + } |
| 87 | + } |
| 88 | + return rdeps; |
| 89 | +}; |
| 90 | + |
| 91 | +reduceToSpecs = function (affected) { |
| 92 | + var result = {}; |
| 93 | + for(var ns in affected) { |
| 94 | + if(ns.endsWith("_spec")) { |
| 95 | + result[ns.replace(/_/g, "-")] = true |
| 96 | + } |
| 97 | + } |
| 98 | + return result; |
| 99 | +}; |
| 100 | + |
| 101 | +findAffectedSpecs = function () { |
| 102 | + var deps = p.evaluate(function () { |
| 103 | + return goog.dependencies_; |
| 104 | + }); |
| 105 | + var rdeps = buildReverseDeps(deps); |
| 106 | + var updated = findUpdatedSpecs(rdeps, deps); |
| 107 | + |
| 108 | + var result = {}; |
| 109 | + |
| 110 | + var walkDeps = function (nses) { |
| 111 | + for(var ns in nses) { |
| 112 | + if(!(ns in result)) { |
| 113 | + result[ns] = true; |
| 114 | + walkDeps(rdeps[ns]) |
| 115 | + } |
| 116 | + } |
| 117 | + }; |
| 118 | + walkDeps(updated); |
| 119 | + |
| 120 | + return reduceToSpecs(result); |
| 121 | +}; |
| 122 | + |
| 123 | +p.open(runnerFile, function (status) { |
| 124 | + try { |
| 125 | + var specs = autoMode() ? findAffectedSpecs() : null; |
| 126 | + |
| 127 | + var result = p.evaluate(function (specSet) { |
| 128 | + return runSpecsPhantom(specSet); |
| 129 | + }, specs); |
| 130 | + |
| 131 | + writeTimestamp(); |
| 132 | + phantom.exit(result); |
| 133 | + } |
| 134 | + catch(e) { |
| 135 | + console.error(e); |
| 136 | + phantom.exit(-1); |
| 137 | + } |
| 138 | + |
| 139 | +}); |
0 commit comments