ddr-models 2.0.1 → 2.1.0.rc1

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.
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