ddr-models 2.0.1 → 2.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +23 -17
  3. data/app/models/collection.rb +1 -35
  4. data/ddr-models.gemspec +2 -1
  5. data/lib/ddr/actions.rb +1 -0
  6. data/lib/ddr/actions/virus_check.rb +28 -0
  7. data/lib/ddr/auth.rb +4 -0
  8. data/lib/ddr/auth/ability_definitions/datastream_ability_definitions.rb +7 -5
  9. data/lib/ddr/auth/grouper_gateway.rb +9 -1
  10. data/lib/ddr/auth/permissions.rb +2 -1
  11. data/lib/ddr/auth/role_based_access_controls_enforcement.rb +5 -5
  12. data/lib/ddr/auth/roles/role_types.rb +2 -1
  13. data/lib/ddr/datastreams.rb +2 -2
  14. data/lib/ddr/datastreams/administrative_metadata_datastream.rb +27 -14
  15. data/lib/ddr/datastreams/datastream_behavior.rb +13 -0
  16. data/lib/ddr/datastreams/fits_datastream.rb +88 -0
  17. data/lib/ddr/derivatives/png_generator.rb +2 -0
  18. data/lib/ddr/derivatives/ptif_generator.rb +2 -0
  19. data/lib/ddr/events/fixity_check_event.rb +2 -2
  20. data/lib/ddr/events/virus_check_event.rb +2 -14
  21. data/lib/ddr/index.rb +29 -0
  22. data/lib/ddr/index/abstract_query_result.rb +23 -0
  23. data/lib/ddr/index/connection.rb +17 -0
  24. data/lib/ddr/index/csv_query_result.rb +61 -0
  25. data/lib/ddr/index/document_builder.rb +9 -0
  26. data/lib/ddr/index/field.rb +23 -0
  27. data/lib/ddr/index/fields.rb +83 -0
  28. data/lib/ddr/index/filter.rb +48 -0
  29. data/lib/ddr/index/filters.rb +19 -0
  30. data/lib/ddr/index/legacy_license_fields.rb +14 -0
  31. data/lib/ddr/index/query.rb +35 -0
  32. data/lib/ddr/index/query_builder.rb +74 -0
  33. data/lib/ddr/index/query_clause.rb +52 -0
  34. data/lib/ddr/index/query_result.rb +70 -0
  35. data/lib/ddr/index/query_value.rb +16 -0
  36. data/lib/ddr/index/response.rb +13 -0
  37. data/lib/ddr/index/unique_key_field.rb +12 -0
  38. data/lib/ddr/index_fields.rb +7 -53
  39. data/lib/ddr/jobs.rb +1 -1
  40. data/lib/ddr/jobs/fits_file_characterization.rb +51 -0
  41. data/lib/ddr/managers.rb +1 -0
  42. data/lib/ddr/managers/technical_metadata_manager.rb +104 -0
  43. data/lib/ddr/models.rb +39 -23
  44. data/lib/ddr/models/base.rb +0 -2
  45. data/lib/ddr/models/describable.rb +1 -1
  46. data/lib/ddr/models/effective_license.rb +9 -0
  47. data/lib/ddr/models/engine.rb +13 -0
  48. data/lib/ddr/models/file_management.rb +157 -160
  49. data/lib/ddr/models/governable.rb +0 -4
  50. data/lib/ddr/models/has_admin_metadata.rb +80 -72
  51. data/lib/ddr/models/has_children.rb +1 -1
  52. data/lib/ddr/models/has_content.rb +18 -0
  53. data/lib/ddr/models/has_struct_metadata.rb +5 -1
  54. data/lib/ddr/models/indexing.rb +32 -20
  55. data/lib/ddr/models/inherited_license.rb +13 -0
  56. data/lib/ddr/models/license.rb +38 -0
  57. data/lib/ddr/models/solr_document.rb +195 -211
  58. data/lib/ddr/models/version.rb +1 -1
  59. data/lib/ddr/models/year_facet.rb +154 -0
  60. data/lib/ddr/utils.rb +13 -1
  61. data/lib/ddr/vocab/roles.rb +0 -10
  62. data/spec/controllers/including_role_based_access_controls_enforcement_spec.rb +4 -4
  63. data/spec/datastreams/fits_datastream_spec.rb +84 -0
  64. data/spec/fixtures/fits/document.xml +65 -0
  65. data/spec/fixtures/fits/image.xml +59 -0
  66. data/spec/index/filter_spec.rb +47 -0
  67. data/spec/index/filters_spec.rb +17 -0
  68. data/spec/index/query_spec.rb +19 -0
  69. data/spec/jobs/fits_file_characterization_spec.rb +52 -0
  70. data/spec/managers/technical_metadata_manager_spec.rb +140 -0
  71. data/spec/models/active_fedora_datastream_spec.rb +44 -0
  72. data/spec/models/collection_spec.rb +7 -12
  73. data/spec/models/component_spec.rb +3 -6
  74. data/spec/models/effective_license_spec.rb +49 -0
  75. data/spec/models/has_admin_metadata_spec.rb +143 -194
  76. data/spec/models/has_struct_metadata_spec.rb +2 -2
  77. data/spec/models/indexing_spec.rb +40 -0
  78. data/spec/models/solr_document_spec.rb +96 -37
  79. data/spec/models/year_facet_spec.rb +65 -0
  80. data/spec/spec_helper.rb +1 -7
  81. data/spec/support/shared_examples_for_ddr_models.rb +0 -2
  82. data/spec/support/shared_examples_for_has_content.rb +37 -3
  83. metadata +79 -32
  84. data/lib/ddr/datastreams/properties_datastream.rb +0 -25
  85. data/lib/ddr/jobs/migrate_legacy_authorization.rb +0 -23
  86. data/lib/ddr/models/has_properties.rb +0 -15
  87. data/lib/ddr/models/licensable.rb +0 -28
  88. data/spec/auth/legacy_authorization_spec.rb +0 -94
  89. data/spec/auth/legacy_roles_spec.rb +0 -32
  90. data/spec/jobs/migrate_legacy_authorization_spec.rb +0 -43
  91. data/spec/support/shared_examples_for_has_properties.rb +0 -5
  92. data/spec/support/shared_examples_for_licensable.rb +0 -15
