releaf-i18n_database 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +24 -0
- data/app/assets/javascripts/releaf/controllers/releaf/i18n_database/translations.js +22 -0
- data/app/assets/stylesheets/releaf/controllers/releaf/i18n_database/translations.scss +95 -0
- data/app/builders/releaf/i18n_database/translations/builders_common.rb +13 -0
- data/app/builders/releaf/i18n_database/translations/edit_builder.rb +41 -0
- data/app/builders/releaf/i18n_database/translations/index_builder.rb +44 -0
- data/app/builders/releaf/i18n_database/translations/table_builder.rb +31 -0
- data/app/controllers/releaf/i18n_database/translations_controller.rb +171 -0
- data/app/lib/releaf/i18n_database/translations_importer.rb +72 -0
- data/app/lib/releaf/i18n_database/translations_utilities.rb +66 -0
- data/app/models/releaf/i18n_database/translation.rb +17 -0
- data/app/models/releaf/i18n_database/translation_data.rb +11 -0
- data/app/views/releaf/i18n_database/translations/_form_fields.haml +40 -0
- data/app/views/releaf/i18n_database/translations/export.xlsx.axlsx +24 -0
- data/lib/releaf-i18n_database.rb +5 -0
- data/lib/releaf/i18n_database/backend.rb +169 -0
- data/lib/releaf/i18n_database/builders_autoload.rb +10 -0
- data/lib/releaf/i18n_database/engine.rb +36 -0
- data/lib/releaf/i18n_database/humanize_missing_translations.rb +15 -0
- data/releaf-i18n_database.gemspec +21 -0
- data/spec/builders/translations/builder_common_spec.rb +39 -0
- data/spec/builders/translations/edit_builder_spec.rb +93 -0
- data/spec/builders/translations/index_builder_spec.rb +96 -0
- data/spec/builders/translations/table_builder_spec.rb +68 -0
- data/spec/controllers/i18n_backend/translations_controller_spec.rb +157 -0
- data/spec/features/translations_spec.rb +162 -0
- data/spec/fixtures/all_translations_exported.xlsx +0 -0
- data/spec/fixtures/time.formats.xlsx +0 -0
- data/spec/fixtures/translations_import.xlsx +0 -0
- data/spec/fixtures/unsupported_import_file.png +0 -0
- data/spec/lib/i18n_database/backend_spec.rb +337 -0
- data/spec/lib/i18n_database/humanize_missing_translations_spec.rb +18 -0
- data/spec/lib/i18n_database/translations_importer_spec.rb +17 -0
- data/spec/lib/i18n_database/translations_utilities_spec.rb +175 -0
- data/spec/models/i18n_database/translation_data_spec.rb +13 -0
- data/spec/models/i18n_database/translation_spec.rb +49 -0
- metadata +151 -0
| @@ -0,0 +1,15 @@ | |
| 1 | 
            +
            module Releaf::I18nDatabase
         | 
| 2 | 
            +
              module HumanizeMissingTranslations
         | 
| 3 | 
            +
                def call(exception, locale, key, options)
         | 
| 4 | 
            +
                  if exception.is_a?(I18n::MissingTranslation)
         | 
| 5 | 
            +
                    key.to_s.split('.').last.humanize
         | 
| 6 | 
            +
                  else
         | 
| 7 | 
            +
                    super
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def self.initialize_component
         | 
| 12 | 
            +
                  I18n.exception_handler.extend(self)
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
            end
         | 
| @@ -0,0 +1,21 @@ | |
| 1 | 
            +
            require File.expand_path("../../releaf-core/lib/releaf/version.rb", __FILE__)
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Gem::Specification.new do |s|
         | 
| 4 | 
            +
              s.name        = "releaf-i18n_database"
         | 
| 5 | 
            +
              s.version     = Releaf::VERSION
         | 
| 6 | 
            +
             | 
| 7 | 
            +
              s.summary     = "i18n database gem for releaf"
         | 
| 8 | 
            +
              s.description = "i18n database backend for releaf"
         | 
| 9 | 
            +
              s.authors     = ["CubeSystems"]
         | 
| 10 | 
            +
              s.email       = 'info@cubesystems.lv'
         | 
| 11 | 
            +
              s.homepage    = 'https://github.com/cubesystems/releaf'
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              s.files             = `git ls-files`.split("\n")
         | 
