iqvoc_skosxl 1.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. data/Gemfile +40 -0
  2. data/Gemfile.lock +154 -0
  3. data/README.md +26 -0
  4. data/Rakefile +11 -0
  5. data/app/assets/javascripts/iqvoc_skosxl/manifest.js +0 -0
  6. data/app/assets/javascripts/manifest.js +3 -0
  7. data/app/assets/stylesheets/iqvoc_skosxl/manifest.css +0 -0
  8. data/app/assets/stylesheets/manifest.css +5 -0
  9. data/app/controllers/labels/versions_controller.rb +109 -0
  10. data/app/controllers/labels_controller.rb +130 -0
  11. data/app/controllers/rdf_controller.rb +23 -0
  12. data/app/helpers/iqvoc_skosxl_helper.rb +18 -0
  13. data/app/helpers/labels_helper.rb +68 -0
  14. data/app/models/concept/skosxl/extension.rb +62 -0
  15. data/app/models/label/relation/base.rb +54 -0
  16. data/app/models/label/relation/skosxl/base.rb +12 -0
  17. data/app/models/label/skosxl/base.rb +219 -0
  18. data/app/models/labeling/skosxl/alt_label.rb +8 -0
  19. data/app/models/labeling/skosxl/base.rb +75 -0
  20. data/app/models/labeling/skosxl/hidden_label.rb +12 -0
  21. data/app/models/labeling/skosxl/pref_label.rb +12 -0
  22. data/app/views/labels/_base_data.html.erb +62 -0
  23. data/app/views/labels/_change_note.html.erb +46 -0
  24. data/app/views/labels/_details.html.erb +6 -0
  25. data/app/views/labels/_label_relation.html.erb +7 -0
  26. data/app/views/labels/_labeling.html.erb +3 -0
  27. data/app/views/labels/_note.html.erb +33 -0
  28. data/app/views/labels/_show_head.html.erb +22 -0
  29. data/app/views/labels/_value_and_language.html.erb +9 -0
  30. data/app/views/labels/edit.html.erb +22 -0
  31. data/app/views/labels/new.html.erb +3 -0
  32. data/app/views/labels/show.ttl.erb +1 -0
  33. data/app/views/labels/show_published.html.erb +13 -0
  34. data/app/views/labels/show_unpublished.html.erb +36 -0
  35. data/app/views/partials/label/relation/_base.html.erb +9 -0
  36. data/app/views/partials/label/relation/_edit_base.html.erb +13 -0
  37. data/app/views/partials/label/skosxl/_edit_link_base.html.erb +1 -0
  38. data/app/views/partials/label/skosxl/_new_link_base.html.erb +7 -0
  39. data/app/views/partials/labeling/skosxl/_base.html.erb +19 -0
  40. data/app/views/partials/labeling/skosxl/_edit_base.html.erb +15 -0
  41. data/app/views/partials/labeling/skosxl/_search_result.html.erb +9 -0
  42. data/app/views/rdf/show_label.iqrdf +5 -0
  43. data/config/application.rb +56 -0
  44. data/config/boot.rb +13 -0
  45. data/config/database.template.yml +38 -0
  46. data/config/database.yml +36 -0
  47. data/config/engine.rb +13 -0
  48. data/config/environment.rb +5 -0
  49. data/config/environments/development.rb +55 -0
  50. data/config/environments/production.rb +64 -0
  51. data/config/environments/test.rb +44 -0
  52. data/config/initializers/iqvoc.rb +4 -0
  53. data/config/initializers/iqvoc_skosxl.rb +1 -0
  54. data/config/initializers/secret_token.rb.template +9 -0
  55. data/config/initializers/session_store.rb +8 -0
  56. data/config/locales/activerecord.de.yml +18 -0
  57. data/config/locales/activerecord.en.yml +18 -0
  58. data/config/locales/de.yml +5 -0
  59. data/config/locales/en.yml +5 -0
  60. data/config/routes.rb +15 -0
  61. data/db/migrate/20110408121540_extend_label.rb +37 -0
  62. data/db/migrate/20110408123644_add_label_relations.rb +24 -0
  63. data/db/schema.rb +146 -0
  64. data/db/seeds.rb +0 -0
  65. data/iqvoc_skosxl.gemspec +22 -0
  66. data/lib/engine_tasks/db.rake +19 -0
  67. data/lib/iqvoc/skosxl/version.rb +5 -0
  68. data/lib/iqvoc/xllabel.rb +60 -0
  69. data/lib/iqvoc_skosxl.rb +22 -0
  70. data/test/factories.rb +23 -0
  71. data/test/integration/concept_label_language_test.rb +95 -0
  72. data/test/integration/dashboard_test.rb +29 -0
  73. data/test/integration/edit_labels_test.rb +26 -0
  74. data/test/integration/labels_order_test.rb +27 -0
  75. data/test/integration_test_helper.rb +27 -0
  76. data/test/test_helper.rb +15 -0
  77. data/test/unit/label_test.rb +30 -0
  78. metadata +154 -0
