mods_display 0.6.0 → 0.9.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 +4 -4
- data/.github/workflows/ruby.yml +24 -0
- data/lib/mods_display.rb +11 -0
- data/lib/mods_display/fields/access_condition.rb +72 -15
- data/lib/mods_display/fields/imprint.rb +16 -0
- data/lib/mods_display/helpers/record_helper.rb +131 -0
- data/lib/mods_display/html.rb +3 -1
- data/lib/mods_display/railtie.rb +10 -0
- data/lib/mods_display/version.rb +1 -1
- data/mods_display.gemspec +2 -0
- data/spec/fake_app.rb +18 -0
- data/spec/fields/access_condition_spec.rb +16 -25
- data/spec/fields/imprint_spec.rb +18 -0
- data/spec/fixtures/access_condition_fixtures.rb +8 -0
- data/spec/fixtures/imprint_fixtures.rb +11 -0
- data/spec/helpers/record_helper_spec.rb +241 -0
- data/spec/integration/html_spec.rb +5 -0
- data/spec/spec_helper.rb +6 -0
- metadata +41 -8
- data/.travis.yml +0 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 04b5809a32a151c63f3c9423f8917046060c12ed6a88a64e30b018f89256f144
|
4
|
+
data.tar.gz: a2104c15cdec18e265fd19349fece71736a2e92f2c0bceb8288d7977a4ffa2a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f4505c49261d1a76e3f1ba8da36fce97a396c5a680de93ac61293d45aefde35716463172e0e92c29e90cbef2a8ed11b65ef9fa2787028e6f8be36f31dadf582
|
7
|
+
data.tar.gz: afbf6a24b41cdc0c097f66b7ff7173501cfd1de626c1ed850e54c6e85319edd4af4484b46612e7828622b78469536ce8d859a8e1068bacb2461ac4d2c8385b25
|
@@ -0,0 +1,24 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches: [ master ]
|
6
|
+
pull_request:
|
7
|
+
branches: [ master ]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
tests:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
strategy:
|
13
|
+
matrix:
|
14
|
+
ruby: [2.6, 2.7, 3.0]
|
15
|
+
steps:
|
16
|
+
- uses: actions/checkout@v2
|
17
|
+
- name: Set up Ruby
|
18
|
+
uses: ruby/setup-ruby@v1
|
19
|
+
with:
|
20
|
+
ruby-version: ${{ matrix.ruby }}
|
21
|
+
- name: Install dependencies
|
22
|
+
run: bundle install
|
23
|
+
- name: Run tests
|
24
|
+
run: bundle exec rake
|
data/lib/mods_display.rb
CHANGED
@@ -49,3 +49,14 @@ require 'i18n/backend/fallbacks'
|
|
49
49
|
I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
|
50
50
|
I18n.load_path += Dir["#{File.expand_path('../..', __FILE__)}/config/locales/*.yml"]
|
51
51
|
I18n.backend.load_translations
|
52
|
+
|
53
|
+
# load Rails/Railtie
|
54
|
+
begin
|
55
|
+
require 'rails'
|
56
|
+
rescue LoadError
|
57
|
+
#do nothing
|
58
|
+
end
|
59
|
+
|
60
|
+
if defined? ::Rails::Railtie
|
61
|
+
require 'mods_display/railtie'
|
62
|
+
end
|
@@ -1,5 +1,53 @@
|
|
1
1
|
module ModsDisplay
|
2
2
|
class AccessCondition < Field
|
3
|
+
LICENSES = {
|
4
|
+
'cc-none' => { desc: '' },
|
5
|
+
'cc-by' => {
|
6
|
+
link: 'http://creativecommons.org/licenses/by/3.0/',
|
7
|
+
desc: 'This work is licensed under a Creative Commons Attribution 3.0 Unported License'
|
8
|
+
},
|
9
|
+
'cc-by-sa' => {
|
10
|
+
link: 'http://creativecommons.org/licenses/by-sa/3.0/',
|
11
|
+
desc: 'This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License'
|
12
|
+
},
|
13
|
+
'cc-by-nd' => {
|
14
|
+
link: 'http://creativecommons.org/licenses/by-nd/3.0/',
|
15
|
+
desc: 'This work is licensed under a Creative Commons Attribution-No Derivative Works 3.0 Unported License'
|
16
|
+
},
|
17
|
+
'cc-by-nc' => {
|
18
|
+
link: 'http://creativecommons.org/licenses/by-nc/3.0/',
|
19
|
+
desc: 'This work is licensed under a Creative Commons Attribution-Noncommercial 3.0 Unported License'
|
20
|
+
},
|
21
|
+
'cc-by-nc-sa' => {
|
22
|
+
link: 'http://creativecommons.org/licenses/by-nc-sa/3.0/',
|
23
|
+
desc: 'This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License'
|
24
|
+
},
|
25
|
+
'cc-by-nc-nd' => {
|
26
|
+
link: 'http://creativecommons.org/licenses/by-nc-nd/3.0/',
|
27
|
+
desc: 'This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 Unported License'
|
28
|
+
},
|
29
|
+
'cc-pdm' => {
|
30
|
+
link: 'http://creativecommons.org/publicdomain/mark/1.0/',
|
31
|
+
desc: 'This work is in the public domain per Creative Commons Public Domain Mark 1.0'
|
32
|
+
},
|
33
|
+
'odc-odc-pddl' => {
|
34
|
+
link: 'http://opendatacommons.org/licenses/pddl/',
|
35
|
+
desc: 'This work is licensed under a Open Data Commons Public Domain Dedication and License (PDDL)'
|
36
|
+
},
|
37
|
+
'odc-pddl' => {
|
38
|
+
link: 'http://opendatacommons.org/licenses/pddl/',
|
39
|
+
desc: 'This work is licensed under a Open Data Commons Public Domain Dedication and License (PDDL)'
|
40
|
+
},
|
41
|
+
'odc-odc-by' => {
|
42
|
+
link: 'http://opendatacommons.org/licenses/by/',
|
43
|
+
desc: 'This work is licensed under a Open Data Commons Attribution License'
|
44
|
+
},
|
45
|
+
'odc-odc-odbl' => {
|
46
|
+
link: 'http://opendatacommons.org/licenses/odbl/',
|
47
|
+
desc: 'This work is licensed under a Open Data Commons Open Database License (ODbL)'
|
48
|
+
}
|
49
|
+
}.freeze
|
50
|
+
|
3
51
|
def fields
|
4
52
|
return_fields = @values.map do |value|
|
5
53
|
ModsDisplay::Values.new(
|
@@ -28,26 +76,35 @@ module ModsDisplay
|
|
28
76
|
end
|
29
77
|
|
30
78
|
def license_statement(element)
|
31
|
-
element.text
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
79
|
+
matches = element.text.match(/^(?<code>.*) (?<type>.*):(?<description>.*)$/)
|
80
|
+
|
81
|
+
return "<div>#{element.text}</div>" unless matches
|
82
|
+
|
83
|
+
code = matches[:code].downcase
|
84
|
+
type = matches[:type].downcase
|
85
|
+
description = license_description(code, type) || matches[:description]
|
86
|
+
url = license_url(code, type)
|
87
|
+
output = "<div class='#{code}-#{type}'>"
|
88
|
+
output << if url
|
89
|
+
"<a href='#{url}'>#{description}</a>"
|
90
|
+
else
|
91
|
+
description
|
92
|
+
end
|
39
93
|
output << '</div>'
|
40
94
|
end
|
41
95
|
|
42
|
-
def
|
43
|
-
|
44
|
-
|
96
|
+
def license_url(code, type)
|
97
|
+
key = "#{code}-#{type}"
|
98
|
+
return unless LICENSES.key?(key)
|
99
|
+
|
100
|
+
LICENSES[key][:link]
|
45
101
|
end
|
46
102
|
|
47
|
-
def
|
48
|
-
|
49
|
-
return unless
|
50
|
-
|
103
|
+
def license_description(code, type)
|
104
|
+
key = "#{code}-#{type}"
|
105
|
+
return unless LICENSES.key?(key) && LICENSES[key][:desc]
|
106
|
+
|
107
|
+
LICENSES[key][:desc]
|
51
108
|
end
|
52
109
|
|
53
110
|
def access_label(element)
|
@@ -68,6 +68,8 @@ module ModsDisplay
|
|
68
68
|
date_fields.map do |date_field|
|
69
69
|
if date_is_w3cdtf?(date_field)
|
70
70
|
process_w3cdtf_date(date_field)
|
71
|
+
elsif date_is_iso8601?(date_field)
|
72
|
+
process_iso8601_date(date_field)
|
71
73
|
else
|
72
74
|
date_field
|
73
75
|
end
|
@@ -158,6 +160,10 @@ module ModsDisplay
|
|
158
160
|
field_is_encoded?(date_field, 'w3cdtf')
|
159
161
|
end
|
160
162
|
|
163
|
+
def date_is_iso8601?(date_field)
|
164
|
+
field_is_encoded?(date_field, 'iso8601')
|
165
|
+
end
|
166
|
+
|
161
167
|
def process_w3cdtf_date(date_field)
|
162
168
|
date_field = date_field.clone
|
163
169
|
date_field.content = begin
|
@@ -174,6 +180,16 @@ module ModsDisplay
|
|
174
180
|
date_field
|
175
181
|
end
|
176
182
|
|
183
|
+
def process_iso8601_date(date_field)
|
184
|
+
date_field = date_field.clone
|
185
|
+
date_field.content = begin
|
186
|
+
Date.iso8601(date_field.text).strftime(@config.full_date_format)
|
187
|
+
rescue
|
188
|
+
date_field.content
|
189
|
+
end
|
190
|
+
date_field
|
191
|
+
end
|
192
|
+
|
177
193
|
def dedup_dates(date_fields)
|
178
194
|
date_text = date_fields.map { |d| normalize_date(d.text) }
|
179
195
|
if date_text != date_text.uniq
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ModsDisplay
|
4
|
+
module Helpers
|
5
|
+
module RecordHelper
|
6
|
+
def display_content_field(field)
|
7
|
+
return unless field.respond_to?(:label, :values) && field.values.any?(&:present?)
|
8
|
+
|
9
|
+
display_content_label(field.label) + display_content_values(field.values)
|
10
|
+
end
|
11
|
+
|
12
|
+
def display_content_label(label)
|
13
|
+
content_tag :dt, label
|
14
|
+
end
|
15
|
+
|
16
|
+
def display_content_values(values)
|
17
|
+
values.map do |value|
|
18
|
+
content_tag :dd, value
|
19
|
+
end.join('').html_safe
|
20
|
+
end
|
21
|
+
|
22
|
+
def mods_display_label(label)
|
23
|
+
content_tag(:dt, label.delete(':')) + "\n".html_safe
|
24
|
+
end
|
25
|
+
|
26
|
+
def mods_display_content(values, delimiter = nil)
|
27
|
+
if delimiter
|
28
|
+
content_tag(:dd, values.map do |value|
|
29
|
+
link_urls_and_email(value) if value.present?
|
30
|
+
end.compact.join(delimiter).html_safe)
|
31
|
+
else
|
32
|
+
Array[values].flatten.map do |value|
|
33
|
+
content_tag(:dd, link_urls_and_email(value.to_s).html_safe) if value.present?
|
34
|
+
end.join.html_safe
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def mods_record_field(field, delimiter = nil)
|
39
|
+
return unless field.respond_to?(:label, :values) && field.values.any?(&:present?)
|
40
|
+
|
41
|
+
mods_display_label(field.label) + mods_display_content(field.values, delimiter)
|
42
|
+
end
|
43
|
+
|
44
|
+
def mods_name_field(field, &block)
|
45
|
+
return unless field.respond_to?(:label, :values) && field.values.any?(&:present?)
|
46
|
+
|
47
|
+
mods_display_label(field.label) + mods_display_name(field.values, &block)
|
48
|
+
end
|
49
|
+
|
50
|
+
def mods_display_name(names, &block)
|
51
|
+
names.map do |name|
|
52
|
+
content_tag(:dd) do
|
53
|
+
block_given? ? yield(name.name) : name.name
|
54
|
+
end
|
55
|
+
end.join.html_safe
|
56
|
+
end
|
57
|
+
|
58
|
+
# We need this to remove the ending ":" from the role labels only in data from
|
59
|
+
# mods_display
|
60
|
+
def sanitize_mods_name_label(label)
|
61
|
+
label.sub(/:$/, '')
|
62
|
+
end
|
63
|
+
|
64
|
+
def mods_subject_field(subject, &block)
|
65
|
+
return unless subject.values.any?(&:present?)
|
66
|
+
|
67
|
+
fields = subject.values.map do |subject_line|
|
68
|
+
content_tag :dd, safe_join(link_mods_subjects(subject_line, &block), ' > ')
|
69
|
+
end
|
70
|
+
|
71
|
+
(mods_display_label(subject.label) + safe_join(fields))
|
72
|
+
end
|
73
|
+
|
74
|
+
def mods_genre_field(genre, &block)
|
75
|
+
return unless genre.values.any?(&:present?)
|
76
|
+
|
77
|
+
fields = genre.values.map do |genre_line|
|
78
|
+
content_tag :dd, link_mods_genres(genre_line, &block)
|
79
|
+
end
|
80
|
+
|
81
|
+
mods_display_label(genre.label) + safe_join(fields)
|
82
|
+
end
|
83
|
+
|
84
|
+
def link_mods_genres(genre, &block)
|
85
|
+
link_buffer = []
|
86
|
+
link_to_mods_subject(genre, link_buffer, &block)
|
87
|
+
end
|
88
|
+
|
89
|
+
def link_mods_subjects(subjects, &block)
|
90
|
+
link_buffer = []
|
91
|
+
linked_subjects = []
|
92
|
+
subjects.each do |subject|
|
93
|
+
if subject.present?
|
94
|
+
linked_subjects << link_to_mods_subject(subject, link_buffer, &block)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
linked_subjects
|
98
|
+
end
|
99
|
+
|
100
|
+
def link_to_mods_subject(subject, buffer, &block)
|
101
|
+
subject_text = subject.respond_to?(:name) ? subject.name : subject
|
102
|
+
link = block_given? ? yield(subject_text, buffer) : subject_text
|
103
|
+
buffer << subject_text.strip
|
104
|
+
link << " (#{subject.roles.join(', ')})" if subject.respond_to?(:roles) && subject.roles.present?
|
105
|
+
link
|
106
|
+
end
|
107
|
+
|
108
|
+
# rubocop:disable Layout/LineLength
|
109
|
+
def link_urls_and_email(val)
|
110
|
+
val = val.dup
|
111
|
+
# http://daringfireball.net/2010/07/improved_regex_for_matching_urls
|
112
|
+
url = %r{(?i)\b(?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\([^\s()<>]+|\([^\s()<>]+\)*\))+(?:\([^\s()<>]+|\([^\s()<>]+\)*\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])}i
|
113
|
+
# http://www.regular-expressions.info/email.html
|
114
|
+
email = %r{[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+(?:[A-Z]{2}|com|org|net|edu|gov|mil|biz|info|mobi|name|aero|asia|jobs|museum)\b}i
|
115
|
+
matches = [val.scan(url), val.scan(email)].flatten.uniq
|
116
|
+
unless val =~ /<a/ # we'll assume that linking has alraedy occured and we don't want to double link
|
117
|
+
matches.each do |match|
|
118
|
+
if match =~ email
|
119
|
+
val.gsub!(match, "<a href='mailto:#{match}'>#{match}</a>")
|
120
|
+
else
|
121
|
+
val.gsub!(match, "<a href='#{match}'>#{match}</a>")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
val
|
126
|
+
end
|
127
|
+
# rubocop:enable Layout/LineLength
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
data/lib/mods_display/html.rb
CHANGED
@@ -41,7 +41,9 @@ module ModsDisplay
|
|
41
41
|
if to_s.respond_to?(method_name)
|
42
42
|
to_html.send(method_name, *args, &block)
|
43
43
|
elsif method_name == :subTitle || mods_display_fields.include?(method_name)
|
44
|
-
mods_field(@xml, method_name)
|
44
|
+
field = mods_field(@xml, method_name)
|
45
|
+
return field if (args.dig(0, :raw))
|
46
|
+
field.fields
|
45
47
|
else
|
46
48
|
super
|
47
49
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ModsDisplay
|
4
|
+
class Railtie < ::Rails::Railtie
|
5
|
+
ActiveSupport.on_load :action_view do
|
6
|
+
require 'mods_display/helpers/record_helper'
|
7
|
+
::ActionView::Base.send :include, ModsDisplay::Helpers::RecordHelper
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
data/lib/mods_display/version.rb
CHANGED
data/mods_display.gemspec
CHANGED
@@ -22,7 +22,9 @@ Gem::Specification.new do |gem|
|
|
22
22
|
|
23
23
|
gem.add_development_dependency 'rake'
|
24
24
|
gem.add_development_dependency 'rspec', '~> 3.0'
|
25
|
+
gem.add_development_dependency 'rspec-rails'
|
25
26
|
gem.add_development_dependency 'rubocop'
|
26
27
|
gem.add_development_dependency 'capybara'
|
27
28
|
gem.add_development_dependency 'byebug'
|
29
|
+
gem.add_development_dependency 'rails', '~> 6.0'
|
28
30
|
end
|
data/spec/fake_app.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'action_controller/railtie'
|
4
|
+
require 'action_view/railtie'
|
5
|
+
|
6
|
+
class ModsDisplayTestApp < Rails::Application
|
7
|
+
end
|
8
|
+
|
9
|
+
Rails.application.routes.draw do
|
10
|
+
resources 'searches', only: :index
|
11
|
+
end
|
12
|
+
|
13
|
+
class ApplicationController < ActionController::Base; end
|
14
|
+
class SearchesController < ApplicationController
|
15
|
+
def index; end
|
16
|
+
end
|
17
|
+
|
18
|
+
Object.const_set(:ApplicationHelper, Module.new)
|
@@ -8,14 +8,6 @@ def mods_display_access_condition(mods_record)
|
|
8
8
|
)
|
9
9
|
end
|
10
10
|
|
11
|
-
def mods_display_versioned_access_condition(mods_record, version)
|
12
|
-
ModsDisplay::AccessCondition.new(
|
13
|
-
mods_record,
|
14
|
-
ModsDisplay::Configuration::AccessCondition.new { cc_license_version version },
|
15
|
-
double('controller')
|
16
|
-
)
|
17
|
-
end
|
18
|
-
|
19
11
|
def mods_display_non_ignore_access_condition(mods_record)
|
20
12
|
ModsDisplay::AccessCondition.new(
|
21
13
|
mods_record,
|
@@ -33,6 +25,7 @@ describe ModsDisplay::AccessCondition do
|
|
33
25
|
@cc_license_note = Stanford::Mods::Record.new.from_str(cc_license_fixture, false).accessCondition
|
34
26
|
@odc_license_note = Stanford::Mods::Record.new.from_str(odc_license_fixture, false).accessCondition
|
35
27
|
@no_link_license_note = Stanford::Mods::Record.new.from_str(no_license_fixture, false).accessCondition
|
28
|
+
@garbage_license_fixture = Stanford::Mods::Record.new.from_str(garbage_license_fixture, false).accessCondition
|
36
29
|
end
|
37
30
|
describe 'labels' do
|
38
31
|
it 'should normalize types and assign proper labels' do
|
@@ -62,37 +55,25 @@ describe ModsDisplay::AccessCondition do
|
|
62
55
|
expect(fields.first.values.length).to eq(1)
|
63
56
|
expect(fields.first.values.first).to match(%r{^<div class='unknown-something'>.*</div>$})
|
64
57
|
end
|
65
|
-
it 'should
|
58
|
+
it 'should identify and link CreativeCommons licenses properly' do
|
66
59
|
fields = mods_display_access_condition(@cc_license_note).fields
|
67
60
|
expect(fields.length).to eq(1)
|
68
61
|
expect(fields.first.values.length).to eq(1)
|
69
62
|
expect(fields.first.values.first).to include("<a href='http://creativecommons.org/licenses/by-sa/3.0/'>")
|
70
63
|
expect(fields.first.values.first).to include(
|
71
|
-
'This work is licensed under a Creative Commons Attribution-
|
64
|
+
'This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License'
|
72
65
|
)
|
73
66
|
end
|
74
|
-
it 'should
|
67
|
+
it 'should identify and link OpenDataCommons licenses properly' do
|
75
68
|
fields = mods_display_access_condition(@odc_license_note).fields
|
76
69
|
expect(fields.length).to eq(1)
|
77
70
|
expect(fields.first.values.length).to eq(1)
|
78
|
-
expect(fields.first.values.first).to include("<a href='http://opendatacommons.org/licenses/pddl'>")
|
71
|
+
expect(fields.first.values.first).to include("<a href='http://opendatacommons.org/licenses/pddl/'>")
|
79
72
|
expect(fields.first.values.first).to include(
|
80
73
|
'This work is licensed under a Open Data Commons Public Domain Dedication and License (PDDL)'
|
81
74
|
)
|
82
75
|
end
|
83
|
-
|
84
|
-
fields = mods_display_versioned_access_condition(@cc_license_note, '4.0').fields
|
85
|
-
expect(fields.length).to eq(1)
|
86
|
-
expect(fields.first.values.length).to eq(1)
|
87
|
-
expect(fields.first.values.first).to include('http://creativecommons.org/licenses/by-sa/4.0/')
|
88
|
-
expect(fields.first.values.first).not_to include('http://creativecommons.org/licenses/by-sa/3.0/')
|
89
|
-
end
|
90
|
-
it 'should not apply configured version to NON-CC licenses' do
|
91
|
-
fields = mods_display_versioned_access_condition(@odc_license_note, '4.0').fields
|
92
|
-
expect(fields.length).to eq(1)
|
93
|
-
expect(fields.first.values.length).to eq(1)
|
94
|
-
expect(fields.first.values.first).not_to include('/4.0/')
|
95
|
-
end
|
76
|
+
|
96
77
|
it 'should not attempt unknown license types' do
|
97
78
|
fields = mods_display_access_condition(@no_link_license_note).fields
|
98
79
|
expect(fields.length).to eq(1)
|
@@ -102,6 +83,16 @@ describe ModsDisplay::AccessCondition do
|
|
102
83
|
)
|
103
84
|
expect(fields.first.values.first).not_to include('<a.*>')
|
104
85
|
end
|
86
|
+
|
87
|
+
it 'returns the license text if it does not look like our expected format' do
|
88
|
+
fields = mods_display_access_condition(@garbage_license_fixture).fields
|
89
|
+
expect(fields.length).to eq(1)
|
90
|
+
expect(fields.first.values.length).to eq(1)
|
91
|
+
expect(fields.first.values.first).to include(
|
92
|
+
'Unknown garbage that does not look like a license'
|
93
|
+
)
|
94
|
+
expect(fields.first.values.first).not_to include('<a.*>')
|
95
|
+
end
|
105
96
|
end
|
106
97
|
end
|
107
98
|
describe 'to_html' do
|
data/spec/fields/imprint_spec.rb
CHANGED
@@ -43,6 +43,7 @@ describe ModsDisplay::Imprint do
|
|
43
43
|
@imprint_date_range = Stanford::Mods::Record.new.from_str(imprint_date_range, false).origin_info
|
44
44
|
@encoded_place = Stanford::Mods::Record.new.from_str(encoded_place, false).origin_info
|
45
45
|
@encoded_dates = Stanford::Mods::Record.new.from_str(encoded_dates, false).origin_info
|
46
|
+
@iso8601_encoded_dates = Stanford::Mods::Record.new.from_str(iso8601_encoded_dates, false).origin_info
|
46
47
|
@bad_dates = Stanford::Mods::Record.new.from_str(bad_dates, false).origin_info
|
47
48
|
@invalid_dates = Stanford::Mods::Record.new.from_str(invalid_dates, false).origin_info
|
48
49
|
@punctuation_imprint = Stanford::Mods::Record.new.from_str(punctuation_imprint_fixture, false).origin_info
|
@@ -209,6 +210,23 @@ describe ModsDisplay::Imprint do
|
|
209
210
|
end.values).to eq(['July (2013)'])
|
210
211
|
end
|
211
212
|
end
|
213
|
+
|
214
|
+
describe 'iso8601' do
|
215
|
+
it 'handles full dates properly' do
|
216
|
+
fields = mods_display_imprint(@iso8601_encoded_dates).fields
|
217
|
+
expect(fields.length).to eq(2)
|
218
|
+
expect(fields.find do |field|
|
219
|
+
field.label == 'Date created:'
|
220
|
+
end.values).to eq(['November 14, 2013'])
|
221
|
+
end
|
222
|
+
it "should not try to handle dates we can't parse" do
|
223
|
+
fields = mods_display_imprint(@iso8601_encoded_dates).fields
|
224
|
+
expect(fields.length).to eq(2)
|
225
|
+
expect(fields.find do |field|
|
226
|
+
field.label == 'Date modified:'
|
227
|
+
end.values).to eq(['Jul. 22, 2013'])
|
228
|
+
end
|
229
|
+
end
|
212
230
|
end
|
213
231
|
describe 'bad dates' do
|
214
232
|
it 'should ignore date values' do
|
@@ -280,6 +280,17 @@ module ImprintFixtures
|
|
280
280
|
MODS
|
281
281
|
end
|
282
282
|
|
283
|
+
def iso8601_encoded_dates
|
284
|
+
<<-MODS
|
285
|
+
<mods>
|
286
|
+
<originInfo>
|
287
|
+
<dateCreated encoding="iso8601">20131114161429</dateCreated>
|
288
|
+
<dateModified encoding="iso8601">Jul. 22, 2013</dateModified>
|
289
|
+
</originInfo>
|
290
|
+
</mods>
|
291
|
+
MODS
|
292
|
+
end
|
293
|
+
|
283
294
|
def bad_dates
|
284
295
|
<<-MODS
|
285
296
|
<mods>
|
@@ -0,0 +1,241 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'byebug'
|
5
|
+
|
6
|
+
describe ModsDisplay::Helpers::RecordHelper, type: :helper do
|
7
|
+
let(:empty_field) { OpenStruct.new(label: 'test', values: ['']) }
|
8
|
+
|
9
|
+
describe 'display_content_field' do
|
10
|
+
let(:values) { ['guitar (1)', 'solo cowbell, trombone (2)'] }
|
11
|
+
let(:content) { OpenStruct.new(label: 'Instrumentation', values: values) }
|
12
|
+
|
13
|
+
it 'should return dt with label and dd with values' do
|
14
|
+
expect(helper.display_content_field(content)).to have_css('dt', text: 'Instrumentation')
|
15
|
+
expect(helper.display_content_field(content)).to have_css('dd', count: 2)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe 'display_content_label' do
|
20
|
+
it 'should return correct dt' do
|
21
|
+
expect(helper.display_content_label('test')).to have_css('dt', text: 'test')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe 'display_content_values' do
|
26
|
+
let(:values) { ['guitar (1)', 'solo cowbell, trombone (2)'] }
|
27
|
+
|
28
|
+
it 'should return dds of values' do
|
29
|
+
expect(helper.display_content_values(values)).to have_css('dd', count: 2)
|
30
|
+
expect(helper.display_content_values(values)).to have_css('dd', text: 'guitar (1)')
|
31
|
+
expect(helper.display_content_values(values)).to have_css('dd', text: 'solo cowbell, trombone (2)')
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'mods_display_label' do
|
36
|
+
it 'should return correct label' do
|
37
|
+
expect(helper.mods_display_label('test:')).not_to have_content ':'
|
38
|
+
expect(helper.mods_display_label('test:')).to have_css('dt', text: 'test')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'mods_display_content' do
|
43
|
+
it 'should return correct content' do
|
44
|
+
expect(helper.mods_display_content('hello, there')).to have_css('dd', text: 'hello, there')
|
45
|
+
end
|
46
|
+
it 'should return multiple dd elements when a multi-element array is passed' do
|
47
|
+
expect(helper.mods_display_content(%w(hello there))).to have_css('dd', count: 2)
|
48
|
+
end
|
49
|
+
it 'should handle nil values correctly' do
|
50
|
+
expect(helper.mods_display_content(['something', nil])).to have_css('dd', count: 1)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe 'mods_record_field' do
|
55
|
+
let(:mods_field) { OpenStruct.new(label: 'test', values: ['hello, there']) }
|
56
|
+
let(:url_field) { OpenStruct.new(label: 'test', values: ['https://library.stanford.edu']) }
|
57
|
+
let(:multi_values) { double(label: 'test', values: %w(123 321)) }
|
58
|
+
|
59
|
+
it 'should return correct content' do
|
60
|
+
expect(helper.mods_record_field(mods_field)).to have_css('dt', text: 'test')
|
61
|
+
expect(helper.mods_record_field(mods_field)).to have_css('dd', text: 'hello, there')
|
62
|
+
end
|
63
|
+
it 'should link fields with URLs' do
|
64
|
+
expect(mods_record_field(url_field)).to have_css("a[href='https://library.stanford.edu']", text: 'https://library.stanford.edu')
|
65
|
+
end
|
66
|
+
it 'should not print empty labels' do
|
67
|
+
expect(helper.mods_record_field(empty_field)).not_to be_present
|
68
|
+
end
|
69
|
+
it 'should join values with a <dd> by default' do
|
70
|
+
expect(helper.mods_record_field(multi_values)).to have_css('dd', count: 2)
|
71
|
+
end
|
72
|
+
it 'should join values with a supplied delimiter' do
|
73
|
+
expect(helper.mods_record_field(multi_values, 'DELIM')).to have_css('dd', count: 1)
|
74
|
+
expect(helper.mods_record_field(multi_values, 'DELIM')).to have_css('dd', text: '123DELIM321')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe 'names' do
|
79
|
+
let(:name_field) do
|
80
|
+
OpenStruct.new(
|
81
|
+
label: 'Contributor',
|
82
|
+
values: [
|
83
|
+
OpenStruct.new(name: 'Winefrey, Oprah', roles: %w(Host Producer)),
|
84
|
+
OpenStruct.new(name: 'Kittenz, Emergency')
|
85
|
+
]
|
86
|
+
)
|
87
|
+
end
|
88
|
+
|
89
|
+
describe '#mods_name_field' do
|
90
|
+
it 'should join the label and values' do
|
91
|
+
name = mods_name_field(name_field) do |name|
|
92
|
+
link_to(name, searches_path(q: "\"#{name}\"", search_field: 'search_author'))
|
93
|
+
end
|
94
|
+
expect(name).to match /<dt>Contributor<\/dt>/
|
95
|
+
expect(name).to match /<dd><a href.*<\/dd>/
|
96
|
+
end
|
97
|
+
it 'should not print empty labels' do
|
98
|
+
expect(mods_name_field(empty_field)).not_to be_present
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#mods_display_name' do
|
103
|
+
let(:name) do
|
104
|
+
mods_display_name(name_field.values) do |name|
|
105
|
+
link_to(name, searches_path(q: "\"#{name}\"", search_field: 'search_author'))
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
it 'should link to the name' do
|
110
|
+
expect(name).to match /<a href=.*%22Winefrey%2C\+Oprah%22.*>Winefrey, Oprah<\/a>/
|
111
|
+
expect(name).to match /<a href=.*%22Kittenz%2C\+Emergency%22.*>Kittenz, Emergency<\/a>/
|
112
|
+
end
|
113
|
+
it 'should link to an author search' do
|
114
|
+
expect(name).to match /<a href.*search_field=search_author.*>/
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe '#sanitize_mods_name_label' do
|
119
|
+
it 'removes a ":" at the end of label if present' do
|
120
|
+
expect(sanitize_mods_name_label('Test String:')).to eq 'Test String'
|
121
|
+
expect(sanitize_mods_name_label('Test String')).to eq 'Test String'
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
describe 'subjects' do
|
127
|
+
let(:subjects) { [OpenStruct.new(label: 'Subjects', values: [%w(Subject1a Subject1b), %w(Subject2a Subject2b Subject2c)])] }
|
128
|
+
let(:name_subjects) { [OpenStruct.new(label: 'Subjects', values: [OpenStruct.new(name: 'Person Name', roles: %w(Role1 Role2))])] }
|
129
|
+
let(:genres) { [OpenStruct.new(label: 'Genres', values: %w(Genre1 Genre2 Genre3))] }
|
130
|
+
|
131
|
+
describe '#mods_subject_field' do
|
132
|
+
let(:subject) do
|
133
|
+
mods_subject_field(subjects.first) do |subject_text|
|
134
|
+
link_to(
|
135
|
+
subject_text,
|
136
|
+
searches_path(
|
137
|
+
q: "\"#{[[], subject_text.strip].flatten.join(' ')}\"",
|
138
|
+
search_field: 'subject_terms'
|
139
|
+
)
|
140
|
+
)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
it 'should join the subject fields in a dd' do
|
144
|
+
expect(subject).to match /<dd><a href=*.*\">Subject1a*.*Subject1b<\/a><\/dd><dd><a/
|
145
|
+
end
|
146
|
+
it "should join the individual subjects with a '>'" do
|
147
|
+
expect(subject).to match /Subject2b<\/a> > <a href/
|
148
|
+
end
|
149
|
+
it 'should not print empty labels' do
|
150
|
+
expect(mods_subject_field(empty_field)).not_to be_present
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe '#mods_genre_field' do
|
155
|
+
it 'should join the genre fields with a dd' do
|
156
|
+
expect(mods_genre_field(genres.first) do |text|
|
157
|
+
link_to(text, searches_path(q: text))
|
158
|
+
end).to match /<dd><a href=*.*>Genre1*.*<\/a><\/dd><dd><a*.*Genre2<\/a><\/dd>/
|
159
|
+
end
|
160
|
+
it 'should not print empty labels' do
|
161
|
+
expect(mods_genre_field(empty_field)).not_to be_present
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
describe '#link_mods_subjects' do
|
166
|
+
let(:linked_subjects) do
|
167
|
+
link_mods_subjects(subjects.first.values.last) do |subject_text, buffer|
|
168
|
+
link_to(
|
169
|
+
subject_text,
|
170
|
+
searches_path(
|
171
|
+
q: "\"#{[buffer, subject_text.strip].flatten.join(' ')}\"",
|
172
|
+
search_field: 'subject_terms'
|
173
|
+
)
|
174
|
+
)
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
it 'should return all subjects' do
|
179
|
+
expect(linked_subjects.length).to eq 3
|
180
|
+
end
|
181
|
+
it 'should link to the subject hierarchically' do
|
182
|
+
expect(linked_subjects[0]).to match /^<a href=.*q=%22Subject2a%22.*>Subject2a<\/a>$/
|
183
|
+
expect(linked_subjects[1]).to match /^<a href=.*q=%22Subject2a\+Subject2b%22.*>Subject2b<\/a>$/
|
184
|
+
expect(linked_subjects[2]).to match /^<a href=.*q=%22Subject2a\+Subject2b\+Subject2c%22.*>Subject2c<\/a>$/
|
185
|
+
end
|
186
|
+
it 'should link to subject terms search field' do
|
187
|
+
linked_subjects.each do |subject|
|
188
|
+
expect(subject).to match /search_field=subject_terms/
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe '#link_mods_genres' do
|
194
|
+
let(:linked_genres) do
|
195
|
+
link_mods_genres(genres.first.values.last) do |text|
|
196
|
+
link_to(
|
197
|
+
text,
|
198
|
+
searches_path(
|
199
|
+
q: "\"#{[[], text.strip].flatten.join(' ')}\"",
|
200
|
+
search_field: 'subject_terms'
|
201
|
+
)
|
202
|
+
)
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
it 'should return correct link' do
|
207
|
+
expect(linked_genres).to match /<a href=*.*Genre3*.*<\/a>/
|
208
|
+
end
|
209
|
+
it 'should link to subject terms search field' do
|
210
|
+
expect(linked_genres).to match /search_field=subject_terms/
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
describe '#link_to_mods_subject' do
|
215
|
+
it 'should handle subjects that behave like names' do
|
216
|
+
name_subject = link_to_mods_subject(name_subjects.first.values.first, []) do |subject_text|
|
217
|
+
link_to(
|
218
|
+
subject_text,
|
219
|
+
searches_path(
|
220
|
+
q: "\"#{[[], subject_text.strip].flatten.join(' ')}\"",
|
221
|
+
search_field: 'subject_terms'
|
222
|
+
)
|
223
|
+
)
|
224
|
+
end
|
225
|
+
expect(name_subject).to match /<a href=.*%22Person\+Name%22.*>Person Name<\/a> \(Role1, Role2\)/
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
describe '#link_urls_and_email' do
|
231
|
+
let(:url) { 'This is a field that contains an https://library.stanford.edu URL' }
|
232
|
+
let(:email) { 'This is a field that contains an email@email.com address' }
|
233
|
+
|
234
|
+
it 'should link URLs' do
|
235
|
+
expect(link_urls_and_email(url)).to eq "This is a field that contains an <a href='https://library.stanford.edu'>https://library.stanford.edu</a> URL"
|
236
|
+
end
|
237
|
+
it 'should link email addresses' do
|
238
|
+
expect(link_urls_and_email(email)).to eq "This is a field that contains an <a href='mailto:email@email.com'>email@email.com</a> address"
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
@@ -79,4 +79,9 @@ describe 'HTML Output' do
|
|
79
79
|
expect { @abstract.not_a_real_field }.to raise_error NoMethodError
|
80
80
|
end
|
81
81
|
end
|
82
|
+
describe 'individual fields' do
|
83
|
+
it 'should return ModsDispaly::Class when raw is specified' do
|
84
|
+
expect(@abstract.abstract(raw: true)).to be_a ModsDisplay::Abstract
|
85
|
+
end
|
86
|
+
end
|
82
87
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
|
+
ENV['RAILS_ENV'] ||= 'test'
|
1
2
|
require 'mods_display'
|
2
3
|
require 'stanford-mods'
|
3
4
|
require 'capybara'
|
5
|
+
require 'rails'
|
6
|
+
require 'fake_app'
|
7
|
+
require 'rspec/rails'
|
8
|
+
require 'mods_display/helpers/record_helper'
|
4
9
|
|
5
10
|
Dir["#{File.expand_path('..', __FILE__)}/fixtures/*.rb"].each { |file| require file }
|
6
11
|
# Load i18n test file.
|
@@ -24,6 +29,7 @@ RSpec.configure do |config|
|
|
24
29
|
# the seed, which is printed after each run.
|
25
30
|
# --seed 1234
|
26
31
|
config.order = 'random'
|
32
|
+
config.include Rails.application.routes.url_helpers
|
27
33
|
end
|
28
34
|
class TestModel
|
29
35
|
attr_accessor :modsxml
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mods_display
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jessie Keck
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-05-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: stanford-mods
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec-rails
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: rubocop
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +122,20 @@ dependencies:
|
|
108
122
|
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rails
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '6.0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '6.0'
|
111
139
|
description: MODS Display is a gem to centralize the display logic of MODS medadata.
|
112
140
|
email:
|
113
141
|
- jessie.keck@gmail.com
|
@@ -115,10 +143,10 @@ executables: []
|
|
115
143
|
extensions: []
|
116
144
|
extra_rdoc_files: []
|
117
145
|
files:
|
146
|
+
- ".github/workflows/ruby.yml"
|
118
147
|
- ".gitignore"
|
119
148
|
- ".rubocop.yml"
|
120
149
|
- ".rubocop_todo.yml"
|
121
|
-
- ".travis.yml"
|
122
150
|
- Gemfile
|
123
151
|
- LICENSE.txt
|
124
152
|
- README.md
|
@@ -163,14 +191,17 @@ files:
|
|
163
191
|
- lib/mods_display/fields/subject.rb
|
164
192
|
- lib/mods_display/fields/title.rb
|
165
193
|
- lib/mods_display/fields/values.rb
|
194
|
+
- lib/mods_display/helpers/record_helper.rb
|
166
195
|
- lib/mods_display/html.rb
|
167
196
|
- lib/mods_display/model_extension.rb
|
197
|
+
- lib/mods_display/railtie.rb
|
168
198
|
- lib/mods_display/related_item_concerns.rb
|
169
199
|
- lib/mods_display/relator_codes.rb
|
170
200
|
- lib/mods_display/version.rb
|
171
201
|
- mods_display.gemspec
|
172
202
|
- spec/configuration/access_condition_spec.rb
|
173
203
|
- spec/configuration/base_spec.rb
|
204
|
+
- spec/fake_app.rb
|
174
205
|
- spec/fields/abstract_spec.rb
|
175
206
|
- spec/fields/access_condition_spec.rb
|
176
207
|
- spec/fields/audience_spec.rb
|
@@ -203,6 +234,7 @@ files:
|
|
203
234
|
- spec/fixtures/related_item_fixtures.rb
|
204
235
|
- spec/fixtures/subjects_fixtures.rb
|
205
236
|
- spec/fixtures/title_fixtures.rb
|
237
|
+
- spec/helpers/record_helper_spec.rb
|
206
238
|
- spec/integration/configuration_spec.rb
|
207
239
|
- spec/integration/html_spec.rb
|
208
240
|
- spec/integration/installation_spec.rb
|
@@ -211,7 +243,7 @@ files:
|
|
211
243
|
homepage: https://github.com/sul-dlss/mods_display
|
212
244
|
licenses: []
|
213
245
|
metadata: {}
|
214
|
-
post_install_message:
|
246
|
+
post_install_message:
|
215
247
|
rdoc_options: []
|
216
248
|
require_paths:
|
217
249
|
- lib
|
@@ -226,9 +258,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
226
258
|
- !ruby/object:Gem::Version
|
227
259
|
version: '0'
|
228
260
|
requirements: []
|
229
|
-
|
230
|
-
|
231
|
-
signing_key:
|
261
|
+
rubygems_version: 3.2.3
|
262
|
+
signing_key:
|
232
263
|
specification_version: 4
|
233
264
|
summary: The MODS Display gem allows implementers to configure a customized display
|
234
265
|
of MODS metadata. This display implements the specifications defined at Stanford
|
@@ -236,6 +267,7 @@ summary: The MODS Display gem allows implementers to configure a customized disp
|
|
236
267
|
test_files:
|
237
268
|
- spec/configuration/access_condition_spec.rb
|
238
269
|
- spec/configuration/base_spec.rb
|
270
|
+
- spec/fake_app.rb
|
239
271
|
- spec/fields/abstract_spec.rb
|
240
272
|
- spec/fields/access_condition_spec.rb
|
241
273
|
- spec/fields/audience_spec.rb
|
@@ -268,6 +300,7 @@ test_files:
|
|
268
300
|
- spec/fixtures/related_item_fixtures.rb
|
269
301
|
- spec/fixtures/subjects_fixtures.rb
|
270
302
|
- spec/fixtures/title_fixtures.rb
|
303
|
+
- spec/helpers/record_helper_spec.rb
|
271
304
|
- spec/integration/configuration_spec.rb
|
272
305
|
- spec/integration/html_spec.rb
|
273
306
|
- spec/integration/installation_spec.rb
|