| 14 | 
            +
              s.test_files = Dir["spec/**/*"]
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              s.add_dependency 'releaf-core', Releaf::VERSION
         | 
| 17 | 
            +
              s.add_dependency 'twitter_cldr'
         | 
| 18 | 
            +
              s.add_dependency 'axlsx_rails', '>= 0.3.0'
         | 
| 19 | 
            +
              s.add_dependency 'roo'
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            end
         | 
| @@ -0,0 +1,39 @@ | |
| 1 | 
            +
            require "rails_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Releaf::I18nDatabase::Translations::BuildersCommon, type: :class do
         | 
| 4 | 
            +
              class I18nBuildersCommonInheriter < Releaf::Builders::IndexBuilder
         | 
| 5 | 
            +
                include Releaf::I18nDatabase::Translations::BuildersCommon
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
              class TableBuilderTestHelper < ActionView::Base; end
         | 
| 8 | 
            +
              let(:template){ TableBuilderTestHelper.new }
         | 
| 9 | 
            +
              let(:subject){ I18nBuildersCommonInheriter.new(template) }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              describe "#action_url" do
         | 
| 12 | 
            +
                before do
         | 
| 13 | 
            +
                  request = ActionDispatch::Request.new("X")
         | 
| 14 | 
            +
                  allow(request).to receive(:query_parameters).and_return(a: "b", c: "d")
         | 
| 15 | 
            +
                  allow(subject).to receive(:request).and_return(request)
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                it "returns url for given action with current query params" do
         | 
| 19 | 
            +
                  allow(subject).to receive(:url_for).with(a: "b", c: "d", action: :edit).and_return("url")
         | 
| 20 | 
            +
                  expect(subject.action_url(:edit)).to eq("url")
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                context "when extra params given" do
         | 
| 24 | 
            +
                  it "merges given params to url" do
         | 
| 25 | 
            +
                    allow(subject).to receive(:url_for).with(a: "b", c: "z", action: :edit, format: "xx").and_return("url")
         | 
| 26 | 
            +
                    expect(subject.action_url(:edit, format: "xx", c: "z")).to eq("url")
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
              describe "#export_button" do
         | 
| 32 | 
            +
                it "returns export button" do
         | 
| 33 | 
            +
                  allow(subject).to receive(:t).with("export").and_return("exp")
         | 
| 34 | 
            +
                  allow(subject).to receive(:action_url).with(:export, format: :xlsx).and_return("_exp_url_")
         | 
| 35 | 
            +
                  allow(subject).to receive(:button).with("exp", "download", class: "secondary", href: "_exp_url_").and_return("btn")
         | 
| 36 | 
            +
                  expect(subject.export_button).to eq('btn')
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
            end
         | 
| @@ -0,0 +1,93 @@ | |
| 1 | 
            +
            require "rails_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Releaf::I18nDatabase::Translations::EditBuilder, type: :class do
         | 
| 4 | 
            +
              class TableBuilderTestHelper < ActionView::Base
         | 
| 5 | 
            +
                def protect_against_forgery?; end
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
              let(:template){ TableBuilderTestHelper.new }
         | 
| 8 | 
            +
              let(:resource_class){ Releaf::I18nDatabase::Translation }
         | 
| 9 | 
            +
              let(:subject){ described_class.new(template) }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              describe "#section" do
         | 
| 12 | 
            +
                it "returns section blocks wrapped within edit form" do
         | 
| 13 | 
            +
                  allow(subject).to receive(:action_url).with(:update).and_return("update_url")
         | 
| 14 | 
            +
                  allow(subject).to receive(:section_blocks).and_return(["a", "b"])
         | 
| 15 | 
            +
                  result = '<section><form action="update_url" accept-charset="UTF-8" method="post"><input name="utf8" type="hidden" value="✓" />ab</form></section>'
         | 
| 16 | 
            +
                  expect(subject.section).to eq(result)
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              describe "#section_body" do
         | 
| 21 | 
            +
                it "returns section body with form fields partial" do
         | 
| 22 | 
            +
                  allow(subject).to receive(:render).with(partial: "form_fields", locals: {builder: subject}).and_return("xxx")
         | 
| 23 | 
            +
                  expect(subject.section_body).to eq('<div class="body">xxx</div>')
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              describe "#import?" do
         | 
