UNPKG

4.66 kBJavaScriptView Raw
1// Load our dependencies
2var stringify = require('../common/stringify')
3
4// Define our context Karma constructor
5var ContextKarma = function (callParentKarmaMethod) {
6 // Define local variables
7 var hasError = false
8 var self = this
9
10 // Define our loggers
11 // DEV: These are intentionally repeated in client and context
12 this.log = function (type, args) {
13 var values = []
14
15 for (var i = 0; i < args.length; i++) {
16 values.push(this.stringify(args[i], 3))
17 }
18
19 this.info({log: values.join(', '), type: type})
20 }
21
22 this.stringify = stringify
23
24 // Define our proxy error handler
25 // DEV: We require one in our context to track `hasError`
26 this.error = function () {
27 hasError = true
28 callParentKarmaMethod('error', [].slice.call(arguments))
29 return false
30 }
31
32 // Define our start handler
33 var UNIMPLEMENTED_START = function () {
34 this.error('You need to include some adapter that implements __karma__.start method!')
35 }
36 // all files loaded, let's start the execution
37 this.loaded = function () {
38 // has error -> cancel
39 if (!hasError) {
40 this.start(this.config)
41 }
42
43 // remove reference to child iframe
44 this.start = UNIMPLEMENTED_START
45 }
46 // supposed to be overriden by the context
47 // TODO(vojta): support multiple callbacks (queue)
48 this.start = UNIMPLEMENTED_START
49
50 // Define proxy methods
51 // DEV: This is a closured `for` loop (same as a `forEach`) for IE support
52 var proxyMethods = ['complete', 'info', 'result']
53 for (var i = 0; i < proxyMethods.length; i++) {
54 (function bindProxyMethod (methodName) {
55 self[methodName] = function boundProxyMethod () {
56 callParentKarmaMethod(methodName, [].slice.call(arguments))
57 }
58 }(proxyMethods[i]))
59 }
60
61 // Define bindings for context window
62 this.setupContext = function (contextWindow) {
63 // If we clear the context after every run and we already had an error
64 // then stop now. Otherwise, carry on.
65 if (self.config.clearContext && hasError) {
66 return
67 }
68
69 // Perform window level bindings
70 // DEV: We return `self.error` since we want to `return false` to ignore errors
71 contextWindow.onerror = function () {
72 return self.error.apply(self, arguments)
73 }
74 // DEV: We must defined a function since we don't want to pass the event object
75 contextWindow.onbeforeunload = function (e, b) {
76 callParentKarmaMethod('onbeforeunload', [])
77 }
78
79 contextWindow.dump = function () {
80 self.log('dump', arguments)
81 }
82
83 var _confirm = contextWindow.confirm
84 var _prompt = contextWindow.prompt
85
86 contextWindow.alert = function (msg) {
87 self.log('alert', [msg])
88 }
89
90 contextWindow.confirm = function (msg) {
91 self.log('confirm', [msg])
92 return _confirm(msg)
93 }
94
95 contextWindow.prompt = function (msg, defaultVal) {
96 self.log('prompt', [msg, defaultVal])
97 return _prompt(msg, defaultVal)
98 }
99
100 // If we want to overload our console, then do it
101 var getConsole = function (currentWindow) {
102 return currentWindow.console || {
103 log: function () {},
104 info: function () {},
105 warn: function () {},
106 error: function () {},
107 debug: function () {}
108 }
109 }
110 if (self.config.captureConsole) {
111 // patch the console
112 var localConsole = contextWindow.console = getConsole(contextWindow)
113 var logMethods = ['log', 'info', 'warn', 'error', 'debug']
114 var patchConsoleMethod = function (method) {
115 var orig = localConsole[method]
116 if (!orig) {
117 return
118 }
119 localConsole[method] = function () {
120 self.log(method, arguments)
121 return Function.prototype.apply.call(orig, localConsole, arguments)
122 }
123 }
124 for (var i = 0; i < logMethods.length; i++) {
125 patchConsoleMethod(logMethods[i])
126 }
127 }
128 }
129}
130
131// Define call/proxy methods
132ContextKarma.getDirectCallParentKarmaMethod = function (parentWindow) {
133 return function directCallParentKarmaMethod (method, args) {
134 // If the method doesn't exist, then error out
135 if (!parentWindow.karma[method]) {
136 parentWindow.karma.error('Expected Karma method "' + method + '" to exist but it doesn\'t')
137 return
138 }
139
140 // Otherwise, run our method
141 parentWindow.karma[method].apply(parentWindow.karma, args)
142 }
143}
144ContextKarma.getPostMessageCallParentKarmaMethod = function (parentWindow) {
145 return function postMessageCallParentKarmaMethod (method, args) {
146 parentWindow.postMessage({__karmaMethod: method, __karmaArguments: args}, window.location.origin)
147 }
148}
149
150// Export our module
151module.exports = ContextKarma