@@ -0,0 +1,17 @@
1
+ module Ddr::Index
2
+ RSpec.describe Filters do
3
+
4
+ describe "HAS_CONTENT" do
5
+ subject { Filters::HAS_CONTENT }
6
+ its(:clauses) { is_expected.to eq(["active_fedora_model_ssi:(Component OR Attachment OR Target)"]) }
7
+ end
8
+
9
+ describe "class methods" do
10
+ describe "is_governed_by(pid)" do
11
+ subject { Filters.is_governed_by("test:1") }
12
+ its(:clauses) { is_expected.to eq(["{!term f=is_governed_by_ssim}info:fedora/test:1"]) }
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ module Ddr::Index
2
+ RSpec.describe Query do
3
+
4
+ subject do
5
+ QueryBuilder.build do |query|
6
+ query
7
+ .q("foo:bar")
8
+ .where("spam"=>"eggs")
9
+ .fields("id", "foo", "spam")
10
+ .limit(50)
11
+ end
12
+ end
13
+
14
+ its(:to_s) { is_expected.to eq("q=foo%3Abar&fq=%7B%21term+f%3Dspam%7Deggs&fl=id%2Cfoo%2Cspam&rows=50") }
15
+
16
+ its(:params) { is_expected.to eq({q: "foo:bar", fl: "id,foo,spam", fq: ["{!term f=spam}eggs"], rows: 50}) }
17
+
18
+ end
19
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ module Ddr::Jobs
4
+ RSpec.describe FitsFileCharacterization, jobs: true, file_characterization: true do
5
+
6
+ shared_examples "has a fits update event" do
7
+ let(:event) { object.update_events.last }
8
+ it "should have the correct event attributes" do
9
+ expect(event.outcome).to eq(expected_outcome)
10
+ expect(event.detail).to eq(expected_detail)
11
+ expect(event.software).to eq("fits #{fits_version}")
12
+ end
13
+ end
14
+
15
+ context "content-bearing object" do
16
+ let(:object) { TestContent.create }
17
+ let(:stdout_msg) { '<fits />' }
18
+ let(:stderr_msg) { 'stderr msg' }
19
+ let(:fits_version) { '0.9.9 '}
20
+ before { allow(Ddr::Jobs::FitsFileCharacterization).to receive(:fits_version) { fits_version } }
21
+ context "fits command is successful" do
22
+ let(:expected_outcome) { Ddr::Events::Event::SUCCESS }
23
+ let(:expected_detail) { nil }
24
+ before do
25
+ allow(Open3).to receive(:capture3) { [ stdout_msg, stderr_msg, $? ] }
26
+ allow_any_instance_of(Process::Status).to receive(:success?) { true }
27
+ Ddr::Jobs::FitsFileCharacterization.perform(object.pid)
28
+ object.reload
29
+ end
30
+ it "should populate the fits datastream" do
31
+ expect(object.fits.content).to be_present
32
+ end
33
+ it_behaves_like "has a fits update event"
34
+ end
35
+ context "fits command is not successful" do
36
+ let(:expected_outcome) { Ddr::Events::Event::FAILURE }
37
+ let(:expected_detail) { stderr_msg }
38
+ before do
39
+ allow(Open3).to receive(:capture3) { [ stdout_msg, stderr_msg, $? ] }
40
+ allow_any_instance_of(Process::Status).to receive(:success?) { false }
41
+ Ddr::Jobs::FitsFileCharacterization.perform(object.pid)
42
+ object.reload
43
+ end
44
+ it "should not populate the fits datastream" do
45
+ expect(object.fits.content).to_not be_present
46
+ end
47
+ it_behaves_like "has a fits update event"
48
+ end
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,140 @@
1
+ require 'spec_helper'
2
+
3
+ module Ddr::Managers
4
+ RSpec.describe TechnicalMetadataManager do
5
+
6
+ subject { described_class.new(obj) }
7
+
8
+ let(:obj) { Component.new }
9
+
10
+ describe "when fits datastream not present" do
11
+ its(:valid) { is_expected.to be_empty }
12
+ its(:well_formed) { is_expected.to be_empty }
13
+ its(:format_label) { is_expected.to be_empty }
14
+ its(:media_type) { is_expected.to be_empty }
15
+ its(:format_version) { is_expected.to be_empty }
16
+ its(:last_modified) { is_expected.to be_empty }
17
+ its(:modification_time) { is_expected.to be_empty }
18
+ its(:created) { is_expected.to be_empty }
19
+ its(:creation_time) { is_expected.to be_empty }
20
+ its(:pronom_identifier) { is_expected.to be_empty }
21
+ its(:creating_application) { is_expected.to be_empty }
22
+ its(:file_size) { is_expected.to be_empty }
23
+ its(:fits_version) { is_expected.to be_nil }
24
+ its(:fits_datetime) { is_expected.to be_nil }
25
+ its(:fits?) { is_expected.to be false }
26
+ end
27
+
28
+ describe "when content is not present" do
29
+ its(:checksum_digest) { is_expected.to be_nil }
30
+ its(:checksum_value) { is_expected.to be_nil }
31
+ end
32
+
33
+ describe "common metadata" do
34
+ before do
35
+ obj.fits.content = fixture_file_upload(File.join("fits", "document.xml"))
36
+ end
37
+ its(:fits?) { is_expected.to be true }
38
+ its(:valid) { is_expected.to eq(["false"]) }
39
+ its(:well_formed) { is_expected.to eq(["true"]) }
40
+ its(:format_label) { is_expected.to eq(["Portable Document Format"]) }
41
+ its(:media_type) { is_expected.to eq(["application/pdf"]) }
42
+ its(:format_version) { is_expected.to eq(["1.6"]) }
43
+ its(:last_modified) { is_expected.to eq(["2015-06-08T21:22:35Z"]) }
44
+ its(:created) { is_expected.to eq(["2015:06:05 15:16:23-04:00"]) }
45
+ its(:pronom_identifier) { is_expected.to eq(["fmt/20"]) }
46
+ its(:creating_application) { is_expected.to contain_exactly("Adobe Acrobat Pro 11.0.3 Paper Capture Plug-in/PREMIS Editorial Committee", "Adobe Acrobat Pro 11.0.3 Paper Capture Plug-in/Acrobat PDFMaker 11 for Word") }
47
+ its(:fits_version) { is_expected.to eq("0.8.5") }
48
+ its(:extent) { is_expected.to eq(["3786205"]) }
49
+ its(:file_size) { is_expected.to eq([3786205]) }
50
+ its(:media_type) { is_expected.to eq(["application/pdf"]) }
51
+
52
+ describe "datetime fields" do
53
+ its(:creation_time) { is_expected.to contain_exactly(DateTime.parse("2015-06-05 15:16:23-04:00").to_time.utc) }
54
+ its(:modification_time) { is_expected.to contain_exactly(DateTime.parse("2015-06-08T21:22:35Z").to_time.utc) }
55
+ end
56
+ end
57
+
58
+ describe "checksum fields" do
59
+ before do
60
+ allow(obj.content).to receive(:checksumType) { "SHA-256" }
61
+ allow(obj.content).to receive(:checksum) { "b744b4b308a11a7b6282b383ec428a91d77b21701d4bd09021bf0543dc8946fa" }
62
+ end
63
+
64
+ its(:checksum_digest) { is_expected.to eq("SHA-256") }
65
+ its(:checksum_value) { is_expected.to eq("b744b4b308a11a7b6282b383ec428a91d77b21701d4bd09021bf0543dc8946fa") }
66
+ end
67
+
68
+ describe "image metadata" do
69
+ before do
70
+ obj.fits.content = fixture_file_upload(File.join("fits", "image.xml"))
71
+ end
72
+ its(:image_width) { is_expected.to eq(["500"]) }
73
+ its(:image_height) { is_expected.to eq(["569"]) }
74
+ its(:color_space) { is_expected.to eq(["YCbCr"]) }
75
+ end
76
+
77
+ describe "valid? / invalid?" do
78
+ describe "when #valid has a 'false' value" do
79
+ before do
80
+ allow(subject).to receive(:valid) { ["false"] }
81
+ end
82
+ it { is_expected.to be_invalid }
83
+ it { is_expected.not_to be_valid }
84
+ end
85
+ describe "when #valid has 'false' and 'true' values" do
86
+ before do
87
+ allow(subject).to receive(:valid) { ["false", "true"] }
88
+ end
89
+ it { is_expected.to be_invalid }
90
+ it { is_expected.not_to be_valid }
91
+ end
92
+ describe "when #valid has a 'true' value" do
93
+ before do
94
+ allow(subject).to receive(:valid) { ["true"] }
95
+ end
96
+ it { is_expected.not_to be_invalid }
97
+ it { is_expected.to be_valid }
98
+ end
99
+ describe "when #valid is empty" do
100
+ before do
101
+ allow(subject).to receive(:valid) { [] }
102
+ end
103
+ it { is_expected.not_to be_invalid }
104
+ it { is_expected.to be_valid }
105
+ end
106
+ end
107
+
108
+ describe "ill_formed? / well_formed?" do
109
+ describe "when #well_formed has a 'false' value" do
110
+ before do
111
+ allow(subject).to receive(:well_formed) { ["false"] }
112
+ end
113
+ it { is_expected.to be_ill_formed }
114
+ it { is_expected.not_to be_well_formed }
115
+ end
116
+ describe "when #well_formed has 'false' and 'true' values" do
117
+ before do
118
+ allow(subject).to receive(:well_formed) { ["false", "true"] }
119
+ end
120
+ it { is_expected.to be_ill_formed }
121
+ it { is_expected.not_to be_well_formed }
122
+ end
123
+ describe "when #well_formed has a 'true' value" do
124
+ before do
125
+ allow(subject).to receive(:well_formed) { ["true"] }
126
+ end
127
+ it { is_expected.not_to be_ill_formed }
128
+ it { is_expected.to be_well_formed }
129
+ end
130
+ describe "when #well_formed is empty" do
131
+ before do
132
+ allow(subject).to receive(:well_formed) { [] }
133
+ end
134
+ it { is_expected.not_to be_ill_formed }
135
+ it { is_expected.to be_well_formed }
136
+ end
137
+ end
138
+
139
+ end
140
+ end
@@ -3,6 +3,50 @@ require 'spec_helper'
3
3
  module ActiveFedora