| 28 | 
            +
                it "returns template `import` value" do
         | 
| 29 | 
            +
                  allow(subject).to receive(:template_variable).with("import").and_return("x")
         | 
| 30 | 
            +
                  expect(subject.import?).to eq("x")
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              describe "#save_button" do
         | 
| 35 | 
            +
                it "returns localized value for given resource and column(locale)" do
         | 
| 36 | 
            +
                  allow(subject).to receive(:save_button_text).and_return("sv_txt")
         | 
| 37 | 
            +
                  allow(subject).to receive(:button).with("sv_txt", "check", class: "primary", data: { type: 'ok' }, type: "submit").and_return("save_btn")
         | 
| 38 | 
            +
                  expect(subject.save_button).to eq("save_btn")
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              describe "#save_button_text" do
         | 
| 43 | 
            +
                context "when within import view" do
         | 
| 44 | 
            +
                  it "returns translated `Import` text" do
         | 
| 45 | 
            +
                    allow(subject).to receive(:t).with("Import").and_return("_import_")
         | 
| 46 | 
            +
                    allow(subject).to receive(:import?).and_return(true)
         | 
| 47 | 
            +
                    expect(subject.save_button_text).to eq("_import_")
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                context "when not within import view" do
         | 
| 52 | 
            +
                  it "returns translated `Save` text" do
         | 
| 53 | 
            +
                    allow(subject).to receive(:t).with("Save").and_return("_save_")
         | 
| 54 | 
            +
                    allow(subject).to receive(:import?).and_return(false)
         | 
| 55 | 
            +
                    expect(subject.save_button_text).to eq("_save_")
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              describe "#footer_secondary_tools" do
         | 
| 61 | 
            +
                before do
         | 
| 62 | 
            +
                  allow(subject).to receive(:back_to_index_button).and_return("indx_btn")
         | 
| 63 | 
            +
                  allow(subject).to receive(:export_button).and_return("xprt_btn")
         | 
| 64 | 
            +
                end
         | 
| 65 | 
            +
             | 
| 66 | 
            +
                it "returns array with back and export links" do
         | 
| 67 | 
            +
                  allow(subject).to receive(:import?).and_return(false)
         | 
| 68 | 
            +
                  expect(subject.footer_secondary_tools).to eq(["indx_btn", "xprt_btn"])
         | 
| 69 | 
            +
                end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                context "when within import view" do
         | 
| 72 | 
            +
                  it "does not incliude export button" do
         | 
| 73 | 
            +
                    allow(subject).to receive(:import?).and_return(true)
         | 
| 74 | 
            +
                    expect(subject.footer_secondary_tools).to eq(["indx_btn"])
         | 
| 75 | 
            +
                  end
         | 
| 76 | 
            +
                end
         | 
| 77 | 
            +
              end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
              describe "#back_to_index_button" do
         | 
| 80 | 
            +
                it "returns localized value for given resource and column(locale)" do
         | 
| 81 | 
            +
                  allow(subject).to receive(:t).with("Back to list").and_return("back")
         | 
| 82 | 
            +
                  allow(subject).to receive(:action_url).with(:index).and_return("index_url")
         | 
| 83 | 
            +
                  allow(subject).to receive(:button).with("back", "caret-left", class: "secondary", href: "index_url").and_return("index_btn")
         | 
| 84 | 
            +
                  expect(subject.back_to_index_button).to eq("index_btn")
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
              end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
              describe "#section_header" do
         | 
| 89 | 
            +
                it "returns nil" do
         | 
| 90 | 
            +
                  expect(subject.section_header).to be nil
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
              end
         | 
| 93 | 
            +
            end
         | 
| @@ -0,0 +1,96 @@ | |
| 1 | 
            +
            require "rails_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Releaf::I18nDatabase::Translations::IndexBuilder, type: :class do
         | 
| 4 | 
            +
              class IndexBuilderTestHelper < ActionView::Base
         | 
| 5 | 
            +
                include Releaf::ApplicationHelper
         | 
| 6 | 
            +
                delegate :resource_class, :table_options, to: :controller
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def protect_against_forgery?; end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def controller
         | 
| 11 | 
            +
                  @controller ||= begin
         | 
| 12 | 
            +
                                    c = Releaf::I18nDatabase::TranslationsController.new
         | 
| 13 | 
            +
                                    c.setup
         | 
