# frozen_string_literal: true require 'rails_helper' describe ThemeJavascriptCompiler do let(:theme_id) { 22 } describe ThemeJavascriptCompiler::RawTemplatePrecompiler do # For the raw templates, we can easily render them serverside, so let's do that let(:compiler) { described_class.new(theme_id) } let(:helpers) { <<~JS Handlebars.registerHelper('theme-prefix', function(themeId, string) { return `theme_translations.${themeId}.${string}` }) Handlebars.registerHelper('theme-i18n', function(themeId, string) { return `translated(theme_translations.${themeId}.${string})` }) Handlebars.registerHelper('theme-setting', function(themeId, string) { return `setting(${themeId}:${string})` }) Handlebars.registerHelper('dummy-helper', function(string) { return `dummy(${string})` }) JS } let(:mini_racer) { ctx = MiniRacer::Context.new ctx.eval(File.open("#{Rails.root}/vendor/assets/javascripts/handlebars.js").read) ctx.eval(helpers) ctx } def render(template) compiled = compiler.compile(template) mini_racer.eval "Handlebars.template(#{compiled.squish})({})" end it 'adds the theme id to the helpers' do # Works normally expect(render("{{theme-prefix 'translation_key'}}")). to eq('theme_translations.22.translation_key') expect(render("{{theme-i18n 'translation_key'}}")). to eq('translated(theme_translations.22.translation_key)') expect(render("{{theme-setting 'setting_key'}}")). to eq('setting(22:setting_key)') # Works when used inside other statements expect(render("{{dummy-helper (theme-prefix 'translation_key')}}")). to eq('dummy(theme_translations.22.translation_key)') end it 'works with the old settings syntax' do expect(render("{{themeSettings.setting_key}}")). to eq('setting(22:setting_key)') # Works when used inside other statements expect(render("{{dummy-helper themeSettings.setting_key}}")). to eq('dummy(setting(22:setting_key))') end it "doesn't duplicate number parameter inside {{each}}" do expect(compiler.compile("{{#each item as |test test2|}}{{theme-setting 'setting_key'}}{{/each}}")). to include('{"name":"theme-setting","hash":{},"hashTypes":{},"hashContexts":{},"types":["NumberLiteral","StringLiteral"]') # Fail would be if theme-setting is defined with types:["NumberLiteral","NumberLiteral","StringLiteral"] end end describe ThemeJavascriptCompiler::EmberTemplatePrecompiler do # For the Ember (Glimmer) templates, serverside rendering is not trivial, # so check the compiled JSON against known working output let(:compiler) { described_class.new(theme_id) } let(:helper_opcode) do append = statement("{{dummy-helper 1}}")[0] helper = append[1] helper[0] end def statement(template) compiled = compiler.compile(template) data = JSON.parse(compiled) block = JSON.parse(data["block"]) block["statements"] end it 'adds the theme id to the helpers' do expect(statement("{{theme-prefix 'translation_key'}}")). to eq([[1, [helper_opcode, "theme-prefix", [22, "translation_key"], nil], false]]) expect(statement("{{theme-i18n 'translation_key'}}")). to eq([[1, [helper_opcode, "theme-i18n", [22, "translation_key"], nil], false]]) expect(statement("{{theme-setting 'setting_key'}}")). to eq([[1, [helper_opcode, "theme-setting", [22, "setting_key"], nil], false]]) # Works when used inside other statements expect(statement("{{dummy-helper (theme-prefix 'translation_key')}}")). to eq([[1, [helper_opcode, "dummy-helper", [[helper_opcode, "theme-prefix", [22, "translation_key"], nil]], nil], false]]) end it 'works with the old settings syntax' do expect(statement("{{themeSettings.setting_key}}")). to eq([[1, [helper_opcode, "theme-setting", [22, "setting_key"], [["deprecated"], [true]]], false]]) # Works when used inside other statements expect(statement("{{dummy-helper themeSettings.setting_key}}")). to eq([[1, [helper_opcode, "dummy-helper", [[helper_opcode, "theme-setting", [22, "setting_key"], [["deprecated"], [true]]]], nil], false]]) end end describe "#append_raw_template" do let(:compiler) { ThemeJavascriptCompiler.new(1, 'marks') } it 'uses the correct template paths' do template = "

hello

" name = "/path/to/templates1" compiler.append_raw_template("#{name}.raw", template) expect(compiler.content.to_s).to include("addRawTemplate(\"#{name}\"") name = "/path/to/templates2" compiler.append_raw_template("#{name}.hbr", template) expect(compiler.content.to_s).to include("addRawTemplate(\"#{name}\"") name = "/path/to/templates3" compiler.append_raw_template("#{name}.hbs", template) expect(compiler.content.to_s).to include("addRawTemplate(\"#{name}.hbs\"") end end describe "#append_ember_template" do let(:compiler) { ThemeJavascriptCompiler.new(1, 'marks') } it 'prepends `javascripts/` to template name if it is not prepended' do compiler.append_ember_template("/connectors/blah-1", "{{var}}") expect(compiler.content.to_s).to include('Ember.TEMPLATES["javascripts/connectors/blah-1"]') compiler.append_ember_template("connectors/blah-2", "{{var}}") expect(compiler.content.to_s).to include('Ember.TEMPLATES["javascripts/connectors/blah-2"]') compiler.append_ember_template("javascripts/connectors/blah-3", "{{var}}") expect(compiler.content.to_s).to include('Ember.TEMPLATES["javascripts/connectors/blah-3"]') end end end