4
4
  RSpec.describe Datastream do
5
5
 
6
+ describe "#tempfile" do
7
+ subject { described_class.new(nil, "DS1", controlGroup: "M") }
8
+ describe "when the datastream has no content" do
9
+ it "should raise an exception" do
10
+ expect { subject.tempfile { |f| puts f.path } }.to raise_error(Ddr::Models::Error)
11
+ end
12
+ end
13
+ describe "when the datastream has content" do
14
+ let(:file) { fixture_file_upload("sample.pdf", "application/pdf") }
15
+ before do
16
+ subject.content = file.read
17
+ subject.mimeType = file.content_type
18
+ allow(subject).to receive(:pid) { "test:1" }
19
+ end
20
+ describe "the yielded file" do
21
+ it "should by default have an extension for the datastream media type" do
22
+ subject.tempfile do |f|
23
+ expect(f.path.end_with?(".pdf")).to be true
24
+ end
25
+ end
26
+ it "should use the prefix provided" do
27
+ subject.tempfile(prefix: "foo") do |f|
28
+ expect(File.basename(f.path).start_with?("foo")).to be true
29
+ end
30
+ end
31
+ it "should use the sufffix provided" do
32
+ subject.tempfile(suffix: "bar") do |f|
33
+ expect(f.path.end_with?("bar")).to be true
34
+ end
35
+ end
36
+ it "should by default have a prefix based on the PID" do
37
+ subject.tempfile do |f|
38
+ expect(File.basename(f.path).start_with?("test_1_DS1--")).to be true
39
+ end
40
+ end
41
+ it "should have the same size as the datastream content" do
42
+ subject.tempfile do |f|
43
+ expect(f.size).to eq(subject.content.length)
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
6
50
  describe "#validate_checksum!" do