| 14 | 
            +
                                    c
         | 
| 15 | 
            +
                                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
              let(:template){ IndexBuilderTestHelper.new }
         | 
| 19 | 
            +
              let(:resource_class){ Releaf::I18nDatabase::Translation }
         | 
| 20 | 
            +
              let(:subject){ described_class.new(template) }
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              describe "#text_search_content" do
         | 
| 23 | 
            +
                it "adds blank translation checbox to text search" do
         | 
| 24 | 
            +
                  allow(subject).to receive(:t).and_return("search")
         | 
| 25 | 
            +
                  allow(subject).to receive(:params).and_return(search: "xx")
         | 
| 26 | 
            +
                  allow(subject).to receive(:button).and_return("btn")
         | 
| 27 | 
            +
                  allow(subject).to receive(:search_only_blank_ui).and_return("_blank_ui_")
         | 
| 28 | 
            +
                  expect(subject.text_search_content).to start_with("_blank_ui_")
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
              describe "#search_only_blank_ui" do
         | 
| 33 | 
            +
                before do
         | 
| 34 | 
            +
                  allow(subject).to receive(:t).with("Only blank").and_return("trnls")
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                it "returns only blank translation search ui" do
         | 
| 38 | 
            +
                  allow(subject).to receive(:params).and_return(search: "xx")
         | 
| 39 | 
            +
                  expect(subject.search_only_blank_ui).to match_html(%Q[
         | 
| 40 | 
            +
                      <div class="search-field" data-name="only-blank">
         | 
| 41 | 
            +
                          <input type="checkbox" name="only_blank" id="only_blank" value="true" />
         | 
| 42 | 
            +
                          <label for="only_blank">trnls</label>
         | 
| 43 | 
            +
                      </div>
         | 
| 44 | 
            +
                  ])
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                it "reflects `only_blank` params to checkbox state" do
         | 
| 48 | 
            +
                  allow(subject).to receive(:params).and_return(only_blank: "1", search: true)
         | 
| 49 | 
            +
                  expect(subject.search_only_blank_ui).to match_html(%Q[
         | 
| 50 | 
            +
                      <div class="search-field" data-name="only-blank">
         | 
| 51 | 
            +
                          <input type="checkbox" name="only_blank" id="only_blank" value="true" checked="checked" />
         | 
| 52 | 
            +
                          <label for=\"only_blank\">trnls</label>
         | 
| 53 | 
            +
                      </div>
         | 
| 54 | 
            +
                  ])
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
              end
         | 
| 57 | 
            +
             | 
| 58 | 
            +
              describe "#footer_primary_tools" do
         | 
| 59 | 
            +
                it "returns array with edit button" do
         | 
| 60 | 
            +
                  allow(subject).to receive(:edit_button).and_return("btn")
         | 
| 61 | 
            +
                  expect(subject.footer_primary_tools).to eq(["btn"])
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
              end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
              describe "#footer_secondary_tools" do
         | 
| 66 | 
            +
                it "returns array with edit button" do
         | 
| 67 | 
            +
                  allow(subject).to receive(:export_button).and_return("a")
         | 
| 68 | 
            +
                  allow(subject).to receive(:import_button).and_return("b")
         | 
| 69 | 
            +
                  allow(subject).to receive(:import_form).and_return("c")
         | 
| 70 | 
            +
                  expect(subject.footer_secondary_tools).to eq(["a", "b", "c"])
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
              end
         | 
| 73 | 
            +
             | 
| 74 | 
            +
              describe "#import_form" do
         | 
| 75 | 
            +
                it "returns import form" do
         | 
| 76 | 
            +
                  allow(subject).to receive(:url_for).with(action: 'import').and_return("import_url")
         | 
| 77 | 
            +
                  result = "<form class=\"import\" enctype=\"multipart/form-data\" action=\"import_url\" accept-charset=\"UTF-8\" method=\"post\"><input name=\"utf8\" type=\"hidden\" value=\"✓\" /><input type=\"file\" name=\"import_file\" id=\"import_file\" /></form>"
         | 
| 78 | 
            +
                  expect(subject.import_form).to eq(result)
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
              describe "#edit_button" do
         | 
| 83 | 
            +
                it "return edit button" do
         | 
| 84 | 
            +
                  allow(subject).to receive(:t).with("Edit").and_return("edt")
         | 