@@ -0,0 +1,5 @@
1
+ de:
2
+ txt:
3
+ models:
4
+ label:
5
+ origin_invalid: "enthält ungültige Zeichen."
@@ -0,0 +1,5 @@
1
+ en:
2
+ txt:
3
+ models:
4
+ label:
5
+ origin_invalid: "Origin contains invalid characters."
data/config/routes.rb ADDED
@@ -0,0 +1,15 @@
1
+ Rails.application.routes.draw do
2
+ scope '(:lang)', :lang => /#{Iqvoc::Concept.pref_labeling_languages.join("|")}/ do
3
+
4
+ resources :labels
5
+
6
+ match "labels/versions/:origin/branch(.:format)" => "labels/versions#branch", :as => "label_versions_branch"
7
+ match "labels/versions/:origin/merge(.:format)" => "labels/versions#merge", :as => "label_versions_merge"
8
+ match "labels/versions/:origin/lock(.:format)" => "labels/versions#lock", :as => "label_versions_lock"
9
+ match "labels/versions/:origin/unlock(.:format)" => "labels/versions#unlock", :as => "label_versions_unlock"
10
+ match "labels/versions/:origin/to_review(.:format)" => "labels/versions#to_review", :as => "label_versions_to_review"
11
+ match "labels/versions/:origin/consistency_check(.:format)" => "labels/versions#consistency_check", :as => "label_versions_consistency_check"
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,37 @@
1
+ class ExtendLabel < ActiveRecord::Migration
2
+
3
+ FIELDS = [
4
+ {"rev" => {:type => :integer, :options => {:default => 1}}},
5
+ {"published_version_id" => {:type => :integer}},
6
+ {"published_at" => {:type => :date}},
7
+ {"locked_by" => {:type => :integer}},
8
+ {"expired_at" => {:type => :date}},
9
+ {"follow_up" => {:type => :date}},
10
+ {"to_review" => {:type => :boolean}},
11
+ {"rdf_updated_at" => {:type => :date}}
12
+ ]
13
+
14
+ def self.up
15
+ FIELDS.each do |hsh|
16
+ hsh.each do |column_name, hsh2|
17
+ unless column_exists?(:labels, column_name)
18
+ add_column(:labels, column_name, hsh2[:type], (hsh2[:options] || {}))
19
+ end
20
+ end
21
+ end
22
+
23
+ add_index :labels, "published_version_id", :name => "ix_labels_on_published_v" unless index_exists?(:labels, "published_version_id", :name => "ix_labels_on_published_v")
24
+
25
+ end
26
+
27
+ def self.down
28
+ FIELDS.each do |hsh|
29
+ hsh.each do |column_name, hsh2|
30
+ if column_exists?(:labels, column_name)
31
+ remove_column(:labels, column_name)
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,24 @@
1
+ class AddLabelRelations < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ unless table_exists?("label_relations")
5
+ create_table "label_relations", :force => true do |t|
6
+ t.string "type"
7
+ t.integer "domain_id"
8
+ t.integer "range_id"
9
+ t.datetime "created_at"
10
+ t.datetime "updated_at"
11
+ end
12
+
13
+ add_index "label_relations", ["domain_id", "range_id", "type"], :name => "ix_label_rel_dom_rng_type"
14
+ add_index "label_relations", ["type"], :name => "ix_label_relations_on_type"
15
+ end
16
+ end
17
+
18
+ def self.down
19
+ if table_exists?("label_relations")
20
+ drop_table("label_relations")
21
+ end
22
+ end
23
+
24
+ end
data/db/schema.rb ADDED
@@ -0,0 +1,146 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # Note that this schema.rb definition is the authoritative source for your
6
+ # database schema. If you need to create the application database on another
7
+ # system, you should be using db:schema:load, not running all the migrations
8
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
10
+ #
11
+ # It's strongly recommended to check this file into your version control system.
12
+
13
+ ActiveRecord::Schema.define(:version => 20110615134040) do
14
+
15
+ create_table "collection_members", :force => true do |t|
16
+ t.integer "collection_id"
17
+ t.integer "target_id"
18
+ t.string "type"
19
+ end
20
+
21
+ add_index "collection_members", ["collection_id", "target_id", "type"], :name => "ix_collections_fk_type"
22
+
23
+ create_table "concept_relations", :force => true do |t|
24
+ t.string "type"
25
+ t.integer "owner_id"
26
+ t.integer "target_id"
27
+ t.datetime "created_at"
28
+ t.datetime "updated_at"
29
+ end
30
+
31
+ add_index "concept_relations", ["owner_id", "target_id"], :name => "ix_concept_relations_fk"
32
+
33
+ create_table "concepts", :force => true do |t|
34
+ t.string "type"
35
+ t.string "origin", :limit => 4000
36
+ t.integer "rev", :default => 1
37
+ t.date "published_at"
38
+ t.integer "published_version_id"
39
+ t.integer "locked_by"
40
+ t.date "expired_at"
41
+ t.date "follow_up"
42
+ t.boolean "to_review"
43
+ t.date "rdf_updated_at"
44
+ t.datetime "created_at"
45
+ t.datetime "updated_at"
46
+ end
47
+
48
+ add_index "concepts", ["origin"], :name => "ix_concepts_on_origin", :length => {"origin"=>255}
49
+ add_index "concepts", ["published_version_id"], :name => "ix_concepts_publ_version_id"
50
+
51
+ create_table "label_relations", :force => true do |t|
52
+ t.string "type"
53
+ t.integer "domain_id"
54
+ t.integer "range_id"
55
+ t.datetime "created_at"
56
+ t.datetime "updated_at"
57
+ end
58
+
59
+ add_index "label_relations", ["domain_id", "range_id", "type"], :name => "index_label_relations_on_domain_id_and_range_id_and_type"
60
+ add_index "label_relations", ["type"], :name => "index_label_relations_on_type"
61
+
62
+ create_table "labelings", :force => true do |t|
63
+ t.string "type"
64
+ t.integer "owner_id"
65
+ t.integer "target_id"
66
+ t.datetime "created_at"
67
+ t.datetime "updated_at"
68
+ end
69
+
70
+ add_index "labelings", ["owner_id", "target_id", "type"], :name => "ix_labelings_fk_type"
71
+ add_index "labelings", ["type"], :name => "ix_labelings_on_type"
72
+
73
+ create_table "labels", :force => true do |t|
74
+ t.string "type"
75
+ t.string "origin", :limit => 4000
76
+ t.string "language"
77
+ t.string "value", :limit => 1024
78
+ t.datetime "created_at"
79
+ t.datetime "updated_at"
80
+ t.integer "rev", :default => 1
81
+ t.integer "published_version_id"
82
+ t.date "published_at"
83
+ t.integer "locked_by"
84
+ t.date "expired_at"
85
+ t.date "follow_up"
86
+ t.boolean "to_review"
87
+ t.date "rdf_updated_at"
88
+ end
89
+
90
+ add_index "labels", ["language"], :name => "ix_labels_on_language"
91
+ add_index "labels", ["origin"], :name => "ix_labels_on_origin", :length => {"origin"=>255}
92
+ add_index "labels", ["published_version_id"], :name => "ix_labels_on_published_v"
93
+ add_index "labels", ["value"], :name => "ix_labels_on_value", :length => {"value"=>255}
94
+
95
+ create_table "matches", :force => true do |t|
96
+ t.integer "concept_id"
97
+ t.string "type"
98
+ t.string "value"
99
+ t.datetime "created_at"
100
+ t.datetime "updated_at"
101
+ end
102
+
103
+ add_index "matches", ["concept_id", "type"], :name => "ix_matches_fk_type"
104
+ add_index "matches", ["type"], :name => "ix_matches_on_type"
105
+
106
+ create_table "note_annotations", :force => true do |t|
107
+ t.integer "note_id"
108
+ t.string "predicate", :limit => 50
109
+ t.string "value", :limit => 1024
110
+ t.datetime "created_at"
111
+ t.datetime "updated_at"
112
+ t.string "namespace", :limit => 50
113
+ end
114
+
115
+ add_index "note_annotations", ["note_id"], :name => "ix_note_annotations_fk"
116
+
117
+ create_table "notes", :force => true do |t|
118
+ t.string "language", :limit => 2
119
+ t.string "value", :limit => 4000
120
+ t.string "type", :limit => 50
121
+ t.datetime "created_at"
122
+ t.datetime "updated_at"
123
+ t.integer "owner_id"
124
+ t.string "owner_type", :null => false
125
+ end
126
+
127
+ add_index "notes", ["language"], :name => "ix_notes_on_language"
128
+ add_index "notes", ["owner_id", "owner_type", "type"], :name => "ix_notes_fk_type"
129
+ add_index "notes", ["type"], :name => "ix_notes_on_type"
130
+
131
+ create_table "users", :force => true do |t|
132
+ t.string "forename"
133
+ t.string "surname"
134
+ t.string "email"
135
+ t.string "crypted_password"
136
+ t.boolean "active"
137
+ t.datetime "created_at"
138
+ t.datetime "updated_at"
139
+ t.string "password_salt"
140
+ t.string "persistence_token"
141
+ t.string "perishable_token"
142
+ t.string "role"
143
+ t.string "telephone_number"
144
+ end
145
+
146
+ end
data/db/seeds.rb ADDED
File without changes
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "iqvoc/skosxl/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "iqvoc_skosxl"
7
+ s.version = Iqvoc::SKOSXL::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Robert Glaser", "Till Schulte-Coerne", "Frederik Dohr"]
10
+ s.email = ["till.schulte-coerne@innoq.com"]
11
+ s.homepage = "http://innoq.com"
12
+ s.summary = "iQvoc SKOS-XL extension"
13
+ s.description = ""
14
+
15
+ s.add_dependency "iqvoc"
16
+ s.add_dependency "bundler"
17
+
18
+ s.files = %w(README.md Gemfile Gemfile.lock Rakefile iqvoc_skosxl.gemspec) + Dir.glob("{app,config,db,public,lib,test}/**/*")
19
+ s.test_files = Dir.glob("{test}/**/*")
20
+ s.executables = Dir.glob("{bin}/**/*")
21
+ s.require_paths = ["lib"]
22
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: UTF-8
2
+
3
+ namespace :iqvoc_skosxl do
4
+ namespace :db do
5
+
6
+ desc "Migrate the database through scripts in db/migrate and update db/schema.rb by invoking db:schema:dump. Target specific version with VERSION=x. Turn off output with VERBOSE=false."
7
+ task :migrate => :environment do
8
+ ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
9
+ ActiveRecord::Migrator.migrate(Iqvoc::SKOSXL::Engine.find_root_with_flag("db").join('db/migrate'), ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
10
+ Rake::Task["db:schema:dump"].invoke if ActiveRecord::Base.schema_format == :ruby
11
+ end
12
+
13
+ desc "Load seeds (task is idempotent)"
14
+ task :seed => :environment do
15
+ Iqvoc::SKOSXL::Engine.load_seed
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,5 @@
1
+ module Iqvoc
2
+ module SKOSXL
3
+ VERSION = "1.1.4"
4
+ end
5
+ end
@@ -0,0 +1,60 @@
1
+ module Iqvoc
2
+
3
+ module XLLabel # This are the settings when using SKOSXL
4
+
5
+ Iqvoc.first_level_class_configuration_modules << self
6
+
7
+ mattr_accessor :base_class_name,
8
+ :note_class_names,
9
+ :relation_class_names,
10
+ :additional_association_class_names,
11
+ :view_sections,
12
+ :has_additional_base_data,
13
+ :searchable_class_names
14
+
15
+ self.base_class_name = 'Label::SKOSXL::Base'
16
+
17
+ self.relation_class_names = ['Label::Relation::SKOSXL::Base']
18
+
19
+ self.note_class_names = Iqvoc::Concept.note_class_names
20
+
21
+ self.additional_association_class_names = {}
22
+
23
+ self.view_sections = ["main", "concepts", "relations", "notes"]
24
+
25
+ # Set this to true if you're having a migration which extends the labels table
26
+ # and you want to be able to edit these fields.
27
+ # This is done by:
28
+ # render :partial => 'partials/label/additional_base_data'
29
+ # You'll have to define this partial
30
+ # FIXME: This wouldn't be necessary if there would be an empty partial in
31
+ # iqvoc and the view loading sequence would be correct.
32
+ self.has_additional_base_data = false
33
+
34
+ # Do not use the following method in models. This will propably cause a
35
+ # loading loop (something like "expected file xyz to load ...")
36
+ def self.base_class
37
+ base_class_name.constantize
38
+ end
39
+
40
+ def self.relation_classes
41
+ relation_class_names.map(&:constantize)
42
+ end
43
+
44
+ def self.note_classes
45
+ note_class_names.map(&:constantize)
46
+ end
47
+
48
+ def self.change_note_class
49
+ change_note_class_name.constantize
50
+ end
51
+
52
+ def self.additional_association_classes
53
+ additional_association_class_names.keys.each_with_object({}) do |class_name, hash|
54
+ hash[class_name.constantize] = additional_association_class_names[class_name]
55
+ end
56
+ end
57
+
58
+ end
59
+
60
+ end
@@ -0,0 +1,22 @@
1
+ module IqvocSKOSXL
2
+
3
+ require File.join(File.dirname(__FILE__), '../config/engine') unless Iqvoc.const_defined?(:SKOSXL) && Iqvoc::SKOSXL.const_defined?(:Application)
4
+
5
+ ActiveSupport.on_load(:after_iqvoc_config) do
6
+ require('iqvoc')
7
+
8
+ Iqvoc.rdf_namespaces[:skosxl] = "http://www.w3.org/2008/05/skos-xl#" unless Iqvoc.rdf_namespaces[:skosxl]
9
+
10
+ Iqvoc.default_rdf_namespace_helper_methods << :iqvoc_skosxl_default_rdf_namespaces
11
+
12
+ Iqvoc::Concept.include_module_names << "Concept::SKOSXL::Extension"
13
+
14
+ Iqvoc::Concept.pref_labeling_class_name = 'Labeling::SKOSXL::PrefLabel'
15
+ Iqvoc::Concept.further_labeling_class_names = {
16
+ 'Labeling::SKOSXL::AltLabel' => [ :de, :en ]
17
+ }
18
+
19
+ # TODO Iqvoc.searchable_class_names = Iqvoc::Concept.labeling_class_names.keys + Iqvoc::Concept.note_class_names
20
+ end
21
+
22
+ end
data/test/factories.rb ADDED
@@ -0,0 +1,23 @@
1
+ FactoryGirl.define do
2
+
3
+ factory :xllabel, :class => Iqvoc::XLLabel.base_class do |l|
4
+ l.origin 'Forest'
5
+ l.language 'en'
6
+ l.value 'Forest'
7
+ l.published_at 3.days.ago
8
+ end
9
+
10
+ factory :xllabel_with_association, :parent => :xllabel do |l|
11
+ end
12
+
13
+ factory :user do |u|
14
+ u.forename 'Test'
15
+ u.surname 'User'
16
+ u.email 'testuser@iqvoc.local'
17
+ u.password 'omgomgomg'
18
+ u.password_confirmation 'omgomgomg'
19
+ u.role 'reader'
20
+ u.active true
21
+ end
22
+
23
+ end
@@ -0,0 +1,95 @@
1
+ # encoding: UTF-8
2
+
3
+ # Copyright 2011 innoQ Deutschland GmbH
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ require 'integration_test_helper'
18
+
19
+ class ConceptLabelLanguageTest < ActionDispatch::IntegrationTest
20
+
21
+ setup do
22
+ # create a few XL labels
23
+ @labels = {}
24
+ {
25
+ "English" => "en",
26
+ "Deutsch" => "de"
27
+ }.each { |name, lang|
28
+ @labels[name] = FactoryGirl.create(:xllabel, :origin => "_#{name}",
29
+ :language => lang, :value => name, :published_at => Time.now)
30
+ }
31
+ end
32
+
33
+ test "invalid alt label languages are rejected" do
34
+ login("administrator")
35
+
36
+ visit new_concept_path(:lang => "de", :format => "html")
37
+ # NB: label language does not match relation language
38
+ fill_in "labeling_skosxl_alt_labels_en",
39
+ :with => "#{@labels["Deutsch"].origin},"
40
+ click_button "Speichern"
41
+
42
+ assert page.has_css?(".flash_error")
43
+ assert page.has_css?("#concept_new")
44
+ assert page.source.include?( # XXX: page.has_content? didn't work
45
+ I18n.t("txt.controllers.versioned_concept.label_error") % "Deutsch")
46
+
47
+ # ensure concept was not saved
48
+ visit dashboard_path(:lang => "de", :format => "html")
49
+ assert page.has_no_css?("td")
50
+ end
51
+
52
+ test "invalid pref label languages are rejected during creation" do
53
+ login("administrator")
54
+
55
+ visit new_concept_path(:lang => "de", :format => "html")
56
+ # NB: label language does not match relation language
57
+ fill_in "labeling_skosxl_pref_labels_en",
58
+ :with => "#{@labels["Deutsch"].origin},"
59
+ click_button "Speichern"
60
+
61
+ assert page.has_css?(".flash_error")
62
+ assert page.has_css?("#concept_new")
63
+ assert page.source.include?( # XXX: page.has_content? didn't work
64
+ I18n.t("txt.controllers.versioned_concept.label_error") % "Deutsch")
65
+
66
+ # ensure concept was not saved
67
+ visit dashboard_path(:lang => "de", :format => "html")
68
+ assert page.has_no_css?("td")
69
+ end
70
+
71
+ test "invalid label languages are rejected during update" do
72
+ login("administrator")
73
+
74
+ # create, then edit concept
75
+ visit new_concept_path(:lang => "de", :format => "html")
76
+ click_button "Speichern"
77
+ visit dashboard_path(:lang => "de", :format => "html")
78
+ page.find("td a").click
79
+ page.click_link_or_button "In Bearbeitung versetzen"
80
+
81
+ # NB: label languages do not match relation languages
82
+ fill_in "labeling_skosxl_pref_labels_en",
83
+ :with => "#{@labels["Deutsch"].origin},"
84
+ fill_in "labeling_skosxl_alt_labels_de",
85
+ :with => "#{@labels["English"].origin},"
86
+ click_button "Speichern"
87
+
88
+ assert page.has_css?(".flash_error")
89
+ assert page.has_css?("#concept_edit")
90
+ assert page.source.include?( # XXX: page.has_content? didn't work
91
+ I18n.t("txt.controllers.versioned_concept.label_error") % "English")
92
+ assert page.source.include?( # XXX: page.has_content? didn't work
93
+ I18n.t("txt.controllers.versioned_concept.label_error") % "Deutsch")
94
+ end
95
+ end