7
51
  subject { described_class.new(nil, nil, controlGroup: "M") }
8
52
  let!(:checksum) { "dea56f15b309e47b74fa24797f85245dda0ca3d274644a96804438bbd659555a" }
@@ -6,21 +6,16 @@ RSpec.describe Collection, type: :model do
6
6
  it_behaves_like "it has an association", :has_many, :children, :is_member_of_collection, "Item"
7
7
  it_behaves_like "it has an association", :has_many, :targets, :is_external_target_for, "Target"
8
8
 
9
- describe "terms delegated to defaultRights" do
9
+ describe "legacy license information" do
10
10
  before do
11
- subject.default_license_title = "License Title"
12
- subject.default_license_description = "License Description"
13
- subject.default_license_url = "http://library.duke.edu"
14
- end
15
- it "should set the terms correctly" do
16
- expect(subject.defaultRights.license.title.first).to eq("License Title")
17
- expect(subject.defaultRights.license.description.first).to eq("License Description")
18
- expect(subject.defaultRights.license.url.first).to eq("http://library.duke.edu")
11
+ subject.defaultRights.license.title = ["License Title"]
12
+ subject.defaultRights.license.description = ["License Description"]
13
+ subject.defaultRights.license.url = ["http://library.duke.edu"]
19
14
  end
20
15
  it "should index the terms" do
