]> source.dussan.org Git - redmine.git/commitdiff
Adds Enumeration custom field format (#21060).
authorJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 25 Oct 2015 08:32:47 +0000 (08:32 +0000)
committerJean-Philippe Lang <jp_lang@yahoo.fr>
Sun, 25 Oct 2015 08:32:47 +0000 (08:32 +0000)
Similar to List format but stores possible values as records.

git-svn-id: http://svn.redmine.org/redmine/trunk@14745 e93f8b46-1217-0410-a6f0-8f06a7374b81

16 files changed:
app/controllers/custom_field_enumerations_controller.rb [new file with mode: 0644]
app/models/custom_field.rb
app/models/custom_field_enumeration.rb [new file with mode: 0644]
app/views/custom_field_enumerations/create.js.erb [new file with mode: 0644]
app/views/custom_field_enumerations/destroy.html.erb [new file with mode: 0644]
app/views/custom_field_enumerations/index.html.erb [new file with mode: 0644]
app/views/custom_fields/formats/_enumeration.erb [new file with mode: 0644]
config/locales/en.yml
config/locales/fr.yml
config/routes.rb
db/migrate/20151025072118_create_custom_field_enumerations.rb [new file with mode: 0644]
lib/redmine/field_format.rb
public/stylesheets/application.css
test/functional/custom_field_enumerations_controller_test.rb [new file with mode: 0644]
test/integration/routing/custom_fields_test.rb
test/unit/lib/redmine/field_format/enumeration_format_test.rb [new file with mode: 0644]

diff --git a/app/controllers/custom_field_enumerations_controller.rb b/app/controllers/custom_field_enumerations_controller.rb
new file mode 100644 (file)
index 0000000..ba746d2
--- /dev/null
@@ -0,0 +1,69 @@
+# Redmine - project management software
+# Copyright (C) 2006-2015  Jean-Philippe Lang
+#
+# 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.
+
+class CustomFieldEnumerationsController < ApplicationController
+  layout 'admin'
+
+  before_filter :require_admin
+  before_filter :find_custom_field
+  before_filter :find_enumeration, :only => :destroy
+
+  def index
+    @values = @custom_field.enumerations.order(:position)
+  end
+
+  def create
+    @value = @custom_field.enumerations.build(params[:custom_field_enumeration])
+    @value.save
+    respond_to do |format|
+      format.html { redirect_to custom_field_enumerations_path(@custom_field) }
+      format.js
+    end
+  end
+
+  def update_each
+    if CustomFieldEnumeration.update_each(@custom_field, params[:custom_field_enumerations])
+      flash[:notice] = l(:notice_successful_update)
+    end
+    redirect_to :action => 'index'
+  end
+
+  def destroy
+    reassign_to = @custom_field.enumerations.find_by_id(params[:reassign_to_id])
+    if reassign_to.nil? && @value.in_use?
+      @enumerations = @custom_field.enumerations - [@value]
+      render :action => 'destroy'
+      return
+    end
+    @value.destroy(reassign_to)
+    redirect_to custom_field_enumerations_path(@custom_field)
+  end
+
+  private
+
+  def find_custom_field
+    @custom_field = CustomField.find(params[:custom_field_id])
+  rescue ActiveRecord::RecordNotFound
+    render_404
+  end
+
+  def find_enumeration
+    @value = @custom_field.enumerations.find(params[:id])
+  rescue ActiveRecord::RecordNotFound
+    render_404
+  end
+end
index ad87aa34eb80d53d300f68c7716b041eac379d75..a1373d12b95ba015ee3798a5579c8892f0622896 100644 (file)
 class CustomField < ActiveRecord::Base
   include Redmine::SubclassFactory
 
+  has_many :enumerations,
+           lambda { order(:position) },
+           :class_name => 'CustomFieldEnumeration',
+           :dependent => :delete_all
   has_many :custom_values, :dependent => :delete_all
   has_and_belongs_to_many :roles, :join_table => "#{table_name_prefix}custom_fields_roles#{table_name_suffix}", :foreign_key => "custom_field_id"
   acts_as_list :scope => 'type = \'#{self.class}\''
diff --git a/app/models/custom_field_enumeration.rb b/app/models/custom_field_enumeration.rb
new file mode 100644 (file)
index 0000000..26a580d
--- /dev/null
@@ -0,0 +1,74 @@
+# Redmine - project management software
+# Copyright (C) 2006-2015  Jean-Philippe Lang
+#
+# 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.
+
+class CustomFieldEnumeration < ActiveRecord::Base
+  belongs_to :custom_field
+  attr_accessible :name, :active, :position
+
+  validates_presence_of :name, :position, :custom_field_id
+  validates_length_of :name, :maximum => 60
+  validates_numericality_of :position, :only_integer => true
+  before_create :set_position
+
+  scope :active, lambda { where(:active => true) }
+
+  def to_s
+    name.to_s
+  end
+
+  def objects_count
+    custom_values.count
+  end
+
+  def in_use?
+    objects_count > 0
+  end
+
+  alias :destroy_without_reassign :destroy
+  def destroy(reassign_to=nil)
+    if reassign_to
+      custom_values.update_all(:value => reassign_to.id.to_s)
+    end
+    destroy_without_reassign
+  end
+
+  def custom_values
+    custom_field.custom_values.where(:value => id.to_s)
+  end
+
+  def self.update_each(custom_field, attributes)
+    return unless attributes.is_a?(Hash)
+    transaction do
+      attributes.each do |enumeration_id, enumeration_attributes|
+        enumeration = custom_field.enumerations.find_by_id(enumeration_id)
+        if enumeration
+          enumeration.attributes = enumeration_attributes
+          unless enumeration.save
+            raise ActiveRecord::Rollback
+          end
+        end
+      end
+    end
+  end
+
+  private
+
+  def set_position
+    max = self.class.where(:custom_field_id => custom_field_id).maximum(:position) || 0
+    self.position = max + 1
+  end
+end
diff --git a/app/views/custom_field_enumerations/create.js.erb b/app/views/custom_field_enumerations/create.js.erb
new file mode 100644 (file)
index 0000000..9a9d404
--- /dev/null
@@ -0,0 +1,2 @@
+$('#content').html('<%= escape_javascript(render(:template => 'custom_field_enumerations/index')) %>');
+$('#custom_field_enumeration_name').focus();
diff --git a/app/views/custom_field_enumerations/destroy.html.erb b/app/views/custom_field_enumerations/destroy.html.erb
new file mode 100644 (file)
index 0000000..d2ae2ed
--- /dev/null
@@ -0,0 +1,14 @@
+<%= title [l(:label_custom_field_plural), custom_fields_path],
+  [l(@custom_field.type_name), custom_fields_path(:tab => @custom_field.class.name)],
+  @custom_field.name %>
+
+<%= form_tag(custom_field_enumeration_path(@custom_field, @value), :method => :delete) do %>
+<div class="box">
+<p><strong><%= l(:text_enumeration_destroy_question, :name => @value.name, :count => @value.objects_count) %></strong></p>
+<p><label for='reassign_to_id'><%= l(:text_enumeration_category_reassign_to) %></label>
+<%= select_tag('reassign_to_id', content_tag('option', "--- #{l(:actionview_instancetag_blank_option)} ---", :value => '') + options_from_collection_for_select(@enumerations, 'id', 'name')) %></p>
+</div>
+
+<%= submit_tag l(:button_apply) %>
+<%= link_to l(:button_cancel), custom_field_enumerations_path(@custom_field) %>
+<% end %>
diff --git a/app/views/custom_field_enumerations/index.html.erb b/app/views/custom_field_enumerations/index.html.erb
new file mode 100644 (file)
index 0000000..9ca9314
--- /dev/null
@@ -0,0 +1,49 @@
+<%= title [l(:label_custom_field_plural), custom_fields_path],
+  [l(@custom_field.type_name), custom_fields_path(:tab => @custom_field.class.name)],
+  @custom_field.name %>
+
+<% if @custom_field.enumerations.any? %>
+<%= form_tag custom_field_enumerations_path(@custom_field), :method => 'put' do %>
+<div class="box">
+  <ul id="custom_field_enumerations" class="flat">
+  <% @custom_field.enumerations.each_with_index do |value, position| %>
+    <li>
+      <span class="sort-handle ui-icon ui-icon-arrowthick-2-n-s"></span>
+      <%= hidden_field_tag "custom_field_enumerations[#{value.id}][position]", position, :class => 'position' %>
+      <%= text_field_tag "custom_field_enumerations[#{value.id}][name]", value.name, :size => 40 %>
+      <%= hidden_field_tag "custom_field_enumerations[#{value.id}][active]", 0 %>
+      <label>
+        <%= check_box_tag "custom_field_enumerations[#{value.id}][active]", 1, value.active? %>
+        <%= l(:field_active) %>
+      </label>
+      <%= delete_link custom_field_enumeration_path(@custom_field, value) %>
+    </li>
+  <% end %>
+  </ul>
+</div>
+<p>
+  <%= submit_tag(l(:button_save)) %> |
+  <%= link_to l(:button_back), edit_custom_field_path(@custom_field) %>
+</p>
+<% end %>
+<% end %>
+
+<p><%= l(:label_enumeration_new) %></p>
+
+<%= form_tag custom_field_enumerations_path(@custom_field), :method => 'post', :remote => true do %>
+  <p><%= text_field_tag 'custom_field_enumeration[name]', '', :size => 40 %>
+  <%= submit_tag(l(:button_add)) %></p>
+<% end %>
+
+<%= javascript_tag do %>
+$(function() {
+  $("#custom_field_enumerations").sortable({
+    handle: ".sort-handle",
+    update: function(event, ui) {
+      $("#custom_field_enumerations li").each(function(){
+        $(this).find("input.position").val($(this).index()+1);
+      });
+    }
+  });
+});
+<% end %>
diff --git a/app/views/custom_fields/formats/_enumeration.erb b/app/views/custom_fields/formats/_enumeration.erb
new file mode 100644 (file)
index 0000000..07e4cf4
--- /dev/null
@@ -0,0 +1,12 @@
+<% unless @custom_field.new_record? %>
+<p>
+  <label><%= l(:field_possible_values) %></label>
+  <%= link_to l(:button_edit), custom_field_enumerations_path(@custom_field), :class => 'icon icon-edit' %>
+</p>
+<% if @custom_field.enumerations.active.any? %>
+  <p><%= f.select :default_value, @custom_field.enumerations.active.map{|v| [v.name, v.id.to_s]}, :include_blank => true %></p>
+<% end %>
+<% end %>
+
+<p><%= f.text_field :url_pattern, :size => 50, :label => :label_link_values_to %></p>
+<p><%= edit_tag_style_tag f %></p>
index 3e1e949066e6ac6d8cb1fbee6b67629916d784cf..dada67a9f65ad0252546870defafcccddfe020cf 100644 (file)
@@ -970,6 +970,7 @@ en:
   label_file_content_preview: File content preview
   label_create_missing_values: Create missing values
   label_api: API
+  label_field_format_enumeration: Key/value list
 
   button_login: Login
   button_submit: Submit
index 517b227bbae97aa3f36e8db37985016c5687f245..2cedaa2cdcead630b98f07e42b21dc91576843c2 100644 (file)
@@ -988,6 +988,7 @@ fr:
   label_file_content_preview: Aperçu du contenu du fichier
   label_create_missing_values: Créer les valeurs manquantes
   label_api: API
+  label_field_format_enumeration: Liste clé/valeur
 
   button_login: Connexion
   button_submit: Soumettre
index d7ddac190a3fcc881979dad46a6aec2031de21f2..47451453f0c7e6ce0d714f24d87cddab769c5bfe 100644 (file)
@@ -311,7 +311,10 @@ Rails.application.routes.draw do
       post 'update_issue_done_ratio'
     end
   end
-  resources :custom_fields, :except => :show
+  resources :custom_fields, :except => :show do
+    resources :enumerations, :controller => 'custom_field_enumerations', :except => [:show, :new, :edit]
+    put 'enumerations', :to => 'custom_field_enumerations#update_each'
+  end
   resources :roles do
     collection do
       match 'permissions', :via => [:get, :post]
diff --git a/db/migrate/20151025072118_create_custom_field_enumerations.rb b/db/migrate/20151025072118_create_custom_field_enumerations.rb
new file mode 100644 (file)
index 0000000..ea2e510
--- /dev/null
@@ -0,0 +1,10 @@
+class CreateCustomFieldEnumerations < ActiveRecord::Migration
+  def change
+    create_table :custom_field_enumerations do |t|
+      t.integer :custom_field_id, :null => false
+      t.string :name, :null => false
+      t.boolean :active, :default => true, :null => false
+      t.integer :position, :default => 1, :null => false
+    end
+  end
+end
index 3d97f601b304bd4c1a0b5b88e06027dec9a74a80..841d6a08d9f27952e9fd56b364b9214bff4933db 100644 (file)
@@ -539,7 +539,7 @@ module Redmine
       add 'list'
       self.searchable_supported = true
       self.form_partial = 'custom_fields/formats/list'
+
       def possible_custom_value_options(custom_value)
         options = possible_values_options(custom_value.custom_field)
         missing = [custom_value.value].flatten.reject(&:blank?) - options
@@ -636,7 +636,6 @@ module Redmine
         missing = [custom_value.value_was].flatten.reject(&:blank?) - options.map(&:last)
         if missing.any?
           options += target_class.where(:id => missing.map(&:to_i)).map {|o| [o.to_s, o.id.to_s]}
-          options.sort_by!(&:first)
         end
         options
       end
@@ -674,6 +673,32 @@ module Redmine
       protected :value_join_alias
     end
 
+    class EnumerationFormat < RecordList
+      add 'enumeration'
+      self.form_partial = 'custom_fields/formats/enumeration'
+      def label
+        "label_field_format_enumeration"
+      end
+
+      def target_class
+        @target_class ||= CustomFieldEnumeration
+      end
+
+      def possible_values_options(custom_field, object=nil)
+        possible_values_records(custom_field, object).map {|u| [u.name, u.id.to_s]}
+      end
+
+      def possible_values_records(custom_field, object=nil)
+        custom_field.enumerations.active
+      end
+
+      def value_from_keyword(custom_field, keyword, object)
+        value = custom_field.enumerations.where("LOWER(name) LIKE LOWER(?)", keyword)
+        value ? value.id : nil
+      end
+    end
+
     class UserFormat < RecordList
       add 'user'
       self.form_partial = 'custom_fields/formats/user'
index bb07cb62166737ce95b3508225d4433662522706..aa5872c4ed6e480c817b2d1d3fa94efd059ddd83 100644 (file)
@@ -77,8 +77,8 @@ pre, code {font-family: Consolas, Menlo, "Liberation Mono", Courier, monospace;}
 #sidebar hr{ width: 100%; margin: 0 auto; height: 1px; background: #ccc; border: 0; }
 * html #sidebar hr{ width: 95%; position: relative; left: -6px; color: #ccc; }
 #sidebar .contextual { margin-right: 1em; }
-#sidebar ul {margin: 0;  padding: 0;}
-#sidebar ul li {list-style-type:none;margin: 0px 2px 0px 0px; padding: 0px 0px 0px 0px;}
+#sidebar ul, ul.flat {margin: 0;  padding: 0;}
+#sidebar ul li, ul.flat li {list-style-type:none;margin: 0px 2px 0px 0px; padding: 0px 0px 0px 0px;}
 
 #content { width: 75%; background-color: #fff; margin: 0px; border-right: 1px solid #ddd; padding: 6px 10px 10px 10px; z-index: 10; }
 * html #content{ width: 75%; padding-left: 0; margin-top: 0px; padding: 6px 10px 10px 10px;}
@@ -483,6 +483,7 @@ select.expandable {vertical-align:top;}
 
 textarea#custom_field_possible_values {width: 95%; resize:vertical}
 textarea#custom_field_default_value {width: 95%; resize:vertical}
+.sort-handle {display:inline-block; vertical-align:middle;}
 
 input#content_comments {width: 99%}
 
diff --git a/test/functional/custom_field_enumerations_controller_test.rb b/test/functional/custom_field_enumerations_controller_test.rb
new file mode 100644 (file)
index 0000000..6bcddac
--- /dev/null
@@ -0,0 +1,111 @@
+# Redmine - project management software
+# Copyright (C) 2006-2015  Jean-Philippe Lang
+#
+# 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.
+
+require File.expand_path('../../test_helper', __FILE__)
+
+class CustomFieldEnumerationsControllerTest < ActionController::TestCase
+  fixtures :users, :email_addresses
+
+  def setup
+    @request.session[:user_id] = 1
+    @field = GroupCustomField.create!(:name => 'List', :field_format => 'enumeration', :is_required => false)
+    @foo = CustomFieldEnumeration.new(:name => 'Foo')
+    @bar = CustomFieldEnumeration.new(:name => 'Bar')
+    @field.enumerations << @foo
+    @field.enumerations << @bar
+  end
+
+  def test_index
+    get :index, :custom_field_id => @field.id
+    assert_response :success
+    assert_template 'index'
+  end
+
+  def test_create
+    assert_difference 'CustomFieldEnumeration.count' do
+      post :create, :custom_field_id => @field.id, :custom_field_enumeration => { :name => 'Baz' }
+      assert_redirected_to "/custom_fields/#{@field.id}/enumerations"
+    end
+
+    assert_equal 3, @field.reload.enumerations.count
+    enum = @field.enumerations.last
+    assert_equal 'Baz', enum.name
+    assert_equal true, enum.active
+    assert_equal 3, enum.position
+  end
+
+  def test_create_xhr
+    assert_difference 'CustomFieldEnumeration.count' do
+      xhr :post, :create, :custom_field_id => @field.id, :custom_field_enumeration => { :name => 'Baz' }
+      assert_response :success
+    end
+  end
+
+  def test_update_each
+    put :update_each, :custom_field_id => @field.id, :custom_field_enumerations => {
+      @bar.id => {:position => "1", :name => "Baz", :active => "1"},
+      @foo.id => {:position => "2", :name => "Foo", :active => "0"}
+    }
+    assert_response 302
+
+    @bar.reload
+    assert_equal "Baz", @bar.name
+    assert_equal true, @bar.active
+    assert_equal 1, @bar.position
+
+    @foo.reload
+    assert_equal "Foo", @foo.name
+    assert_equal false, @foo.active
+    assert_equal 2, @foo.position
+  end
+
+  def test_destroy
+    assert_difference 'CustomFieldEnumeration.count', -1 do
+      delete :destroy, :custom_field_id => @field.id, :id => @foo.id
+      assert_redirected_to "/custom_fields/#{@field.id}/enumerations"
+    end
+
+    assert_equal 1, @field.reload.enumerations.count
+    enum = @field.enumerations.last
+    assert_equal 'Bar', enum.name
+  end
+
+  def test_destroy_enumeration_in_use_should_display_destroy_form
+    group = Group.generate!
+    group.custom_field_values = {@field.id.to_s => @foo.id.to_s}
+    group.save!
+
+    assert_no_difference 'CustomFieldEnumeration.count' do
+      delete :destroy, :custom_field_id => @field.id, :id => @foo.id
+      assert_response 200
+      assert_template 'destroy'
+    end
+  end
+
+  def test_destroy_enumeration_in_use_should_destroy_and_reassign_values
+    group = Group.generate!
+    group.custom_field_values = {@field.id.to_s => @foo.id.to_s}
+    group.save!
+
+    assert_difference 'CustomFieldEnumeration.count', -1 do
+      delete :destroy, :custom_field_id => @field.id, :id => @foo.id, :reassign_to_id => @bar.id
+      assert_response 302
+    end
+
+    assert_equal @bar.id.to_s, group.reload.custom_field_value(@field)
+  end
+end
index e0fccb7c6e349f6ecab7cea4c46d0642fe09a481..0fbb10b143ba3fb6d82a7c5052ef11ff5747712e 100644 (file)
@@ -27,4 +27,11 @@ class RoutingCustomFieldsTest < Redmine::RoutingTest
     should_route 'PUT /custom_fields/2' => 'custom_fields#update', :id => '2'
     should_route 'DELETE /custom_fields/2' => 'custom_fields#destroy', :id => '2'
   end
+
+  def test_custom_field_enumerations
+    should_route 'GET /custom_fields/3/enumerations' => 'custom_field_enumerations#index', :custom_field_id => '3'
+    should_route 'POST /custom_fields/3/enumerations' => 'custom_field_enumerations#create', :custom_field_id => '3'
+    should_route 'PUT /custom_fields/3/enumerations' => 'custom_field_enumerations#update_each', :custom_field_id => '3'
+    should_route 'DELETE /custom_fields/3/enumerations/6' => 'custom_field_enumerations#destroy', :custom_field_id => '3', :id => '6'
+  end
 end
diff --git a/test/unit/lib/redmine/field_format/enumeration_format_test.rb b/test/unit/lib/redmine/field_format/enumeration_format_test.rb
new file mode 100644 (file)
index 0000000..961957f
--- /dev/null
@@ -0,0 +1,86 @@
+# Redmine - project management software
+# Copyright (C) 2006-2015  Jean-Philippe Lang
+#
+# 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.
+
+require File.expand_path('../../../../../test_helper', __FILE__)
+require 'redmine/field_format'
+
+class Redmine::EnumerationFieldFormatTest < ActionView::TestCase
+  include ApplicationHelper
+
+  def setup
+    @field = IssueCustomField.create!(:name => 'List', :field_format => 'enumeration', :is_required => false)
+    @foo = CustomFieldEnumeration.new(:name => 'Foo')
+    @bar = CustomFieldEnumeration.new(:name => 'Bar')
+    @field.enumerations << @foo
+    @field.enumerations << @bar
+  end
+
+  def test_edit_tag_should_contain_possible_values
+    value = CustomFieldValue.new(:custom_field => @field, :customized => Issue.new)
+
+    tag = @field.format.edit_tag(self, 'id', 'name', value)
+    assert_select_in tag, 'select' do
+      assert_select 'option', 3
+      assert_select 'option[value=""]'
+      assert_select 'option[value=?]', @foo.id.to_s, :text => 'Foo'
+      assert_select 'option[value=?]', @bar.id.to_s, :text => 'Bar'
+    end
+  end
+
+  def test_edit_tag_should_select_current_value
+    value = CustomFieldValue.new(:custom_field => @field, :customized => Issue.new, :value => @bar.id.to_s)
+
+    tag = @field.format.edit_tag(self, 'id', 'name', value)
+    assert_select_in tag, 'select' do
+      assert_select 'option[selected=selected]', 1
+      assert_select 'option[value=?][selected=selected]', @bar.id.to_s, :text => 'Bar'
+    end
+  end
+
+  def test_edit_tag_with_multiple_should_select_current_values
+    @field.multiple = true
+    @field.save!
+    value = CustomFieldValue.new(:custom_field => @field, :customized => Issue.new, :value => [@foo.id.to_s, @bar.id.to_s])
+
+    tag = @field.format.edit_tag(self, 'id', 'name', value)
+    assert_select_in tag, 'select[multiple=multiple]' do
+      assert_select 'option[selected=selected]', 2
+      assert_select 'option[value=?][selected=selected]', @foo.id.to_s, :text => 'Foo'
+      assert_select 'option[value=?][selected=selected]', @bar.id.to_s, :text => 'Bar'
+    end
+  end
+
+  def test_edit_tag_with_check_box_style_should_contain_possible_values
+    @field.edit_tag_style = 'check_box'
+    @field.save!
+    value = CustomFieldValue.new(:custom_field => @field, :customized => Issue.new)
+
+    tag = @field.format.edit_tag(self, 'id', 'name', value)
+    assert_select_in tag, 'span' do
+      assert_select 'input[type=radio]', 3
+      assert_select 'label', :text => '(none)' do
+        assert_select 'input[value=""]'
+      end
+      assert_select 'label', :text => 'Foo' do
+        assert_select 'input[value=?]', @foo.id.to_s
+      end
+      assert_select 'label', :text => 'Bar' do
+        assert_select 'input[value=?]', @bar.id.to_s
+      end
+    end
+  end
+end