discourse/spec/lib/stylesheet/compiler_spec.rb
Rafael dos Santos Silva 6e522e4aad
DEV: Move to Sass compilation to dart-sass (#19910)
This PR is a major change to Sass compilation in Discourse.

The new version of sass-ruby moves to dart-sass putting we back on the supported version of Sass. It does so while keeping compatibility with the existing method signatures, so minimal change is needed in Discourse for this change.

This moves us

From:
  - sassc 2.0.1 (Feb 2019)
  - libsass 3.5.2 (May 2018)

To:
  - dart-sass 1.58

This update applies the following breaking changes:

> 
> These breaking changes are coming soon or have recently been released:
> 
>  [Functions are stricter about which units they allow](https://sass-lang.com/documentation/breaking-changes/function-units) beginning in Dart Sass 1.32.0.
> 
>  [Selectors with invalid combinators are invalid](https://sass-lang.com/documentation/breaking-changes/bogus-combinators) beginning in Dart Sass 1.54.0.
> 
>  [/ is changing from a division operation to a list separator](https://sass-lang.com/documentation/breaking-changes/slash-div) beginning in Dart Sass 1.33.0.
> 
>  [Parsing the special syntax of @-moz-document will be invalid](https://sass-lang.com/documentation/breaking-changes/moz-document) beginning in Dart Sass 1.7.2.
> 
>  [Compound selectors could not be extended](https://sass-lang.com/documentation/breaking-changes/extend-compound) in Dart Sass 1.0.0 and Ruby Sass 4.0.0.


SCSS files have been migrated automatically using `sass-migrator division app/assets/stylesheets/**/*.scss`
2023-02-07 12:24:57 -03:00

225 lines
7.0 KiB
Ruby

# frozen_string_literal: true
require "stylesheet/compiler"
RSpec.describe Stylesheet::Compiler do
describe "compilation" do
Dir["#{Rails.root.join("app/assets/stylesheets")}/*.scss"].each do |path|
next if path =~ /ember_cli/
path = File.basename(path, ".scss")
it "can compile '#{path}' css" do
css, _map = Stylesheet::Compiler.compile_asset(path)
expect(css.length).to be > 500
end
end
end
context "with a theme" do
let!(:theme) { Fabricate(:theme) }
let!(:upload) do
UploadCreator.new(file_from_fixtures("logo.png"), "logo.png").create_for(
Discourse.system_user.id,
)
end
let!(:upload_theme_field) do
ThemeField.create!(
theme: theme,
target_id: 0,
name: "primary",
upload: upload,
value: "",
type_id: ThemeField.types[:theme_upload_var],
)
end
let!(:stylesheet_theme_field) do
ThemeField.create!(
theme: theme,
target_id: 0,
name: "scss",
value: "body { background: $primary }",
type_id: ThemeField.types[:scss],
)
end
before { stylesheet_theme_field.save! }
it "theme stylesheet should be able to access theme asset variables" do
css, _map =
Stylesheet::Compiler.compile_asset(
"desktop_theme",
theme_id: theme.id,
theme_variables: theme.scss_variables,
)
expect(css).to include(upload.url)
end
context "with a plugin" do
let :plugin1 do
plugin1 = Plugin::Instance.new
plugin1.path = "#{Rails.root}/spec/fixtures/plugins/my_plugin/plugin.rb"
plugin1.register_css "body { background: $primary }"
plugin1
end
let :plugin2 do
plugin2 = Plugin::Instance.new
plugin2.path = "#{Rails.root}/spec/fixtures/plugins/scss_plugin/plugin.rb"
plugin2
end
before do
Discourse.plugins << plugin1
Discourse.plugins << plugin2
plugin1.activate!
plugin2.activate!
Stylesheet::Importer.register_imports!
end
after do
Discourse.plugins.delete plugin1
Discourse.plugins.delete plugin2
Stylesheet::Importer.register_imports!
DiscoursePluginRegistry.reset!
end
it "does not include theme variables in plugins" do
css, _map = Stylesheet::Compiler.compile_asset("my_plugin", theme_id: theme.id)
expect(css).not_to include(upload.url)
expect(css).to include("background:")
end
it "supports SCSS imports" do
css, _map = Stylesheet::Compiler.compile_asset("scss_plugin", theme_id: theme.id)
expect(css).to include("border-color:red")
expect(css).to include("fill:green")
expect(css).to include("line-height:1.2em")
expect(css).to include("border-color:#c00")
end
end
end
it "supports absolute-image-url" do
scss = Stylesheet::Importer.new({}).prepended_scss
scss += ".body{background-image: absolute-image-url('/favicons/github.png');}"
css, _map = Stylesheet::Compiler.compile(scss, "test.scss")
expect(css).to include('url("http://test.localhost/images/favicons/github.png")')
expect(css).not_to include("absolute-image-url")
end
it "supports absolute-image-url in subfolder" do
set_subfolder "/subfo"
scss = Stylesheet::Importer.new({}).prepended_scss
scss += ".body{background-image: absolute-image-url('/favicons/github.png');}"
css, _map = Stylesheet::Compiler.compile(scss, "test2.scss")
expect(css).to include('url("http://test.localhost/subfo/images/favicons/github.png")')
expect(css).not_to include("absolute-image-url")
end
it "supports absolute-image-url with CDNs" do
set_cdn_url "https://awesome.com"
scss = Stylesheet::Importer.new({}).prepended_scss
scss += ".body{background-image: absolute-image-url('/favicons/github.png');}"
css, _map = Stylesheet::Compiler.compile(scss, "test2.scss")
expect(css).to include('url("https://awesome.com/images/favicons/github.png")')
expect(css).not_to include("absolute-image-url")
end
it "supports absolute-image-url in plugins" do
set_cdn_url "https://awesome.com"
scss = Stylesheet::Importer.new({}).prepended_scss
scss +=
".body{background-image: absolute-image-url('/plugins/discourse-special/images/somefile.png');}"
css, _map = Stylesheet::Compiler.compile(scss, "discourse-special.scss")
expect(css).to include(
'url("https://awesome.com/plugins/discourse-special/images/somefile.png")',
)
expect(css).not_to include("absolute-image-url")
end
context "with a color scheme" do
it "returns the default color definitions when no color scheme is specified" do
css, _map = Stylesheet::Compiler.compile_asset("color_definitions")
expect(css).to include("--header_background:")
expect(css).to include("--primary:")
end
it "returns color definitions for a custom color scheme" do
cs =
Fabricate(
:color_scheme,
name: "Stylish",
color_scheme_colors: [
Fabricate(:color_scheme_color, name: "header_primary", hex: "88af8e"),
Fabricate(:color_scheme_color, name: "header_background", hex: "f8745c"),
],
)
css, _map = Stylesheet::Compiler.compile_asset("color_definitions", color_scheme_id: cs.id)
expect(css).to include("--header_background: #f8745c")
expect(css).to include("--header_primary: #88af8e")
expect(css).to include("--header_background-rgb: 248, 116, 92")
end
context "with a plugin" do
before do
plugin = Plugin::Instance.new
plugin.path = "#{Rails.root}/spec/fixtures/plugins/color_definition/plugin.rb"
Discourse.plugins << plugin
plugin.activate!
end
after do
Discourse.plugins.pop
DiscoursePluginRegistry.reset!
end
it "includes color definitions from plugins" do
css, _map = Stylesheet::Compiler.compile_asset("color_definitions")
expect(css).to include("--plugin-color")
end
end
end
describe "indexes" do
it "include all SCSS files in their respective folders" do
refs = []
Dir
.glob(Rails.root.join("app/assets/stylesheets/**/*/"))
.each do |dir|
Dir
.glob("#{dir}_index.scss")
.each do |indexfile|
contents = File.read indexfile
files = Dir["#{dir}*.scss"]
files -= Dir["#{dir}_index.scss"]
files.each do |path|
filename = File.basename(path, ".scss")
if !contents.match(/@import "#{filename}";/)
refs << "#{filename} import missing in #{indexfile}"
end
end
end
end
expect(refs).to eq([])
end
end
describe ".compile" do
it "produces RTL CSS when rtl option is given" do
css, _ = Stylesheet::Compiler.compile("a{right:1px}", "test.scss", rtl: true)
expect(css).to eq("a{left:1px}")
end
end
end