21
- expect(subject.to_solr[Ddr::IndexFields::DEFAULT_LICENSE_TITLE]).to eq("License Title")
22
- expect(subject.to_solr[Ddr::IndexFields::DEFAULT_LICENSE_DESCRIPTION]).to eq("License Description")
23
- expect(subject.to_solr[Ddr::IndexFields::DEFAULT_LICENSE_URL]).to eq("http://library.duke.edu")
16
+ expect(subject.to_solr[Ddr::Index::Fields::DEFAULT_LICENSE_TITLE]).to eq("License Title")
17
+ expect(subject.to_solr[Ddr::Index::Fields::DEFAULT_LICENSE_DESCRIPTION]).to eq("License Description")
18
+ expect(subject.to_solr[Ddr::Index::Fields::DEFAULT_LICENSE_URL]).to eq("http://library.duke.edu")
24
19
  end
25
20
  end
26
21
 
@@ -9,14 +9,11 @@ RSpec.describe Component, type: :model, components: true do
9
9
  it_behaves_like "a non-collection model"
10
10
 
11
11
  describe "indexing" do
12
- let(:component) { FactoryGirl.build(:component) }
12
+ subject { FactoryGirl.build(:component) }
13
13
  before do
14
- allow_any_instance_of(Component).to receive(:collection) { Collection.new(pid: 'test:1') }
15
- end
16
- it "should include the COLLECTION_URI field in its indexing" do
17
- expect(component.index_fields).to have_key(Ddr::IndexFields::COLLECTION_URI)
18
- expect(component.index_fields[Ddr::IndexFields::COLLECTION_URI]).to eq('info:fedora/test:1')
14
+ allow(subject).to receive(:collection) { Collection.new(pid: "test:1") }
19
15
  end
16
+ its(:index_fields) { is_expected.to include(Ddr::Index::Fields::COLLECTION_URI => "info:fedora/test:1") }
20
17
  end
21
18
 
22
19
  end
@@ -0,0 +1,49 @@
1
+ module Ddr::Models
2
+ RSpec.describe EffectiveLicense do
3
+
4
+ subject { described_class.call(obj) }
5
+
6
+ let(:mock) { Struct.new(:license, :parent, :admin_policy, :pid) }
7
+ let(:obj) { mock.new }
8
+
9
+ let(:url) { "https://creativecommons.org/licenses/by-nc-nd/4.0/" }
10
+ let(:license) { License.new(url: url) }
11
+ before { allow(License).to receive(:get).with(url) { license } }
12
+
13
+ describe "when the object has a licence" do
14
+ before { obj.license = url }
15
+ it { is_expected.to eq(license) }
16
+ end
17
+
18
+ describe "when the object does not have a license" do
19
+ describe "when the object has a parent" do
20
+ let(:parent) { mock.new }
21
+ before do
22
+ parent.license = url
23
+ obj.parent = parent
24
+ end
25
+ it { is_expected.to eq(license) }
26
+ end
27
+ describe "when the object does not have a parent" do
28
+ describe "when the object has an admin policy" do
29
+ describe "and the admin policy is a different object" do
30
+ let(:admin_policy) { mock.new }
31
+ before do
32
+ admin_policy.license = url
33
+ obj.admin_policy = admin_policy
34
+ end
35
+ it { is_expected.to eq(license) }
36
+ end
37
+ describe "and the admin policy is the object itself" do
38
+ before { obj.admin_policy = obj }
39
+ it { is_expected.to be_nil }
40
+ end
41
+ end
42
+ describe "otherwise" do
43
+ it { is_expected.to be_nil }
44
+ end
45
+ end
46
+ end
47
+
48
+ end
49
+ end
@@ -1,246 +1,195 @@
1
1
  require 'spec_helper'
2
2
  require 'support/ezid_mock_identifier'
3
3
 
4
- module Ddr
5
- module Models
6
- RSpec.describe HasAdminMetadata, type: :model, contacts: true do
7
-
8
- describe "local id" do
9
- subject { FactoryGirl.build(:item) }
10
- describe "indexing" do
11
- before { subject.local_id = "foo" }
12
- it "should index the local id value" do
13
- expect(subject.to_solr).to include(Ddr::IndexFields::LOCAL_ID => "foo")
14
- end
15
- end
16
- end
4
+ module Ddr::Models
5
+ RSpec.describe HasAdminMetadata, type: :model, contacts: true do
17
6
 
18
- describe "permanent id and permanent url" do
19
- subject { FactoryGirl.build(:item) }
7
+ describe "permanent id and permanent url" do
8
+ subject { FactoryGirl.build(:item) }
20
9
 
21
- describe "#assign_permanent_id!" do
22
- it "should assign the permanent id later" do
23
- expect(subject.permanent_id_manager).to receive(:assign_later) { nil }
24
- subject.assign_permanent_id!
25
- end
26
- context "when the object is created (first saved)" do
27
- context "and auto-assignment is enabled" do
28
- before { allow(Ddr::Models).to receive(:auto_assign_permanent_ids) { true } }
29
- it "should assign a permanent id" do
30
- expect(subject).to receive(:assign_permanent_id!) { nil }
31
- subject.save!
32
- end
33
- end
34
- context "and auto-assignment is disabled" do
35
- before { allow(Ddr::Models).to receive(:auto_assign_permanent_ids) { false } }
36
- it "should not assign a permanent id" do
37
- expect(subject).not_to receive(:assign_permanent_id!)
38
- subject.save!
39
- end
10
+ describe "#assign_permanent_id!" do
11
+ it "should assign the permanent id later" do
12
+ expect(subject.permanent_id_manager).to receive(:assign_later) { nil }
13
+ subject.assign_permanent_id!
14
+ end
15
+ context "when the object is created (first saved)" do
16
+ context "and auto-assignment is enabled" do
17
+ before { allow(Ddr::Models).to receive(:auto_assign_permanent_ids) { true } }
18
+ it "should assign a permanent id" do
19
+ expect(subject).to receive(:assign_permanent_id!) { nil }
20
+ subject.save!
40
21
  end