| 85 | 
            +
                  allow(subject).to receive(:action_url).with(:edit).and_return("edt_url")
         | 
| 86 | 
            +
                  allow(subject).to receive(:button).with("edt", "edit", class: "primary", href: "edt_url").and_return("edt_btn")
         | 
| 87 | 
            +
                  expect(subject.edit_button).to eq("edt_btn")
         | 
| 88 | 
            +
                end
         | 
| 89 | 
            +
              end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
              describe "#text_search_available?" do
         | 
| 92 | 
            +
                it "return true" do
         | 
| 93 | 
            +
                  expect(subject.text_search_available?).to be true
         | 
| 94 | 
            +
                end
         | 
| 95 | 
            +
              end
         | 
| 96 | 
            +
            end
         | 
| @@ -0,0 +1,68 @@ | |
| 1 | 
            +
            require "rails_helper"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Releaf::I18nDatabase::Translations::TableBuilder, type: :class do
         | 
| 4 | 
            +
              class TableBuilderTestHelper < ActionView::Base; end
         | 
| 5 | 
            +
              let(:template){ TableBuilderTestHelper.new }
         | 
| 6 | 
            +
              let(:resource_class){ Releaf::I18nDatabase::Translation }
         | 
| 7 | 
            +
              let(:subject){ described_class.new([], resource_class, template, {}) }
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              before do
         | 
| 10 | 
            +
                allow(Releaf.application.config).to receive(:all_locales).and_return(["de", "ze"])
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              describe "#column_names" do
         | 
| 14 | 
            +
                it "returns key and Releaf.application.config column names array" do
         | 
| 15 | 
            +
                  expect(subject.column_names).to eq([:key, "de", "ze"])
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
              describe "#head_cell_content" do
         | 
| 20 | 
            +
                context "when locale column given" do
         | 
| 21 | 
            +
                  it "returns head cell content with translated locale" do
         | 
| 22 | 
            +
                    allow(subject).to receive(:translate_locale).with("de").and_return("gegxxxeg")
         | 
| 23 | 
            +
                    expect(subject.head_cell_content("de")).to eq('gegxxxeg')
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                context "when non locale column given" do
         | 
| 28 | 
            +
                  it "returns head cell content with translated locale" do
         | 
| 29 | 
            +
                    expect(subject).to_not receive(:translate_locale)
         | 
| 30 | 
            +
                    expect(subject.head_cell_content("lv")).to eq('Lv')
         | 
| 31 | 
            +
                  end
         | 
| 32 | 
            +
                end
         | 
| 33 | 
            +
              end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              describe "#cell_content" do
         | 
| 36 | 
            +
                it "wraps content within span element" do
         | 
| 37 | 
            +
                  resource = resource_class.new(key: "xx")
         | 
| 38 | 
            +
                  expect(subject.cell_content(resource, :key, format_method: :format_string_content)).to eq("<span>xx</span>")
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              describe "#locale_value" do
         | 
| 43 | 
            +
                it "returns localized value for given resource and column(locale)" do
         | 
| 44 | 
            +
                  resource = resource_class.new
         | 
| 45 | 
            +
                  allow(resource).to receive(:locale_value).with(:en).and_return("en value")
         | 
| 46 | 
            +
                  expect(subject.locale_value(resource, :en)).to eq("en value")
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              describe "#cell_format_method" do
         | 
| 51 | 
            +
                before do
         | 
| 52 | 
            +
                  allow(Releaf.application.config).to receive(:all_locales).and_return([:de, :ze])
         | 
| 53 | 
            +
                end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                context "when given column name exists within Releaf.application.config.all_locales" do
         | 
| 56 | 
            +
                  it "returns :locale_value" do
         | 
| 57 | 
            +
                    expect(subject.cell_format_method(:de)).to eq(:locale_value)
         | 
| 58 | 
            +
                    expect(subject.cell_format_method(:ze)).to eq(:locale_value)
         | 
| 59 | 
            +
                  end
         | 
| 60 | 
            +
                end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                context "when given column name does not  exists within Releaf.application.config.all_locales" do
         | 
| 63 | 
            +
                  it "return super" do
         | 
| 64 | 
            +
                    expect(subject.cell_format_method(:en)).to eq(:format_string_content)
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
                end
         | 
| 67 | 
            +
              end
         | 
