Remove usage of CF translations

This commit is contained in:
Oliver Günther
2017-03-30 14:30:14 +02:00
parent b93b088940
commit 93dcd386f4
28 changed files with 74 additions and 1116 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ gem 'coderay', '~> 1.1.0'
gem 'rubytree', '~> 0.9.7'
gem 'rdoc', '>= 2.4.2'
gem 'globalize', git: 'https://github.com/globalize/globalize', ref: '38443bcd'
gem 'globalize', git: 'https://github.com/globalize/globalize', ref: '38443bcd', require: false
gem 'omniauth', git: 'https://github.com/oliverguenther/omniauth', ref: '8385bc0'
gem 'request_store', '~> 1.3.1'
gem 'gravatar_image_tag', '~> 1.2.0'
@@ -35,13 +35,13 @@ module Api
accept_key_auth :index, :show
def index
wp_fields = WorkPackageCustomField.visible_by_user(User.current)
.includes(:translations, :projects, :types)
wp_fields = WorkPackageCustomField
.visible_by_user(User.current)
.includes(:projects, :types)
.order(:id)
.uniq
other_fields = CustomField.includes(:translations)
.where("type != 'WorkPackageCustomField'")
.order(:type, :id)
other_fields = CustomField.where("type != 'WorkPackageCustomField'")
.order(:type, :id)
@custom_fields = wp_fields + other_fields
@@ -51,7 +51,7 @@ module Api
end
def show
@custom_field = CustomField.includes(:translations).find params[:id]
@custom_field = CustomField.find params[:id]
respond_to do |format|
format.api
@@ -84,8 +84,8 @@ module Api
def show
@planning_element = @project.work_packages
.includes([{ custom_values: [{ custom_field: :translations }] }])
.find(params[:id])
.includes(custom_values: :custom_field)
.find(params[:id])
respond_to do |format|
format.api
@@ -73,7 +73,7 @@ module Api
end
def planning_element_custom_fields
@custom_fields = @project.all_work_package_custom_fields include: [:projects, :types, :translations]
@custom_fields = @project.all_work_package_custom_fields include: [:projects, :types]
respond_to do |format|
format.api
@@ -84,7 +84,7 @@ module Api
def find_project
@project = Project
.includes([{ custom_values: [{ custom_field: :translations }] }])
.includes(custom_values: :custom_field)
.find params[:id]
end
+10 -18
View File
@@ -32,10 +32,10 @@ class CustomFieldsController < ApplicationController
before_action :require_admin
before_action :find_custom_field, only: [:edit, :update, :destroy, :move, :delete_option]
before_action :blank_translation_attributes_as_nil, only: [:create, :update]
before_action :get_custom_field_params, only: [:create, :update]
def index
@custom_fields_by_type = CustomField.includes(:translations).group_by { |f| f.class.name }
@custom_fields_by_type = CustomField.all.group_by { |f| f.class.name }
@tab = params[:tab] || 'WorkPackageCustomField'
end
@@ -104,6 +104,14 @@ class CustomFieldsController < ApplicationController
private
def get_custom_field_params
@custom_field_params = permitted_params.custom_field
if !EnterpriseToken.allows_to?(:multiselect_custom_fields)
@custom_field_params.delete :multi_value
end
end
def delete_custom_values!(custom_option)
CustomValue
.where(custom_field_id: custom_option.custom_field_id, value: custom_option.id)
@@ -144,22 +152,6 @@ class CustomFieldsController < ApplicationController
end
end
def blank_translation_attributes_as_nil
@custom_field_params = permitted_params.custom_field
if !EnterpriseToken.allows_to?(:multiselect_custom_fields)
@custom_field_params.delete :multi_value
end
return unless @custom_field_params['translations_attributes']
@custom_field_params['translations_attributes'].each do |_index, attributes|
attributes.each do |key, value|
attributes[key] = nil if value.blank?
end
end
end
def careful_new_custom_field(type, params = {})
cf = begin
if type.to_s.match(/.+CustomField\z/)
+1 -1
View File
@@ -44,7 +44,7 @@ class CustomField < ActiveRecord::Base
def uniqueness_of_name_with_scope
taken_names = CustomField.where(type: type)
taken_names = taken_names.where('id != ?', id) if id
taken_names = taken_names.map { |cf| cf.read_attribute(:name, locale: I18n.locale) }
taken_names = taken_names.pluck(:name)
errors.add(:name, :taken) if name.in?(taken_names)
end
-6
View File
@@ -471,12 +471,6 @@ class PermittedParams
:default_value,
:possible_values,
:multi_value,
translations_attributes: [
:_destroy,
:id,
:locale,
:name
],
type_ids: []],
enumeration: [
:active,
@@ -99,11 +99,9 @@ class Queries::WorkPackages::Filter::CustomFieldFilter <
def self.custom_fields(context)
if context
context
.all_work_package_custom_fields(include: :translations)
context.all_work_package_custom_fields
else
WorkPackageCustomField
.includes(:translations)
.filter
.for_all
.where.not(field_format: ['user', 'version'])
+2 -2
View File
@@ -626,9 +626,9 @@ class Query < ActiveRecord::Base
def custom_field_columns
if project
project.all_work_package_custom_fields(include: :translations)
project.all_work_package_custom_fields
else
WorkPackageCustomField.includes(:translations).all
WorkPackageCustomField.includes.all
end.map { |cf| ::QueryCustomFieldColumn.new(cf) }
end
end
+1 -1
View File
@@ -75,7 +75,7 @@ module Type::Attributes
attributes.delete 'start_date'
end
WorkPackageCustomField.includes(:translations, :custom_options).all.each do |field|
WorkPackageCustomField.includes(:custom_options).all.each do |field|
attributes["custom_field_#{field.id}"] = {
required: field.is_required,
has_default: field.default_value.present?,
@@ -219,6 +219,6 @@ class AddCustomOptions < ActiveRecord::Migration[5.0]
end
def list_custom_fields
@list_custom_fields ||= CustomField.includes(:translations).where(field_format: "list")
@list_custom_fields ||= CustomField.where(field_format: "list")
end
end
@@ -1,57 +0,0 @@
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2017 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
Feature: Text custom fields can be created
Background:
Given I am already admin
And the following languages are active:
| en |
| de |
When I go to the custom fields page
When I follow "Create a new custom field" within "#tab-content-WorkPackageCustomField"
@wip
@javascript
Scenario: Creating a text custom field with multiple name and default_value localizations
When I select "Text" from "custom_field_field_format"
And I set the english localization of the "name" attribute to "New Field"
And I add the german localization of the "name" attribute as "Neues Feld"
And I set the english localization of the "default_value" attribute to "default"
And I add the german localization of the "default_value" attribute as "Standard"
And I press "Save"
And I follow "New Field"
Then there should be the following localizations:
| locale | name | default_value |
| en | New Field | default |
| de | Neues Feld | Standard |
Scenario: Creating a custom field with one name
And I set the english localization of the "name" attribute to "Issue Field"
And I press "Save"
Then I should be on the custom fields page
-72
View File
@@ -1,72 +0,0 @@
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2017 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
Feature: Editing a bool custom field
Background:
Given I am already admin
And the following languages are active:
| en |
| de |
And the following issue custom fields are defined:
| name | type |
| IssueCustomField | bool |
When I go to the custom fields page
@wip
@javascript
Scenario: Adding a localized name
When I follow "IssueCustomField"
And I set the english localization of the "name" attribute to "Issue Field"
And I add the german localization of the "name" attribute as "Ticket Feld"
And I press "Save"
Then I should be on the custom fields page
When I follow "Issue Field"
Then there should be the following localizations:
| locale | name | default_value |
| en | Issue Field | 0 |
| de | Ticket Feld | nil |
And I should not see "Add" within "#custom_field_name_attributes"
Scenario: Entering a long name displays an error
When I follow "IssueCustomField"
And I fill in "custom_field_translations_attributes_0_name" with "Long name which forces an error"
And I press "Save"
Then the "custom_field_translations_attributes_0_name" field should contain "Long name which forces an error"
And I should see "Name is too long" within "#errorExplanation"
Scenario: Entering an already taken name displays an error
Given the following issue custom fields are defined:
| name | type |
| Taken name | bool |
When I follow "IssueCustomField"
And I set the english localization of the "name" attribute to "Taken name"
And I press "Save"
Then I should see "Name has already been taken" within "#errorExplanation"
And the "custom_field_translations_attributes_0_name" field should contain "Taken name"
@@ -1,101 +0,0 @@
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2017 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
Feature: Name localizations of bool custom fields can be deleted
Background:
Given I am already admin
And the following languages are active:
| en |
| de |
And the following issue custom fields are defined:
| name | type |
| My Custom Field | bool |
And the Custom Field called "My Custom Field" has the following localizations:
| locale | name |
| en | My Custom Field |
| de | Mein Benutzerdefiniertes Feld |
When I go to the custom fields page
@wip
@javascript
Scenario: Deleting a localized name
When I follow "My Custom Field"
And I delete the german localization of the "name" attribute
And I press "Save"
And I follow "My Custom Field"
Then there should be the following localizations:
| locale | name | default_value |
| en | My Custom Field | 0 |
@wip
@javascript
Scenario: Deleting a name localization and adding another of same locale in same action
When I follow "My Custom Field"
And I delete the german localization of the "name" attribute
And I add the german localization of the "name" attribute as "Neuer Name"
And I press "Save"
And I follow "My Custom Field"
Then there should be the following localizations:
| locale | name | default_value |
| en | My Custom Field | 0 |
| de | Neuer Name | nil |
@wip
@javascript
Scenario: Deleting a name localization frees the locale to be used by other translation field
When I follow "My Custom Field"
And I delete the english localization of the "name" attribute
And I change the german localization of the "name" attribute to be english
And I press "Save"
And I follow "Mein Benutzerdefiniertes Feld"
Then there should be the following localizations:
| locale | name | default_value |
| en | Mein Benutzerdefiniertes Feld | 0 |
@wip
@javascript
Scenario: Deleting a newly added localization
When I follow "My Custom Field"
And I delete the german localization of the "name" attribute
And I press "Save"
And I follow "My Custom Field"
And I add the german localization of the "name" attribute as "To delete"
And I delete the german localization of the "name" attribute
And I press "Save"
And I follow "My Custom Field"
Then there should be the following localizations:
| locale | name | default_value |
| en | My Custom Field | 0 |
@wip
@javascript
Scenario: Deletion link is hidden when only one localization exists
When I follow "My Custom Field"
And I delete the german localization of the "name" attribute
Then the delete link for the english localization of the "name" attribute should not be visible
-38
View File
@@ -1,38 +0,0 @@
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2017 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
Feature: Editing text custom fields
Background:
Given I am already admin
And the following languages are active:
| en |
| de |
And the following issue custom fields are defined:
| name | type |
| My Custom Field | text |
+1 -2
View File
@@ -418,8 +418,7 @@ def add_custom_value_to_issue(object, key, value)
cv ||= CustomValue.new
cv.customized_type = 'WorkPackage'
cv.customized_id = object.id
cv.custom_field_id = WorkPackageCustomField.joins(:translations)
.where(['custom_field_translations.name = ?', key]).id
cv.custom_field_id = WorkPackageCustomField.find_by(name: key).id
cv.value = value
cv.save!
end
-44
View File
@@ -105,50 +105,6 @@ def update_localization(container, language, value)
new_locale.select(locale_name.text) if locale_name
end
Then /^there should be the following localizations:$/ do |table|
cleaned_expectation = table.hashes.map { |x|
x.reject { |_k, v| v == 'nil' }
}
attributes = []
page.should have_selector(:xpath, '(//*[contains(@name, "translations_attributes") and not(contains(@disabled,"disabled"))])[1]')
attributes = page.all(:css, "[name*=\"translations_attributes\"]:not([disabled=disabled])", visible: false)
name_regexp = /\[(\d)+\]\[(\w+)\]$/
attribute_group = attributes.inject({}) { |h, element|
if element['name'] =~ name_regexp
h[$1] ||= []
h[$1] << element
end
h
}
actual_localizations = attribute_group.inject([]) { |a, (_k, group)|
a << group.inject({}) { |h, element|
if element['name'] =~ name_regexp
if $2 != 'id' and
$2 != '_destroy' and
(element['type'] != 'checkbox' or (element['type'] == 'checkbox' and element.checked?))
h[$2] = element['value']
end
end
h
}
a
}
actual_localizations = actual_localizations.group_by { |e| e['locale'] }.map { |(_k, v)| v.inject({}) { |a, x| a.merge(x) } }
actual_localizations.should =~ cleaned_expectation
end
Then /^the delete link for the (.+) localization of the "(.+)" attribute should not be visible$/ do |locale, attribute_name|
attribute_span = span_for_localization locale, attribute_name
+2 -5
View File
@@ -208,11 +208,8 @@ module API
results
}
self.to_eager_load = [
:query_menu_item,
project: [:enabled_modules,
{ work_package_custom_fields: :translations }]
]
self.to_eager_load = [:query_menu_item,
project: :work_package_custom_fields]
private
@@ -44,7 +44,7 @@ module API
end
def available_custom_fields
project.all_work_package_custom_fields(include: :translations).to_a & type.custom_fields.includes(:translations).to_a
project.all_work_package_custom_fields.to_a & type.custom_fields.to_a
end
end
end
@@ -33,7 +33,7 @@ module API
module Schema
class WorkPackageSumsSchema < BaseWorkPackageSchema
def available_custom_fields
WorkPackageCustomField.summable.includes(:translations)
WorkPackageCustomField.summable
end
end
end
+4 -9
View File
@@ -52,8 +52,7 @@ class CustomFieldFormBuilder < TabularFormBuilder
input_options = options.merge(no_label: true,
name: custom_field_field_name,
id: custom_field_field_id,
lang: object.custom_field.name_locale)
id: custom_field_field_id)
field_format = Redmine::CustomFieldFormat.find_by_name(object.custom_field.field_format)
@@ -122,13 +121,9 @@ class CustomFieldFormBuilder < TabularFormBuilder
content_tag 'label',
for: custom_field_field_id,
class: classes,
title: custom_value.custom_field.name,
lang: custom_value.custom_field.name_locale do
content_tag('span', custom_value.custom_field.name) +
(content_tag('span',
'*',
class: 'form--label-required',
:'aria-hidden' => true) if is_required)
title: custom_value.custom_field.name do
content_tag('span', custom_value.custom_field.name) +
(content_tag('span', '*', class: 'form--label-required', :'aria-hidden' => true) if is_required)
end
end
end
+34 -112
View File
@@ -30,7 +30,6 @@ require 'spec_helper'
describe CustomFieldsController, type: :controller do
let(:custom_field) { FactoryGirl.build(:custom_field) }
let(:available_languages) { ['de', 'en'] }
before do
allow(@controller).to receive(:authorize)
@@ -40,144 +39,67 @@ describe CustomFieldsController, type: :controller do
describe 'POST edit' do
before do
allow(Setting).to receive(:available_languages).and_return(available_languages)
allow(CustomField).to receive(:find).and_return(custom_field)
end
describe 'WITH all ok params' do
let(:de_name) { 'Ticket Feld' }
let(:en_name) { 'Issue Field' }
let(:params) {
{ 'custom_field' => { 'translations_attributes' => { '0' => { 'name' => de_name, 'locale' => 'de' },
'1' => { 'name' => en_name, 'locale' => 'en' } } } }
}
let(:params) do
{
'custom_field' => { 'name' => 'Issue Field' }
}
end
before do
put :update, params: params
end
it { expect(response).to be_redirect }
it { expect(custom_field.name(:de)).to eq(de_name) }
it { expect(custom_field.name(:en)).to eq(en_name) }
end
describe 'WITH one empty name params' do
let(:en_name) { 'Issue Field' }
let(:de_name) { '' }
let(:params) {
{ 'custom_field' => { 'translations_attributes' => { '0' => { 'name' => de_name, 'locale' => 'de' },
'1' => { 'name' => en_name, 'locale' => 'en' } } } }
}
before do
put :update, params: params
it 'works' do
expect(response).to be_redirect
expect(custom_field.name).to eq('Issue Field')
end
it { expect(response).to be_redirect }
it { expect(custom_field.name(:de)).to eq(en_name) }
it { expect(custom_field.name(:en)).to eq(en_name) }
end
end
describe 'POST new' do
before do
allow(Setting).to receive(:available_languages).and_return(available_languages)
end
describe 'WITH empty name param' do
let(:en_name) { '' }
let(:de_name) { '' }
let(:params) {
{ 'type' => 'WorkPackageCustomField',
'custom_field' => { 'translations_attributes' => { '0' => { 'name' => de_name, 'locale' => 'de' },
'1' => { 'name' => en_name, 'locale' => 'en' } },
'field_format' => 'string' } }
}
let(:params) do
{
'type' => 'WorkPackageCustomField',
'custom_field' => {
'name' => '',
'field_format' => 'string'
}
}
end
before do
post :create, params: params
end
it { expect(response).to render_template 'new' }
it { expect(assigns(:custom_field).errors.messages[:name].first).to eq "can't be blank." }
it { expect(assigns(:custom_field).translations(true)).to be_empty }
it 'responds with error' do
expect(response).to render_template 'new'
expect(assigns(:custom_field).errors.messages[:name].first).to eq("can't be blank.")
end
end
describe 'WITH all ok params' do
let(:de_name) { 'Ticket Feld' }
let(:en_name) { 'Issue Field' }
let(:params) {
{ 'type' => 'WorkPackageCustomField',
'custom_field' => { 'translations_attributes' => { '0' => { 'name' => de_name, 'locale' => 'de' },
'1' => { 'name' => en_name, 'locale' => 'en' } },
'field_format' => 'string' } }
}
let(:params) do
{
'type' => 'WorkPackageCustomField',
'custom_field' => {
'name' => 'field',
'field_format' => 'string'
}
}
end
before do
post :create, params: params
end
it { expect(response.status).to eql(302) }
it { expect(assigns(:custom_field).translations.find { |elem| elem.locale == :de }[:name]).to eq(de_name) }
it { expect(assigns(:custom_field).translations.find { |elem| elem.locale == :en }[:name]).to eq(en_name) }
end
describe 'WITH one empty name params' do
let(:en_name) { 'Issue Field' }
let(:de_name) { '' }
let(:params) {
{ 'type' => 'WorkPackageCustomField',
'custom_field' => { 'translations_attributes' => { '0' => { 'name' => de_name, 'locale' => 'de' },
'1' => { 'name' => en_name, 'locale' => 'en' } },
'field_format' => 'string' } }
}
before do
post :create, params: params
end
it { expect(response.status).to eql(302) }
it { expect(assigns(:custom_field).translations.find { |elem| elem.locale == :de }).to be_nil }
it { expect(assigns(:custom_field).translations.find { |elem| elem.locale == :en }[:name]).to eq(en_name) }
end
describe 'WITH different language and default_value params' do
let(:en_name) { 'Issue Field' }
let(:de_name) { '' }
let(:default_value) { 'Default Value' }
let(:params) {
{ 'type' => 'WorkPackageCustomField',
'custom_field' => { 'translations_attributes' =>
{ '0' => { 'name' => de_name, 'locale' => 'de' },
'1' => { 'name' => en_name, 'locale' => 'en' } },
'default_value' => default_value,
'field_format' => 'string' } }
}
before do
post :create, params: params
end
around do |example|
old_fallbacks = Globalize.fallbacks
Globalize.fallbacks = { de: [:de, :en], en: [] }
example.run
Globalize.fallbacks = old_fallbacks
end
it { expect(response.status).to eql(302) }
it 'sets correct values for EN' do
I18n.with_locale(:en) do
expect(assigns(:custom_field).name).to eq(en_name)
expect(assigns(:custom_field).default_value).to eq default_value
end
end
it 'sets correct values for DE' do
I18n.with_locale(:de) do
expect(assigns(:custom_field).name).to eq(en_name)
expect(assigns(:custom_field).default_value).to eq default_value
end
it 'responds ok' do
expect(response.status).to eq(302)
expect(assigns(:custom_field).name).to eq('field')
end
end
end
@@ -1,402 +0,0 @@
#-- copyright
# OpenProject is a project management system.
# Copyright (C) 2012-2017 the OpenProject Foundation (OPF)
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License version 3.
#
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows:
# Copyright (C) 2006-2017 Jean-Philippe Lang
# Copyright (C) 2010-2013 the ChiliProject Team
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# See doc/COPYRIGHT.rdoc for more details.
#++
require 'spec_helper'
require 'features/custom_fields/custom_fields_page'
require 'features/projects/project_settings_page'
require 'features/work_packages/work_packages_page'
RSpec.describe 'Custom field accessibility', type: :feature, selenium: true do
describe 'language tag' do
let(:custom_field) {
FactoryGirl.create(:work_package_custom_field,
name_locales: { en: 'Field1', de: 'Feld1' },
field_format: 'text',
is_required: true)
}
let(:type) {
FactoryGirl.create(:type_standard,
custom_fields: [custom_field])
}
let(:project) {
FactoryGirl.create :project,
types: [type],
work_package_custom_fields: [custom_field]
}
let(:role) {
FactoryGirl.create :role,
permissions: [:view_work_packages, :edit_project]
}
let(:current_user) {
FactoryGirl.create :admin, member_in_project: project,
member_through_role: role
}
shared_examples_for 'Element has lang tag' do
let(:lang_tag_locale) { defined?(element_locale) ? element_locale : locale }
it { expect(element['lang']).to eq(lang_tag_locale) }
end
before do
allow(User).to receive(:current).and_return current_user
end
describe 'Custom Field Admin Page', js: true do
let(:custom_fields_page) { CustomFieldsPage.new }
let(:element) { custom_fields_page.name_attributes }
shared_context 'custom field new page' do
let(:available_languages) { [locale] }
before do
allow(I18n).to receive(:locale).and_return locale
allow(Setting).to receive(:available_languages).and_return(available_languages)
custom_fields_page.visit_new
end
end
context 'en' do
let(:locale) { 'en' }
include_context 'custom field new page'
it_behaves_like 'Element has lang tag'
end
context 'de' do
let(:locale) { 'de' }
include_context 'custom field new page'
it_behaves_like 'Element has lang tag'
end
describe 'Locale change' do
shared_context 'custom field new page with changed name locale' do
include_context 'custom field new page' do
let(:available_languages) { ['en', 'de'] }
end
before { find(element_selector).click }
end
describe 'Name locale change' do
let(:element_selector) { "#custom_field_name_attributes select.locale_selector option[value='#{element_locale}']" }
context 'en' do
let(:locale) { 'en' }
let(:element_locale) { 'de' }
include_context 'custom field new page with changed name locale'
it_behaves_like 'Element has lang tag'
end
context 'de' do
let(:locale) { 'de' }
let(:element_locale) { 'en' }
include_context 'custom field new page with changed name locale'
it_behaves_like 'Element has lang tag'
end
end
end
end
describe 'Project Settings' do
let(:project_settings_page) { ProjectSettingsPage.new(project) }
let(:element) { project_settings_page.fieldset_label }
shared_context 'project settings page' do
before do
allow(I18n).to receive(:locale).and_return locale
project_settings_page.visit_settings_tab('custom_fields')
end
end
context 'en' do
let(:locale) { 'en' }
include_context 'project settings page'
it_behaves_like 'Element has lang tag'
end
context 'de' do
let(:locale) { 'de' }
include_context 'project settings page'
it_behaves_like 'Element has lang tag'
end
end
describe 'Work Package', js: true do
let(:work_packages_page) { WorkPackagesPage.new(project) }
let!(:work_package) {
FactoryGirl.create(:work_package,
project: project,
type: type,
custom_values: { custom_field.id => 'value' })
}
describe 'index' do
shared_context 'index page with query' do
let!(:query) do
query = FactoryGirl.build(:query, project: project)
query.column_names = ["cf_#{custom_field.id}"]
query.save!
query
end
before do
allow(I18n).to receive(:locale).and_return locale
work_packages_page.visit_index
work_packages_page.select_query query
end
end
shared_examples_for 'localized table header' do
it_behaves_like 'Element has lang tag' do
let(:element) { find('th a', text: custom_field.name) }
end
it_behaves_like 'Element has lang tag' do
let(:element) { find("td[class='cf_#{custom_field.id}']") }
end
end
context 'en' do
let(:locale) { 'en' }
include_context 'index page with query'
skip # it_behaves_like "localized table header"
end
context 'de' do
let(:locale) { 'de' }
include_context 'index page with query'
skip # it_behaves_like "localized table header"
end
end
let(:value) { 'Wert' }
describe 'show' do
shared_context 'work package show view' do
before do
work_packages_page.visit_show work_package.id
end
end
shared_examples_for 'attribute header lang' do
let(:element) { find("dt.attributes-key-value--key.-custom_field.-cf_#{custom_field.id}") }
it_behaves_like 'Element has lang tag'
end
shared_examples_for 'attribute value lang' do
let(:element) { find("dt.attributes-key-value--key.-custom_field.-cf_#{custom_field.id} + dd") }
it_behaves_like 'Element has lang tag'
end
context 'de' do
let(:locale) { 'de' }
let(:element_locale) { 'en' }
include_context 'work package show view'
skip # it_behaves_like 'attribute header lang'
skip # it_behaves_like 'attribute value lang'
end
context 'en' do
let(:locale) { 'en' }
let(:element_locale) { 'en' }
include_context 'work package show view'
skip # it_behaves_like 'attribute header lang'
skip # it_behaves_like 'attribute value lang'
end
describe 'mixed language for custom field name and default value' do
let(:cf_with_mixed_lang) {
FactoryGirl.create(:work_package_custom_field,
name_locales: { en: 'Field2', de: nil },
default_locales: { en: nil, de: value },
field_format: 'text',
is_required: false)
}
let(:custom_field) { cf_with_mixed_lang }
before do
Globalize.fallbacks = { en: [:en, :de] }
work_package.custom_field_values.first.value = value
work_package.save!
end
after do Globalize.fallbacks = [:en] end
shared_context 'work package show view' do
before do
allow(I18n).to receive(:locale).and_return locale
work_packages_page.visit_show work_package.id
end
end
context 'attribute header' do
context 'de' do
let(:locale) { 'de' }
let(:element_locale) { 'en' }
include_context 'work package show view'
skip # it_behaves_like 'attribute header lang'
end
context 'en' do
let(:locale) { 'en' }
let(:element_locale) { 'en' }
include_context 'work package show view'
skip # it_behaves_like 'attribute header lang'
end
end
context 'attribute value' do
context 'de' do
let(:locale) { 'de' }
let(:element_locale) { 'de' }
include_context 'work package show view'
skip # it_behaves_like 'attribute value lang'
end
context 'en' do
let(:locale) { 'en' }
let(:element_locale) { 'de' }
include_context 'work package show view'
skip # it_behaves_like 'attribute value lang'
end
end
end
end
describe 'edit' do
shared_context 'work package edit view' do
before { work_packages_page.visit_edit work_package.id }
end
shared_examples_for 'attribute header lang' do
let(:element) { find("#attributes label[for='work_package_custom_field_values_#{custom_field.id}']") }
it_behaves_like 'Element has lang tag'
end
shared_examples_for 'attribute value lang' do
let(:element) { find("#work_package_custom_field_values_#{custom_field.id}") }
it_behaves_like 'Element has lang tag'
end
context 'de' do
let(:locale) { 'de' }
let(:element_locale) { 'en' }
include_context 'work package edit view'
skip # it_behaves_like 'attribute header lang'
skip # it_behaves_like 'attribute value lang'
end
context 'en' do
let(:locale) { 'en' }
let(:element_locale) { 'en' }
include_context 'work package edit view'
skip # it_behaves_like 'attribute header lang'
skip # it_behaves_like 'attribute value lang'
end
describe 'default value language is different' do
let(:cf_with_mixed_lang) {
FactoryGirl.create(:work_package_custom_field,
name_locales: { en: 'Field2', de: nil },
default_locales: { en: nil, de: value },
field_format: 'text',
is_required: false)
}
let(:custom_field) { cf_with_mixed_lang }
before do
Globalize.fallbacks = { en: [:en, :de] }
work_package.custom_field_values.first.value = value
work_package.save!
end
after do Globalize.fallbacks = [:en] end
context 'attribute value' do
context 'en' do
let(:locale) { 'en' }
let(:element_locale) { 'en' }
include_context 'work package edit view'
skip # it_behaves_like 'attribute value lang'
end
end
end
end
end
end
end
@@ -34,8 +34,8 @@ class CustomFieldsPage
visit new_custom_field_path type: type
end
def name_attributes
find '#custom_field_name_attributes span[lang]'
def name_attribute
find '#custom_field_name'
end
def default_value_attributes
@@ -17,7 +17,7 @@ describe 'custom fields', js: true do
end
it "creates a new list custom field with its options in the right order" do
find("#custom_field_translations_attributes_0_name").set "Operating System"
cf_page.set_name "Operating System"
select "List", from: "custom_field_field_format"
expect(page).to have_text("Allow multi-select")
@@ -68,7 +68,6 @@ describe CustomFieldFormBuilder do
expect(output).to be_html_eql(%{
<input class="custom-class form--check-box"
id="user#{resource.custom_field_id}"
lang=\"en\"
name="user[#{resource.custom_field_id}]"
type="checkbox"
value="1" />
@@ -93,7 +92,6 @@ describe CustomFieldFormBuilder do
expect(output).to be_html_eql(%{
<input class="custom-class form--text-field"
id="user#{resource.custom_field_id}"
lang=\"en\"
name="user[#{resource.custom_field_id}]"
type="text" />
}).at_path('input')
@@ -113,7 +111,6 @@ describe CustomFieldFormBuilder do
expect(output).to be_html_eql(%{
<textarea class="custom-class form--text-area"
id="user#{resource.custom_field_id}"
lang=\"en\"
name="user[#{resource.custom_field_id}]"
rows="3">
</textarea>
@@ -134,7 +131,6 @@ describe CustomFieldFormBuilder do
expect(output).to be_html_eql(%{
<input class="custom-class form--text-field"
id="user#{resource.custom_field_id}"
lang=\"en\"
name="user[#{resource.custom_field_id}]"
type="text" />
}).at_path('input')
@@ -154,7 +150,6 @@ describe CustomFieldFormBuilder do
expect(output).to be_html_eql(%{
<input class="custom-class form--text-field"
id="user#{resource.custom_field_id}"
lang=\"en\"
name="user[#{resource.custom_field_id}]"
type="text" />
}).at_path('input')
@@ -174,7 +169,6 @@ describe CustomFieldFormBuilder do
expect(output).to be_html_eql(%{
<input class="custom-class form--text-field"
id="user#{resource.custom_field_id}"
lang=\"en\"
name="user[#{resource.custom_field_id}]"
type="text" />
}).at_path('input')
@@ -199,7 +193,6 @@ describe CustomFieldFormBuilder do
expect(output).to be_html_eql(%{
<select class="custom-class form--select"
id="user#{resource.custom_field_id}"
lang=\"en\"
name="user[#{resource.custom_field_id}]"
no_label="true"><option
value=\"\"></option>
@@ -218,7 +211,6 @@ describe CustomFieldFormBuilder do
expect(output).to be_html_eql(%{
<select class="custom-class form--select"
id="user#{resource.custom_field_id}"
lang=\"en\"
name="user[#{resource.custom_field_id}]"
no_label="true"><option value=\"\">---
Please select ---</option>
@@ -239,7 +231,6 @@ describe CustomFieldFormBuilder do
expect(output).to be_html_eql(%{
<select class="custom-class form--select"
id="user#{resource.custom_field_id}"
lang=\"en\"
name="user[#{resource.custom_field_id}]"
no_label="true"><option
value=\"#{value}\">my_option</option></select>
@@ -259,7 +250,6 @@ describe CustomFieldFormBuilder do
expect(output).to be_html_eql(%{
<select class="custom-class form--select"
id="user#{resource.custom_field_id}"
lang=\"en\"
name="user[#{resource.custom_field_id}]"
no_label="true"><option value=\"\"></option>
</select>
@@ -275,7 +265,6 @@ describe CustomFieldFormBuilder do
expect(output).to be_html_eql(%{
<select class="custom-class form--select"
id="user#{resource.custom_field_id}"
lang=\"en\"
name="user[#{resource.custom_field_id}]"
no_label="true"><option value=\"\">---
Please select ---</option>
@@ -296,7 +285,6 @@ describe CustomFieldFormBuilder do
expect(output).to be_html_eql(%{
<select class="custom-class form--select"
id="user#{resource.custom_field_id}"
lang=\"en\"
name="user[#{resource.custom_field_id}]"
no_label="true"><option value=\"\"></option>
</select>
@@ -312,7 +300,6 @@ describe CustomFieldFormBuilder do
expect(output).to be_html_eql(%{
<select class="custom-class form--select"
id="user#{resource.custom_field_id}"
lang=\"en\"
name="user[#{resource.custom_field_id}]"
no_label="true"><option value=\"\">---
Please select ---</option>
-212
View File
@@ -67,222 +67,10 @@ describe CustomField, type: :model do
it { expect(field).to be_valid }
end
describe 'WHEN value and type are identical and locale is different' do
before do
I18n.locale = :de
field2.name = 'taken_name'
# this fields needs an explicit english translations
# otherwise it falls back using the german one
I18n.locale = :en
field2.name = 'unique_name'
field2.save!
field.name = 'taken_name'
end
it { expect(field).to be_valid }
end
end
describe 'localization' do
before do
I18n.locale = :de
field.name = 'Feld'
I18n.locale = :en
field.name = 'Field'
end
after do
I18n.locale = :en
end
it 'should return english name when in locale en' do
I18n.locale = :en
expect(field.name).to eq('Field')
end
it 'should return german name when in locale de' do
I18n.locale = :de
expect(field.name).to eq('Feld')
end
end
end
describe '#translations_attributes' do
describe 'WHEN providing a hash with locale and values' do
before do
field.translations_attributes = [{ 'name' => 'Feld',
'locale' => 'de' }]
end
it { expect(field.translations.size).to eq(1) }
it { expect(field.name(:de)).to eq('Feld') }
end
describe 'WHEN providing a hash with only a locale' do
before do
field.translations_attributes = [{ 'locale' => 'de' }]
end
it { expect(field.translations.size).to eq(0) }
end
describe 'WHEN providing a hash with a locale and blank values' do
before do
field.translations_attributes = [{ 'name' => '',
'locale' => 'de' }]
end
it { expect(field.translations.size).to eq(0) }
end
describe 'WHEN providing a hash with a locale and only one values' do
before do
field.translations_attributes = [{ 'name' => 'Feld',
'locale' => 'de' }]
end
it { expect(field.translations.size).to eq(1) }
it { expect(field.name(:de)).to eq('Feld') }
end
describe 'WHEN providing a hash without a locale but with values' do
before do
field.translations_attributes = [{ 'name' => 'Feld',
'locale' => '' }]
end
it { expect(field.translations.size).to eq(0) }
end
describe 'WHEN already having a translation and wishing to delete it' do
before do
I18n.locale = :de
field.name = 'Feld'
I18n.locale = :en
field.name = 'Field'
field.save!
field.reload
field.translations_attributes = [{ 'id' => field.translations.first.id.to_s,
'_destroy' => '1' }]
field.save!
end
it { expect(field.translations.size).to eq(1) }
end
end
describe '#valid?' do
describe "WITH a list field
WITH two translations
WITH default_value not included in possible_values in the non current locale translation" do
before { skip("skip until replaced") }
before do
field.field_format = 'list'
field.translations_attributes = [{ 'name' => 'Feld',
'default_value' => 'vier',
'possible_values' => ['eins', 'zwei', 'drei'],
'locale' => 'de' },
{ 'name' => 'Field',
'locale' => 'en',
'possible_values' => "one\ntwo\nthree\n",
'default_value' => 'two' }]
end
it { expect(field).not_to be_valid }
end
describe "WITH a list field
WITH two translations
WITH default_value included in possible_values" do
before { skip("skip until replaced") }
before do
field.field_format = 'list'
field.translations_attributes = [{ 'name' => 'Feld',
'default_value' => 'zwei',
'possible_values' => ['eins', 'zwei', 'drei'],
'locale' => 'de' },
{ 'name' => 'Field',
'locale' => 'en',
'possible_values' => "one\ntwo\nthree\n",
'default_value' => 'two' }]
end
it { expect(field).to be_valid }
end
describe "WITH a list field
WITH two translations
WITH default_value not included in possible_values in the current locale translation" do
before { skip("skip until replaced") }
before do
field.field_format = 'list'
field.translations_attributes = [{ 'name' => 'Feld',
'default_value' => 'zwei',
'possible_values' => ['eins', 'zwei', 'drei'],
'locale' => 'de' },
{ 'name' => 'Field',
'locale' => 'en',
'possible_values' => "one\ntwo\nthree\n",
'default_value' => 'four' }]
end
it { expect(field).not_to be_valid }
end
describe "WITH a list field
WITH two translations
WITH possible_values being empty in a fallbacked translation" do
before { skip("skip until replaced") }
before do
field.field_format = 'list'
field.translations_attributes = [{ 'name' => 'Feld',
'locale' => 'de' },
{ 'name' => 'Field',
'locale' => 'en',
'possible_values' => "one\ntwo\nthree\n",
'default_value' => 'two' }]
end
it { expect(field).to be_valid }
end
describe "WITH a list field
WITH the field being required
WITH two translations
WITH neither translation defining a default_value" do
before { skip("skip until replaced") }
before do
field.field_format = 'list'
field.is_required = true
field.translations_attributes = [{ 'name' => 'Feld',
'locale' => 'de' },
{ 'name' => 'Field',
'possible_values' => "one\ntwo\nthree\n",
'locale' => 'en' }]
end
it { expect(field).to be_valid }
end
describe "WITH a text field
WITH minimum length blank" do
before do
+1 -1
View File
@@ -39,7 +39,7 @@ module Pages
end
def set_name(name)
find("#custom_field_name_attributes input.form--text-field").set name
find("#custom_field_name").set name
end
def set_default_value(value)