41
22
  end
42
- context "when saved" do
43
- context "and auto-assignment is enabled" do
44
- before { allow(Ddr::Models).to receive(:auto_assign_permanent_ids) { true } }
45
- it "should assign a permanent id once" do
46
- expect(subject).to receive(:assign_permanent_id!).once { nil }
47
- subject.save!
48
- subject.title = ["New Title"]
49
- subject.save!
50
- end
51
- end
52
- context "and auto-assignment is disabled" do
53
- before { allow(Ddr::Models).to receive(:auto_assign_permanent_ids) { false } }
54
- it "should not assign a permanent id" do
55
- expect(subject).not_to receive(:assign_permanent_id!)
56
- subject.save!
57
- end
23
+ context "and auto-assignment is disabled" do
24
+ before { allow(Ddr::Models).to receive(:auto_assign_permanent_ids) { false } }
25
+ it "should not assign a permanent id" do
26
+ expect(subject).not_to receive(:assign_permanent_id!)
27
+ subject.save!
58
28
  end
59
29
  end
60
30
  end
61
-
62
- describe "lifecycle" do
63
- let!(:identifier) { Ezid::MockIdentifier.new(id: "ark:/99999/fk4zzz", status: "public") }
64
- before do
65
- allow(Ddr::Models).to receive(:auto_assign_permanent_ids) { false }
66
- allow(Ezid::Identifier).to receive(:find).with("ark:/99999/fk4zzz") { identifier }
67
- subject.permanent_id = "ark:/99999/fk4zzz"
68
- subject.save!
69
- end
70
- it "should update the status of the identifier when the object is destroyed" do
71
- expect { subject.destroy }.to change(identifier, :status).from("public").to("unavailable | deleted")
72
- end
73
- end
74
-
75
- describe "events" do
76
- before { allow(Ddr::Models).to receive(:auto_assign_permanent_ids) { true } }
77
- context "when the operation succeeds" do
78
- let!(:mock_identifier) { Ezid::MockIdentifier.new(id: "ark:/99999/fk4zzz",
79
- metadata: "_target: http://example.com") }
80
- before do
81
- allow(Ezid::Identifier).to receive(:create) { mock_identifier }
82
- allow(Ezid::Identifier).to receive(:find) { mock_identifier }
83
- allow(subject.permanent_id_manager).to receive(:record) { mock_identifier }
84
- end
85
- it "should create a success event" do
86
- expect { subject.save }.to change { subject.update_events.count }.by(1)
31
+ context "when saved" do
32
+ context "and auto-assignment is enabled" do
33
+ before { allow(Ddr::Models).to receive(:auto_assign_permanent_ids) { true } }
34
+ it "should assign a permanent id once" do
35
+ expect(subject).to receive(:assign_permanent_id!).once { nil }
36
+ subject.save!
37
+ subject.title = ["New Title"]
38
+ subject.save!
87
39
  end
88
40
  end
89
- context "when there's an exception" do
90
- before { allow(Ezid::Identifier).to receive(:create).and_raise(Ezid::Error) }
91
- it "should create a failure event" do
92
- begin
93
- subject.save
94
- rescue Ezid::Error
95
- end
96
- expect(subject.update_events.last).to be_failure
41
+ context "and auto-assignment is disabled" do
42
+ before { allow(Ddr::Models).to receive(:auto_assign_permanent_ids) { false } }
43
+ it "should not assign a permanent id" do
44
+ expect(subject).not_to receive(:assign_permanent_id!)
45
+ subject.save!
97
46
  end
98
47
  end
99
48
  end
49
+ end
50
+
51
+ describe "lifecycle" do
52
+ let!(:identifier) { Ezid::MockIdentifier.new(id: "ark:/99999/fk4zzz", status: "public") }
53
+ before do
54
+ allow(Ddr::Models).to receive(:auto_assign_permanent_ids) { false }
55
+ allow(Ezid::Identifier).to receive(:find).with("ark:/99999/fk4zzz") { identifier }
56
+ subject.permanent_id = "ark:/99999/fk4zzz"
57
+ subject.save!
58
+ end
59
+ it "should update the status of the identifier when the object is destroyed" do
60
+ expect { subject.destroy }.to change(identifier, :status).from("public").to("unavailable | deleted")
61
+ end
62
+ end
100
63
 
