File: compiler_test.rb

package info (click to toggle)
ruby-sass 3.7.4-6
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 3,396 kB
  • sloc: ruby: 32,443; sh: 26; makefile: 25
file content (225 lines) | stat: -rwxr-xr-x 5,568 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
require 'minitest/autorun'
require File.dirname(__FILE__) + '/../test_helper'
require 'sass/plugin'
require 'sass/plugin/compiler'

class CompilerTest < Minitest::Test
  class FakeListener
    attr_accessor :options
    attr_accessor :directories
    attr_reader :start_called
    attr_reader :thread

    def initialize(*args, &on_filesystem_event)
      self.options = args.last.is_a?(Hash) ? args.pop : {}
      self.directories = args
      @on_filesystem_event = on_filesystem_event
      @start_called = false
      reset_events!
    end

    def fire_events!(*args)
      @on_filesystem_event.call(@modified, @added, @removed)
      reset_events!
    end

    def changed(filename)
      @modified << File.expand_path(filename)
    end

    def added(filename)
      @added << File.expand_path(filename)
    end

    def removed(filename)
      @removed << File.expand_path(filename)
    end

    def on_start!(&run_during_start)
      @run_during_start = run_during_start
    end

    def start!
      @run_during_start.call(self) if @run_during_start
    end

    def start
      parent = Thread.current
      @thread = Thread.new do
        @run_during_start.call(self) if @run_during_start
        parent.raise Interrupt
      end
    end

    def stop
    end

    def reset_events!
      @modified = []
      @added = []
      @removed = []
    end
  end

  module MockWatcher
    attr_accessor :run_during_start
    attr_accessor :update_stylesheets_times
    attr_accessor :update_stylesheets_called_with
    attr_accessor :deleted_css_files

    def fake_listener
      @fake_listener
    end

    def update_stylesheets(individual_files)
      @update_stylesheets_times ||= 0
      @update_stylesheets_times += 1
      (@update_stylesheets_called_with ||= []) << individual_files
    end

    def try_delete_css(css_filename)
      (@deleted_css_files ||= []) << css_filename
    end

    private
    def create_listener(*args, &on_filesystem_event)
      args.pop if args.last.is_a?(Hash)
      @fake_listener = FakeListener.new(*args, &on_filesystem_event)
      @fake_listener.on_start!(&run_during_start)
      @fake_listener
    end
  end

  def test_initialize
    watcher
  end

  def test_watch_starts_the_listener
    start_called = false
    c = watcher do |listener|
      start_called = true
    end
    c.watch
    assert start_called, "start! was not called"
  end

  def test_sass_callbacks_fire_from_listener_events
    c = watcher do |listener|
      listener.changed "changed.scss"
      listener.added "added.scss"
      listener.removed "removed.scss"
      listener.fire_events!
    end

    modified_fired = false
    c.on_template_modified do |sass_file|
      modified_fired = true
      assert_equal "changed.scss", sass_file
    end

    added_fired = false
    c.on_template_created do |sass_file|
      added_fired = true
      assert_equal "added.scss", sass_file
    end

    removed_fired = false
    c.on_template_deleted do |sass_file|
      removed_fired = true
      assert_equal "removed.scss", sass_file
    end

    c.watch

    assert_equal 2, c.update_stylesheets_times
    assert modified_fired
    assert added_fired
    assert removed_fired
  end

  def test_removing_a_sass_file_removes_corresponding_css_file
    c = watcher do |listener|
      listener.removed "remove_me.scss"
      listener.fire_events!
    end

    c.watch

    assert_equal "./remove_me.css", c.deleted_css_files.first
  end

  def test_an_importer_can_watch_an_image
    image_importer = Sass::Importers::Filesystem.new(".")
    class << image_importer
      def watched_file?(filename)
        filename =~ /\.png$/
      end
    end
    c = watcher(:load_paths => [image_importer]) do |listener|
      listener.changed "image.png"
      listener.fire_events!
    end

    modified_fired = false
    c.on_template_modified do |f|
      modified_fired = true
      assert_equal "image.png", f
    end

    c.watch

    assert_equal 2, c.update_stylesheets_times
    assert modified_fired
  end

  def test_watching_specific_files_and_one_is_deleted
    directories = nil
    c = watcher do |listener|
      directories = listener.directories
      listener.removed File.expand_path("./foo.scss")
      listener.fire_events!
    end
    c.watch([[File.expand_path("./foo.scss"), File.expand_path("./foo.css"), nil]])
    assert directories.include?(File.expand_path(".")), directories.inspect
    assert_equal File.expand_path("./foo.css"), c.deleted_css_files.first, "the corresponding css file was not deleted"
    assert_equal [], c.update_stylesheets_called_with[1], "the sass file should not have been compiled"
  end

  def test_watched_directories_are_dedupped
    directories = nil
    c = watcher(:load_paths => [".", "./foo", "."]) do |listener|
      directories = listener.directories
    end
    c.watch
    assert_equal [File.expand_path(".")], directories
  end

  def test_a_changed_css_in_a_watched_directory_does_not_force_a_compile
    c = watcher do |listener|
      listener.changed "foo.css"
      listener.fire_events!
    end

    c.on_template_modified do |f|
      assert false, "Should not have been called"
    end

    c.watch

    assert_equal 1, c.update_stylesheets_times
  end

  private

  def default_options
    {:template_location => [[".","."]]}
  end

  def watcher(options = {}, &run_during_start)
    options = default_options.merge(options)
    watcher = Sass::Plugin::Compiler.new(options)
    watcher.extend(MockWatcher)
    watcher.run_during_start = run_during_start
    watcher
  end
end