common.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* Add js reporter for sauce */
  2. jasmine.getEnv().addReporter(new jasmine.JSReporter2());
  3. /* record log messages for testing */
  4. var logMessages = [];
  5. window.less = window.less || {};
  6. var logLevel_debug = 4,
  7. logLevel_info = 3,
  8. logLevel_warn = 2,
  9. logLevel_error = 1;
  10. // The amount of logging in the javascript console.
  11. // 3 - Debug, information and errors
  12. // 2 - Information and errors
  13. // 1 - Errors
  14. // 0 - None
  15. // Defaults to 2
  16. less.loggers = [
  17. {
  18. debug: function(msg) {
  19. if (less.options.logLevel >= logLevel_debug) {
  20. logMessages.push(msg);
  21. }
  22. },
  23. info: function(msg) {
  24. if (less.options.logLevel >= logLevel_info) {
  25. logMessages.push(msg);
  26. }
  27. },
  28. warn: function(msg) {
  29. if (less.options.logLevel >= logLevel_warn) {
  30. logMessages.push(msg);
  31. }
  32. },
  33. error: function(msg) {
  34. if (less.options.logLevel >= logLevel_error) {
  35. logMessages.push(msg);
  36. }
  37. }
  38. }
  39. ];
  40. var testLessEqualsInDocument = function () {
  41. testLessInDocument(testSheet);
  42. };
  43. var testLessErrorsInDocument = function (isConsole) {
  44. testLessInDocument(isConsole ? testErrorSheetConsole : testErrorSheet);
  45. };
  46. var testLessInDocument = function (testFunc) {
  47. var links = document.getElementsByTagName('link'),
  48. typePattern = /^text\/(x-)?less$/;
  49. for (var i = 0; i < links.length; i++) {
  50. if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
  51. (links[i].type.match(typePattern)))) {
  52. testFunc(links[i]);
  53. }
  54. }
  55. };
  56. var ieFormat = function(text) {
  57. var styleNode = document.createElement('style');
  58. styleNode.setAttribute('type', 'text/css');
  59. var headNode = document.getElementsByTagName('head')[0];
  60. headNode.appendChild(styleNode);
  61. try {
  62. if (styleNode.styleSheet) {
  63. styleNode.styleSheet.cssText = text;
  64. } else {
  65. styleNode.innerText = text;
  66. }
  67. } catch (e) {
  68. throw new Error("Couldn't reassign styleSheet.cssText.");
  69. }
  70. var transformedText = styleNode.styleSheet ? styleNode.styleSheet.cssText : styleNode.innerText;
  71. headNode.removeChild(styleNode);
  72. return transformedText;
  73. };
  74. var testSheet = function (sheet) {
  75. it(sheet.id + " should match the expected output", function (done) {
  76. var lessOutputId = sheet.id.replace("original-", ""),
  77. expectedOutputId = "expected-" + lessOutputId,
  78. lessOutputObj,
  79. lessOutput,
  80. expectedOutputHref = document.getElementById(expectedOutputId).href,
  81. expectedOutput = loadFile(expectedOutputHref);
  82. // Browser spec generates less on the fly, so we need to loose control
  83. less.pageLoadFinished
  84. .then(function () {
  85. lessOutputObj = document.getElementById(lessOutputId);
  86. lessOutput = lessOutputObj.styleSheet ? lessOutputObj.styleSheet.cssText :
  87. (lessOutputObj.innerText || lessOutputObj.innerHTML);
  88. expectedOutput
  89. .then(function (text) {
  90. if (window.navigator.userAgent.indexOf("MSIE") >= 0 ||
  91. window.navigator.userAgent.indexOf("Trident/") >= 0) {
  92. text = ieFormat(text);
  93. }
  94. expect(lessOutput).toEqual(text);
  95. done();
  96. });
  97. });
  98. });
  99. };
  100. //TODO: do it cleaner - the same way as in css
  101. function extractId(href) {
  102. return href.replace(/^[a-z-]+:\/+?[^\/]+/i, '') // Remove protocol & domain
  103. .replace(/^\//, '') // Remove root /
  104. .replace(/\.[a-zA-Z]+$/, '') // Remove simple extension
  105. .replace(/[^\.\w-]+/g, '-') // Replace illegal characters
  106. .replace(/\./g, ':'); // Replace dots with colons(for valid id)
  107. }
  108. var waitFor = function (waitFunc) {
  109. return new Promise(function (resolve) {
  110. var timeoutId = setInterval(function () {
  111. if (waitFunc()) {
  112. clearInterval(timeoutId);
  113. resolve();
  114. }
  115. }, 5);
  116. });
  117. };
  118. var testErrorSheet = function (sheet) {
  119. it(sheet.id + " should match an error", function (done) {
  120. var lessHref = sheet.href,
  121. id = "less-error-message:" + extractId(lessHref),
  122. errorHref = lessHref.replace(/.less$/, ".txt"),
  123. errorFile = loadFile(errorHref),
  124. actualErrorElement,
  125. actualErrorMsg;
  126. // Less.js sets 10ms timer in order to add error message on top of page.
  127. waitFor(function () {
  128. actualErrorElement = document.getElementById(id);
  129. return actualErrorElement !== null;
  130. }).then(function () {
  131. var innerText = (actualErrorElement.innerHTML
  132. .replace(/<h3>|<\/?p>|<a href="[^"]*">|<\/a>|<ul>|<\/?pre( class="?[^">]*"?)?>|<\/li>|<\/?label>/ig, "")
  133. .replace(/<\/h3>/ig, " ")
  134. .replace(/<li>|<\/ul>|<br>/ig, "\n"))
  135. .replace(/&amp;/ig, "&")
  136. // for IE8
  137. .replace(/\r\n/g, "\n")
  138. .replace(/\. \nin/, ". in");
  139. actualErrorMsg = innerText
  140. .replace(/\n\d+/g, function (lineNo) {
  141. return lineNo + " ";
  142. })
  143. .replace(/\n\s*in /g, " in ")
  144. .replace(/\n{2,}/g, "\n")
  145. .replace(/\nStack Trace\n[\s\S]*/i, "")
  146. .replace(/\n$/, "");
  147. errorFile
  148. .then(function (errorTxt) {
  149. errorTxt = errorTxt
  150. .replace(/\{path\}/g, "")
  151. .replace(/\{pathrel\}/g, "")
  152. .replace(/\{pathhref\}/g, "http://localhost:8081/test/less/errors/")
  153. .replace(/\{404status\}/g, " (404)")
  154. .replace(/\{node\}.*\{\/node\}/g, "")
  155. .replace(/\n$/, "");
  156. expect(actualErrorMsg).toEqual(errorTxt);
  157. if (errorTxt == actualErrorMsg) {
  158. actualErrorElement.style.display = "none";
  159. }
  160. done();
  161. });
  162. });
  163. });
  164. };
  165. var testErrorSheetConsole = function (sheet) {
  166. it(sheet.id + " should match an error", function (done) {
  167. var lessHref = sheet.href,
  168. id = sheet.id.replace(/^original-less:/, "less-error-message:"),
  169. errorHref = lessHref.replace(/.less$/, ".txt"),
  170. errorFile = loadFile(errorHref),
  171. actualErrorElement = document.getElementById(id),
  172. actualErrorMsg = logMessages[logMessages.length - 1]
  173. .replace(/\nStack Trace\n[\s\S]*/, "");
  174. describe("the error", function () {
  175. expect(actualErrorElement).toBe(null);
  176. });
  177. errorFile
  178. .then(function (errorTxt) {
  179. errorTxt
  180. .replace(/\{path\}/g, "")
  181. .replace(/\{pathrel\}/g, "")
  182. .replace(/\{pathhref\}/g, "http://localhost:8081/browser/less/")
  183. .replace(/\{404status\}/g, " (404)")
  184. .replace(/\{node\}.*\{\/node\}/g, "")
  185. .trim();
  186. expect(actualErrorMsg).toEqual(errorTxt);
  187. done();
  188. });
  189. });
  190. };
  191. var loadFile = function (href) {
  192. return new Promise(function (resolve, reject) {
  193. var request = new XMLHttpRequest();
  194. request.open('GET', href, true);
  195. request.onreadystatechange = function () {
  196. if (request.readyState == 4) {
  197. resolve(request.responseText.replace(/\r/g, ""));
  198. }
  199. };
  200. request.send(null);
  201. });
  202. };
  203. jasmine.DEFAULT_TIMEOUT_INTERVAL = 90000;