| 68 | 
            +
            end
         | 
| @@ -0,0 +1,157 @@ | |
| 1 | 
            +
            require 'rails_helper'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Releaf::I18nDatabase::TranslationsController do
         | 
| 4 | 
            +
              def file_attachment
         | 
| 5 | 
            +
                test_document = File.expand_path('../../fixtures/translations_import.xlsx', __dir__)
         | 
| 6 | 
            +
                Rack::Test::UploadedFile.new(test_document)
         | 
| 7 | 
            +
              end
         | 
| 8 | 
            +
             | 
| 9 | 
            +
              login_as_user :user
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              before do
         | 
| 12 | 
            +
                @time_now = Time.parse("1981-02-23 21:00:00 UTC")
         | 
| 13 | 
            +
                allow(Time).to receive(:now).and_return(@time_now)
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              before build_translations: true do
         | 
| 17 | 
            +
                @t1 = FactoryGirl.create(:translation, key: 'test.key1')
         | 
| 18 | 
            +
                @t2 = FactoryGirl.create(:translation, key: 'great.stuff')
         | 
| 19 | 
            +
                @t3 = FactoryGirl.create(:translation, key: 'geek.stuff')
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                @t1_en = FactoryGirl.create(:translation_data, lang: 'en', localization: 'testa atslēga', translation_id: @t1.id)
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                @t2_en = FactoryGirl.create(:translation_data, lang: 'en', localization: 'awesome stuff', translation_id: @t2.id)
         | 
| 24 | 
            +
                @t2_lv = FactoryGirl.create(:translation_data, lang: 'lv', localization: 'lieliska manta', translation_id: @t2.id)
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                @t3_en = FactoryGirl.create(:translation_data, lang: 'en', localization: 'geek stuff', translation_id: @t3.id)
         | 
| 27 | 
            +
                @t3_lv = FactoryGirl.create(:translation_data, lang: 'lv', localization: 'nūģu lieta', translation_id: @t3.id)
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
             | 
| 31 | 
            +
              describe "GET #index", build_translations: true do
         | 
| 32 | 
            +
                context "when not searching" do
         | 
| 33 | 
            +
                  it "renders all translations" do
         | 
| 34 | 
            +
                    get :index
         | 
| 35 | 
            +
                    expect( assigns(:collection).size ).to eq(3)
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                context "when searching" do
         | 
| 40 | 
            +
                  it "searches by translation key" do
         | 
| 41 | 
            +
                    get :index, search: 'great'
         | 
| 42 | 
            +
                    expect( assigns(:collection).size ).to eq(1)
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  it "searched by localized values" do
         | 
| 46 | 
            +
                    get :index, search: 'manta'
         | 
| 47 | 
            +
                    expect( assigns(:collection).size ).to eq(1)
         | 
| 48 | 
            +
                  end
         | 
| 49 | 
            +
                end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                context "when searching blank translations" do
         | 
| 52 | 
            +
                  it "returns translations that has blank translation in any localization" do
         | 
| 53 | 
            +
                    get :index, only_blank: 'true'
         | 
| 54 | 
            +
                    expect( assigns(:collection).map(&:id) ).to match_array [@t1.id]
         | 
| 55 | 
            +
                  end
         | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
             | 
| 59 | 
            +
              describe "GET #edit", build_translations: true do
         | 
| 60 | 
            +
                context "when search scope is not given" do
         | 
| 61 | 
            +
                  it "renders all translations" do
         | 
| 62 | 
            +
                    get :edit
         | 
| 63 | 
            +
                    expect( assigns(:collection).size ).to eq(3)
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                context "when search scope is given" do
         | 
| 68 | 
            +
                  it "renders translations matching search pattern" do
         | 
| 69 | 
            +
                    get :index, search: 'stuff'
         | 
| 70 | 
            +
                    expect( assigns(:collection).size ).to eq(2)
         | 
| 71 | 
            +
                  end
         | 
| 72 | 
            +
                end
         | 
| 73 | 
            +
              end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
              describe "#update" do
         | 
| 76 | 
            +
                context "when save successful" do
         | 
| 77 | 
            +
                  it "updates translations updated_at" do
         | 
| 78 | 
            +
                    expect(Releaf::I18nDatabase::Backend).to receive("translations_updated_at=").with(@time_now)
         | 