101
- describe "indexing" do
102
- let(:permanent_id) { "ark:/99999/fk4zzz" }
103
- let(:permanent_url) { "http://id.library.duke.edu/ark:/99999/fk4zzz" }
104
- let(:display_format) { "Image" }
64
+ describe "events" do
65
+ before { allow(Ddr::Models).to receive(:auto_assign_permanent_ids) { true } }
66
+ context "when the operation succeeds" do
67
+ let!(:mock_identifier) { Ezid::MockIdentifier.new(id: "ark:/99999/fk4zzz",
68
+ metadata: "_target: http://example.com") }
105
69
  before do
106
- subject.permanent_id = permanent_id
107
- subject.permanent_url = permanent_url
108
- subject.display_format = display_format
70
+ allow(Ezid::Identifier).to receive(:create) { mock_identifier }
71
+ allow(Ezid::Identifier).to receive(:find) { mock_identifier }
72
+ allow(subject.permanent_id_manager).to receive(:record) { mock_identifier }
109
73
  end
110
- it "should index the permanent id value" do
111
- expect(subject.to_solr[Ddr::IndexFields::PERMANENT_ID]).to eq(permanent_id)
74
+ it "should create a success event" do
75
+ expect { subject.save }.to change { subject.update_events.count }.by(1)
112
76
  end
113
- it "should index the permanent url" do
114
- expect(subject.to_solr[Ddr::IndexFields::PERMANENT_URL]).to eq(permanent_url)
115
- end
116
- it "should index the display format" do
117
- expect(subject.to_solr[Ddr::IndexFields::DISPLAY_FORMAT]).to eq(display_format)
77
+ end
78
+ context "when there's an exception" do
79
+ before { allow(Ezid::Identifier).to receive(:create).and_raise(Ezid::Error) }
80
+ it "should create a failure event" do
81
+ begin
82
+ subject.save
83
+ rescue Ezid::Error
84
+ end
85
+ expect(subject.update_events.last).to be_failure
118
86
  end
119
87
  end
120
-
121
88
  end
89
+ end
122
90
 
123
- describe "workflow" do
91
+ describe "workflow" do
124
92
 
125
- subject { FactoryGirl.build(:item) }
93
+ subject { FactoryGirl.build(:item) }
126
94
 
127
- describe "#published?" do
128
- context "object is published" do
129
- before { allow(subject).to receive(:workflow_state) { Ddr::Managers::WorkflowManager::PUBLISHED } }
130
- it "should return true" do
131
- expect(subject).to be_published
132
- end
95
+ describe "#published?" do
96
+ context "object is published" do
97
+ before { allow(subject).to receive(:workflow_state) { Ddr::Managers::WorkflowManager::PUBLISHED } }
98
+ it "should return true" do
99
+ expect(subject).to be_published
133
100
  end
134
- context "object is not published" do
135
- before { allow(subject).to receive(:workflow_state) { nil } }
136
- it "should return false" do
137
- expect(subject).not_to be_published
138
- end
101
+ end
102
+ context "object is not published" do
103
+ before { allow(subject).to receive(:workflow_state) { nil } }
104
+ it "should return false" do
105
+ expect(subject).not_to be_published
139
106
  end
140
107
  end
108
+ end
141
109
 
142
- describe "#publish" do
143
- it "should publish the object" do
144
- subject.publish
145
- expect(subject).to be_published
146
- end
110
+ describe "#publish" do
111
+ it "should publish the object" do
112
+ subject.publish
113
+ expect(subject).to be_published
147
114
  end
115
+ end
148
116
 
149
- describe "#publish!" do
150
- it "should publish and persist the object" do
151
- subject.publish!
152
- expect(subject.reload).to be_published
153
- end
117
+ describe "#publish!" do
118
+ it "should publish and persist the object" do
119
+ subject.publish!
120
+ expect(subject.reload).to be_published
154
121
  end
122
+ end
155
123
 
156
- describe "#unpublish" do
157
- before { subject.publish }
158
- it "should unpublish the object" do
159
- subject.unpublish
160
- expect(subject).not_to be_published
161
- end
124
+ describe "#unpublish" do
125
+ before { subject.publish }
126
+ it "should unpublish the object" do
127
+ subject.unpublish
128
+ expect(subject).not_to be_published
162
129
  end
130
+ end
163
131
 
164
- describe "#unpublish!" do
165
- before { subject.publish! }
166
- it "should unpublish and persist the object" do
167
- subject.unpublish!
168
- expect(subject.reload).not_to be_published
169
- end
132
+ describe "#unpublish!" do
133
+ before { subject.publish! }
134
+ it "should unpublish and persist the object" do
135
+ subject.unpublish!
136
+ expect(subject.reload).not_to be_published
170
137
  end
171
138
  end
139
+ end
172
140
 
173
- describe "roles" do
141
+ describe "roles" do
174
142
 
175
- subject { FactoryGirl.build(:item) }
143
+ subject { FactoryGirl.build(:item) }
176
144
 
