1test_that("throws on invalid output dir", {
2  local_temp_cache()
3
4  # Prime the cache
5  sass("div { border: 1px solid black; }")
6
7  # Cache
8  expect_error(
9    sass(
10      "div { border: 1px solid black; }",
11      output = file.path("not", "a", "path.css")
12    )
13  )
14})
15
16test_that("reads from and writes to cache", {
17  local_temp_cache()
18  expected <- read_utf8("test-unicode-var-expected.css")
19
20  css <- sass(sass_file("test-unicode-var-input.scss"))
21  expect_equal(as.character(css), expected)
22
23  css <- sass(sass_file("test-unicode-var-input.scss"))
24  expect_equal(as.character(css), expected)
25
26  expect_equal(sass_cache_get()$size(), 1)
27
28  # Modifying the file busts the cache (even it if has the same contents)
29  Sys.setFileTime("test-unicode-var-input.scss", Sys.time() + 5)
30  css <- sass(sass_file("test-unicode-var-input.scss"))
31  expect_equal(as.character(css), expected)
32  expect_equal(sass_cache_get()$size(), 2)
33})
34
35test_that("writes to cache", {
36
37  expect_cached <- function(input, css) {
38    local_temp_cache()
39    cache <- sass_cache_get()
40    # Allow input to be an expression, like layer(), that can generate
41    # different input everytime it gets evaluated
42    input_code <- substitute(input)
43    # Did we get the right CSS result?
44    expect_css(eval(input_code), css)
45    # Did a cache entry get added?
46    expect_equal(cache$size(), 1)
47    # Compile again, now with an output file
48    out_file <- tempfile(fileext = ".css")
49    expect_css(eval(input_code), css, output = out_file)
50    # If there was a cache hit, the size should be the same
51    expect_equal(cache$size(), 1)
52    # Now manipulate the cache directly to make sure it is actually being read
53    # from. We'll change the value in the cache and see if sass() reads from it.
54    cache$set_content(cache$keys(), "foo")
55    expect_css(eval(input_code), "foo")
56  }
57
58  expect_cached(
59    list(
60      list(text_color = "#313131"),
61      list("body { color: $text_color; }")
62    ),
63    "body{color:#313131;}"
64  )
65
66  # Make sure cache key doesn't change with new/temporary HTML dependencies
67  my_layer <- function() {
68    src <- tempfile()
69    dir.create(src)
70    sass_layer(
71      "@function fib($x) {
72         @if $x <= 1 {
73           @return $x
74         }
75         @return fib($x - 2) + fib($x - 1);
76       }
77       body { width: fib(27);}",
78      html_deps = htmltools::htmlDependency("foo", "1.0", src)
79    )
80  }
81
82  expect_cached(
83    my_layer(),
84    "body{width:196418;}"
85  )
86
87})
88
89test_that("unicode characters work OK after caching", {
90  local_temp_cache()
91  expected <- read_utf8("test-unicode-var-expected.css")
92  class(expected) <- c("css", "html", "character")
93  attr(expected, "html") <- TRUE
94
95  css <- sass(sass_file("test-unicode-var-input.scss"))
96  expect_equal(css, expected)
97
98  css <- sass(sass_file("test-unicode-var-input.scss"))
99  expect_equal(css, expected)
100
101  expect_equal(sass_cache_get()$size(), 1)
102})
103
104test_that("cache isn't written if a compilation error occurs", {
105  local_temp_cache()
106
107  input <- list(
108    list(text_color = "#a0a0a0"),
109    list("body { color is: $text_color; }")
110  )
111  options <- sass_options(output_style = "compact")
112
113  expect_error(sass(input, options), "must be followed")
114
115  expect_equal(sass_cache_get()$size(), 0)
116})
117
118test_that("cache key components", {
119  tmpfile <- tempfile(fileext = ".tmp")
120  file.create(tmpfile)
121  old_mtime <- file.mtime(tmpfile)
122
123  input <- list(sass_file(tmpfile))
124  options <- sass_options()
125
126  key1 <- sass_hash(list(input, options))
127  while (file.mtime(tmpfile) == old_mtime) {
128    # Force timestamp to change
129    Sys.sleep(0.1)
130    file.remove(tmpfile)
131    file.create(tmpfile)
132  }
133
134  # Files differing by mtime should have different keys
135  key2 <- sass_hash(list(input, options))
136  expect_true(key1 != key2)
137
138  # Options that are identical should have same key
139  options3 <- sass_options()
140  key3 <- sass_hash(list(input, options3))
141  expect_true(key2 == key3)
142
143  # Options that are different should have different keys
144  options4 <- sass_options(output_style = "compact")
145  key4 <- sass_hash(list(input, options4))
146  expect_true(key3 != key4)
147})
148
149
150
151test_that("output_template() is cache and options aware", {
152  local_temp_cache()
153
154  input <- list(
155    list(color = "red"),
156    "body{color:red}"
157  )
158  opts <- sass_options(output_style = "compressed")
159  expect_red <- function(file) {
160    expect_equal(
161      "body{color:red}",
162      gsub("(\\s+)|(\t)|(;)", "", paste(readLines(file), collapse = ""))
163    )
164  }
165
166  # File is exactly the same with the same input+options
167  output1 <- sass(input, output = output_template(), options = opts)
168  output2 <- sass(input, output = output_template(), options = opts)
169  expect_true(output1 == output2)
170  expect_match(output1, ".min.css$")
171  expect_red(output1)
172  expect_red(output2)
173
174  # If cache is different, should get a different output file
175  output3 <- sass(input, output = output_template(), options = opts, cache_key_extra = "foo")
176  expect_true(output1 != output3)
177  expect_red(output3)
178
179  # Not minimized by default (because output_style = "expanded")
180  output4 <- sass(input, output = output_template())
181  expect_false(grepl(".min.css$", output4))
182  expect_red(output4)
183
184  # If no caching, should get a different output files
185  output5 <- sass(input, output = output_template(), cache = FALSE)
186  output6 <- sass(input, output = output_template(), cache = FALSE)
187  expect_true(dirname(output5) != dirname(output6))
188  expect_red(output5)
189  expect_red(output6)
190
191  # File can be written in another dir and still be cache aware
192  temp_dir <- withr::local_tempdir()
193  output7 <- sass(input, output = output_template(path = temp_dir), options = opts)
194  expect_true(basename(dirname(dirname(output7))) == basename(temp_dir))
195  expect_true(basename(dirname(output7)) == basename(dirname(output1)))
196})
197
198test_that("Cache directory getting/setting", {
199  cache_dir <- tempfile("sass-cache-test-")
200  cache <- sass_file_cache(dir = cache_dir)
201
202  # Can normalize path _after_ dir is created.
203  cache_dir <- normalizePath(cache_dir)
204  expect_identical(normalizePath(cache$dir()), cache_dir)
205
206  # Setting the cache for a directory works
207  sass_cache_set_dir(cache_dir, cache)
208  expect_identical(sass_cache_get_dir(cache_dir), cache)
209
210  # It checks that the specified dir and the cache's dir match
211  expect_error(sass_cache_set_dir(file.path(cache_dir, "foo"), cache))
212
213  # Check that the path is normalized. Create another cache object and set
214  # it as the cache for this path. Then fetching the cache for the path should
215  # return the new one.
216  cache2 <- sass_file_cache(dir = cache_dir)
217  expect_false(identical(cache, cache2))
218  sass_cache_set_dir(
219    file.path(cache_dir, "..", basename(cache_dir)),
220    cache2
221  )
222  expect_identical(sass_cache_get_dir(cache_dir), cache2)
223
224  # Can unset cache for a given directory
225  sass_cache_set_dir(cache_dir, NULL)
226  expect_false(exists(cache_dir, envir = .caches))
227
228  # Calling sass_cache_get_dir() when it doesn't exist should error
229  cache_dir <- tempfile("sass-cache-test-")
230  expect_error(sass_cache_get_dir(cache_dir))
231
232  # Calling sass_cache_get_dir() when the dir exists but no cache object has
233  # been registered returns NULL
234  dir.create(cache_dir)
235  expect_null(sass_cache_get_dir(cache_dir))
236
237
238  # Calling sass_cache_get_dir() when the dir doesn't exist (and cache object
239  # isn't registered) with create=TRUE should create the dir and the cache
240  # object.
241  cache_dir <- tempfile("sass-cache-test-")
242  cache_obj <- sass_cache_get_dir(cache_dir, create = TRUE)
243  expect_true(dir.exists(cache_dir))
244  expect_true(inherits(cache_obj, "FileCache"))
245
246  # Calling sass_cache_get_dir() when the dir exists but cache object does not
247  # with create=TRUE should create the cache object.
248  cache_dir <- tempfile("sass-cache-test-")
249  dir.create(cache_dir)
250  cache_obj <- sass_cache_get_dir(cache_dir, create = TRUE)
251  expect_true(dir.exists(cache_dir))
252  expect_true(inherits(cache_obj, "FileCache"))
253})
254
255
256test_that("Can pass a cache directory to sass()", {
257  cache_dir <- tempfile()
258  sass("body {color: red; }", cache = cache_dir)
259
260  # Cache directory should have been created
261  cache_obj <- sass_cache_get_dir(cache_dir, create = FALSE)
262  expect_true(inherits(cache_obj, "FileCache"))
263})
264