| 79 | 
            +
                    put :update, translations: [{key: 'a.b.c', localizations: {en: 'test', lv: 'xxl'}}]
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                  context "when save with import" do
         | 
| 83 | 
            +
                    before do
         | 
| 84 | 
            +
                      put :update, translations: [{key: 'a.b.c', localizations: {en: 'test', lv: 'xxl'}}], import: "true"
         | 
| 85 | 
            +
                    end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                    it "redirects to index view" do
         | 
| 88 | 
            +
                      expect(subject).to redirect_to(action: :index)
         | 
| 89 | 
            +
                    end
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                    it "flash success notification with updated count" do
         | 
| 92 | 
            +
                      expect(flash["success"]).to eq("id" => "resource_status", "message" => "successfuly imported 1 translations")
         | 
| 93 | 
            +
                    end
         | 
| 94 | 
            +
                  end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
                  context "when save without import" do
         | 
| 97 | 
            +
                    before do
         | 
| 98 | 
            +
                      put :update, translations: [{key: 'a.b.c', localizations: {en: 'test', lv: 'xxl'}}]
         | 
| 99 | 
            +
                    end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                    it "redirects to edit view" do
         | 
| 102 | 
            +
                      expect(subject).to redirect_to(action: :edit)
         | 
| 103 | 
            +
                    end
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                    it "flash success notification" do
         | 
| 106 | 
            +
                      expect(flash["success"]).to eq("id" => "resource_status", "message" => "Update succeeded")
         | 
| 107 | 
            +
                    end
         | 
| 108 | 
            +
                  end
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                context "when save failed" do
         | 
| 112 | 
            +
                  it "renders edit view" do
         | 
| 113 | 
            +
                    put :update, translations: [{key: '', localizations: {en: 'test', lv: 'xxl'}}]
         | 
| 114 | 
            +
                    expect(response).to render_template(:edit)
         | 
| 115 | 
            +
                  end
         | 
| 116 | 
            +
             | 
| 117 | 
            +
                  it "flash error notification" do
         | 
| 118 | 
            +
                    put :update, translations: [{key: '', localizations: {en: 'test', lv: 'xxl'}}]
         | 
| 119 | 
            +
                    expect(flash["error"]).to eq("id" => "resource_status", "message" => "Update failed")
         | 
| 120 | 
            +
                  end
         | 
| 121 | 
            +
                end
         | 
| 122 | 
            +
              end
         | 
| 123 | 
            +
             | 
| 124 | 
            +
              describe "#import" do
         | 
| 125 | 
            +
                context "when file uploaded" do
         | 
| 126 | 
            +
                  before do
         | 
| 127 | 
            +
                    file = fixture_file_upload(File.expand_path('../../fixtures/translations_import.xlsx', __dir__), 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
         | 
| 128 | 
            +
                    class << file
         | 
| 129 | 
            +
                      # The reader method is present in a real invocation,
         | 
| 130 | 
            +
                      # but missing from the fixture object for some reason (Rails 3.1.1)
         | 
| 131 | 
            +
                      attr_reader :tempfile
         | 
| 132 | 
            +
                    end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                    post :import, import_file: file
         | 
| 135 | 
            +
                  end
         | 
| 136 | 
            +
             | 
| 137 | 
            +
                  it "parses uploaded file and assigns content to collection" do
         | 
| 138 | 
            +
                    expect( assigns(:collection).size ).to eq(4)
         | 
| 139 | 
            +
                  end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                  it "assigns @import to true" do
         | 
| 142 | 
            +
                    expect( assigns(:import) ).to be true
         | 
| 143 | 
            +
                  end
         | 
| 144 | 
            +
             | 
| 145 | 
            +
                  it "appends breadcrumb with 'import' part" do
         | 
| 146 | 
            +
                    expect( assigns(:breadcrumbs).last ).to eq({name: "Import"})
         | 
| 147 | 
            +
                  end
         | 
| 148 | 
            +
                end
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                context "when no file uploaded" do
         | 
| 151 | 
            +
                  it "redirects to index" do
         | 
| 152 | 
            +
                    post :import
         | 
| 153 | 
            +
                    expect(subject).to redirect_to(action: :index)
         | 
| 154 | 
            +
                  end
         | 
| 155 | 
            +
                end
         | 
| 156 | 
            +
              end
         | 
| 157 | 
            +
            end
         |