PageRenderTime 39ms CodeModel.GetById 0ms RepoModel.GetById 1ms app.codeStats 0ms

/training-web/vendor/bundle/gems/sass-3.2.9/test/sass/plugin_test.rb

https://bitbucket.org/ohimmelreich/asalia-training
Ruby | 533 lines | 445 code | 80 blank | 8 comment | 33 complexity | 2c4921d328d68863e0cf57d311f6e388 MD5 | raw file
  1. #!/usr/bin/env ruby
  2. require File.dirname(__FILE__) + '/../test_helper'
  3. require File.dirname(__FILE__) + '/test_helper'
  4. require 'sass/plugin'
  5. require 'fileutils'
  6. module Sass::Script::Functions
  7. def filename
  8. filename = options[:filename].gsub(%r{.*((/[^/]+){4})}, '\1')
  9. Sass::Script::String.new(filename)
  10. end
  11. def whatever
  12. custom = options[:custom]
  13. whatever = custom && custom[:whatever]
  14. Sass::Script::String.new(whatever || "incorrect")
  15. end
  16. end
  17. class SassPluginTest < Test::Unit::TestCase
  18. @@templates = %w{
  19. complex script parent_ref import scss_import alt
  20. subdir/subdir subdir/nested_subdir/nested_subdir
  21. options import_content filename_fn
  22. }
  23. @@templates += %w[import_charset import_charset_ibm866] unless Sass::Util.ruby1_8?
  24. @@templates << 'import_charset_1_8' if Sass::Util.ruby1_8?
  25. @@cache_store = Sass::CacheStores::Memory.new
  26. def setup
  27. FileUtils.mkdir_p tempfile_loc
  28. FileUtils.mkdir_p tempfile_loc(nil,"more_")
  29. set_plugin_opts
  30. check_for_updates!
  31. reset_mtimes
  32. end
  33. def teardown
  34. clean_up_sassc
  35. Sass::Plugin.reset!
  36. FileUtils.rm_r tempfile_loc
  37. FileUtils.rm_r tempfile_loc(nil,"more_")
  38. end
  39. @@templates.each do |name|
  40. define_method("test_template_renders_correctly (#{name})") do
  41. assert_renders_correctly(name)
  42. end
  43. end
  44. def test_no_update
  45. File.delete(tempfile_loc('basic'))
  46. assert_needs_update 'basic'
  47. check_for_updates!
  48. assert_stylesheet_updated 'basic'
  49. end
  50. def test_update_needed_when_modified
  51. touch 'basic'
  52. assert_needs_update 'basic'
  53. check_for_updates!
  54. assert_stylesheet_updated 'basic'
  55. end
  56. def test_update_needed_when_dependency_modified
  57. touch 'basic'
  58. assert_needs_update 'import'
  59. check_for_updates!
  60. assert_stylesheet_updated 'basic'
  61. assert_stylesheet_updated 'import'
  62. end
  63. def test_update_needed_when_scss_dependency_modified
  64. touch 'scss_importee'
  65. assert_needs_update 'import'
  66. check_for_updates!
  67. assert_stylesheet_updated 'scss_importee'
  68. assert_stylesheet_updated 'import'
  69. end
  70. def test_scss_update_needed_when_dependency_modified
  71. touch 'basic'
  72. assert_needs_update 'scss_import'
  73. check_for_updates!
  74. assert_stylesheet_updated 'basic'
  75. assert_stylesheet_updated 'scss_import'
  76. end
  77. def test_update_needed_when_nested_import_dependency_modified
  78. touch 'basic'
  79. assert_needs_update 'nested_import'
  80. check_for_updates!
  81. assert_stylesheet_updated 'basic'
  82. assert_stylesheet_updated 'scss_import'
  83. end
  84. def test_no_updates_when_always_check_and_always_update_both_false
  85. Sass::Plugin.options[:always_update] = false
  86. Sass::Plugin.options[:always_check] = false
  87. touch 'basic'
  88. assert_needs_update 'basic'
  89. check_for_updates!
  90. # Check it's still stale
  91. assert_needs_update 'basic'
  92. end
  93. def test_full_exception_handling
  94. File.delete(tempfile_loc('bork1'))
  95. check_for_updates!
  96. File.open(tempfile_loc('bork1')) do |file|
  97. assert_equal(<<CSS.strip, file.read.split("\n")[0...6].join("\n"))
  98. /*
  99. Syntax error: Undefined variable: "$bork".
  100. on line 2 of #{template_loc('bork1')}
  101. 1: bork
  102. 2: :bork $bork
  103. CSS
  104. end
  105. File.delete(tempfile_loc('bork1'))
  106. end
  107. def test_single_level_import_loop
  108. File.delete(tempfile_loc('single_import_loop'))
  109. check_for_updates!
  110. File.open(tempfile_loc('single_import_loop')) do |file|
  111. assert_equal(<<CSS.strip, file.read.split("\n")[0...2].join("\n"))
  112. /*
  113. Syntax error: An @import loop has been found: #{template_loc('single_import_loop')} imports itself
  114. CSS
  115. end
  116. end
  117. def test_double_level_import_loop
  118. File.delete(tempfile_loc('double_import_loop1'))
  119. check_for_updates!
  120. File.open(tempfile_loc('double_import_loop1')) do |file|
  121. assert_equal(<<CSS.strip, file.read.split("\n")[0...4].join("\n"))
  122. /*
  123. Syntax error: An @import loop has been found:
  124. #{template_loc('double_import_loop1')} imports #{template_loc('_double_import_loop2')}
  125. #{template_loc('_double_import_loop2')} imports #{template_loc('double_import_loop1')}
  126. CSS
  127. end
  128. end
  129. def test_nonfull_exception_handling
  130. old_full_exception = Sass::Plugin.options[:full_exception]
  131. Sass::Plugin.options[:full_exception] = false
  132. File.delete(tempfile_loc('bork1'))
  133. assert_raise(Sass::SyntaxError) {check_for_updates!}
  134. ensure
  135. Sass::Plugin.options[:full_exception] = old_full_exception
  136. end
  137. def test_two_template_directories
  138. set_plugin_opts :template_location => {
  139. template_loc => tempfile_loc,
  140. template_loc(nil,'more_') => tempfile_loc(nil,'more_')
  141. }
  142. check_for_updates!
  143. ['more1', 'more_import'].each { |name| assert_renders_correctly(name, :prefix => 'more_') }
  144. end
  145. def test_two_template_directories_with_line_annotations
  146. set_plugin_opts :line_comments => true,
  147. :style => :nested,
  148. :template_location => {
  149. template_loc => tempfile_loc,
  150. template_loc(nil,'more_') => tempfile_loc(nil,'more_')
  151. }
  152. check_for_updates!
  153. assert_renders_correctly('more1_with_line_comments', 'more1', :prefix => 'more_')
  154. end
  155. def test_doesnt_render_partials
  156. assert !File.exists?(tempfile_loc('_partial'))
  157. end
  158. def test_template_location_array
  159. assert_equal [[template_loc, tempfile_loc]], Sass::Plugin.template_location_array
  160. end
  161. def test_add_template_location
  162. Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_"))
  163. assert_equal(
  164. [[template_loc, tempfile_loc], [template_loc(nil, "more_"), tempfile_loc(nil, "more_")]],
  165. Sass::Plugin.template_location_array)
  166. touch 'more1', 'more_'
  167. touch 'basic'
  168. assert_needs_update "more1", "more_"
  169. assert_needs_update "basic"
  170. check_for_updates!
  171. assert_doesnt_need_update "more1", "more_"
  172. assert_doesnt_need_update "basic"
  173. end
  174. def test_remove_template_location
  175. Sass::Plugin.add_template_location(template_loc(nil, "more_"), tempfile_loc(nil, "more_"))
  176. Sass::Plugin.remove_template_location(template_loc, tempfile_loc)
  177. assert_equal(
  178. [[template_loc(nil, "more_"), tempfile_loc(nil, "more_")]],
  179. Sass::Plugin.template_location_array)
  180. touch 'more1', 'more_'
  181. touch 'basic'
  182. assert_needs_update "more1", "more_"
  183. assert_needs_update "basic"
  184. check_for_updates!
  185. assert_doesnt_need_update "more1", "more_"
  186. assert_needs_update "basic"
  187. end
  188. def test_import_same_name
  189. assert_warning <<WARNING do
  190. WARNING: In #{template_loc}:
  191. There are multiple files that match the name "same_name_different_partiality.scss":
  192. _same_name_different_partiality.scss
  193. same_name_different_partiality.scss
  194. WARNING
  195. touch "_same_name_different_partiality"
  196. assert_needs_update "same_name_different_partiality"
  197. end
  198. end
  199. # Callbacks
  200. def test_updating_stylesheets_callback
  201. # Should run even when there's nothing to update
  202. Sass::Plugin.options[:template_location] = nil
  203. assert_callback :updating_stylesheets, []
  204. end
  205. def test_updating_stylesheets_callback_with_never_update
  206. Sass::Plugin.options[:never_update] = true
  207. assert_no_callback :updating_stylesheets
  208. end
  209. def test_updated_stylesheet_callback_for_updated_template
  210. Sass::Plugin.options[:always_update] = false
  211. touch 'basic'
  212. assert_no_callback :updated_stylesheet, template_loc("complex"), tempfile_loc("complex") do
  213. assert_callbacks(
  214. [:updated_stylesheet, template_loc("basic"), tempfile_loc("basic")],
  215. [:updated_stylesheet, template_loc("import"), tempfile_loc("import")])
  216. end
  217. end
  218. def test_updated_stylesheet_callback_for_fresh_template
  219. Sass::Plugin.options[:always_update] = false
  220. assert_no_callback :updated_stylesheet
  221. end
  222. def test_updated_stylesheet_callback_for_error_template
  223. Sass::Plugin.options[:always_update] = false
  224. touch 'bork1'
  225. assert_no_callback :updated_stylesheet
  226. end
  227. def test_not_updating_stylesheet_callback_for_fresh_template
  228. Sass::Plugin.options[:always_update] = false
  229. assert_callback :not_updating_stylesheet, template_loc("basic"), tempfile_loc("basic")
  230. end
  231. def test_not_updating_stylesheet_callback_for_updated_template
  232. Sass::Plugin.options[:always_update] = false
  233. assert_callback :not_updating_stylesheet, template_loc("complex"), tempfile_loc("complex") do
  234. assert_no_callbacks(
  235. [:updated_stylesheet, template_loc("basic"), tempfile_loc("basic")],
  236. [:updated_stylesheet, template_loc("import"), tempfile_loc("import")])
  237. end
  238. end
  239. def test_not_updating_stylesheet_callback_with_never_update
  240. Sass::Plugin.options[:never_update] = true
  241. assert_no_callback :not_updating_stylesheet
  242. end
  243. def test_not_updating_stylesheet_callback_for_partial
  244. Sass::Plugin.options[:always_update] = false
  245. assert_no_callback :not_updating_stylesheet, template_loc("_partial"), tempfile_loc("_partial")
  246. end
  247. def test_not_updating_stylesheet_callback_for_error
  248. Sass::Plugin.options[:always_update] = false
  249. touch 'bork1'
  250. assert_no_callback :not_updating_stylesheet, template_loc("bork1"), tempfile_loc("bork1")
  251. end
  252. def test_compilation_error_callback
  253. Sass::Plugin.options[:always_update] = false
  254. touch 'bork1'
  255. assert_callback(:compilation_error,
  256. lambda {|e| e.message == 'Undefined variable: "$bork".'},
  257. template_loc("bork1"), tempfile_loc("bork1"))
  258. end
  259. def test_compilation_error_callback_for_file_access
  260. Sass::Plugin.options[:always_update] = false
  261. assert_callback(:compilation_error,
  262. lambda {|e| e.is_a?(Errno::ENOENT)},
  263. template_loc("nonexistent"), tempfile_loc("nonexistent")) do
  264. Sass::Plugin.update_stylesheets([[template_loc("nonexistent"), tempfile_loc("nonexistent")]])
  265. end
  266. end
  267. def test_creating_directory_callback
  268. Sass::Plugin.options[:always_update] = false
  269. dir = File.join(tempfile_loc, "subdir", "nested_subdir")
  270. FileUtils.rm_r dir
  271. assert_callback :creating_directory, dir
  272. end
  273. ## Regression
  274. def test_cached_dependencies_update
  275. FileUtils.mv(template_loc("basic"), template_loc("basic", "more_"))
  276. set_plugin_opts :load_paths => [template_loc(nil, "more_")]
  277. touch 'basic', 'more_'
  278. assert_needs_update "import"
  279. check_for_updates!
  280. assert_renders_correctly("import")
  281. ensure
  282. FileUtils.mv(template_loc("basic", "more_"), template_loc("basic"))
  283. end
  284. def test_cached_relative_import
  285. old_always_update = Sass::Plugin.options[:always_update]
  286. Sass::Plugin.options[:always_update] = true
  287. check_for_updates!
  288. assert_renders_correctly('subdir/subdir')
  289. ensure
  290. Sass::Plugin.options[:always_update] = old_always_update
  291. end
  292. def test_cached_if
  293. set_plugin_opts :cache_store => Sass::CacheStores::Filesystem.new(tempfile_loc + '/cache')
  294. check_for_updates!
  295. assert_renders_correctly 'if'
  296. check_for_updates!
  297. assert_renders_correctly 'if'
  298. ensure
  299. set_plugin_opts
  300. end
  301. def test_cached_import_option
  302. set_plugin_opts :custom => {:whatever => "correct"}
  303. check_for_updates!
  304. assert_renders_correctly "cached_import_option"
  305. @@cache_store.reset!
  306. set_plugin_opts :custom => nil, :always_update => false
  307. check_for_updates!
  308. assert_renders_correctly "cached_import_option"
  309. set_plugin_opts :custom => {:whatever => "correct"}, :always_update => true
  310. check_for_updates!
  311. assert_renders_correctly "cached_import_option"
  312. ensure
  313. set_plugin_opts :custom => nil
  314. end
  315. private
  316. def assert_renders_correctly(*arguments)
  317. options = arguments.last.is_a?(Hash) ? arguments.pop : {}
  318. prefix = options[:prefix]
  319. result_name = arguments.shift
  320. tempfile_name = arguments.shift || result_name
  321. expected_str = File.read(result_loc(result_name, prefix))
  322. actual_str = File.read(tempfile_loc(tempfile_name, prefix))
  323. unless Sass::Util.ruby1_8?
  324. expected_str = expected_str.force_encoding('IBM866') if result_name == 'import_charset_ibm866'
  325. actual_str = actual_str.force_encoding('IBM866') if tempfile_name == 'import_charset_ibm866'
  326. end
  327. expected_lines = expected_str.split("\n")
  328. actual_lines = actual_str.split("\n")
  329. if actual_lines.first == "/*" && expected_lines.first != "/*"
  330. assert(false, actual_lines[0..Sass::Util.enum_with_index(actual_lines).find {|l, i| l == "*/"}.last].join("\n"))
  331. end
  332. expected_lines.zip(actual_lines).each_with_index do |pair, line|
  333. message = "template: #{result_name}\nline: #{line + 1}"
  334. assert_equal(pair.first, pair.last, message)
  335. end
  336. if expected_lines.size < actual_lines.size
  337. assert(false, "#{actual_lines.size - expected_lines.size} Trailing lines found in #{tempfile_name}.css: #{actual_lines[expected_lines.size..-1].join('\n')}")
  338. end
  339. end
  340. def assert_stylesheet_updated(name)
  341. assert_doesnt_need_update name
  342. # Make sure it isn't an exception
  343. expected_lines = File.read(result_loc(name)).split("\n")
  344. actual_lines = File.read(tempfile_loc(name)).split("\n")
  345. if actual_lines.first == "/*" && expected_lines.first != "/*"
  346. assert(false, actual_lines[0..actual_lines.enum_with_index.find {|l, i| l == "*/"}.last].join("\n"))
  347. end
  348. end
  349. def assert_callback(name, *expected_args)
  350. run = false
  351. received_args = nil
  352. Sass::Plugin.send("on_#{name}") do |*args|
  353. received_args = args
  354. run ||= expected_args.zip(received_args).all? do |ea, ra|
  355. ea.respond_to?(:call) ? ea.call(ra) : ea == ra
  356. end
  357. end
  358. if block_given?
  359. Sass::Util.silence_sass_warnings {yield}
  360. else
  361. check_for_updates!
  362. end
  363. assert run, "Expected #{name} callback to be run with arguments:\n #{expected_args.inspect}\nHowever, it got:\n #{received_args.inspect}"
  364. end
  365. def assert_no_callback(name, *unexpected_args)
  366. Sass::Plugin.send("on_#{name}") do |*a|
  367. next unless unexpected_args.empty? || a == unexpected_args
  368. msg = "Expected #{name} callback not to be run"
  369. if !unexpected_args.empty?
  370. msg << " with arguments #{unexpected_args.inspect}"
  371. elsif !a.empty?
  372. msg << ",\n was run with arguments #{a.inspect}"
  373. end
  374. flunk msg
  375. end
  376. if block_given?
  377. yield
  378. else
  379. check_for_updates!
  380. end
  381. end
  382. def assert_callbacks(*args)
  383. return check_for_updates! if args.empty?
  384. assert_callback(*args.pop) {assert_callbacks(*args)}
  385. end
  386. def assert_no_callbacks(*args)
  387. return check_for_updates! if args.empty?
  388. assert_no_callback(*args.pop) {assert_no_callbacks(*args)}
  389. end
  390. def check_for_updates!
  391. Sass::Util.silence_sass_warnings do
  392. Sass::Plugin.check_for_updates
  393. end
  394. end
  395. def assert_needs_update(*args)
  396. assert(Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), template_loc(*args)),
  397. "Expected #{template_loc(*args)} to need an update.")
  398. end
  399. def assert_doesnt_need_update(*args)
  400. assert(!Sass::Plugin::StalenessChecker.stylesheet_needs_update?(tempfile_loc(*args), template_loc(*args)),
  401. "Expected #{template_loc(*args)} not to need an update.")
  402. end
  403. def touch(*args)
  404. FileUtils.touch(template_loc(*args))
  405. end
  406. def reset_mtimes
  407. Sass::Plugin::StalenessChecker.dependencies_cache = {}
  408. atime = Time.now
  409. mtime = Time.now - 5
  410. Dir["{#{template_loc},#{tempfile_loc}}/**/*.{css,sass,scss}"].each {|f| File.utime(atime, mtime, f)}
  411. end
  412. def template_loc(name = nil, prefix = nil)
  413. if name
  414. scss = absolutize "#{prefix}templates/#{name}.scss"
  415. File.exists?(scss) ? scss : absolutize("#{prefix}templates/#{name}.sass")
  416. else
  417. absolutize "#{prefix}templates"
  418. end
  419. end
  420. def tempfile_loc(name = nil, prefix = nil)
  421. if name
  422. absolutize "#{prefix}tmp/#{name}.css"
  423. else
  424. absolutize "#{prefix}tmp"
  425. end
  426. end
  427. def result_loc(name = nil, prefix = nil)
  428. if name
  429. absolutize "#{prefix}results/#{name}.css"
  430. else
  431. absolutize "#{prefix}results"
  432. end
  433. end
  434. def set_plugin_opts(overrides = {})
  435. Sass::Plugin.options.merge!(
  436. :template_location => template_loc,
  437. :css_location => tempfile_loc,
  438. :style => :compact,
  439. :always_update => true,
  440. :never_update => false,
  441. :full_exception => true,
  442. :cache_store => @@cache_store
  443. )
  444. Sass::Plugin.options.merge!(overrides)
  445. end
  446. end
  447. class Sass::Engine
  448. alias_method :old_render, :render
  449. def render
  450. raise "bork bork bork!" if @template[0] == "{bork now!}"
  451. old_render
  452. end
  453. end