177
- describe "#copy_resource_roles_from" do
178
- let(:other) { FactoryGirl.build(:collection) }
179
- let(:resource_roles) do
180
- [ FactoryGirl.build(:role, :viewer, :public, :resource),
181
- FactoryGirl.build(:role, :editor, :group, :resource) ]
182
- end
183
- let(:policy_roles) do
184
- [ FactoryGirl.build(:role, :curator, :person, :policy) ]
185
- end
186
- before do
187
- other.roles.grant *resource_roles
188
- other.roles.grant *policy_roles
189
- subject.copy_resource_roles_from(other)
190
- end
191
- its(:roles) { should include(*resource_roles) }
192
- its(:roles) { should_not include(*policy_roles) }
145
+ describe "#copy_resource_roles_from" do
146
+ let(:other) { FactoryGirl.build(:collection) }
147
+ let(:resource_roles) do
148
+ [ FactoryGirl.build(:role, :viewer, :public, :resource),
149
+ FactoryGirl.build(:role, :editor, :group, :resource) ]
193
150
  end
194
-
195
- describe "#grant_roles_to_creator" do
196
- let(:user) { FactoryGirl.build(:user) }
197
- before { subject.grant_roles_to_creator(user) }
198
- its(:roles) { should include(Ddr::Auth::Roles::Role.build(type: "Editor", agent: user.agent, scope: "resource")) }
151
+ let(:policy_roles) do
152
+ [ FactoryGirl.build(:role, :curator, :person, :policy) ]
199
153
  end
200
-
201
- describe "persistence" do
202
- let(:role) { FactoryGirl.build(:role, :downloader, :public) }
203
- it "should persist the role information" do
204
- subject.roles.grant role
205
- subject.save!
206
- subject.reload
207
- expect(subject.roles).to contain_exactly(role)
208
- end
154
+ before do
155
+ other.roles.grant *resource_roles
156
+ other.roles.grant *policy_roles
157
+ subject.copy_resource_roles_from(other)
209
158
  end
159
+ its(:roles) { should include(*resource_roles) }
160
+ its(:roles) { should_not include(*policy_roles) }
161
+ end
210
162
 
211
- describe "indexing" do
212
- let(:role1) { FactoryGirl.build(:role, :curator, :person, :resource) }
213
- let(:role2) { FactoryGirl.build(:role, :curator, :person, :policy) }
214
- let(:role3) { FactoryGirl.build(:role, :editor, :group, :policy) }
215
- let(:role4) { FactoryGirl.build(:role, :editor, :person, :policy) }
216
- let(:indexed) { subject.to_solr }
217
- before { subject.roles.grant role1, role2, role3, role4 }
218
- it "should index the role data serialized as JSON" do
219
- expect(indexed[Ddr::IndexFields::ACCESS_ROLE]).to eq(subject.roles.to_json)
220
- end
221
- it "should index the agents having roles in policy scope" do
222
- expect(indexed[Ddr::IndexFields::POLICY_ROLE]).to contain_exactly(role2.agent.first, role3.agent.first, role4.agent.first)
223
- end
224
- it "should index the agents having roles in resource scope" do
225
- expect(indexed[Ddr::IndexFields::RESOURCE_ROLE]).to contain_exactly(role1.agent.first)
226
- end
163
+ describe "#grant_roles_to_creator" do
164
+ let(:user) { FactoryGirl.build(:user) }
165
+ before { subject.grant_roles_to_creator(user) }
166
+ its(:roles) { should include(Ddr::Auth::Roles::Role.build(type: "Editor", agent: user.agent, scope: "resource")) }
167
+ end
168
+
169
+ describe "persistence" do
170
+ let(:role) { FactoryGirl.build(:role, :downloader, :public) }
171
+ it "should persist the role information" do
172
+ subject.roles.grant role
173
+ subject.save!
174
+ subject.reload
175
+ expect(subject.roles).to contain_exactly(role)
227
176
  end
177
+ end
228
178
 
229
- describe "contacts" do
230
- before do
231
- allow(YAML).to receive(:load_file) { { 'a' => { 'name' => 'Contact A', 'short_name' => 'A' },
232
- 'b' => { 'name' => 'Contact B', 'short_name' => 'B' } } }
233
- Ddr::Contacts.load_contacts
234
- end
235
- describe "#research_help" do
236
- before { subject.research_help_contact = 'b' }
237
- it "should return the appropriate contact" do
238
- expect(subject.research_help.slug).to eq('b')
239
- end
179
+ describe "contacts" do
180
+ before do
181
+ allow(YAML).to receive(:load_file) { { 'a' => { 'name' => 'Contact A', 'short_name' => 'A' },
182
+ 'b' => { 'name' => 'Contact B', 'short_name' => 'B' } } }
183
+ Ddr::Contacts.load_contacts
184
+ end
185
+ describe "#research_help" do
186
+ before { subject.research_help_contact = 'b' }
187
+ it "should return the appropriate contact" do
188
+ expect(subject.research_help.slug).to eq('b')
240
189
  end
241
190
  end
242
-
243
191
  end
192
+
244
193
  end
245
194
  end
246
195
  end