mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
DEV: Move spec/components to spec/lib (#15987)
Lib specs were inexplicably split into two directories (`lib` and `components`) This moves them all into `lib`.
This commit is contained in:
195
spec/lib/stylesheet/compiler_spec.rb
Normal file
195
spec/lib/stylesheet/compiler_spec.rb
Normal file
@@ -0,0 +1,195 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require 'stylesheet/compiler'
|
||||
|
||||
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 > 1000
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "with a theme" do
|
||||
let!(:theme) { Fabricate(:theme) }
|
||||
let!(:upload) { UploadCreator.new(file_from_fixtures("logo.png"), "logo.png").create_for(Discourse.system_user.id) }
|
||||
let!(:upload_theme_field) { ThemeField.create!(theme: theme, target_id: 0, name: "primary", upload: upload, value: "", type_id: ThemeField.types[:theme_upload_var]) }
|
||||
let!(:stylesheet_theme_field) { ThemeField.create!(theme: theme, target_id: 0, name: "scss", value: "body { background: $primary }", type_id: ThemeField.types[:scss]) }
|
||||
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 asset-url" do
|
||||
css, _map = Stylesheet::Compiler.compile(".body{background-image: asset-url('/images/favicons/github.png');}", "test.scss")
|
||||
|
||||
expect(css).to include("url('/images/favicons/github.png')")
|
||||
expect(css).not_to include('asset-url')
|
||||
end
|
||||
|
||||
it "supports image-url" do
|
||||
css, _map = Stylesheet::Compiler.compile(".body{background-image: image-url('/favicons/github.png');}", "test.scss")
|
||||
|
||||
expect(css).to include("url('/favicons/github.png')")
|
||||
expect(css).not_to include('image-url')
|
||||
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
|
||||
end
|
||||
130
spec/lib/stylesheet/importer_spec.rb
Normal file
130
spec/lib/stylesheet/importer_spec.rb
Normal file
@@ -0,0 +1,130 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require 'stylesheet/importer'
|
||||
|
||||
describe Stylesheet::Importer do
|
||||
|
||||
def compile_css(name)
|
||||
Stylesheet::Compiler.compile_asset(name)[0]
|
||||
end
|
||||
|
||||
context "#category_backgrounds" do
|
||||
it "applies CDN to background category images" do
|
||||
expect(compile_css("color_definitions")).to_not include("body.category-")
|
||||
|
||||
background = Fabricate(:upload)
|
||||
parent_category = Fabricate(:category)
|
||||
category = Fabricate(:category, parent_category_id: parent_category.id, uploaded_background: background)
|
||||
|
||||
expect(compile_css("color_definitions")).to include("body.category-#{parent_category.slug}-#{category.slug}{background-image:url(#{background.url})}")
|
||||
|
||||
GlobalSetting.stubs(:cdn_url).returns("//awesome.cdn")
|
||||
expect(compile_css("color_definitions")).to include("body.category-#{parent_category.slug}-#{category.slug}{background-image:url(//awesome.cdn#{background.url})}")
|
||||
end
|
||||
|
||||
it "applies S3 CDN to background category images" do
|
||||
setup_s3
|
||||
SiteSetting.s3_use_iam_profile = true
|
||||
SiteSetting.s3_upload_bucket = 'test'
|
||||
SiteSetting.s3_region = 'ap-southeast-2'
|
||||
SiteSetting.s3_cdn_url = "https://s3.cdn"
|
||||
|
||||
background = Fabricate(:upload_s3)
|
||||
category = Fabricate(:category, uploaded_background: background)
|
||||
|
||||
expect(compile_css("color_definitions")).to include("body.category-#{category.slug}{background-image:url(https://s3.cdn/original")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
context "#font" do
|
||||
it "includes font variable" do
|
||||
default_font = ":root{--font-family: Arial, sans-serif}"
|
||||
expect(compile_css("color_definitions")).to include(default_font)
|
||||
expect(compile_css("embed")).to include(default_font)
|
||||
expect(compile_css("publish")).to include(default_font)
|
||||
end
|
||||
|
||||
it "includes separate body and heading font declarations" do
|
||||
base_font = DiscourseFonts.fonts[2]
|
||||
heading_font = DiscourseFonts.fonts[3]
|
||||
|
||||
SiteSetting.base_font = base_font[:key]
|
||||
SiteSetting.heading_font = heading_font[:key]
|
||||
|
||||
expect(compile_css("color_definitions"))
|
||||
.to include(":root{--font-family: #{base_font[:stack]}}")
|
||||
.and include(":root{--heading-font-family: #{heading_font[:stack]}}")
|
||||
|
||||
set_cdn_url("http://cdn.localhost")
|
||||
|
||||
# uses CDN and includes cache-breaking param
|
||||
expect(compile_css("color_definitions"))
|
||||
.to include("http://cdn.localhost/fonts/#{base_font[:variants][0][:filename]}?v=#{DiscourseFonts::VERSION}")
|
||||
.and include("http://cdn.localhost/fonts/#{heading_font[:variants][0][:filename]}?v=#{DiscourseFonts::VERSION}")
|
||||
end
|
||||
|
||||
it "includes all fonts in wizard" do
|
||||
expect(compile_css("wizard").scan(/\.body-font-/).count)
|
||||
.to eq(DiscourseFonts.fonts.count)
|
||||
|
||||
expect(compile_css("wizard").scan(/\.heading-font-/).count)
|
||||
.to eq(DiscourseFonts.fonts.count)
|
||||
|
||||
expect(compile_css("wizard").scan(/@font-face/).count)
|
||||
.to eq(DiscourseFonts.fonts.map { |f| f[:variants]&.count || 0 }.sum)
|
||||
end
|
||||
end
|
||||
|
||||
context "#import_color_definitions" do
|
||||
let(:scss) { ":root{--custom-color: green}" }
|
||||
let(:scss_child) { "$navy: #000080; :root{--custom-color: red; --custom-color-rgb: \#{hexToRGB($navy)}}" }
|
||||
|
||||
let(:theme) do
|
||||
Fabricate(:theme).tap do |t|
|
||||
t.set_field(target: :common, name: "color_definitions", value: scss)
|
||||
t.save!
|
||||
end
|
||||
end
|
||||
|
||||
let(:child) { Fabricate(:theme, component: true, name: "Child Theme").tap { |t|
|
||||
t.set_field(target: :common, name: "color_definitions", value: scss_child)
|
||||
t.save!
|
||||
}}
|
||||
|
||||
it "should include color definitions in the theme" do
|
||||
styles = Stylesheet::Importer.new({ theme_id: theme.id }).import_color_definitions
|
||||
expect(styles).to include(scss)
|
||||
end
|
||||
|
||||
it "should include color definitions from components" do
|
||||
theme.add_relative_theme!(:child, child)
|
||||
theme.save!
|
||||
|
||||
styles = Stylesheet::Importer.new({ theme_id: theme.id }).import_color_definitions
|
||||
expect(styles).to include("Color definitions from Child Theme")
|
||||
expect(styles).to include("--custom-color: red")
|
||||
expect(styles).to include("--custom-color-rgb: 0,0,128")
|
||||
|
||||
end
|
||||
|
||||
it "should include default theme color definitions" do
|
||||
SiteSetting.default_theme_id = theme.id
|
||||
styles = Stylesheet::Importer.new({}).import_color_definitions
|
||||
expect(styles).to include(scss)
|
||||
end
|
||||
end
|
||||
|
||||
context "#import_wcag_overrides" do
|
||||
it "should do nothing on a regular scheme" do
|
||||
scheme = ColorScheme.create_from_base(name: 'Regular')
|
||||
expect(Stylesheet::Importer.new({ color_scheme_id: scheme.id }).import_wcag_overrides).to eq("")
|
||||
end
|
||||
|
||||
it "should include WCAG overrides for WCAG based scheme" do
|
||||
scheme = ColorScheme.create_from_base(name: 'WCAG New', base_scheme_id: "WCAG Dark")
|
||||
expect(Stylesheet::Importer.new({ color_scheme_id: scheme.id }).import_wcag_overrides).to eq("@import \"wcag\";")
|
||||
end
|
||||
end
|
||||
end
|
||||
815
spec/lib/stylesheet/manager_spec.rb
Normal file
815
spec/lib/stylesheet/manager_spec.rb
Normal file
@@ -0,0 +1,815 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
require 'stylesheet/compiler'
|
||||
|
||||
describe Stylesheet::Manager do
|
||||
def manager(theme_id = nil)
|
||||
Stylesheet::Manager.new(theme_id: theme_id)
|
||||
end
|
||||
|
||||
it 'does not crash for missing theme' do
|
||||
Theme.clear_default!
|
||||
link = manager.stylesheet_link_tag(:embedded_theme)
|
||||
expect(link).to eq("")
|
||||
end
|
||||
|
||||
it "still returns something for no themes" do
|
||||
link = manager.stylesheet_link_tag(:desktop, 'all')
|
||||
expect(link).not_to eq("")
|
||||
end
|
||||
|
||||
context "themes with components" do
|
||||
let(:child_theme) { Fabricate(:theme, component: true, name: "a component").tap { |c|
|
||||
c.set_field(target: :common, name: "scss", value: ".child_common{.scss{color: red;}}")
|
||||
c.set_field(target: :desktop, name: "scss", value: ".child_desktop{.scss{color: red;}}")
|
||||
c.set_field(target: :mobile, name: "scss", value: ".child_mobile{.scss{color: red;}}")
|
||||
c.set_field(target: :common, name: "embedded_scss", value: ".child_embedded{.scss{color: red;}}")
|
||||
c.save!
|
||||
}}
|
||||
|
||||
let(:theme) { Fabricate(:theme).tap { |t|
|
||||
t.set_field(target: :common, name: "scss", value: ".common{.scss{color: red;}}")
|
||||
t.set_field(target: :desktop, name: "scss", value: ".desktop{.scss{color: red;}}")
|
||||
t.set_field(target: :mobile, name: "scss", value: ".mobile{.scss{color: red;}}")
|
||||
t.set_field(target: :common, name: "embedded_scss", value: ".embedded{.scss{color: red;}}")
|
||||
t.save!
|
||||
|
||||
t.add_relative_theme!(:child, child_theme)
|
||||
}}
|
||||
|
||||
it "generates the right links for non-theme targets" do
|
||||
manager = manager(nil)
|
||||
|
||||
hrefs = manager.stylesheet_details(:desktop, 'all')
|
||||
|
||||
expect(hrefs.length).to eq(1)
|
||||
end
|
||||
|
||||
it 'can correctly compile theme css' do
|
||||
manager = manager(theme.id)
|
||||
old_links = manager.stylesheet_link_tag(:desktop_theme, 'all')
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(
|
||||
target: :desktop_theme, theme: theme, manager: manager
|
||||
)
|
||||
|
||||
builder.compile(force: true)
|
||||
|
||||
css = File.read(builder.stylesheet_fullpath)
|
||||
_source_map = File.read(builder.source_map_fullpath)
|
||||
|
||||
expect(css).to match(/\.common/)
|
||||
expect(css).to match(/\.desktop/)
|
||||
|
||||
# child theme CSS is no longer bundled with main theme
|
||||
expect(css).not_to match(/child_common/)
|
||||
expect(css).not_to match(/child_desktop/)
|
||||
|
||||
child_theme_builder = Stylesheet::Manager::Builder.new(
|
||||
target: :desktop_theme, theme: child_theme, manager: manager
|
||||
)
|
||||
|
||||
child_theme_builder.compile(force: true)
|
||||
|
||||
child_css = File.read(child_theme_builder.stylesheet_fullpath)
|
||||
_child_source_map = File.read(child_theme_builder.source_map_fullpath)
|
||||
|
||||
expect(child_css).to match(/child_common/)
|
||||
expect(child_css).to match(/child_desktop/)
|
||||
|
||||
child_theme.set_field(target: :desktop, name: :scss, value: ".nothing{color: green;}")
|
||||
child_theme.save!
|
||||
|
||||
new_links = manager(theme.id).stylesheet_link_tag(:desktop_theme, 'all')
|
||||
|
||||
expect(new_links).not_to eq(old_links)
|
||||
|
||||
# our theme better have a name with the theme_id as part of it
|
||||
expect(new_links).to include("/stylesheets/desktop_theme_#{theme.id}_")
|
||||
expect(new_links).to include("/stylesheets/desktop_theme_#{child_theme.id}_")
|
||||
end
|
||||
|
||||
it 'can correctly compile embedded theme css' do
|
||||
manager = manager(theme.id)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(
|
||||
target: :embedded_theme, theme: theme, manager: manager
|
||||
)
|
||||
|
||||
builder.compile(force: true)
|
||||
|
||||
css = File.read(builder.stylesheet_fullpath)
|
||||
expect(css).to match(/\.embedded/)
|
||||
expect(css).not_to match(/\.child_embedded/)
|
||||
|
||||
child_theme_builder = Stylesheet::Manager::Builder.new(
|
||||
target: :embedded_theme,
|
||||
theme: child_theme,
|
||||
manager: manager
|
||||
)
|
||||
|
||||
child_theme_builder.compile(force: true)
|
||||
|
||||
css = File.read(child_theme_builder.stylesheet_fullpath)
|
||||
expect(css).to match(/\.child_embedded/)
|
||||
end
|
||||
|
||||
it 'includes both parent and child theme assets' do
|
||||
manager = manager(theme.id)
|
||||
|
||||
hrefs = manager.stylesheet_details(:desktop_theme, 'all')
|
||||
|
||||
expect(hrefs.count).to eq(2)
|
||||
|
||||
expect(hrefs.map { |href| href[:theme_id] }).to contain_exactly(
|
||||
theme.id, child_theme.id
|
||||
)
|
||||
|
||||
hrefs = manager.stylesheet_details(:embedded_theme, 'all')
|
||||
|
||||
expect(hrefs.count).to eq(2)
|
||||
|
||||
expect(hrefs.map { |href| href[:theme_id] }).to contain_exactly(
|
||||
theme.id, child_theme.id
|
||||
)
|
||||
end
|
||||
|
||||
it "includes the escaped theme name" do
|
||||
manager = manager(theme.id)
|
||||
|
||||
theme.update(name: "a strange name\"with a quote in it")
|
||||
|
||||
tag = manager.stylesheet_link_tag(:desktop_theme)
|
||||
expect(tag).to have_tag("link", with: {
|
||||
"data-theme-name" => theme.name.downcase
|
||||
})
|
||||
expect(tag).to have_tag("link", with: {
|
||||
"data-theme-name" => child_theme.name.downcase
|
||||
})
|
||||
end
|
||||
|
||||
context "stylesheet order" do
|
||||
let(:z_child_theme) do
|
||||
Fabricate(:theme, component: true, name: "ze component").tap do |z|
|
||||
z.set_field(target: :desktop, name: "scss", value: ".child_desktop{.scss{color: red;}}")
|
||||
z.save!
|
||||
end
|
||||
end
|
||||
|
||||
let(:remote) { RemoteTheme.create!(remote_url: "https://github.com/org/remote-theme1") }
|
||||
|
||||
let(:child_remote) do
|
||||
Fabricate(:theme, remote_theme: remote, component: true).tap do |t|
|
||||
t.set_field(target: :desktop, name: "scss", value: ".child_desktop{.scss{color: red;}}")
|
||||
t.save!
|
||||
end
|
||||
end
|
||||
|
||||
it 'output remote child, then sort children alphabetically, then local parent' do
|
||||
theme.add_relative_theme!(:child, z_child_theme)
|
||||
theme.add_relative_theme!(:child, child_remote)
|
||||
|
||||
manager = manager(theme.id)
|
||||
hrefs = manager.stylesheet_details(:desktop_theme, 'all')
|
||||
|
||||
parent = hrefs.select { |href| href[:theme_id] == theme.id }.first
|
||||
child_a = hrefs.select { |href| href[:theme_id] == child_theme.id }.first
|
||||
child_z = hrefs.select { |href| href[:theme_id] == z_child_theme.id }.first
|
||||
child_r = hrefs.select { |href| href[:theme_id] == child_remote.id }.first
|
||||
|
||||
child_local_A = "<link href=\"#{child_a[:new_href]}\" data-theme-id=\"#{child_a[:theme_id]}\" data-theme-name=\"#{child_a[:theme_name]}\"/>"
|
||||
child_local_Z = "<link href=\"#{child_z[:new_href]}\" data-theme-id=\"#{child_z[:theme_id]}\" data-theme-name=\"#{child_z[:theme_name]}\"/>"
|
||||
child_remote_R = "<link href=\"#{child_r[:new_href]}\" data-theme-id=\"#{child_r[:theme_id]}\" data-theme-name=\"#{child_r[:theme_name]}\"/>"
|
||||
parent_local = "<link href=\"#{parent[:new_href]}\" data-theme-id=\"#{parent[:theme_id]}\" data-theme-name=\"#{parent[:theme_name]}\"/>"
|
||||
|
||||
link_hrefs = manager.stylesheet_link_tag(:desktop_theme).gsub('media="all" rel="stylesheet" data-target="desktop_theme" ', '')
|
||||
|
||||
expect(link_hrefs).to eq([child_remote_R, child_local_A, child_local_Z, parent_local].join("\n").html_safe)
|
||||
end
|
||||
|
||||
it "output remote child, remote parent, local child" do
|
||||
remote2 = RemoteTheme.create!(remote_url: "https://github.com/org/remote-theme2")
|
||||
remote_main_theme = Fabricate(:theme, remote_theme: remote2, name: "remote main").tap do |t|
|
||||
t.set_field(target: :desktop, name: "scss", value: ".el{color: red;}")
|
||||
t.save!
|
||||
end
|
||||
|
||||
remote_main_theme.add_relative_theme!(:child, z_child_theme)
|
||||
remote_main_theme.add_relative_theme!(:child, child_remote)
|
||||
|
||||
manager = manager(remote_main_theme.id)
|
||||
hrefs = manager.stylesheet_details(:desktop_theme, 'all')
|
||||
|
||||
parent_r = hrefs.select { |href| href[:theme_id] == remote_main_theme.id }.first
|
||||
child_z = hrefs.select { |href| href[:theme_id] == z_child_theme.id }.first
|
||||
child_r = hrefs.select { |href| href[:theme_id] == child_remote.id }.first
|
||||
|
||||
parent_remote = "<link href=\"#{parent_r[:new_href]}\" data-theme-id=\"#{parent_r[:theme_id]}\" data-theme-name=\"#{parent_r[:theme_name]}\"/>"
|
||||
child_local = "<link href=\"#{child_z[:new_href]}\" data-theme-id=\"#{child_z[:theme_id]}\" data-theme-name=\"#{child_z[:theme_name]}\"/>"
|
||||
child_remote = "<link href=\"#{child_r[:new_href]}\" data-theme-id=\"#{child_r[:theme_id]}\" data-theme-name=\"#{child_r[:theme_name]}\"/>"
|
||||
|
||||
link_hrefs = manager.stylesheet_link_tag(:desktop_theme).gsub('media="all" rel="stylesheet" data-target="desktop_theme" ', '')
|
||||
expect(link_hrefs).to eq([child_remote, parent_remote, child_local].join("\n").html_safe)
|
||||
end
|
||||
end
|
||||
|
||||
it 'outputs tags for non-theme targets for theme component' do
|
||||
child_theme = Fabricate(:theme, component: true)
|
||||
|
||||
hrefs = manager(child_theme.id).stylesheet_details(:desktop, 'all')
|
||||
|
||||
expect(hrefs.count).to eq(1) # desktop
|
||||
end
|
||||
|
||||
it 'does not output tags for component targets with no styles' do
|
||||
embedded_scss_child = Fabricate(:theme, component: true)
|
||||
embedded_scss_child.set_field(target: :common, name: "embedded_scss", value: ".scss{color: red;}")
|
||||
embedded_scss_child.save!
|
||||
|
||||
theme.add_relative_theme!(:child, embedded_scss_child)
|
||||
|
||||
manager = manager(theme.id)
|
||||
|
||||
hrefs = manager.stylesheet_details(:desktop_theme, 'all')
|
||||
expect(hrefs.count).to eq(2) # theme + child_theme
|
||||
|
||||
hrefs = manager.stylesheet_details(:embedded_theme, 'all')
|
||||
expect(hrefs.count).to eq(3) # theme + child_theme + embedded_scss_child
|
||||
end
|
||||
|
||||
it '.stylesheet_details can find components mobile SCSS when target is `:mobile_theme`' do
|
||||
child_with_mobile_scss = Fabricate(:theme, component: true)
|
||||
child_with_mobile_scss.set_field(target: :mobile, name: :scss, value: "body { color: red; }")
|
||||
child_with_mobile_scss.save!
|
||||
theme.add_relative_theme!(:child, child_with_mobile_scss)
|
||||
|
||||
manager = manager(theme.id)
|
||||
hrefs = manager.stylesheet_details(:mobile_theme, 'all')
|
||||
|
||||
expect(hrefs.count).to eq(3)
|
||||
expect(hrefs.find { |h| h[:theme_id] == child_with_mobile_scss.id }).to be_present
|
||||
end
|
||||
|
||||
it 'does not output multiple assets for non-theme targets' do
|
||||
manager = manager()
|
||||
|
||||
hrefs = manager.stylesheet_details(:admin, 'all')
|
||||
expect(hrefs.count).to eq(1)
|
||||
|
||||
hrefs = manager.stylesheet_details(:mobile, 'all')
|
||||
expect(hrefs.count).to eq(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'digest' do
|
||||
after do
|
||||
DiscoursePluginRegistry.reset!
|
||||
end
|
||||
|
||||
it 'can correctly account for plugins in default digest' do
|
||||
builder = Stylesheet::Manager::Builder.new(target: :desktop, manager: manager)
|
||||
digest1 = builder.digest
|
||||
|
||||
DiscoursePluginRegistry.stylesheets["fake"] = Set.new(["fake_file"])
|
||||
builder = Stylesheet::Manager::Builder.new(target: :desktop, manager: manager)
|
||||
digest2 = builder.digest
|
||||
|
||||
expect(digest1).not_to eq(digest2)
|
||||
end
|
||||
|
||||
it "can correctly account for settings in theme's components" do
|
||||
theme = Fabricate(:theme)
|
||||
child = Fabricate(:theme, component: true)
|
||||
theme.add_relative_theme!(:child, child)
|
||||
|
||||
child.set_field(target: :settings, name: :yaml, value: "childcolor: red")
|
||||
child.set_field(target: :common, name: :scss, value: "body {background-color: $childcolor}")
|
||||
child.save!
|
||||
|
||||
manager = manager(theme.id)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(
|
||||
target: :desktop_theme, theme: theme, manager: manager
|
||||
)
|
||||
|
||||
digest1 = builder.digest
|
||||
|
||||
child.update_setting(:childcolor, "green")
|
||||
|
||||
manager = manager(theme.id)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(
|
||||
target: :desktop_theme, theme: theme, manager: manager
|
||||
)
|
||||
|
||||
digest2 = builder.digest
|
||||
|
||||
expect(digest1).not_to eq(digest2)
|
||||
end
|
||||
|
||||
let(:image) { file_from_fixtures("logo.png") }
|
||||
let(:image2) { file_from_fixtures("logo-dev.png") }
|
||||
|
||||
it 'can correctly account for theme uploads in digest' do
|
||||
theme = Fabricate(:theme)
|
||||
|
||||
upload = UploadCreator.new(image, "logo.png").create_for(-1)
|
||||
field = ThemeField.create!(
|
||||
theme_id: theme.id,
|
||||
target_id: Theme.targets[:common],
|
||||
name: "logo",
|
||||
value: "",
|
||||
upload_id: upload.id,
|
||||
type_id: ThemeField.types[:theme_upload_var]
|
||||
)
|
||||
|
||||
manager = manager(theme.id)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(
|
||||
target: :desktop_theme, theme: theme, manager: manager
|
||||
)
|
||||
|
||||
digest1 = builder.digest
|
||||
field.destroy!
|
||||
|
||||
upload = UploadCreator.new(image2, "logo.png").create_for(-1)
|
||||
field = ThemeField.create!(
|
||||
theme_id: theme.id,
|
||||
target_id: Theme.targets[:common],
|
||||
name: "logo",
|
||||
value: "",
|
||||
upload_id: upload.id,
|
||||
type_id: ThemeField.types[:theme_upload_var]
|
||||
)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(
|
||||
target: :desktop_theme, theme: theme.reload, manager: manager
|
||||
)
|
||||
|
||||
digest2 = builder.digest
|
||||
|
||||
expect(digest1).not_to eq(digest2)
|
||||
end
|
||||
|
||||
it 'returns different digest based on target' do
|
||||
theme = Fabricate(:theme)
|
||||
builder = Stylesheet::Manager::Builder.new(target: :desktop_theme, theme: theme, manager: manager)
|
||||
expect(builder.digest).to eq(builder.theme_digest)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(target: :color_definitions, manager: manager)
|
||||
expect(builder.digest).to eq(builder.color_scheme_digest)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(target: :admin, manager: manager)
|
||||
expect(builder.digest).to eq(builder.default_digest)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(target: :desktop, manager: manager)
|
||||
expect(builder.digest).to eq(builder.default_digest)
|
||||
end
|
||||
|
||||
it 'returns different digest based on hostname' do
|
||||
theme = Fabricate(:theme)
|
||||
|
||||
SiteSetting.force_hostname = "host1.example.com"
|
||||
initial_theme_digest = Stylesheet::Manager::Builder.new(target: :desktop_theme, theme: theme, manager: manager).digest
|
||||
initial_color_scheme_digest = Stylesheet::Manager::Builder.new(target: :color_definitions, manager: manager).digest
|
||||
initial_default_digest = Stylesheet::Manager::Builder.new(target: :desktop, manager: manager).digest
|
||||
|
||||
SiteSetting.force_hostname = "host2.example.com"
|
||||
new_theme_digest = Stylesheet::Manager::Builder.new(target: :desktop_theme, theme: theme, manager: manager).digest
|
||||
new_color_scheme_digest = Stylesheet::Manager::Builder.new(target: :color_definitions, manager: manager).digest
|
||||
new_default_digest = Stylesheet::Manager::Builder.new(target: :desktop, manager: manager).digest
|
||||
|
||||
expect(initial_theme_digest).not_to eq(new_theme_digest)
|
||||
expect(initial_color_scheme_digest).not_to eq(new_color_scheme_digest)
|
||||
expect(initial_default_digest).not_to eq(new_default_digest)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'color_scheme_digest' do
|
||||
fab!(:theme) { Fabricate(:theme) }
|
||||
|
||||
it "changes with category background image" do
|
||||
category1 = Fabricate(:category, uploaded_background_id: 123, updated_at: 1.week.ago)
|
||||
category2 = Fabricate(:category, uploaded_background_id: 456, updated_at: 2.days.ago)
|
||||
|
||||
manager = manager(theme.id)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(
|
||||
target: :desktop_theme, theme: theme, manager: manager
|
||||
)
|
||||
|
||||
digest1 = builder.color_scheme_digest
|
||||
|
||||
category2.update!(uploaded_background_id: 789, updated_at: 1.day.ago)
|
||||
|
||||
digest2 = builder.color_scheme_digest
|
||||
expect(digest2).to_not eq(digest1)
|
||||
|
||||
category1.update!(uploaded_background_id: nil, updated_at: 5.minutes.ago)
|
||||
|
||||
digest3 = builder.color_scheme_digest
|
||||
expect(digest3).to_not eq(digest2)
|
||||
expect(digest3).to_not eq(digest1)
|
||||
end
|
||||
|
||||
it "updates digest when updating a color scheme" do
|
||||
scheme = ColorScheme.create_from_base(name: "Neutral", base_scheme_id: "Neutral")
|
||||
manager = manager(theme.id)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(
|
||||
target: :color_definitions, theme: theme, color_scheme: scheme, manager: manager
|
||||
)
|
||||
|
||||
digest1 = builder.color_scheme_digest
|
||||
|
||||
ColorSchemeRevisor.revise(scheme, colors: [{ name: "primary", hex: "CC0000" }])
|
||||
|
||||
digest2 = builder.color_scheme_digest
|
||||
|
||||
expect(digest1).to_not eq(digest2)
|
||||
end
|
||||
|
||||
it "updates digest when updating a theme's color definitions" do
|
||||
scheme = ColorScheme.base
|
||||
manager = manager(theme.id)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(
|
||||
target: :color_definitions, theme: theme, color_scheme: scheme, manager: manager
|
||||
)
|
||||
|
||||
digest1 = builder.color_scheme_digest
|
||||
|
||||
theme.set_field(target: :common, name: :color_definitions, value: 'body {color: brown}')
|
||||
theme.save!
|
||||
|
||||
manager = manager(theme.id)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(
|
||||
target: :color_definitions, theme: theme, color_scheme: scheme, manager: manager
|
||||
)
|
||||
|
||||
digest2 = builder.color_scheme_digest
|
||||
|
||||
expect(digest1).to_not eq(digest2)
|
||||
end
|
||||
|
||||
it "updates digest when updating a theme component's color definitions" do
|
||||
scheme = ColorScheme.base
|
||||
manager = manager(theme.id)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(
|
||||
target: :color_definitions, theme: theme, color_scheme: scheme, manager: manager
|
||||
)
|
||||
|
||||
digest1 = builder.color_scheme_digest
|
||||
|
||||
child_theme = Fabricate(:theme, component: true)
|
||||
child_theme.set_field(target: :common, name: "color_definitions", value: 'body {color: fuchsia}')
|
||||
child_theme.save!
|
||||
theme.add_relative_theme!(:child, child_theme)
|
||||
theme.save!
|
||||
|
||||
manager = manager(theme.id)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(
|
||||
target: :color_definitions, theme: theme, color_scheme: scheme, manager: manager
|
||||
)
|
||||
|
||||
digest2 = builder.color_scheme_digest
|
||||
expect(digest1).to_not eq(digest2)
|
||||
|
||||
child_theme.set_field(target: :common, name: "color_definitions", value: 'body {color: blue}')
|
||||
child_theme.save!
|
||||
|
||||
manager = manager(theme.id)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(
|
||||
target: :color_definitions, theme: theme, color_scheme: scheme, manager: manager
|
||||
)
|
||||
|
||||
digest3 = builder.color_scheme_digest
|
||||
expect(digest2).to_not eq(digest3)
|
||||
end
|
||||
|
||||
it "updates digest when setting fonts" do
|
||||
manager = manager(theme.id)
|
||||
builder = Stylesheet::Manager::Builder.new(
|
||||
target: :desktop_theme, theme: theme, manager: manager
|
||||
)
|
||||
digest1 = builder.color_scheme_digest
|
||||
SiteSetting.base_font = DiscourseFonts.fonts[2][:key]
|
||||
digest2 = builder.color_scheme_digest
|
||||
|
||||
expect(digest1).to_not eq(digest2)
|
||||
|
||||
SiteSetting.heading_font = DiscourseFonts.fonts[4][:key]
|
||||
digest3 = builder.color_scheme_digest
|
||||
|
||||
expect(digest3).to_not eq(digest2)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe 'color_scheme_stylesheets' do
|
||||
it "returns something by default" do
|
||||
link = manager.color_scheme_stylesheet_link_tag
|
||||
expect(link).to include("color_definitions_base")
|
||||
end
|
||||
|
||||
it "does not crash when no default theme is set" do
|
||||
SiteSetting.default_theme_id = -1
|
||||
link = manager.color_scheme_stylesheet_link_tag
|
||||
|
||||
expect(link).to include("color_definitions_base")
|
||||
end
|
||||
|
||||
it "loads base scheme when defined scheme id is missing" do
|
||||
link = manager.color_scheme_stylesheet_link_tag(125)
|
||||
expect(link).to include("color_definitions_base")
|
||||
end
|
||||
|
||||
it "loads nothing when defined dark scheme id is missing" do
|
||||
link = manager.color_scheme_stylesheet_link_tag(125, "(prefers-color-scheme: dark)")
|
||||
expect(link).to eq("")
|
||||
end
|
||||
|
||||
it "uses the correct color scheme from the default site theme" do
|
||||
cs = Fabricate(:color_scheme, name: 'Funky')
|
||||
theme = Fabricate(:theme, color_scheme_id: cs.id)
|
||||
SiteSetting.default_theme_id = theme.id
|
||||
|
||||
link = manager.color_scheme_stylesheet_link_tag()
|
||||
expect(link).to include("/stylesheets/color_definitions_funky_#{cs.id}_")
|
||||
end
|
||||
|
||||
it "uses the correct color scheme when a non-default theme is selected and it uses the base 'Light' scheme" do
|
||||
cs = Fabricate(:color_scheme, name: 'Not This')
|
||||
ColorSchemeRevisor.revise(cs, colors: [{ name: "primary", hex: "CC0000" }])
|
||||
default_theme = Fabricate(:theme, color_scheme_id: cs.id)
|
||||
SiteSetting.default_theme_id = default_theme.id
|
||||
|
||||
user_theme = Fabricate(:theme, color_scheme_id: nil)
|
||||
|
||||
link = manager(user_theme.id).color_scheme_stylesheet_link_tag(nil, "all")
|
||||
expect(link).to include("/stylesheets/color_definitions_base_")
|
||||
|
||||
stylesheet = Stylesheet::Manager::Builder.new(
|
||||
target: :color_definitions, theme: user_theme, manager: manager
|
||||
).compile(force: true)
|
||||
|
||||
expect(stylesheet).not_to include("--primary: #c00;")
|
||||
expect(stylesheet).to include("--primary: #222;") # from base scheme
|
||||
end
|
||||
|
||||
it "uses the correct scheme when a valid scheme id is used" do
|
||||
link = manager.color_scheme_stylesheet_link_tag(ColorScheme.first.id)
|
||||
slug = Slug.for(ColorScheme.first.name) + "_" + ColorScheme.first.id.to_s
|
||||
expect(link).to include("/stylesheets/color_definitions_#{slug}_")
|
||||
end
|
||||
|
||||
it "does not fail with a color scheme name containing spaces and special characters" do
|
||||
cs = Fabricate(:color_scheme, name: 'Funky Bunch -_ @#$*(')
|
||||
theme = Fabricate(:theme, color_scheme_id: cs.id)
|
||||
SiteSetting.default_theme_id = theme.id
|
||||
|
||||
link = manager.color_scheme_stylesheet_link_tag
|
||||
expect(link).to include("/stylesheets/color_definitions_funky-bunch_#{cs.id}_")
|
||||
end
|
||||
|
||||
it "updates outputted colors when updating a color scheme" do
|
||||
scheme = ColorScheme.create_from_base(name: "Neutral", base_scheme_id: "Neutral")
|
||||
theme = Fabricate(:theme)
|
||||
manager = manager(theme.id)
|
||||
|
||||
builder = Stylesheet::Manager::Builder.new(
|
||||
target: :color_definitions, theme: theme, color_scheme: scheme, manager: manager
|
||||
)
|
||||
stylesheet = builder.compile
|
||||
|
||||
ColorSchemeRevisor.revise(scheme, colors: [{ name: "primary", hex: "CC0000" }])
|
||||
|
||||
builder2 = Stylesheet::Manager::Builder.new(
|
||||
target: :color_definitions, theme: theme, color_scheme: scheme, manager: manager
|
||||
)
|
||||
|
||||
stylesheet2 = builder2.compile
|
||||
|
||||
expect(stylesheet).not_to eq(stylesheet2)
|
||||
expect(stylesheet2).to include("--primary: #c00;")
|
||||
end
|
||||
|
||||
it "includes updated font definitions" do
|
||||
details1 = manager.color_scheme_stylesheet_details(nil, "all")
|
||||
|
||||
SiteSetting.base_font = DiscourseFonts.fonts[2][:key]
|
||||
|
||||
details2 = manager.color_scheme_stylesheet_details(nil, "all")
|
||||
expect(details1[:new_href]).not_to eq(details2[:new_href])
|
||||
end
|
||||
|
||||
context "theme colors" do
|
||||
let(:theme) { Fabricate(:theme).tap { |t|
|
||||
t.set_field(target: :common, name: "color_definitions", value: ':root {--special: rebeccapurple;}')
|
||||
t.save!
|
||||
}}
|
||||
let(:scss_child) { ':root {--child-definition: #{dark-light-choose(#c00, #fff)};}' }
|
||||
let(:child) { Fabricate(:theme, component: true, name: "Child Theme").tap { |t|
|
||||
t.set_field(target: :common, name: "color_definitions", value: scss_child)
|
||||
t.save!
|
||||
}}
|
||||
|
||||
let(:scheme) { ColorScheme.base }
|
||||
let(:dark_scheme) { ColorScheme.create_from_base(name: 'Dark', base_scheme_id: 'Dark') }
|
||||
|
||||
it "includes theme color definitions in color scheme" do
|
||||
manager = manager(theme.id)
|
||||
|
||||
stylesheet = Stylesheet::Manager::Builder.new(
|
||||
target: :color_definitions, theme: theme, color_scheme: scheme, manager: manager
|
||||
).compile(force: true)
|
||||
|
||||
expect(stylesheet).to include("--special: rebeccapurple")
|
||||
end
|
||||
|
||||
it "includes child color definitions in color schemes" do
|
||||
theme.add_relative_theme!(:child, child)
|
||||
theme.save!
|
||||
manager = manager(theme.id)
|
||||
|
||||
stylesheet = Stylesheet::Manager::Builder.new(
|
||||
target: :color_definitions, theme: theme, color_scheme: scheme, manager: manager
|
||||
).compile(force: true)
|
||||
|
||||
expect(stylesheet).to include("--special: rebeccapurple")
|
||||
expect(stylesheet).to include("--child-definition: #c00")
|
||||
end
|
||||
|
||||
it "respects selected color scheme in child color definitions" do
|
||||
theme.add_relative_theme!(:child, child)
|
||||
theme.save!
|
||||
|
||||
manager = manager(theme.id)
|
||||
|
||||
stylesheet = Stylesheet::Manager::Builder.new(
|
||||
target: :color_definitions, theme: theme, color_scheme: dark_scheme, manager: manager
|
||||
).compile(force: true)
|
||||
|
||||
expect(stylesheet).to include("--special: rebeccapurple")
|
||||
expect(stylesheet).to include("--child-definition: #fff")
|
||||
end
|
||||
|
||||
it "fails gracefully for broken SCSS" do
|
||||
scss = "$test: $missing-var;"
|
||||
theme.set_field(target: :common, name: "color_definitions", value: scss)
|
||||
theme.save!
|
||||
|
||||
manager = manager(theme.id)
|
||||
|
||||
stylesheet = Stylesheet::Manager::Builder.new(
|
||||
target: :color_definitions, theme: theme, color_scheme: scheme, manager: manager
|
||||
)
|
||||
|
||||
expect { stylesheet.compile }.not_to raise_error
|
||||
end
|
||||
|
||||
it "child theme SCSS includes the default theme's color scheme variables" do
|
||||
SiteSetting.default_theme_id = theme.id
|
||||
custom_scheme = ColorScheme.create_from_base(name: "Neutral", base_scheme_id: "Neutral")
|
||||
ColorSchemeRevisor.revise(custom_scheme, colors: [{ name: "primary", hex: "CC0000" }])
|
||||
theme.color_scheme_id = custom_scheme.id
|
||||
theme.save!
|
||||
|
||||
scss = "body{ border: 2px solid $primary;}"
|
||||
child.set_field(target: :common, name: "scss", value: scss)
|
||||
child.save!
|
||||
|
||||
manager = manager(theme.id)
|
||||
|
||||
child_theme_manager = Stylesheet::Manager::Builder.new(
|
||||
target: :desktop_theme, theme: child, manager: manager
|
||||
)
|
||||
|
||||
child_theme_manager.compile(force: true)
|
||||
|
||||
child_css = File.read(child_theme_manager.stylesheet_fullpath)
|
||||
expect(child_css).to include("body{border:2px solid #c00}")
|
||||
end
|
||||
end
|
||||
|
||||
context 'encoded slugs' do
|
||||
before { SiteSetting.slug_generation_method = 'encoded' }
|
||||
after { SiteSetting.slug_generation_method = 'ascii' }
|
||||
|
||||
it "strips unicode in color scheme stylesheet filenames" do
|
||||
cs = Fabricate(:color_scheme, name: 'Grün')
|
||||
cs2 = Fabricate(:color_scheme, name: '어두운')
|
||||
|
||||
link = manager.color_scheme_stylesheet_link_tag(cs.id)
|
||||
expect(link).to include("/stylesheets/color_definitions_grun_#{cs.id}_")
|
||||
link2 = manager.color_scheme_stylesheet_link_tag(cs2.id)
|
||||
expect(link2).to include("/stylesheets/color_definitions_scheme_#{cs2.id}_")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe ".precompile css" do
|
||||
before do
|
||||
class << STDERR
|
||||
alias_method :orig_write, :write
|
||||
def write(x)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
after do
|
||||
class << STDERR
|
||||
def write(x)
|
||||
orig_write(x)
|
||||
end
|
||||
end
|
||||
FileUtils.rm_rf("tmp/stylesheet-cache")
|
||||
end
|
||||
|
||||
it "correctly generates precompiled CSS" do
|
||||
scheme1 = ColorScheme.create!(name: "scheme1")
|
||||
scheme2 = ColorScheme.create!(name: "scheme2")
|
||||
core_targets = [:desktop, :mobile, :desktop_rtl, :mobile_rtl, :admin, :wizard]
|
||||
theme_targets = [:desktop_theme, :mobile_theme]
|
||||
|
||||
Theme.update_all(user_selectable: false)
|
||||
user_theme = Fabricate(:theme, user_selectable: true, color_scheme: scheme1)
|
||||
default_theme = Fabricate(:theme, user_selectable: true, color_scheme: scheme2)
|
||||
|
||||
child_theme = Fabricate(:theme).tap do |t|
|
||||
t.component = true
|
||||
t.save!
|
||||
user_theme.add_relative_theme!(:child, t)
|
||||
end
|
||||
|
||||
child_theme_with_css = Fabricate(:theme).tap do |t|
|
||||
t.component = true
|
||||
|
||||
t.set_field(
|
||||
target: :common,
|
||||
name: :scss,
|
||||
value: "body { background: green }"
|
||||
)
|
||||
|
||||
t.save!
|
||||
|
||||
user_theme.add_relative_theme!(:child, t)
|
||||
default_theme.add_relative_theme!(:child, t)
|
||||
end
|
||||
|
||||
default_theme.set_default!
|
||||
|
||||
StylesheetCache.destroy_all
|
||||
|
||||
# only core
|
||||
output = capture_output(:stderr) do
|
||||
Stylesheet::Manager.precompile_css
|
||||
end
|
||||
|
||||
results = StylesheetCache.pluck(:target)
|
||||
expect(results.size).to eq(core_targets.size)
|
||||
|
||||
StylesheetCache.destroy_all
|
||||
|
||||
# only themes
|
||||
output = capture_output(:stderr) do
|
||||
Stylesheet::Manager.precompile_theme_css
|
||||
end
|
||||
|
||||
# Ensure we force compile each theme only once
|
||||
expect(output.scan(/#{child_theme_with_css.name}/).length).to eq(2)
|
||||
results = StylesheetCache.pluck(:target)
|
||||
expect(results.size).to eq(16) # (3 themes * 2 targets) + 10 color schemes (2 themes * 5 color schemes (4 defaults + 1 theme scheme))
|
||||
|
||||
# themes + core
|
||||
Stylesheet::Manager.precompile_css
|
||||
results = StylesheetCache.pluck(:target)
|
||||
expect(results.size).to eq(22) # 6 core targets + 6 theme + 10 color schemes
|
||||
|
||||
theme_targets.each do |tar|
|
||||
expect(results.count { |target| target =~ /^#{tar}_(#{user_theme.id}|#{default_theme.id})$/ }).to eq(2)
|
||||
end
|
||||
|
||||
Theme.clear_default!
|
||||
StylesheetCache.destroy_all
|
||||
|
||||
# themes + core with no theme set as default
|
||||
Stylesheet::Manager.precompile_css
|
||||
Stylesheet::Manager.precompile_theme_css
|
||||
results = StylesheetCache.pluck(:target)
|
||||
expect(results.size).to eq(22) # 6 core targets + 6 theme + 10 color schemes
|
||||
|
||||
expect(results).to include("color_definitions_#{scheme1.name}_#{scheme1.id}_#{user_theme.id}")
|
||||
expect(results).to include("color_definitions_#{scheme2.name}_#{scheme2.id}_#{default_theme.id}")
|
||||
|
||||
# Check that sourceMappingURL includes __ws parameter
|
||||
content = StylesheetCache.last.content
|
||||
expect(content).to match(/# sourceMappingURL=[^\/]+\.css\.map\?__ws=test\.localhost/)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user