2017-04-12 10:52:52 -04:00
require 'rails_helper'
describe Theme do
before do
Theme . clear_cache!
end
let :user do
Fabricate ( :user )
end
2017-09-04 07:27:58 -04:00
let ( :guardian ) do
Guardian . new ( user )
end
2017-04-12 10:52:52 -04:00
let :customization_params do
2017-07-27 21:20:09 -04:00
{ name : 'my name' , user_id : user . id , header : " my awesome header " }
2017-04-12 10:52:52 -04:00
end
let :customization do
Theme . create! ( customization_params )
end
2017-05-04 14:03:07 -04:00
it 'can properly clean up color schemes' do
theme = Theme . create! ( name : 'bob' , user_id : - 1 )
scheme = ColorScheme . create! ( theme_id : theme . id , name : 'test' )
scheme2 = ColorScheme . create! ( theme_id : theme . id , name : 'test2' )
Theme . create! ( name : 'bob' , user_id : - 1 , color_scheme_id : scheme2 . id )
theme . destroy!
scheme2 . reload
expect ( scheme2 ) . not_to eq ( nil )
expect ( scheme2 . theme_id ) . to eq ( nil )
expect ( ColorScheme . find_by ( id : scheme . id ) ) . to eq ( nil )
end
2017-04-12 10:52:52 -04:00
it 'can support child themes' do
child = Theme . new ( name : '2' , user_id : user . id )
2017-05-02 16:01:01 -04:00
child . set_field ( target : :common , name : " header " , value : " World " )
child . set_field ( target : :desktop , name : " header " , value : " Desktop " )
child . set_field ( target : :mobile , name : " header " , value : " Mobile " )
2017-04-12 10:52:52 -04:00
child . save!
2018-07-12 00:18:21 -04:00
expect ( Theme . lookup_field ( child . id , :desktop , " header " ) ) . to eq ( " World \n Desktop " )
expect ( Theme . lookup_field ( child . id , " mobile " , :header ) ) . to eq ( " World \n Mobile " )
2017-04-12 10:52:52 -04:00
2017-05-02 16:01:01 -04:00
child . set_field ( target : :common , name : " header " , value : " Worldie " )
2017-04-12 10:52:52 -04:00
child . save!
2018-07-12 00:18:21 -04:00
expect ( Theme . lookup_field ( child . id , :mobile , :header ) ) . to eq ( " Worldie \n Mobile " )
2017-04-12 10:52:52 -04:00
parent = Theme . new ( name : '1' , user_id : user . id )
2017-05-02 16:01:01 -04:00
parent . set_field ( target : :common , name : " header " , value : " Common Parent " )
parent . set_field ( target : :mobile , name : " header " , value : " Mobile Parent " )
2017-04-12 10:52:52 -04:00
parent . save!
parent . add_child_theme! ( child )
2018-07-12 00:18:21 -04:00
expect ( Theme . lookup_field ( parent . id , :mobile , " header " ) ) . to eq ( " Common Parent \n Mobile Parent \n Worldie \n Mobile " )
2017-04-12 10:52:52 -04:00
end
it 'can correctly find parent themes' do
grandchild = Theme . create! ( name : 'grandchild' , user_id : user . id )
child = Theme . create! ( name : 'child' , user_id : user . id )
theme = Theme . create! ( name : 'theme' , user_id : user . id )
theme . add_child_theme! ( child )
child . add_child_theme! ( grandchild )
expect ( grandchild . dependant_themes . length ) . to eq ( 2 )
end
it 'should correct bad html in body_tag_baked and head_tag_baked' do
theme = Theme . new ( user_id : - 1 , name : " test " )
2017-05-02 16:01:01 -04:00
theme . set_field ( target : :common , name : " head_tag " , value : " <b>I am bold " )
2017-04-12 10:52:52 -04:00
theme . save!
2018-07-12 00:18:21 -04:00
expect ( Theme . lookup_field ( theme . id , :desktop , " head_tag " ) ) . to eq ( " <b>I am bold</b> " )
2017-04-12 10:52:52 -04:00
end
it 'should precompile fragments in body and head tags' do
with_template = <<HTML
< script type = 'text/x-handlebars' name = 'template' >
{ { hello } }
< / script>
< script type = 'text/x-handlebars' data - template - name = 'raw_template.raw' >
{ { hello } }
< / script>
HTML
theme = Theme . new ( user_id : - 1 , name : " test " )
2017-05-02 16:01:01 -04:00
theme . set_field ( target : :common , name : " header " , value : with_template )
2017-04-12 10:52:52 -04:00
theme . save!
2018-07-12 00:18:21 -04:00
baked = Theme . lookup_field ( theme . id , :mobile , " header " )
2017-04-12 10:52:52 -04:00
expect ( baked ) . to match ( / HTMLBars / )
expect ( baked ) . to match ( / raw-handlebars / )
end
it 'should create body_tag_baked on demand if needed' do
theme = Theme . new ( user_id : - 1 , name : " test " )
2017-05-02 16:01:01 -04:00
theme . set_field ( target : :common , name : :body_tag , value : " <b>test " )
2017-04-12 10:52:52 -04:00
theme . save
ThemeField . update_all ( value_baked : nil )
2018-07-12 00:18:21 -04:00
expect ( Theme . lookup_field ( theme . id , :desktop , :body_tag ) ) . to match ( / <b>test< \/ b> / )
2017-04-12 10:52:52 -04:00
end
context " plugin api " do
def transpile ( html )
2018-03-04 19:04:23 -05:00
f = ThemeField . create! ( target_id : Theme . targets [ :mobile ] , theme_id : 1 , name : " after_header " , value : html )
2017-04-12 10:52:52 -04:00
f . value_baked
end
it " transpiles ES6 code " do
html = <<HTML
< script type = 'text/discourse-plugin' version = '0.1' >
const x = 1 ;
< / script>
HTML
transpiled = transpile ( html )
expect ( transpiled ) . to match ( / \ <script \ > / )
expect ( transpiled ) . to match ( / var x = 1; / )
expect ( transpiled ) . to match ( / _registerPluginCode \ ('0.1' / )
end
it " converts errors to a script type that is not evaluated " do
html = <<HTML
< script type = 'text/discourse-plugin' version = '0.1' >
const x = 1 ;
x = 2 ;
< / script>
HTML
transpiled = transpile ( html )
expect ( transpiled ) . to match ( / text \/ discourse-js-error / )
expect ( transpiled ) . to match ( / read-only / )
end
end
2017-05-02 16:01:01 -04:00
context 'theme vars' do
2017-11-13 23:22:59 -05:00
it 'works in parent theme' do
theme = Theme . new ( name : 'theme' , user_id : - 1 )
theme . set_field ( target : :common , name : :scss , value : 'body {color: $magic; }' )
theme . set_field ( target : :common , name : :magic , value : 'red' , type : :theme_var )
theme . set_field ( target : :common , name : :not_red , value : 'red' , type : :theme_var )
theme . save
parent_theme = Theme . new ( name : 'parent theme' , user_id : - 1 )
parent_theme . set_field ( target : :common , name : :scss , value : 'body {background-color: $not_red; }' )
parent_theme . set_field ( target : :common , name : :not_red , value : 'blue' , type : :theme_var )
parent_theme . save
parent_theme . add_child_theme! ( theme )
scss , _map = Stylesheet :: Compiler . compile ( '@import "theme_variables"; @import "desktop_theme"; ' , " theme.scss " , theme_id : parent_theme . id )
expect ( scss ) . to include ( " color:red " )
expect ( scss ) . to include ( " background-color:blue " )
end
2017-05-02 16:01:01 -04:00
it 'can generate scss based off theme vars' do
theme = Theme . new ( name : 'theme' , user_id : - 1 )
theme . set_field ( target : :common , name : :scss , value : 'body {color: $magic; content: quote($content)}' )
theme . set_field ( target : :common , name : :magic , value : 'red' , type : :theme_var )
theme . set_field ( target : :common , name : :content , value : 'Sam\'s Test' , type : :theme_var )
theme . save
2017-07-27 21:20:09 -04:00
scss , _map = Stylesheet :: Compiler . compile ( '@import "theme_variables"; @import "desktop_theme"; ' , " theme.scss " , theme_id : theme . id )
2017-05-02 16:01:01 -04:00
expect ( scss ) . to include ( " red " )
expect ( scss ) . to include ( '"Sam\'s Test"' )
end
2017-05-08 11:38:48 -04:00
let :image do
file_from_fixtures ( " logo.png " )
end
it 'can handle uploads based of ThemeField' do
theme = Theme . new ( name : 'theme' , user_id : - 1 )
2017-05-10 18:16:57 -04:00
upload = UploadCreator . new ( image , " logo.png " ) . create_for ( - 1 )
2017-05-08 11:38:48 -04:00
theme . set_field ( target : :common , name : :logo , upload_id : upload . id , type : :theme_upload_var )
theme . set_field ( target : :common , name : :scss , value : 'body {background-image: url($logo)}' )
theme . save!
# make sure we do not nuke it
freeze_time ( SiteSetting . clean_orphan_uploads_grace_period_hours + 1 ) . hours . from_now
Jobs :: CleanUpUploads . new . execute ( nil )
expect ( Upload . where ( id : upload . id ) ) . to be_exist
2017-05-09 17:20:28 -04:00
# no error for theme field
theme . reload
expect ( theme . theme_fields . find_by ( name : :scss ) . error ) . to eq ( nil )
2017-05-08 11:38:48 -04:00
2017-07-27 21:20:09 -04:00
scss , _map = Stylesheet :: Compiler . compile ( '@import "theme_variables"; @import "desktop_theme"; ' , " theme.scss " , theme_id : theme . id )
2017-05-08 11:38:48 -04:00
expect ( scss ) . to include ( upload . url )
end
2017-05-02 16:01:01 -04:00
end
2018-03-04 19:04:23 -05:00
context " theme settings " do
2018-03-04 23:35:41 -05:00
it " allows values to be used in scss " do
2018-03-04 19:04:23 -05:00
theme = Theme . new ( name : " awesome theme " , user_id : - 1 )
theme . set_field ( target : :settings , name : :yaml , value : " background_color: red \n font_size: 25px " )
theme . set_field ( target : :common , name : :scss , value : 'body {background-color: $background_color; font-size: $font-size}' )
theme . save!
scss , _map = Stylesheet :: Compiler . compile ( '@import "theme_variables"; @import "desktop_theme"; ' , " theme.scss " , theme_id : theme . id )
expect ( scss ) . to include ( " background-color:red " )
expect ( scss ) . to include ( " font-size:25px " )
2018-03-04 23:35:41 -05:00
setting = theme . settings . find { | s | s . name == :font_size }
setting . value = '30px'
scss , _map = Stylesheet :: Compiler . compile ( '@import "theme_variables"; @import "desktop_theme"; ' , " theme.scss " , theme_id : theme . id )
expect ( scss ) . to include ( " font-size:30px " )
2018-03-04 19:04:23 -05:00
end
2018-03-04 23:35:41 -05:00
it " allows values to be used in JS " do
theme = Theme . new ( name : " awesome theme " , user_id : - 1 )
theme . set_field ( target : :settings , name : :yaml , value : " name: bob " )
theme . set_field ( target : :common , name : :after_header , value : '<script type="text/discourse-plugin" version="1.0">alert(settings.name); let a = ()=>{};</script>' )
theme . save!
transpiled = << ~ HTML
2018-07-18 01:13:47 -04:00
< script > if ( 'Discourse' in window ) {
Discourse . _registerPluginCode ( '1.0' , function ( api ) {
var settings = { " name " : " bob " } ;
alert ( settings . name ) ; var a = function a ( ) { } ;
} ) ;
} < / script>
2018-03-04 23:35:41 -05:00
HTML
2018-07-12 00:18:21 -04:00
expect ( Theme . lookup_field ( theme . id , :desktop , :after_header ) ) . to eq ( transpiled . strip )
2018-03-04 23:35:41 -05:00
setting = theme . settings . find { | s | s . name == :name }
setting . value = 'bill'
transpiled = << ~ HTML
2018-07-18 01:13:47 -04:00
< script > if ( 'Discourse' in window ) {
Discourse . _registerPluginCode ( '1.0' , function ( api ) {
var settings = { " name " : " bill " } ;
alert ( settings . name ) ; var a = function a ( ) { } ;
} ) ;
} < / script>
2018-03-04 23:35:41 -05:00
HTML
2018-07-12 00:18:21 -04:00
expect ( Theme . lookup_field ( theme . id , :desktop , :after_header ) ) . to eq ( transpiled . strip )
2018-03-04 23:35:41 -05:00
end
2018-03-04 19:04:23 -05:00
end
2018-07-12 00:18:21 -04:00
it 'correctly caches theme ids' do
2017-05-03 11:31:16 -04:00
Theme . destroy_all
2017-04-14 13:35:12 -04:00
theme = Theme . create! ( name : " bob " , user_id : - 1 )
2018-07-12 00:18:21 -04:00
expect ( Theme . theme_ids ) . to eq ( Set . new ( [ theme . id ] ) )
expect ( Theme . user_theme_ids ) . to eq ( Set . new ( [ ] ) )
2017-04-14 13:35:12 -04:00
theme . user_selectable = true
theme . save
2018-07-12 00:18:21 -04:00
expect ( Theme . user_theme_ids ) . to eq ( Set . new ( [ theme . id ] ) )
2017-04-14 13:35:12 -04:00
theme . user_selectable = false
theme . save
theme . set_default!
2018-07-12 00:18:21 -04:00
expect ( Theme . user_theme_ids ) . to eq ( Set . new ( [ theme . id ] ) )
2017-04-14 13:35:12 -04:00
theme . destroy
2018-07-12 00:18:21 -04:00
expect ( Theme . theme_ids ) . to eq ( Set . new ( [ ] ) )
expect ( Theme . user_theme_ids ) . to eq ( Set . new ( [ ] ) )
2017-04-14 13:35:12 -04:00
end
2017-09-04 07:27:58 -04:00
it 'correctly caches user_themes template' do
Theme . destroy_all
json = Site . json_for ( guardian )
user_themes = JSON . parse ( json ) [ " user_themes " ]
expect ( user_themes ) . to eq ( [ ] )
theme = Theme . create! ( name : " bob " , user_id : - 1 , user_selectable : true )
theme . save!
json = Site . json_for ( guardian )
user_themes = JSON . parse ( json ) [ " user_themes " ] . map { | t | t [ " name " ] }
expect ( user_themes ) . to eq ( [ " bob " ] )
theme . name = " sam "
theme . save!
json = Site . json_for ( guardian )
user_themes = JSON . parse ( json ) [ " user_themes " ] . map { | t | t [ " name " ] }
expect ( user_themes ) . to eq ( [ " sam " ] )
Theme . destroy_all
json = Site . json_for ( guardian )
user_themes = JSON . parse ( json ) [ " user_themes " ]
expect ( user_themes ) . to eq ( [ ] )
end
2018-07-12 00:18:21 -04:00
def cached_settings ( id )
Theme . find_by ( id : id ) . included_settings . to_json
2018-03-04 19:04:23 -05:00
end
it 'handles settings cache correctly' do
Theme . destroy_all
theme = Theme . create! ( name : " awesome theme " , user_id : - 1 )
2018-07-12 00:18:21 -04:00
expect ( cached_settings ( theme . id ) ) . to eq ( " {} " )
2018-03-04 19:04:23 -05:00
theme . set_field ( target : :settings , name : " yaml " , value : " boolean_setting: true " )
theme . save!
2018-07-12 00:18:21 -04:00
expect ( cached_settings ( theme . id ) ) . to match ( / \ "boolean_setting \ ":true / )
2018-03-04 19:04:23 -05:00
theme . settings . first . value = " false "
2018-07-12 00:18:21 -04:00
expect ( cached_settings ( theme . id ) ) . to match ( / \ "boolean_setting \ ":false / )
2018-03-04 19:04:23 -05:00
child = Theme . create! ( name : " child theme " , user_id : - 1 )
child . set_field ( target : :settings , name : " yaml " , value : " integer_setting: 54 " )
child . save!
theme . add_child_theme! ( child )
2018-07-12 00:18:21 -04:00
json = cached_settings ( theme . id )
2018-03-04 19:04:23 -05:00
expect ( json ) . to match ( / \ "boolean_setting \ ":false / )
expect ( json ) . to match ( / \ "integer_setting \ ":54 / )
2018-07-12 00:18:21 -04:00
expect ( cached_settings ( child . id ) ) . to eq ( " { \" integer_setting \" :54} " )
2018-03-04 19:04:23 -05:00
child . destroy!
2018-07-12 00:18:21 -04:00
json = cached_settings ( theme . id )
2018-03-04 19:04:23 -05:00
expect ( json ) . not_to match ( / \ "integer_setting \ ":54 / )
expect ( json ) . to match ( / \ "boolean_setting \ ":false / )
end
2017-04-12 10:52:52 -04:00
end