spec/i18n_js_spec.rb in i18n-js-3.0.0.rc8 vs spec/i18n_js_spec.rb in i18n-js-3.0.0.rc9

- old
+ new

@@ -27,17 +27,19 @@ file_should_exist "translations.js" end it "exports messages using custom output path" do set_config "custom_path.yml" - I18n::JS.should_receive(:save).with(translations, "tmp/i18n-js/all.js") + I18n::JS::Segment.should_receive(:new).with("tmp/i18n-js/all.js", translations, {}).and_call_original + I18n::JS::Segment.any_instance.should_receive(:save!).with(no_args) I18n::JS.export end it "sets default scope to * when not specified" do set_config "no_scope.yml" - I18n::JS.should_receive(:save).with(translations, "tmp/i18n-js/no_scope.js") + I18n::JS::Segment.should_receive(:new).with("tmp/i18n-js/no_scope.js", translations, {}).and_call_original + I18n::JS::Segment.any_instance.should_receive(:save!).with(no_args) I18n::JS.export end it "exports to multiple files" do set_config "multiple_files.yml" @@ -57,10 +59,11 @@ it "exports to a JS file per available locale" do set_config "js_file_per_locale.yml" I18n::JS.export file_should_exist "en.js" + file_should_exist "fr.js" end it "exports with multiple conditions" do set_config "multiple_conditions.yml" I18n::JS.export @@ -71,22 +74,27 @@ it "exports with multiple conditions to a JS file per available locale" do allow(::I18n).to receive(:available_locales){ [:en, :fr] } set_config "multiple_conditions_per_locale.yml" - expected_locales = %w(en fr) - result = I18n::JS.translation_segments - expected_files = expected_locales.map { |locale| "tmp/i18n-js/bits.#{locale}.js" } - result.keys.should eql(expected_files) + result.map(&:file).should eql(["tmp/i18n-js/bits.en.js", "tmp/i18n-js/bits.fr.js"]) - expected_locales.each do |lang| - result["tmp/i18n-js/bits.#{lang}.js"].keys.should eql([lang.to_sym]) - result["tmp/i18n-js/bits.#{lang}.js"][lang.to_sym].keys.sort.should eql([:date, :number]) + %w(en fr).each do |lang| + segment = result.select{|s| s.file == "tmp/i18n-js/bits.#{lang}.js"}.first + segment.translations.keys.should eql([lang.to_sym]) + segment.translations[lang.to_sym].keys.sort.should eql([:date, :number]) end end + it "exports with :except condition" do + set_config "except_condition.yml" + I18n::JS.export + + file_should_exist "trimmed.js" + end + it "calls .export_i18n_js" do allow(described_class).to receive(:export_i18n_js) I18n::JS.export expect(described_class).to have_received(:export_i18n_js).once end @@ -130,37 +138,71 @@ result[:en][:admin][:edit][:title].should eql("Edit") result[:fr][:admin][:edit][:title].should eql("Editer") end end + context "exceptions" do + it "does not include a key listed in the exceptions list" do + result = I18n::JS.scoped_translations("*", ['admin']) + + result[:en][:admin].should be_nil + result[:fr][:admin].should be_nil + end + + it "does not include multiple keys listed in the exceptions list" do + result = I18n::JS.scoped_translations("*", ['title', 'note']) + + result[:en][:admin][:show].should be_empty + result[:en][:admin][:edit].should be_empty + + result[:fr][:admin][:show].should be_empty + result[:fr][:admin][:show].should be_empty + result[:fr][:admin][:edit].should be_empty + end + + it "does not include a key listed in the exceptions list and respecs the 'only' option" do + result = I18n::JS.scoped_translations("fr.*", ['date', 'time', 'number', 'show']) + + result[:en].should be_nil + result[:de].should be_nil + result[:ja].should be_nil + + result[:fr][:date].should be_nil + result[:fr][:time].should be_nil + result[:fr][:number].should be_nil + result[:fr][:admin][:show].should be_nil + + result[:fr][:admin][:edit][:title].should be_a(String) + end + end + context "fallbacks" do + subject do + I18n::JS.translation_segments.inject({}) do |hash, segment| + hash[segment.file] = segment.translations + hash + end + end + it "exports without fallback when disabled" do set_config "js_file_per_locale_without_fallbacks.yml" - - result = I18n::JS.translation_segments - result["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql(nil) + subject["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql(nil) end it "exports with default_locale as fallback when enabled" do set_config "js_file_per_locale_with_fallbacks_enabled.yml" - - result = I18n::JS.translation_segments - result["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Success") + subject["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Success") end it "exports with default_locale as fallback when enabled with :default_locale" do set_config "js_file_per_locale_with_fallbacks_as_default_locale_symbol.yml" - - result = I18n::JS.translation_segments - result["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Success") + subject["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Success") end it "exports with given locale as fallback" do set_config "js_file_per_locale_with_fallbacks_as_locale.yml" - - result = I18n::JS.translation_segments - result["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Erfolg") + subject["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Erfolg") end context "with I18n::Fallbacks enabled" do let(:backend_with_fallbacks) { backend_class_with_fallbacks.new } let!(:old_backebad) { I18n.backend } @@ -171,31 +213,57 @@ end after { I18n.backend = old_backebad } it "exports with defined locale as fallback when enabled" do set_config "js_file_per_locale_with_fallbacks_enabled.yml" - - result = I18n::JS.translation_segments - result["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Erfolg") + subject["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Erfolg") end it "exports with defined locale as fallback when enabled with :default_locale" do set_config "js_file_per_locale_with_fallbacks_as_default_locale_symbol.yml" - - result = I18n::JS.translation_segments - result["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Success") + subject["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Success") end it "exports with Fallbacks as Hash" do set_config "js_file_per_locale_with_fallbacks_as_hash.yml" - - result = I18n::JS.translation_segments - result["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Erfolg") + subject["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Erfolg") end end end + context "namespace and pretty_print options" do + + before do + stub_const('I18n::JS::DEFAULT_EXPORT_DIR_PATH', temp_path) + set_config "js_file_with_namespace_and_pretty_print.yml" + end + + it "exports with defined locale as fallback when enabled" do + I18n::JS.export + file_should_exist "en.js" + output = File.read(File.join(I18n::JS.export_i18n_js_dir_path, "en.js")) + expect(output).to match(/^#{ +<<EOS +Foo.translations || (Foo.translations = {}); +Foo.translations["en"] = { + "number": { + "format": { +EOS +}.+#{ +<<EOS + "edit": { + "title": "Edit" + } + }, + "foo": "Foo", + "fallback_test": "Success" +}; +EOS +}$/) + end + end + context "I18n.available_locales" do context "when I18n.available_locales is not set" do it "should allow all locales" do result = I18n::JS.scoped_translations("*.admin.*.title") @@ -234,13 +302,14 @@ config_entry = I18n::JS.config["translations"].first config_entry["only"].should eq("*.date.formats") end end - describe "i18n.js exporting" do - describe ".export_i18n_js" do + after { begin described_class.send(:remove_instance_variable, :@export_i18n_js_dir_path); rescue; end } + + describe ".export_i18n_js with global variable" do before do allow(FileUtils).to receive(:mkdir_p).and_call_original allow(FileUtils).to receive(:cp).and_call_original described_class.stub(:export_i18n_js_dir_path).and_return(export_i18n_js_dir_path) @@ -271,15 +340,51 @@ expect(FileUtils).to_not have_received(:cp) end end end + describe ".export_i18n_js with config" do + let(:export_action) do + allow(FileUtils).to receive(:mkdir_p).and_call_original + allow(FileUtils).to receive(:cp).and_call_original + I18n::JS.export_i18n_js + end + + context 'when :export_i18n_js set in config' do + before { set_config "js_export_dir_custom.yml"; export_action } + let(:export_i18n_js_dir_path) { temp_path } + let(:config_export_path) { "tmp/i18n-js/foo" } + + it "does create the folder before copying" do + expect(FileUtils).to have_received(:mkdir_p).with(config_export_path).once + end + it "does copy the file with FileUtils.cp" do + expect(FileUtils).to have_received(:cp).once + end + it "exports the file" do + File.should be_file(File.join(config_export_path, "i18n.js")) + end + end + + context 'when .export_i18n_js_dir_path is set to false' do + before { set_config "js_export_dir_none.yml"; export_action } + + it "does NOT create the folder before copying" do + expect(FileUtils).to_not have_received(:mkdir_p) + end + + it "does NOT copy the file with FileUtils.cp" do + expect(FileUtils).to_not have_received(:cp) + end + end + end + describe '.export_i18n_js_dir_path' do let(:default_path) { I18n::JS::DEFAULT_EXPORT_DIR_PATH } let(:new_path) { File.join("tmp", default_path) } - before { described_class.send(:remove_instance_variable, :@export_i18n_js_dir_path) } + after { described_class.send(:remove_instance_variable, :@export_i18n_js_dir_path) } subject { described_class.export_i18n_js_dir_path } context "when it is not set" do it { should eq default_path } @@ -290,94 +395,10 @@ it { should eq new_path } end context "when it is set to nil already" do before { described_class.export_i18n_js_dir_path = nil } - it { should be_nil } + it { should eq :none } end end end -end - -describe I18n::JS::Dependencies, ".sprockets_supports_register_preprocessor?" do - - subject { described_class.sprockets_supports_register_preprocessor? } - - context 'when Sprockets is available to register preprocessors' do - let!(:sprockets_double) do - class_double('Sprockets').as_stubbed_const(register_processor: true).tap do |double| - allow(double).to receive(:respond_to?).with(:register_preprocessor).and_return(true) - end - end - - it { is_expected.to be_truthy } - it 'calls respond_to? with register_preprocessor on Sprockets' do - expect(sprockets_double).to receive(:respond_to?).with(:register_preprocessor).and_return(true) - subject - end - end - - context 'when Sprockets is NOT available to register preprocessors' do - let!(:sprockets_double) do - class_double('Sprockets').as_stubbed_const(register_processor: true).tap do |double| - allow(double).to receive(:respond_to?).with(:register_preprocessor).and_return(false) - end - end - - it { is_expected.to be_falsy } - it 'calls respond_to? with register_preprocessor on Sprockets' do - expect(sprockets_double).to receive(:respond_to?).with(:register_preprocessor).and_return(false) - subject - end - end - - context 'when Sprockets is missing' do - before do - hide_const('Sprockets') - expect { Sprockets }.to raise_error(NameError) - end - - it { is_expected.to be_falsy } - end - -end - -describe I18n::JS::Utils do - - describe ".strip_keys_with_nil_values" do - subject { described_class.strip_keys_with_nil_values(input_hash) } - - context 'when input_hash does NOT contain nil value' do - let(:input_hash) { {a: 1, b: { c: 2 }} } - let(:expected_hash) { input_hash } - - it 'returns the original input' do - is_expected.to eq expected_hash - end - end - context 'when input_hash does contain nil value' do - let(:input_hash) { {a: 1, b: { c: 2, d: nil }, e: { f: nil }} } - let(:expected_hash) { {a: 1, b: { c: 2 }, e: {}} } - - it 'returns the original input with nil values removed' do - is_expected.to eq expected_hash - end - end - end - - context "hash merging" do - it "performs a deep merge" do - target = {:a => {:b => 1}} - result = described_class.deep_merge(target, {:a => {:c => 2}}) - - result[:a].should eql({:b => 1, :c => 2}) - end - - it "performs a banged deep merge" do - target = {:a => {:b => 1}} - described_class.deep_merge!(target, {:a => {:c => 2}}) - - target[:a].should eql({:b => 1, :c => 2}) - end - end - end