2 * Karma middleware is responsible for serving:
3 * - client.html (the entrypoint for capturing a browser)
5 * - context.html (the execution context, loaded within an iframe)
8 * The main part is generating context.html, as it contains:
9 * - generating mappings
10 * - including <script> and <link> tags
11 * - setting propert caching headers
14 var path = require('path')
15 var util = require('util')
16 var url = require('url')
18 var urlparse = function (urlStr) {
19 var urlObj = url.parse(urlStr, true)
20 urlObj.query = urlObj.query || {}
24 var common = require('./common')
26 var VERSION = require('../constants').VERSION
27 var SCRIPT_TAG = '<script type="%s" src="%s"></script>'
28 var LINK_TAG_CSS = '<link type="text/css" href="%s" rel="stylesheet">'
29 var LINK_TAG_HTML = '<link href="%s" rel="import">'
31 '.js': 'text/javascript',
32 '.dart': 'application/dart'
35 var filePathToUrlPath = function (filePath, basePath) {
36 if (filePath.indexOf(basePath) === 0) {
37 return '/base' + filePath.substr(basePath.length)
40 return '/absolute' + filePath
43 var getXUACompatibleMetaElement = function (url) {
45 var urlObj = urlparse(url)
46 if (urlObj.query['x-ua-compatible']) {
47 tag = '\n<meta http-equiv="X-UA-Compatible" content="' +
48 urlObj.query['x-ua-compatible'] + '"/>'
53 var getXUACompatibleUrl = function (url) {
55 var urlObj = urlparse(url)
56 if (urlObj.query['x-ua-compatible']) {
57 value = '?x-ua-compatible=' + encodeURIComponent(urlObj.query['x-ua-compatible'])
62 var createKarmaMiddleware = function (filesPromise, serveStaticFile,
63 /* config.basePath */ basePath, /* config.urlRoot */ urlRoot, /* config.client */ client) {
64 return function (request, response, next) {
65 var requestUrl = request.normalizedUrl.replace(/\?.*/, '')
67 // redirect /__karma__ to /__karma__ (trailing slash)
68 if (requestUrl === urlRoot.substr(0, urlRoot.length - 1)) {
69 response.setHeader('Location', urlRoot)
70 response.writeHead(301)
71 return response.end('MOVED PERMANENTLY')
74 // ignore urls outside urlRoot
75 if (requestUrl.indexOf(urlRoot) !== 0) {
79 // remove urlRoot prefix
80 requestUrl = requestUrl.substr(urlRoot.length - 1)
83 if (requestUrl === '/') {
84 return serveStaticFile('/client.html', response, function (data) {
86 .replace('\n%X_UA_COMPATIBLE%', getXUACompatibleMetaElement(request.url))
87 .replace('%X_UA_COMPATIBLE_URL%', getXUACompatibleUrl(request.url))
92 if (requestUrl === '/karma.js') {
93 return serveStaticFile(requestUrl, response, function (data) {
94 return data.replace('%KARMA_URL_ROOT%', urlRoot)
95 .replace('%KARMA_VERSION%', VERSION)
100 if (requestUrl === '/favicon.ico') {
101 return serveStaticFile(requestUrl, response)
104 // serve context.html - execution context within the iframe
105 // or debug.html - execution context without channel to the server
106 if (requestUrl === '/context.html' || requestUrl === '/debug.html') {
107 return filesPromise.then(function (files) {
108 serveStaticFile(requestUrl, response, function (data) {
109 common.setNoCacheHeaders(response)
111 var scriptTags = files.included.map(function (file) {
112 var filePath = file.path
113 var fileExt = path.extname(filePath)
116 // TODO(vojta): serve these files from within urlRoot as well
117 filePath = filePathToUrlPath(filePath, basePath)
119 if (requestUrl === '/context.html') {
120 filePath += '?' + file.sha
124 if (fileExt === '.css') {
125 return util.format(LINK_TAG_CSS, filePath)
128 if (fileExt === '.html') {
129 return util.format(LINK_TAG_HTML, filePath)
132 return util.format(SCRIPT_TAG, SCRIPT_TYPE[fileExt] || 'text/javascript', filePath)
135 // TODO(vojta): don't compute if it's not in the template
136 var mappings = files.served.map(function (file) {
137 // Windows paths contain backslashes and generate bad IDs if not escaped
138 var filePath = filePathToUrlPath(file.path, basePath).replace(/\\/g, '\\\\')
140 return util.format(" '%s': '%s'", filePath, file.sha)
143 var clientConfig = ''
145 if (requestUrl === '/debug.html') {
146 clientConfig = 'window.__karma__.config = ' + JSON.stringify(client) + ';\n'
149 mappings = 'window.__karma__.files = {\n' + mappings.join(',\n') + '\n};\n'
152 .replace('%SCRIPTS%', scriptTags.join('\n'))
153 .replace('%CLIENT_CONFIG%', clientConfig)
154 .replace('%MAPPINGS%', mappings)
155 .replace('\n%X_UA_COMPATIBLE%', getXUACompatibleMetaElement(request.url))
157 }, function (errorFiles) {
158 serveStaticFile(requestUrl, response, function (data) {
159 common.setNoCacheHeaders(response)
160 return data.replace('%SCRIPTS%', '').replace('%CLIENT_CONFIG%', '').replace('%MAPPINGS%',
161 'window.__karma__.error("TEST RUN WAS CANCELLED because ' +
162 (errorFiles.length > 1 ? 'these files contain' : 'this file contains') +
163 ' some errors:\\n ' + errorFiles.join('\\n ') + '");')
172 createKarmaMiddleware.$inject = ['filesPromise', 'serveStaticFile',
173 'config.basePath', 'config.urlRoot', 'config.client']
176 exports.create = createKarmaMiddleware