2019-04-29 20:27:42 -04:00
# frozen_string_literal: true
2017-04-12 10:52:52 -04:00
require 'rails_helper'
describe Theme do
2018-09-13 02:23:32 -04:00
after do
2017-04-12 10:52:52 -04:00
Theme . clear_cache!
end
2020-05-06 16:57:14 -04:00
before do
I18n . locale = :en
end
2019-05-06 23:12:20 -04:00
fab! :user do
2017-04-12 10:52:52 -04:00
Fabricate ( :user )
end
2017-09-04 07:27:58 -04:00
let ( :guardian ) do
Guardian . new ( user )
end
2018-08-08 00:46:34 -04:00
let ( :theme ) { Fabricate ( :theme , user : user ) }
2018-08-23 21:30:00 -04:00
let ( :child ) { Fabricate ( :theme , user : user , component : true ) }
2017-05-04 14:03:07 -04:00
it 'can properly clean up color schemes' do
scheme = ColorScheme . create! ( theme_id : theme . id , name : 'test' )
scheme2 = ColorScheme . create! ( theme_id : theme . id , name : 'test2' )
2018-08-08 00:46:34 -04:00
Fabricate ( :theme , color_scheme_id : scheme2 . id )
2017-05-04 14:03:07 -04:00
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
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
2018-08-08 00:46:34 -04:00
parent = Fabricate ( :theme , user : user )
2017-04-12 10:52:52 -04:00
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!
2019-11-28 00:19:01 -05:00
parent . add_relative_theme! ( :child , child )
2017-04-12 10:52:52 -04:00
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
2019-11-28 00:19:01 -05:00
it 'can support parent themes' do
child . add_relative_theme! ( :parent , theme )
expect ( child . parent_themes ) . to eq ( [ theme ] )
end
2019-01-25 09:19:01 -05:00
it " can automatically disable for mismatching version " do
2019-07-03 04:18:11 -04:00
expect ( theme . supported? ) . to eq ( true )
2019-01-25 09:19:01 -05:00
theme . create_remote_theme! ( remote_url : " " , minimum_discourse_version : " 99.99.99 " )
2019-08-29 10:47:08 -04:00
theme . save!
2019-07-03 04:18:11 -04:00
expect ( theme . supported? ) . to eq ( false )
2018-08-08 00:46:34 -04:00
2019-01-25 09:19:01 -05:00
expect ( Theme . transform_ids ( [ theme . id ] ) ) . to be_empty
2018-08-08 00:46:34 -04:00
end
2019-04-30 14:01:21 -04:00
xit " # transform_ids works with nil values " do
2019-01-25 12:00:19 -05:00
# Used in safe mode
expect ( Theme . transform_ids ( [ nil ] ) ) . to eq ( [ nil ] )
end
2019-07-03 04:18:11 -04:00
it '#transform_ids filters out disabled components' do
2019-11-28 00:19:01 -05:00
theme . add_relative_theme! ( :child , child )
2019-07-03 04:18:11 -04:00
expect ( Theme . transform_ids ( [ theme . id ] , extend : true ) ) . to eq ( [ theme . id , child . id ] )
child . update! ( enabled : false )
expect ( Theme . transform_ids ( [ theme . id ] , extend : true ) ) . to eq ( [ theme . id ] )
end
2018-08-08 00:46:34 -04:00
it " doesn't allow multi-level theme components " do
grandchild = Fabricate ( :theme , user : user )
grandparent = Fabricate ( :theme , user : user )
2017-04-12 10:52:52 -04:00
2018-08-08 00:46:34 -04:00
expect do
2019-11-28 00:19:01 -05:00
child . add_relative_theme! ( :child , grandchild )
2018-08-08 00:46:34 -04:00
end . to raise_error ( Discourse :: InvalidParameters , I18n . t ( " themes.errors.no_multilevels_components " ) )
expect do
2019-11-28 00:19:01 -05:00
grandparent . add_relative_theme! ( :child , theme )
2018-08-08 00:46:34 -04:00
end . to raise_error ( Discourse :: InvalidParameters , I18n . t ( " themes.errors.no_multilevels_components " ) )
end
2017-04-12 10:52:52 -04:00
2018-08-08 00:46:34 -04:00
it " doesn't allow a child to be user selectable " do
child . update ( user_selectable : true )
expect ( child . errors . full_messages ) . to contain_exactly ( I18n . t ( " themes.errors.component_no_user_selectable " ) )
end
it " doesn't allow a child to be set as the default theme " do
expect do
child . set_default!
end . to raise_error ( Discourse :: InvalidParameters , I18n . t ( " themes.errors.component_no_default " ) )
2017-04-12 10:52:52 -04:00
end
2018-08-23 21:30:00 -04:00
it " doesn't allow a component to have color scheme " do
scheme = ColorScheme . create! ( name : " test " )
child . update ( color_scheme : scheme )
expect ( child . errors . full_messages ) . to contain_exactly ( I18n . t ( " themes.errors.component_no_color_scheme " ) )
end
2017-04-12 10:52:52 -04:00
it 'should correct bad html in body_tag_baked and head_tag_baked' do
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
2019-05-24 10:25:55 -04:00
it " changing theme name should re-transpile HTML theme fields " do
theme . update! ( name : " old_name " )
html = << ~ HTML
< script type = 'text/discourse-plugin' version = '0.1' >
const x = 1 ;
< / script>
HTML
theme . set_field ( target : :common , name : " head_tag " , value : html )
theme . save!
field = theme . theme_fields . where ( value : html ) . first
old_value = field . value_baked
theme . update! ( name : " new_name " )
field . reload
new_value = field . value_baked
expect ( old_value ) . not_to eq ( new_value )
end
2017-04-12 10:52:52 -04:00
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
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-10-15 00:55:23 -04:00
field = theme . theme_fields . find_by ( target_id : Theme . targets [ :common ] , name : 'header' )
2018-07-12 00:18:21 -04:00
baked = Theme . lookup_field ( theme . id , :mobile , " header " )
2017-04-12 10:52:52 -04:00
2018-10-15 00:55:23 -04:00
expect ( baked ) . to include ( field . javascript_cache . url )
expect ( field . javascript_cache . content ) . to include ( 'HTMLBars' )
expect ( field . javascript_cache . content ) . to include ( 'raw-handlebars' )
2017-04-12 10:52:52 -04:00
end
2019-02-12 11:14:43 -05:00
it 'can destroy unbaked theme without errors' 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 . set_field ( target : :common , name : " header " , value : with_template )
theme . save!
field = theme . theme_fields . find_by ( target_id : Theme . targets [ :common ] , name : 'header' )
baked = Theme . lookup_field ( theme . id , :mobile , " header " )
ThemeField . where ( id : field . id ) . update_all ( compiler_version : 0 ) # update_all to avoid callbacks
field . reload . destroy!
end
2017-04-12 10:52:52 -04:00
it 'should create body_tag_baked on demand if needed' do
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
2018-08-08 00:46:34 -04:00
it 'can find fields for multiple themes' do
theme2 = Fabricate ( :theme )
theme . set_field ( target : :common , name : :body_tag , value : " <b>testtheme1</b> " )
theme2 . set_field ( target : :common , name : :body_tag , value : " <b>theme2test</b> " )
theme . save!
theme2 . save!
field = Theme . lookup_field ( [ theme . id , theme2 . id ] , :desktop , :body_tag )
expect ( field ) . to match ( / <b>testtheme1< \/ b> / )
expect ( field ) . to match ( / <b>theme2test< \/ b> / )
end
2018-08-23 21:30:00 -04:00
describe " # switch_to_component! " do
it " correctly converts a theme to component " do
2019-11-28 00:19:01 -05:00
theme . add_relative_theme! ( :child , child )
2018-08-23 21:30:00 -04:00
scheme = ColorScheme . create! ( name : 'test' )
theme . update! ( color_scheme_id : scheme . id , user_selectable : true )
theme . set_default!
theme . switch_to_component!
theme . reload
expect ( theme . component ) . to eq ( true )
expect ( theme . user_selectable ) . to eq ( false )
expect ( theme . default? ) . to eq ( false )
expect ( theme . color_scheme_id ) . to eq ( nil )
expect ( ChildTheme . where ( parent_theme : theme ) . exists? ) . to eq ( false )
end
end
describe " # switch_to_theme! " do
it " correctly converts a component to theme " do
2019-11-28 00:19:01 -05:00
theme . add_relative_theme! ( :child , child )
2018-08-23 21:30:00 -04:00
child . switch_to_theme!
theme . reload
child . reload
expect ( child . component ) . to eq ( false )
expect ( ChildTheme . where ( child_theme : child ) . exists? ) . to eq ( false )
end
end
2018-08-08 00:46:34 -04:00
describe " .transform_ids " do
2019-01-25 09:19:01 -05:00
let! ( :orphan1 ) { Fabricate ( :theme , component : true ) }
2018-08-23 21:30:00 -04:00
let! ( :child ) { Fabricate ( :theme , component : true ) }
let! ( :child2 ) { Fabricate ( :theme , component : true ) }
2019-01-25 09:19:01 -05:00
let! ( :orphan2 ) { Fabricate ( :theme , component : true ) }
let! ( :orphan3 ) { Fabricate ( :theme , component : true ) }
let! ( :orphan4 ) { Fabricate ( :theme , component : true ) }
2018-08-08 00:46:34 -04:00
2018-08-23 21:30:00 -04:00
before do
2019-11-28 00:19:01 -05:00
theme . add_relative_theme! ( :child , child )
theme . add_relative_theme! ( :child , child2 )
2018-08-23 21:30:00 -04:00
end
2019-01-25 09:19:01 -05:00
it " returns an empty array if no ids are passed " do
expect ( Theme . transform_ids ( [ ] ) ) . to eq ( [ ] )
end
2018-08-23 21:30:00 -04:00
it " adds the child themes of the parent " do
sorted = [ child . id , child2 . id ] . sort
2018-08-09 20:38:36 -04:00
expect ( Theme . transform_ids ( [ theme . id ] ) ) . to eq ( [ theme . id , * sorted ] )
2019-01-25 09:19:01 -05:00
expect ( Theme . transform_ids ( [ theme . id , orphan1 . id , orphan2 . id ] ) ) . to eq ( [ theme . id , orphan1 . id , * sorted , orphan2 . id ] )
2018-08-08 00:46:34 -04:00
end
it " doesn't insert children when extend is false " do
2019-01-25 09:19:01 -05:00
fake_id = orphan2 . id
fake_id2 = orphan3 . id
fake_id3 = orphan4 . id
2018-08-09 20:38:36 -04:00
2018-08-08 00:46:34 -04:00
expect ( Theme . transform_ids ( [ theme . id ] , extend : false ) ) . to eq ( [ theme . id ] )
2018-08-09 20:38:36 -04:00
expect ( Theme . transform_ids ( [ theme . id , fake_id3 , fake_id , fake_id2 , fake_id2 ] , extend : false ) )
. to eq ( [ theme . id , fake_id , fake_id2 , fake_id3 ] )
2018-08-08 00:46:34 -04:00
end
end
2017-04-12 10:52:52 -04:00
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 )
2019-04-12 06:36:08 -04:00
f . ensure_baked!
2019-11-14 15:10:51 -05:00
[ f . value_baked , f . javascript_cache ]
2017-04-12 10:52:52 -04:00
end
it " transpiles ES6 code " do
html = <<HTML
< script type = 'text/discourse-plugin' version = '0.1' >
const x = 1 ;
< / script>
HTML
2018-10-15 00:55:23 -04:00
baked , javascript_cache = transpile ( html )
expect ( baked ) . to include ( javascript_cache . url )
expect ( javascript_cache . content ) . to include ( 'var x = 1;' )
expect ( javascript_cache . content ) . to include ( " _registerPluginCode('0.1' " )
2017-04-12 10:52:52 -04:00
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
2018-10-15 00:55:23 -04:00
baked , javascript_cache = transpile ( html )
expect ( baked ) . to include ( javascript_cache . url )
expect ( javascript_cache . content ) . to include ( 'Theme Transpilation Error' )
expect ( javascript_cache . content ) . to include ( 'read-only' )
2017-04-12 10:52:52 -04:00
end
end
2019-01-18 07:03:55 -05:00
context 'theme upload vars' do
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
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
2019-02-19 10:55:59 -05:00
scss , _map = Stylesheet :: Compiler . compile ( '@import "common/foundation/variables"; @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 . 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'
2019-04-12 06:36:08 -04:00
theme . save!
2018-03-04 23:35:41 -05:00
scss , _map = Stylesheet :: Compiler . compile ( '@import "theme_variables"; @import "desktop_theme"; ' , " theme.scss " , theme_id : theme . id )
expect ( scss ) . to include ( " font-size:30px " )
2019-03-08 03:58:06 -05:00
# Escapes correctly. If not, compiling this would throw an exception
setting . value = << ~ MULTILINE
\ #{$fakeinterpolatedvariable}
andanothervalue 'withquotes' ; margin : 0 ;
MULTILINE
theme . set_field ( target : :common , name : :scss , value : 'body {font-size: quote($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 ( 'font-size:"#{$fakeinterpolatedvariable}\a andanothervalue \'withquotes\'; margin: 0;\a"' )
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
2019-05-24 10:25:55 -04:00
theme . name = 'awesome theme"'
2018-03-04 23:35:41 -05:00
theme . set_field ( target : :settings , name : :yaml , value : " name: bob " )
2018-10-15 00:55:23 -04:00
theme_field = theme . set_field ( target : :common , name : :after_header , value : '<script type="text/discourse-plugin" version="1.0">alert(settings.name); let a = ()=>{};</script>' )
2018-03-04 23:35:41 -05:00
theme . save!
transpiled = << ~ HTML
2019-01-17 06:46:11 -05:00
( function ( ) {
if ( 'Discourse' in window && Discourse . __container__ ) {
Discourse . __container__
. lookup ( " service:theme-settings " )
. registerSettings ( #{theme.id}, {"name":"bob"});
}
} ) ( ) ;
2019-01-17 09:39:39 -05:00
( function ( ) {
if ( 'Discourse' in window && typeof Discourse . _registerPluginCode === 'function' ) {
2019-05-24 10:25:55 -04:00
var __theme_name__ = " awesome theme \\ \" " ;
2019-01-17 09:39:39 -05:00
var settings = Discourse . __container__ . lookup ( " service:theme-settings " ) . getObjectForTheme ( #{theme.id});
var themePrefix = function themePrefix ( key ) {
return 'theme_translations.#{theme.id}.' + key ;
} ;
2019-06-03 05:41:00 -04:00
2019-01-17 09:39:39 -05:00
Discourse . _registerPluginCode ( '1.0' , function ( api ) {
2019-05-24 10:25:55 -04:00
try {
alert ( settings . name ) ; var a = function a ( ) { } ;
} catch ( err ) {
var rescue = require ( " discourse/lib/utilities " ) . rescueThemeError ;
rescue ( __theme_name__ , err , api ) ;
}
2019-01-17 09:39:39 -05:00
} ) ;
}
} ) ( ) ;
2018-03-04 23:35:41 -05:00
HTML
2018-10-15 00:55:23 -04:00
theme_field . reload
expect ( Theme . lookup_field ( theme . id , :desktop , :after_header ) ) . to include ( theme_field . javascript_cache . url )
expect ( theme_field . javascript_cache . content ) . to eq ( transpiled . strip )
2018-03-04 23:35:41 -05:00
setting = theme . settings . find { | s | s . name == :name }
setting . value = 'bill'
2019-04-12 06:36:08 -04:00
theme . save!
2018-03-04 23:35:41 -05:00
transpiled = << ~ HTML
2019-01-17 06:46:11 -05:00
( function ( ) {
if ( 'Discourse' in window && Discourse . __container__ ) {
Discourse . __container__
. lookup ( " service:theme-settings " )
. registerSettings ( #{theme.id}, {"name":"bill"});
}
} ) ( ) ;
2019-01-17 09:39:39 -05:00
( function ( ) {
if ( 'Discourse' in window && typeof Discourse . _registerPluginCode === 'function' ) {
2019-05-24 10:25:55 -04:00
var __theme_name__ = " awesome theme \\ \" " ;
2019-01-17 09:39:39 -05:00
var settings = Discourse . __container__ . lookup ( " service:theme-settings " ) . getObjectForTheme ( #{theme.id});
var themePrefix = function themePrefix ( key ) {
return 'theme_translations.#{theme.id}.' + key ;
} ;
2019-06-03 05:41:00 -04:00
2019-01-17 09:39:39 -05:00
Discourse . _registerPluginCode ( '1.0' , function ( api ) {
2019-05-24 10:25:55 -04:00
try {
alert ( settings . name ) ; var a = function a ( ) { } ;
} catch ( err ) {
var rescue = require ( " discourse/lib/utilities " ) . rescueThemeError ;
rescue ( __theme_name__ , err , api ) ;
}
2019-01-17 09:39:39 -05:00
} ) ;
}
} ) ( ) ;
2018-03-04 23:35:41 -05:00
HTML
2018-10-15 00:55:23 -04:00
theme_field . reload
expect ( Theme . lookup_field ( theme . id , :desktop , :after_header ) ) . to include ( theme_field . javascript_cache . url )
expect ( theme_field . javascript_cache . content ) . to eq ( transpiled . strip )
2018-03-04 23:35:41 -05:00
end
2018-12-19 10:36:31 -05:00
it 'is empty when the settings are invalid' do
theme . set_field ( target : :settings , name : :yaml , value : 'nil_setting: ' )
theme . save!
expect ( theme . settings ) . to be_empty
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
2018-08-08 00:46:34 -04:00
theme
theme2 = Fabricate ( :theme )
2017-04-14 13:35:12 -04:00
2018-08-08 00:46:34 -04:00
expect ( Theme . theme_ids ) . to contain_exactly ( theme . id , theme2 . id )
expect ( Theme . user_theme_ids ) . to eq ( [ ] )
2017-04-14 13:35:12 -04:00
2018-08-08 00:46:34 -04:00
theme . update! ( user_selectable : true )
2017-04-14 13:35:12 -04:00
2018-08-08 00:46:34 -04:00
expect ( Theme . user_theme_ids ) . to contain_exactly ( theme . id )
2017-04-14 13:35:12 -04:00
2018-08-08 00:46:34 -04:00
theme2 . update! ( user_selectable : true )
expect ( Theme . user_theme_ids ) . to contain_exactly ( theme . id , theme2 . id )
theme . update! ( user_selectable : false )
theme2 . update! ( user_selectable : false )
2017-04-14 13:35:12 -04:00
theme . set_default!
2018-08-08 00:46:34 -04:00
expect ( Theme . user_theme_ids ) . to contain_exactly ( theme . id )
2017-04-14 13:35:12 -04:00
theme . destroy
2018-08-08 00:46:34 -04:00
theme2 . destroy
2017-04-14 13:35:12 -04:00
2018-08-08 00:46:34 -04:00
expect ( Theme . theme_ids ) . to eq ( [ ] )
expect ( Theme . user_theme_ids ) . to eq ( [ ] )
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 ( [ ] )
2018-08-08 00:46:34 -04:00
theme = Fabricate ( :theme , name : " bob " , user_selectable : true )
2019-04-12 06:36:08 -04:00
theme . save!
2017-09-04 07:27:58 -04:00
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
2018-10-15 21:00:33 -04:00
it 'clears color scheme cache correctly' do
Theme . destroy_all
cs = Fabricate ( :color_scheme , name : 'Fancy' , color_scheme_colors : [
Fabricate ( :color_scheme_color , name : 'header_primary' , hex : 'F0F0F0' ) ,
Fabricate ( :color_scheme_color , name : 'header_background' , hex : '1E1E1E' ) ,
Fabricate ( :color_scheme_color , name : 'tertiary' , hex : '858585' )
] )
theme = Fabricate ( :theme ,
user_selectable : true ,
user : Fabricate ( :admin ) ,
color_scheme_id : cs . id
)
theme . set_default!
expect ( ColorScheme . hex_for_name ( 'header_primary' ) ) . to eq ( 'F0F0F0' )
Theme . clear_default!
expect ( ColorScheme . hex_for_name ( 'header_primary' ) ) . to eq ( '333333' )
end
2019-05-08 11:02:55 -04:00
it " correctly notifies about theme changes " do
cs1 = Fabricate ( :color_scheme )
cs2 = Fabricate ( :color_scheme )
theme = Fabricate ( :theme ,
user_selectable : true ,
user : user ,
color_scheme_id : cs1 . id
)
messages = MessageBus . track_publish do
theme . save!
end . filter { | m | m . channel == " /file-change " }
expect ( messages . count ) . to eq ( 1 )
expect ( messages . first . data . map { | d | d [ :target ] } ) . to contain_exactly ( :desktop_theme , :mobile_theme )
# With color scheme change:
messages = MessageBus . track_publish do
theme . color_scheme_id = cs2 . id
theme . save!
end . filter { | m | m . channel == " /file-change " }
expect ( messages . count ) . to eq ( 1 )
expect ( messages . first . data . map { | d | d [ :target ] } ) . to contain_exactly ( :admin , :desktop , :desktop_theme , :mobile , :mobile_theme )
end
2019-08-21 02:50:47 -04:00
it 'includes theme_uploads in settings' do
Theme . destroy_all
upload = Fabricate ( :upload )
theme . set_field ( type : :theme_upload_var , target : :common , name : " bob " , upload_id : upload . id )
theme . save!
json = JSON . parse ( cached_settings ( theme . id ) )
expect ( json [ " theme_uploads " ] [ " bob " ] ) . to eq ( upload . url )
end
2018-03-04 19:04:23 -05:00
it 'handles settings cache correctly' do
Theme . destroy_all
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 "
2019-04-12 06:36:08 -04:00
theme . save!
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 . set_field ( target : :settings , name : " yaml " , value : " integer_setting: 54 " )
child . save!
2019-11-28 00:19:01 -05:00
theme . add_relative_theme! ( :child , child )
2018-03-04 19:04:23 -05:00
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
2019-01-17 06:46:11 -05:00
describe " theme translations " do
it " can list working theme_translation_manager objects " do
en_translation = ThemeField . create! ( theme_id : theme . id , name : " en " , type_id : ThemeField . types [ :yaml ] , target_id : Theme . targets [ :translations ] , value : << ~ YAML )
en :
2019-01-25 09:19:01 -05:00
theme_metadata :
description : " Description of my theme "
2019-01-17 06:46:11 -05:00
group_of_translations :
translation1 : en test1
translation2 : en test2
base_translation1 : en test3
base_translation2 : en test4
YAML
fr_translation = ThemeField . create! ( theme_id : theme . id , name : " fr " , type_id : ThemeField . types [ :yaml ] , target_id : Theme . targets [ :translations ] , value : << ~ YAML )
fr :
group_of_translations :
translation2 : fr test2
base_translation2 : fr test4
base_translation3 : fr test5
YAML
I18n . locale = :fr
theme . update_translation ( " group_of_translations.translation1 " , " overriddentest1 " )
translations = theme . translations
theme . reload
expect ( translations . map ( & :key ) ) . to eq ( [
" group_of_translations.translation1 " ,
" group_of_translations.translation2 " ,
" base_translation1 " ,
" base_translation2 " ,
" base_translation3 "
] )
expect ( translations . map ( & :default ) ) . to eq ( [
" en test1 " ,
" fr test2 " ,
" en test3 " ,
" fr test4 " ,
" fr test5 "
] )
expect ( translations . map ( & :value ) ) . to eq ( [
" overriddentest1 " ,
" fr test2 " ,
" en test3 " ,
" fr test4 " ,
" fr test5 "
] )
end
2019-01-25 09:19:01 -05:00
it " can list internal theme_translation_manager objects " do
en_translation = ThemeField . create! ( theme_id : theme . id , name : " en " , type_id : ThemeField . types [ :yaml ] , target_id : Theme . targets [ :translations ] , value : << ~ YAML )
en :
theme_metadata :
description : " Description of my theme "
another_translation : en test4
YAML
translations = theme . internal_translations
expect ( translations . map ( & :key ) ) . to contain_exactly ( " theme_metadata.description " )
expect ( translations . map ( & :value ) ) . to contain_exactly ( " Description of my theme " )
end
2019-01-17 06:46:11 -05:00
it " can create a hash of overridden values " do
2020-05-06 16:57:14 -04:00
en_translation = ThemeField . create! ( theme_id : theme . id , name : " en " , type_id : ThemeField . types [ :yaml ] , target_id : Theme . targets [ :translations ] , value : << ~ YAML )
en :
2019-01-17 06:46:11 -05:00
group_of_translations :
translation1 : en test1
YAML
theme . update_translation ( " group_of_translations.translation1 " , " overriddentest1 " )
I18n . locale = :fr
theme . update_translation ( " group_of_translations.translation1 " , " overriddentest2 " )
theme . reload
expect ( theme . translation_override_hash ) . to eq (
2020-05-06 16:57:14 -04:00
" en " = > {
2019-01-17 06:46:11 -05:00
" group_of_translations " = > {
" translation1 " = > " overriddentest1 "
}
} ,
" fr " = > {
" group_of_translations " = > {
" translation1 " = > " overriddentest2 "
}
}
)
end
it " fall back when listing baked field " do
theme2 = Fabricate ( :theme )
en_translation = ThemeField . create! ( theme_id : theme . id , name : " en " , type_id : ThemeField . types [ :yaml ] , target_id : Theme . targets [ :translations ] , value : '' )
fr_translation = ThemeField . create! ( theme_id : theme . id , name : " fr " , type_id : ThemeField . types [ :yaml ] , target_id : Theme . targets [ :translations ] , value : '' )
en_translation2 = ThemeField . create! ( theme_id : theme2 . id , name : " en " , type_id : ThemeField . types [ :yaml ] , target_id : Theme . targets [ :translations ] , value : '' )
expect ( Theme . list_baked_fields ( [ theme . id , theme2 . id ] , :translations , 'fr' ) . map ( & :id ) ) . to contain_exactly ( fr_translation . id , en_translation2 . id )
end
end
2019-07-16 10:34:33 -04:00
describe " automatic recompile " do
it 'must recompile after bumping theme_field version' do
def stub_const ( target , const , value )
old = target . const_get ( const )
target . send ( :remove_const , const )
target . const_set ( const , value )
yield
ensure
target . send ( :remove_const , const )
target . const_set ( const , old )
end
child . set_field ( target : :common , name : " header " , value : " World " )
child . set_field ( target : :extra_js , name : " test.js.es6 " , value : " const hello = 'world'; " )
child . save!
first_common_value = Theme . lookup_field ( child . id , :desktop , " header " )
first_extra_js_value = Theme . lookup_field ( child . id , :extra_js , nil )
2020-05-29 08:04:51 -04:00
Theme . stubs ( :compiler_version ) . returns ( " SOME_NEW_HASH " ) do
2019-07-16 10:34:33 -04:00
second_common_value = Theme . lookup_field ( child . id , :desktop , " header " )
second_extra_js_value = Theme . lookup_field ( child . id , :extra_js , nil )
new_common_compiler_version = ThemeField . find_by ( theme_id : child . id , name : " header " ) . compiler_version
new_extra_js_compiler_version = ThemeField . find_by ( theme_id : child . id , name : " test.js.es6 " ) . compiler_version
expect ( first_common_value ) . to eq ( second_common_value )
expect ( first_extra_js_value ) . to eq ( second_extra_js_value )
expect ( new_common_compiler_version ) . to eq ( " SOME_NEW_HASH " )
expect ( new_extra_js_compiler_version ) . to eq ( " SOME_NEW_HASH " )
end
end
2020-05-29 08:04:51 -04:00
it 'recompiles when the hostname changes' do
theme . set_field ( target : :settings , name : :yaml , value : " name: bob " )
theme_field = theme . set_field ( target : :common , name : :after_header , value : '<script>console.log("hello world");</script>' )
theme . save!
expect ( Theme . lookup_field ( theme . id , :common , :after_header ) ) . to include ( " _ws= #{ Discourse . current_hostname } " )
SiteSetting . force_hostname = " someotherhostname.com "
Theme . clear_cache!
expect ( Theme . lookup_field ( theme . id , :common , :after_header ) ) . to include ( " _ws=someotherhostname.com " )
end
2019-07-16 10:34:33 -04:00
end
2017-04-12 10:52:52 -04:00
end