diff --git a/db/seeds.rb b/db/seeds.rb index 157a0163..37e9eea1 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1,118 +1,123 @@ -# reworking this to only create the necessary collections/roles/users for a minimally -# instance, and will move the seeding of works into a rake task +abort("The Rails environment is running in production mode!") if Rails.env.production? -def create_admin_role - @admin_role = Role.find_or_create_by(name: 'admin') -end +ActiveFedora::Cleaner.clean! -def create_default_admin_user - @admin_user = User.create!(email: ENV['DEV_ADMIN_USER_EMAIL'], password: ENV['DEV_ADMIN_USER_PASSWORD']) - admin_role = Role.find_or_create_by(name: 'admin') - admin_role.users << @admin_user -end +# users +admin_user = FactoryBot.create(:admin, email: "admin@example.com") +content_admin_user = FactoryBot.create(:content_admin, email: "content_admin@example.com") +non_admin_user = FactoryBot.create(:user, email: "nonadminuser@example.com") -def create_default_admin_set - @default_admin_set = Hyrax::AdminSetCreateService.find_or_create_default_admin_set -end +# admin sets and collection types +default_admin_set_id = FactoryBot.create(:stored_default_admin_set_id) +admin_set_collection_type = FactoryBot.create(:admin_set_collection_type) +gw_etds_admin_set = FactoryBot.create(:admin_set, title: ["ETDs"],edit_users: [admin_user.user_key, content_admin_user.user_key]) -def create_collection_type(machine_id, options) - coltype = Hyrax::CollectionType.find_by_machine_id(machine_id) - return coltype if coltype.present? - default_options = { - nestable: false, discoverable: false, sharable: false, allow_multiple_membership: false, - require_membership: false, assigns_workflow: false, assigns_visibility: false, - participants: [{ agent_type: Hyrax::CollectionTypeParticipant::GROUP_TYPE, agent_id: ::Ability.admin_group_name, access: Hyrax::CollectionTypeParticipant::MANAGE_ACCESS }, - { agent_type: Hyrax::CollectionTypeParticipant::GROUP_TYPE, agent_id: ::Ability.registered_group_name, access: Hyrax::CollectionTypeParticipant::CREATE_ACCESS }] - } - final_options = default_options.merge(options.except(:title)) - Hyrax::CollectionTypes::CreateService.create_collection_type(machine_id: machine_id, title: options[:title], options: final_options) -end +permission_template = FactoryBot.create(:permission_template, source_id: gw_etds_admin_set.id, with_admin_set: true, with_active_workflow: true) -def create_admin_set_collection_type - admin_set_collection_type = Hyrax::CollectionType.find_or_create_admin_set_type -end +FactoryBot.create(:permission_template_access, + :deposit, + permission_template: permission_template, + agent_type: 'user', + agent_id: admin_user.user_key) -def create_user_collection_type - user_collection_type = Hyrax::CollectionType.find_or_create_default_collection_type -end +# collection to add works to +main_collection = FactoryBot.create(:public_collection, with_permission_template: permission_template) -def create_public_collection(user, type_gid, id, options) - options[:visibility] = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC - create_collection(user, type_gid, id, options) +# other collections +4.times do + FactoryBot.create(:public_collection, with_permission_template: permission_template) end -def create_etds_admin_set - etds_admin_set = Hyrax::AdministrativeSet.new(title: ['ETDs']) - etds_admin_set = Hyrax.persister.save(resource: etds_admin_set) - creating_user = User.where(email: ENV['DEV_ADMIN_USER_EMAIL']).first - Hyrax::AdminSetCreateService.call!(admin_set: etds_admin_set, creating_user: creating_user) - etds_admin_set -end - -def create_collection(user, type_gid, id, options) - col = Collection.where(id: id) - return col.first if col.present? - col = Collection.new(id: id) - col.attributes = options.except(:visibility) - col.apply_depositor_metadata(user.user_key) - col.collection_type_gid = type_gid - col.visibility = options[:visibility] - col.save - Hyrax::Collections::PermissionsCreateService.create_default(collection: col, creating_user: user) - col -end - - -def create_etd(user, id, options) - work = GwEtd.where(id: id) - return work.first if work.present? - actor = Hyrax::CurationConcern.actor - attributes_for_actor = options - work = GwEtd.new(id: id) - actor_environment = Hyrax::Actors::Environment.new(work, Ability.new(user), attributes_for_actor) - actor.create(actor_environment) - work +# private works with specific configurations - will need to log in as admin to see them +FactoryBot.create(:work_with_image_files, user: admin_user, title: ["A Work with an Image File"]) +FactoryBot.create(:embargoed_work, user: admin_user, title: ["An Embargoed Work"]) +FactoryBot.create(:work_with_one_file, user: admin_user, title: ["A Work with a file"]) +FactoryBot.create(:work_with_file_and_work, user: admin_user, title: ["A Work with a file and work"]) +FactoryBot.create(:work_with_files, user: admin_user, title: ["A Work with files"]) +FactoryBot.create(:work_with_one_child, user: admin_user, title: ["A Work with one child"]) +FactoryBot.create(:work_with_two_children, user: admin_user, title: ["A Work with two children"]) + +# public GwWorks with metadata +5.times do |i| + FactoryBot.create(:public_work, + user: admin_user, + admin_set: gw_etds_admin_set, + title: ["Test Public ETD with metadata #{i}"], + gw_affiliation: ["Department of Testing", "Department of Quality Control", "Scholarly Technology Group"], + resource_type: [["Research Paper", "Article", "Archival Work"].sample], + creator: ["Professor Goodtests"], + contributor: ["Assistant Badtests", "Another Collaborator"], + description: ["A work for testing with metadata"], + abstract: Faker::Lorem.paragraphs(number: 1), + keyword: ["Testing", "Examining", "Prodding"], + license: ["http://www.europeana.eu/portal/rights/rr-r.html"], + rights_statement: ["http://rightsstatements.org/vocab/InC/1.0/"], + publisher: ["A Pretty Cool Publisher"], + date_created: [rand(1900..2010).to_s], + subject: ["Automated Testing"], + language: ["English"], + member_of_collections: [main_collection] + ) end -def create_public_etd(user, id, options) - options[:visibility] = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC - create_etd(user, id, options) +# public GwJournalIssues +5.times do |i| + FactoryBot.create(:public_journal_issue, + user: admin_user, + admin_set: gw_etds_admin_set, + title: ["Test Public GW Journal Issue with Metadata #{i}"], + gw_affiliation: ["Department of Testing", "Department of Quality Control", "Scholarly Technology Group"], + resource_type: ["Journal Issue"], + creator: ["Professor Goodtests"], + contributor: ["Assistant Badtests", "Another Collaborator"], + description: ["A work for testing with metadata"], + abstract: Faker::Lorem.paragraphs(number: 1), + keyword: ["Testing", "Examining", "Prodding"], + license: ["http://www.europeana.eu/portal/rights/rr-r.html"], + rights_statement: ["http://rightsstatements.org/vocab/InC/1.0/"], + publisher: ["A Pretty Cool Publisher"], + date_created: [rand(1900..2010).to_s], + subject: ["Automated Testing"], + language: ["English"], + issue: [rand(1..3).to_s], + volume: [rand(1..3).to_s] + ) end -def create_private_etd(user, id, options) - options[:visibility] = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE - create_etd(user, id, options) +# public ETDs +5.times do |i| + FactoryBot.create(:public_etd, + user: admin_user, + admin_set: gw_etds_admin_set, + title: ["Test Public GW Jouranl Issue with metadata #{i}"], + gw_affiliation: ["Department of Testing", "Department of Quality Control", "Scholarly Technology Group"], + resource_type: ["Journal Issue"], + creator: ["Professor Goodtests"], + contributor: ["Assistant Badtests", "Another Collaborator"], + description: ["A work for testing with metadata"], + abstract: Faker::Lorem.paragraphs(number: 1), + keyword: ["Testing", "Examining", "Prodding"], + license: ["http://www.europeana.eu/portal/rights/rr-r.html"], + rights_statement: ["http://rightsstatements.org/vocab/InC/1.0/"], + publisher: ["A Pretty Cool Publisher"], + date_created: [rand(1900..2010).to_s], + subject: ["Automated Testing"], + language: ["English"], + degree: "Ph.D", + advisor: ["Doctor Advisor"], + committee_member: ["Committee Member 1", "Committee Member 2"] + ) end -def create_authenticated_etd(user, id, options) - options[:visibility] = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED - create_etd(user, id, options) -end - -def create_content_admin_role - @content_admin_role = Role.find_or_create_by(name: 'content-admin') -end - -def create_content_admin_user - @content_admin_user = User.create!(email: "content-admin@example.com", password: "password") - content_admin_role = Role.find_or_create_by(name: "content-admin") - content_admin_role.users << @content_admin_user -end - -# -------------- - -# -- Creating admin role and user -create_admin_role -create_default_admin_user - -# -- Creating default admin sets, admin set collection type, and user collection type -- -create_default_admin_set -create_admin_set_collection_type -create_user_collection_type - -# -- Creating the ETDs admin set -@etds_admin_set = create_etds_admin_set - -# -- Creating a content-admin role and user -create_content_admin_role -create_content_admin_user \ No newline at end of file +# content blocks +ContentBlock.find_or_create_by(name: "header_background_color").update!(value: "#FFFFFF") +ContentBlock.find_or_create_by(name: "header_text_color").update!(value: "#444444") +ContentBlock.find_or_create_by(name: "link_color").update!(value: "#28659A") +ContentBlock.find_or_create_by(name: "footer_link_color").update!(value: "#FFFFFF") +ContentBlock.find_or_create_by(name: "primary_button_background_color").update!(value: "#28659A") +ContentBlock.find_or_create_by(name: "featured_researcher").update!(value: File.open("#{Rails.root}/spec/fixtures/content_blocks/featured_researcher.html").read) +ContentBlock.find_or_create_by(name: "about_page").update!(value: File.open("#{Rails.root}/spec/fixtures/content_blocks/about_page.html").read) +ContentBlock.find_or_create_by(name: "help_page").update!(value: File.open("#{Rails.root}/spec/fixtures/content_blocks/help_page.html").read) +ContentBlock.find_or_create_by(name: "share_page").update!(value: File.open("#{Rails.root}/spec/fixtures/content_blocks/share_page.html").read) + +# bundle exec rails db:drop ; bundle exec rails db:create ; bundle exec rails db:migrate ; bundle exec rails db:seed \ No newline at end of file diff --git a/spec/factories/access_control.rb b/spec/factories/access_control.rb new file mode 100644 index 00000000..e4401047 --- /dev/null +++ b/spec/factories/access_control.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :access_control, class: Hyrax::AccessControl do + permissions { build(:permission) } + + trait :with_target do + access_to { valkyrie_create(:hyrax_resource).id } + + permissions { build(:permission, access_to: access_to) } + end + end +end diff --git a/spec/factories/admin_sets.rb b/spec/factories/admin_sets.rb index 5a61b842..36a8a743 100644 --- a/spec/factories/admin_sets.rb +++ b/spec/factories/admin_sets.rb @@ -1,5 +1,4 @@ -# from https://github.com/samvera/hyrax/blob/v2.9.6/spec/factories/admin_sets.rb - +# frozen_string_literal: true FactoryBot.define do factory :admin_set do sequence(:title) { |n| ["Title #{n}"] } @@ -12,6 +11,7 @@ after(:create) do |admin_set, evaluator| if evaluator.with_permission_template attributes = { source_id: admin_set.id } + attributes = evaluator.permission_template_attributes.merge(attributes) if evaluator.permission_template_attributes.respond_to?(:merge) attributes = evaluator.with_permission_template.merge(attributes) if evaluator.with_permission_template.respond_to?(:merge) # There is a unique constraint on permission_templates.source_id; I don't want to # create a permission template if one already exists for this admin_set @@ -22,6 +22,13 @@ transient do # false, true, or Hash with keys for permission_template with_permission_template { false } + permission_template_attributes { {} } + end + + factory :complete_admin_set do + alternative_title { ['alternative admin set title'] } + creator { ['moomin', 'snufkin'] } + description { ['Before a revolution happens', 'it is perceived as impossible'] } end end -end \ No newline at end of file +end diff --git a/spec/factories/admin_sets_lw.rb b/spec/factories/admin_sets_lw.rb new file mode 100644 index 00000000..9803986c --- /dev/null +++ b/spec/factories/admin_sets_lw.rb @@ -0,0 +1,222 @@ +# frozen_string_literal: true +FactoryBot.define do + # Tests that create a Fedora Object are very slow. This factory lets you control which parts of the object ecosystem + # get built. + # + # PREFERRED: Use build whenever possible. You can control the creation of the permission template and solr document + # by passing parameters to the build(:admin_set_lw) method. That way you can build only the parts needed + # for a specific test. + # + # AVOID: Do not use create unless absolutely necessary. It will create everything including the Fedora object. + # + # @example Simple build of an admin set with no additional parts created. Lightest weight. + # NOTE: A user is automatically created as the owner of the admin set. + # let(:adminset) { build(:adminset_lw) } + # + # @example Simple build of an admin set with no additional parts created. User is the owner of the admin set. Lightest weight. + # let(:adminset) { build(:adminset_lw, user:) } + # + # @example Simple build of an admin set with only solr-document. Owner is given edit-access in solr-document. Light weight. + # let(:adminset) { build(:adminset_lw, with_solr_document: true) } + # + # @example Simple build of an admin set with only a permission template created. Owner is set as a manager. Light weight. + # let(:adminset) { build(:adminset_lw, with_permission_template: true) } + # + # @example Build an admin set with only a permission template created. Permissions are set based on + # attributes set for `with_permission_template`. Middle weight. + # # permissions passed thru `with_permission_template` can be any of the following in any combination + # let(:permissions) { { manage_users: [user.user_key], # multiple users can be listed + # deposit_users: [user.user_key], + # view_users: [user.user_key], + # manage_groups: [group_name], # multiple groups can be listed + # deposit_groups: [group_name], + # view_groups: [group_name], } } + # let(:adminset) { build(:adminset_lw, user: , with_permission_template: permissions) } + # + # @example Build an admin set with permission template and solr-document created. Permissions are set based on + # attributes set for `with_permission_template`. Solr-document includes read/edit access defined based + # on attributes passed thru `with_permission_template`. Middle weight. + # # permissions passed thru `with_permission_template` can be any of the following in any combination + # let(:permissions) { { manage_users: [user.user_key], # multiple users can be listed + # deposit_users: [user.user_key], + # view_users: [user.user_key], + # manage_groups: [group_name], # multiple groups can be listed + # deposit_groups: [group_name], + # view_groups: [group_name], } } + # let(:adminset) { build(:adminset_lw, user: , with_permission_template: permissions, with_solr_document: true) } + # + # @example Create an admin set with everything. Extreme heavy weight. This is very slow and should be avoided. + # NOTE: Everything gets created. + # NOTE: Build options effect created admin sets as follows... + # * `with_permission_template` can specify user/group permissions. A permission template is always created. + # * `with_solr_document` is ignored. A solr document is always created. + # let(:adminset) { create(:adminset_lw) } + # + # @example Build the default admin set with permission template, solr doc, and default adminset's metadata. + # let(:default_adminset) { build(:default_adminset) } + + factory :adminset_lw, class: AdminSet do + transient do + user { FactoryBot.create(:user) } + + with_permission_template { false } + with_solr_document { false } + end + sequence(:title) { |n| ["Collection Title #{n}"] } + + after(:build) do |adminset, evaluator| + adminset.creator = [evaluator.user.user_key] + + AdminSetFactoryHelper.process_with_permission_template(adminset, evaluator) + AdminSetFactoryHelper.process_with_solr_document(adminset, evaluator) + end + + before(:create) do |adminset, evaluator| + # force create a permission template if it doesn't exist for the newly created admin set + AdminSetFactoryHelper.process_with_permission_template(adminset, evaluator, true) unless evaluator.with_permission_template + end + + after(:create) do |adminset, _evaluator| + adminset.permission_template.reset_access_controls_for(collection: adminset) + end + + factory :default_adminset, class: AdminSet do + transient do + with_permission_template do + { + deposit_groups: [::Ability.registered_group_name], + manage_groups: [::Ability.admin_group_name] + } + end + with_solr_document { true } + with_persisted_default_id { true } + end + id { AdminSet::DEFAULT_ID } + title { AdminSet::DEFAULT_TITLE } + + after(:create) do |admin_set, evaluator| + Hyrax::DefaultAdministrativeSet.update(default_admin_set_id: admin_set.id) if + evaluator.with_persisted_default_id + end + end + end + + factory :no_solr_grants_adminset, class: AdminSet do + # Builds a pre-Hyrax 2.1.0 adminset without edit/view grants on the admin set. + # Do not use with create because the save will cause the solr grants to be created. + transient do + user { FactoryBot.create(:user) } + with_permission_template { true } + with_solr_document { true } + end + + sequence(:title) { |n| ["No Solr Grant Admin Set Title #{n}"] } + + after(:build) do |adminset, evaluator| + adminset.creator = [evaluator.user.user_key] + AdminSetFactoryHelper.process_with_permission_template(adminset, evaluator, true) + AdminSetFactoryHelper.process_with_solr_document(adminset, evaluator, true) + end + end + + class AdminSetFactoryHelper + # @returns array of user keys + def self.permission_from_template(permission_template_attributes, permission_key) + permissions = [] + return permissions if permission_template_attributes.blank? + return permissions unless permission_template_attributes.is_a? Hash + return permissions unless permission_template_attributes.key?(permission_key) + permission_template_attributes[permission_key] + end + private_class_method :permission_from_template + + # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role + # @parem [String] creator_user is the user who created the new admin set + # @param [Boolean] include_creator, when true, adds the creator_user as a manager + # @returns array of user keys + def self.user_managers(permission_template_attributes, creator_user) + managers = permission_from_template(permission_template_attributes, :manage_users) + managers << creator_user + managers.uniq + end + + # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role + # @returns array of user keys + def self.group_managers(permission_template_attributes) + permission_from_template(permission_template_attributes, :manage_groups).uniq + end + + # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role + # @returns array of user keys + def self.user_depositors(permission_template_attributes) + permission_from_template(permission_template_attributes, :deposit_users).uniq + end + + # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role + # @returns array of user keys + def self.group_depositors(permission_template_attributes) + permission_from_template(permission_template_attributes, :deposit_groups).uniq + end + + # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role + # @returns array of user keys + def self.user_viewers(permission_template_attributes) + permission_from_template(permission_template_attributes, :view_users).uniq + end + + # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role + # @returns array of user keys + def self.group_viewers(permission_template_attributes) + permission_from_template(permission_template_attributes, :view_groups).uniq + end + + # Process the with_permission_template transient property such that... + # * a permission template is created for the admin set + # * a permission template access is created for the admin set creator + # * additional permission template accesses are created for each user/group identified in the attributes + # of with_permission_template (created by the permission_template factory) + # @param [AdminSet] admin set object being built/created by the factory + # @param [Class] evaluator holding the transient properties for the current build/creation process + # @param [Boolean] if true, force the permission template to be created + def self.process_with_permission_template(adminset, evaluator, force = false) + return unless force || evaluator.with_permission_template + adminset.id ||= FactoryBot.generate(:object_id) + attributes = { source_id: adminset.id } + attributes[:manage_users] = user_managers(evaluator.with_permission_template, evaluator.user) + attributes = evaluator.with_permission_template.merge(attributes) if evaluator.with_permission_template.respond_to?(:merge) + FactoryBot.create(:permission_template, attributes) unless Hyrax::PermissionTemplate.find_by(source_id: adminset.id) + end + + # Process the with_solr_document transient property such that... + # * a solr document is created for the admin set + # * permissions identified by with_permission_template, if any, are added to the solr fields + # @param [AdminSet] adminset object being built/created by the factory + # @param [Class] evaluator holding the transient properties for the current build/creation process + def self.process_with_solr_document(adminset, evaluator, creator_only = false) + return unless creator_only || evaluator.with_solr_document + Hyrax::SolrService.add(solr_document_with_permissions(adminset, evaluator, creator_only), commit: true) + end + + # Return the admin set's solr document with permissions added, such that... + # * permissions identified by with_permission_template, if any, are added to the solr fields + # @param [AdminSet] adminset object being built/created by the factory + # @param [Class] evaluator holding the transient properties for the current build/creation process + # @returns the admin set's solr document with permissions added + def self.solr_document_with_permissions(adminset, evaluator, creator_only) + adminset.id ||= FactoryBot.generate(:object_id) + if creator_only + adminset.edit_users = [evaluator.user] + else + adminset.edit_users = user_managers(evaluator.with_permission_template, evaluator.user) + adminset.edit_groups = group_managers(evaluator.with_permission_template) + adminset.read_users = user_viewers(evaluator.with_permission_template) + + user_depositors(evaluator.with_permission_template) + adminset.read_groups = group_viewers(evaluator.with_permission_template) + + group_depositors(evaluator.with_permission_template) - + [::Ability.registered_group_name, ::Ability.public_group_name] + end + adminset.to_solr + end + private_class_method :solr_document_with_permissions + end +end diff --git a/spec/factories/administrative_sets.rb b/spec/factories/administrative_sets.rb new file mode 100644 index 00000000..0f94f495 --- /dev/null +++ b/spec/factories/administrative_sets.rb @@ -0,0 +1,79 @@ +# frozen_string_literal: true + +FactoryBot.define do + ## + # This factory creates a Valkyrized adminstrative set; by default a Hyrax::AdministrativeSet + # + # Why the antics around the class? Because of the Hyrax needs and potential downstream + # applciation needs. + # + # Downstream applications might implement a different # administrative set and the downstream + # application might leverage other Hyrax factories that create a `:hyrax_admin_set` + # (e.g. `:permission_template`) + factory :hyrax_admin_set, class: (Hyrax.config.admin_set_class < Valkyrie::Resource ? Hyrax.config.admin_set_class : Hyrax::AdministrativeSet) do + title { ['My Admin Set'] } + + transient do + with_permission_template { false } + user { FactoryBot.create(:user) } + access_grants { [] } + with_index { true } + end + + after(:build) do |adminset, evaluator| + adminset.creator = [evaluator.user.user_key] + end + + after(:create) do |admin_set, evaluator| + admin_set.permission_manager.edit_groups = evaluator.edit_groups + admin_set.permission_manager.edit_users = evaluator.edit_users + admin_set.permission_manager.read_users = evaluator.read_users + admin_set.permission_manager.read_groups = evaluator.read_groups + + admin_set.permission_manager.acl.save + + if evaluator.with_permission_template + template = Hyrax::PermissionTemplate.find_or_create_by(source_id: admin_set.id.to_s) + evaluator.access_grants.each do |grant| + Hyrax::PermissionTemplateAccess.find_or_create_by(permission_template_id: template.id, + agent_type: grant[:agent_type], + agent_id: grant[:agent_id], + access: grant[:access]) + end + Hyrax::PermissionTemplateAccess.find_or_create_by(permission_template_id: template.id, + agent_type: Hyrax::PermissionTemplateAccess::USER, + agent_id: evaluator.user.user_key, + access: Hyrax::PermissionTemplateAccess::MANAGE) + template.reset_access_controls_for(collection: admin_set) + end + Hyrax.index_adapter.save(resource: admin_set) if evaluator.with_index + end + end + + trait :with_permission_template do + with_permission_template { true } + access_grants do + [{ agent_type: Hyrax::PermissionTemplateAccess::USER, + agent_id: user.user_key, + access: Hyrax::PermissionTemplateAccess::MANAGE }] + end + end + + factory :invalid_hyrax_admin_set, class: 'Hyrax::AdministrativeSet' do + # Title is required. Without title, the admin set is invalid. + end + + factory :default_hyrax_admin_set, class: 'Hyrax::AdministrativeSet' do + id { Hyrax::AdminSetCreateService::DEFAULT_ID } + title { Hyrax::AdminSetCreateService::DEFAULT_TITLE } + + transient do + with_persisted_default_id { true } + end + + after(:create) do |admin_set, evaluator| + Hyrax::DefaultAdministrativeSet.update(default_admin_set_id: admin_set.id) if + evaluator.with_persisted_default_id + end + end +end diff --git a/spec/factories/api_items.rb b/spec/factories/api_items.rb new file mode 100644 index 00000000..d2dd1cbc --- /dev/null +++ b/spec/factories/api_items.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :post_item, class: Hash do + skip_create + + token { 'mock_token' } + + metadata do + { + resourceType: 'Dataset', + title: 'Findings from NSF Study', + creators: [ + { + creatorType: 'author', + firstName: 'John', + lastName: 'Doe' + }, + { + creatorType: 'seriesEditor', + firstName: 'Rafael', + lastName: 'Nadal' + }, + { + creatorType: 'inventor', + name: 'Babs McGee' + }, + { + creatorType: 'contributor', + name: 'Jane Doeski' + } + ], + description: 'This was funded by the NSF in 2013', + publisher: 'National Science Foundation', + dateCreated: '2014-11-02T14:24:64Z', + basedNear: 'Paris, France', + identifier: 'isbn:1234567890', + url: 'http://example.org/nsf/2013/datasets/', + language: 'English--New Jerseyan', + license: 'http://creativecommons.org/licenses/by-sa/3.0/us/', + tags: [ + 'datasets', + 'nsf', + 'stuff' + ] + } + end + + file do + { + base64: 'YXJraXZvCg==', + md5: 'f03313ded2feb96f0a641b8eb098aae0', + filename: 'file.txt', + contentType: 'text/plain' + } + end + + initialize_with { attributes } + end + + factory :put_item, class: Hash, parent: :post_item do + metadata do + { + resourceType: 'Article', + title: 'THE REAL FINDINGS', + creators: [ + { + creatorType: 'author', + firstName: 'John', + lastName: 'Doe' + }, + { + creatorType: 'inventor', + name: 'Babs McGee' + } + ], + license: 'http://creativecommons.org/licenses/by-sa/3.0/us/', + tags: [ + 'datasets' + ] + } + end + + file do + { + base64: 'IyBIRUFERVIKClRoaXMgaXMgYSBwYXJhZ3JhcGghCg==', + md5: '3923077bb477097b8496dbcff5fa44b3', + filename: 'replaced.md', + contentType: 'text/x-markdown' + } + end + end +end diff --git a/spec/factories/collection_branding_infos.rb b/spec/factories/collection_branding_infos.rb new file mode 100644 index 00000000..9ae64f5d --- /dev/null +++ b/spec/factories/collection_branding_infos.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :collection_branding_info do + collection_id { "1" } + role { "banner" } + local_path { "/fake/path/to/banner.png" } + alt_text { "This is the banner" } + target_url { "http://example.com/" } + height { "" } + width { "" } + end +end diff --git a/spec/factories/collection_type_participants.rb b/spec/factories/collection_type_participants.rb new file mode 100644 index 00000000..43db7785 --- /dev/null +++ b/spec/factories/collection_type_participants.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :collection_type_participant, class: Hyrax::CollectionTypeParticipant do + association :hyrax_collection_type, factory: :collection_type + sequence(:agent_id) { |n| "user#{n}@example.com" } + agent_type { 'user' } + access { Hyrax::CollectionTypeParticipant::MANAGE_ACCESS } + end +end diff --git a/spec/factories/collection_types.rb b/spec/factories/collection_types.rb new file mode 100644 index 00000000..8f013ac7 --- /dev/null +++ b/spec/factories/collection_types.rb @@ -0,0 +1,139 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :collection_type, class: Hyrax::CollectionType do + sequence(:title) { |n| "Collection Type #{n}" } + sequence(:machine_id) { |n| "title_#{n}" } + + description { 'Collection type with all options' } + nestable { true } + discoverable { true } + sharable { true } + brandable { true } + share_applies_to_new_works { true } + allow_multiple_membership { true } + require_membership { false } + assigns_workflow { false } + assigns_visibility { false } + + transient do + creator_user { nil } + creator_group { nil } + manager_user { nil } + manager_group { nil } + end + + after(:create) do |collection_type, evaluator| + CollectionTypeFactoryHelper.process_access(collection_type, evaluator) + end + + trait :nestable do + nestable { true } + end + + trait :not_nestable do + nestable { false } + end + + trait :discoverable do + discoverable { true } + end + + trait :not_discoverable do + discoverable { false } + end + + trait :brandable do + brandable { true } + end + + trait :not_brandable do + brandable { false } + end + + trait :sharable do + sharable { true } + share_applies_to_new_works { true } + end + + trait :sharable_no_work_permissions do + sharable { true } + share_applies_to_new_works { false } + end + + trait :not_sharable do + sharable { false } + share_applies_to_new_works { false } + end + + trait :allow_multiple_membership do + allow_multiple_membership { true } + end + + trait :not_allow_multiple_membership do + allow_multiple_membership { false } + end + end + + factory :user_collection_type, class: Hyrax::CollectionType do + initialize_with { Hyrax::CollectionType.find_or_create_default_collection_type } + end + + factory :admin_set_collection_type, class: Hyrax::CollectionType do + initialize_with { Hyrax::CollectionType.find_or_create_admin_set_type } + + transient do + creator_user { nil } + creator_group { nil } + manager_user { nil } + manager_group { nil } + end + + after(:create) do |collection_type, evaluator| + CollectionTypeFactoryHelper.process_access(collection_type, evaluator) + end + end + + class CollectionTypeFactoryHelper + def self.process_access(collection_type, evaluator) # rubocop:disable Metrics/MethodLength + if evaluator.creator_user + Array(evaluator.creator_user).each do |user| + attributes = { hyrax_collection_type_id: collection_type.id, + access: Hyrax::CollectionTypeParticipant::CREATE_ACCESS, + agent_id: user, + agent_type: Hyrax::CollectionTypeParticipant::USER_TYPE } + FactoryBot.create(:collection_type_participant, attributes) + end + end + + if evaluator.creator_group + Array(evaluator.creator_group).each do |group| + attributes = { hyrax_collection_type_id: collection_type.id, + access: Hyrax::CollectionTypeParticipant::CREATE_ACCESS, + agent_id: group, + agent_type: Hyrax::CollectionTypeParticipant::GROUP_TYPE } + FactoryBot.create(:collection_type_participant, attributes) + end + end + + if evaluator.manager_user + Array(evaluator.manager_user).each do |user| + attributes = { hyrax_collection_type_id: collection_type.id, + access: Hyrax::CollectionTypeParticipant::MANAGE_ACCESS, + agent_id: user, + agent_type: Hyrax::CollectionTypeParticipant::USER_TYPE } + FactoryBot.create(:collection_type_participant, attributes) + end + end + + return unless evaluator.manager_group + + Array(evaluator.manager_group).each do |group| + attributes = { hyrax_collection_type_id: collection_type.id, + access: Hyrax::CollectionTypeParticipant::MANAGE_ACCESS, + agent_id: group, + agent_type: Hyrax::CollectionTypeParticipant::GROUP_TYPE } + FactoryBot.create(:collection_type_participant, attributes) + end + end + end +end diff --git a/spec/factories/collections.rb b/spec/factories/collections.rb new file mode 100644 index 00000000..e91d43d6 --- /dev/null +++ b/spec/factories/collections.rb @@ -0,0 +1,282 @@ +# frozen_string_literal: true +FactoryBot.define do + # Tests that create a Fedora Object are very slow. This factory lets you control which parts of the object ecosystem + # get built. + # + # PREFERRED: Use build whenever possible. You can control the creation of the permission template, collection type, and + # solr document by passing parameters to the build(:collection_lw) method. That way you can build only the parts + # needed for a specific test. + # + # AVOID: Do not use create unless absolutely necessary. It will create everything including the Fedora object. + # + # @example Simple build of a collection with no additional parts created. Lightest weight. + # NOTE: A user is automatically created as the owner of the collection. + # let(:collection) { build(:collection_lw) } + # + # @example Simple build of a collection with no additional parts created. User is the owner of the collection. Lightest weight. + # let(:collection) { build(:collection_lw, user:) } + # + # @example Simple build of a collection with only solr-document. Owner is given edit-access in solr-document. Light weight. + # let(:collection) { build(:collection_lw, with_solr_document: true) } + # + # @example Simple build of a collection with only a permission template created. Owner is set as a manager. Light weight. + # let(:collection) { build(:collection_lw, with_permission_template: true) } + # + # @example Build a collection with only a permission template created. Permissions are set based on + # attributes set for `with_permission_template`. Middle weight. + # # permissions passed thru `with_permission_template` can be any of the following in any combination + # let(:permissions) { { manage_users: [user.user_key], # multiple users can be listed + # deposit_users: [user.user_key], + # view_users: [user.user_key], + # manage_groups: [group_name], # multiple groups can be listed + # deposit_groups: [group_name], + # view_groups: [group_name], } } + # let(:collection) { build(:collection_lw, user: , with_permission_template: permissions) } + # + # @example Build a collection with permission template and solr-document created. Permissions are set based on + # attributes set for `with_permission_template`. Solr-document includes read/edit access defined based + # on attributes passed thru `with_permission_template`. Middle weight. + # # permissions passed thru `with_permission_template` can be any of the following in any combination + # let(:permissions) { { manage_users: [user.user_key], # multiple users can be listed + # deposit_users: [user.user_key], + # view_users: [user.user_key], + # manage_groups: [group_name], # multiple groups can be listed + # deposit_groups: [group_name], + # view_groups: [group_name], } } + # let(:collection) { build(:collection_lw, user: , with_permission_template: permissions, with_solr_document: true) } + # + # @example Build a collection generating its collection type with specific settings. Light Weight. + # NOTE: Do not use this approach if you need access to the collection type in the test. + # DEFAULT: If `collection_type_settings` and `collection_type` are not specified, then the default + # User Collection type will be used. + # # Any not specified default to ON. At least one setting should be specified. + # let(:settings) { [ + # :nestable, # OR :not_nestable, + # :discoverable, # OR :not_discoverable + # :brandable, # OR :not_brandable + # :sharable, # OR :not_sharable OR :sharable_no_work_permissions + # :allow_multiple_membership, # OR :not_allow_multiple_membership + # ] } + # let(:collection) { build(:collection_lw, collection_type_settings: settings) } + # + # @example Build a collection using the passed in collection type. Light Weight. + # NOTE: Use this approach if you need access to the collection type in the test. + # # Any not specified default to ON. At least one setting should be specified. + # let(:settings) { [ + # :nestable, # OR :not_nestable, + # :discoverable, # OR :not_discoverable + # :brandable, # OR :not_brandable + # :sharable, # OR :not_sharable OR :sharable_no_work_permissions + # :allow_multiple_membership, # OR :not_allow_multiple_membership + # ] } + # let(:collection_type) { create(:collection_lw_type, settings) } + # let(:collection) { build(:collection_lw, collection_type: collection_type) } + + factory :collection_lw, class: Collection do + transient do + user { FactoryBot.create(:user) } + + collection_type { nil } + collection_type_settings { nil } + with_permission_template { false } + with_solr_document { false } + end + sequence(:title) { |n| ["Collection Title #{n}"] } + + after(:build) do |collection, evaluator| + collection.collection_type_gid = evaluator.collection_type.to_global_id if evaluator.collection_type&.id.present? + collection.apply_depositor_metadata(evaluator.user.user_key) + + CollectionLwFactoryHelper.process_collection_type_settings(collection, evaluator) + CollectionLwFactoryHelper.process_with_permission_template(collection, evaluator) + CollectionLwFactoryHelper.process_with_solr_document(collection, evaluator) + end + + before(:create) do |collection, evaluator| + # force create a permission template if it doesn't exist for the newly created collection + CollectionLwFactoryHelper.process_with_permission_template(collection, evaluator, true) unless evaluator.with_permission_template + end + + after(:create) do |collection, _evaluator| + collection.permission_template.reset_access_controls_for(collection: collection, interpret_visibility: true) + end + + factory :public_collection_lw, traits: [:public_lw] + + factory :private_collection_lw do + visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE } + end + + factory :institution_collection_lw do + visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED } + end + + factory :named_collection_lw do + title { ['collection title'] } + description { ['collection description'] } + end + + trait :public_lw do + visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC } + end + + trait :private_lw do + visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE } + end + + trait :institution_lw do + visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED } + end + + trait :public_lw do + visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC } + end + end + + factory :user_collection_lw, class: Collection do + transient do + user { FactoryBot.create(:user) } + collection_type { create(:user_collection_type) } + end + + sequence(:title) { |n| ["User Collection Title #{n}"] } + + after(:build) do |collection, evaluator| + collection.apply_depositor_metadata(evaluator.user.user_key) + end + end + + factory :typeless_collection_lw, class: Collection do + # To create a pre-Hyrax 2.1.0 collection without a collection type gid... + # col = build(:typeless_collection, ...) + # col.save(validate: false) + transient do + user { FactoryBot.create(:user) } + with_permission_template { false } + do_save { false } + end + + sequence(:title) { |n| ["Typeless Collection Title #{n}"] } + + after(:build) do |collection, evaluator| + collection.apply_depositor_metadata(evaluator.user.user_key) + collection.save(validate: false) if evaluator.do_save || evaluator.with_permission_template + if evaluator.with_permission_template + attributes = { source_id: collection.id } + attributes[:manage_users] = [evaluator.user] + attributes = evaluator.with_permission_template.merge(attributes) if evaluator.with_permission_template.respond_to?(:merge) + create(:permission_template, attributes) unless Hyrax::PermissionTemplate.find_by(source_id: collection.id) + end + end + end + + class CollectionLwFactoryHelper + # @returns array of user keys + def self.permission_from_template(permission_template_attributes, permission_key) + permissions = [] + return permissions if permission_template_attributes.blank? + return permissions unless permission_template_attributes.is_a? Hash + return permissions unless permission_template_attributes.key?(permission_key) + permission_template_attributes[permission_key] + end + private_class_method :permission_from_template + + # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role + # @parem [String] creator_user is the user who created the new collection + # @param [Boolean] include_creator, when true, adds the creator_user as a manager + # @returns array of user keys + def self.user_managers(permission_template_attributes, creator_user) + managers = permission_from_template(permission_template_attributes, :manage_users) + managers << creator_user + managers + end + + # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role + # @returns array of user keys + def self.group_managers(permission_template_attributes) + permission_from_template(permission_template_attributes, :manage_groups) + end + + # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role + # @returns array of user keys + def self.user_depositors(permission_template_attributes) + permission_from_template(permission_template_attributes, :deposit_users) + end + + # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role + # @returns array of user keys + def self.group_depositors(permission_template_attributes) + permission_from_template(permission_template_attributes, :deposit_groups) + end + + # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role + # @returns array of user keys + def self.user_viewers(permission_template_attributes) + permission_from_template(permission_template_attributes, :view_users) + end + + # @param [Hash] permission_template_attributes where names identify the role and value are the user keys for that role + # @returns array of user keys + def self.group_viewers(permission_template_attributes) + permission_from_template(permission_template_attributes, :view_groups) + end + + # Process the collection_type_settings transient property such that... + # * creates the collection type with specified settings if collection_type_settings has settings (ignores collection_type_gid) + # * uses passed in collection type if collection_type_gid is specified AND collection_type_settings is nil + # * uses default User Collection type if neither are specified + # @param [Collection] collection object being built/created by the factory + # @param [Class] evaluator holding the transient properties for the current build/creation process + def self.process_collection_type_settings(collection, evaluator) + if evaluator.collection_type_settings.present? + collection.collection_type = FactoryBot.create(:collection_type, *evaluator.collection_type_settings) + elsif collection.collection_type_gid.blank? + collection.collection_type = FactoryBot.create(:user_collection_type) + end + end + + # Process the with_permission_template transient property such that... + # * a permission template is created for the collection + # * a permission template access is created for the collection creator + # * additional permission template accesses are created for each user/group identified in the attributes + # of with_permission_template (created by the permission_template factory) + # @param [Collection] collection object being built/created by the factory + # @param [Class] evaluator holding the transient properties for the current build/creation process + # @param [Boolean] if true, force the permission template to be created + def self.process_with_permission_template(collection, evaluator, force = false) + return unless force || evaluator.with_permission_template + collection.id ||= FactoryBot.generate(:object_id) + attributes = { source_id: collection.id } + attributes[:manage_users] = user_managers(evaluator.with_permission_template, evaluator.user) + attributes = evaluator.with_permission_template.merge(attributes) if evaluator.with_permission_template.respond_to?(:merge) + FactoryBot.create(:permission_template, attributes) unless Hyrax::PermissionTemplate.find_by(source_id: collection.id) + end + + # Process the with_solr_document transient property such that... + # * a solr document is created for the collection + # * permissions identified by with_permission_template, if any, are added to the solr fields + # @param [Collection] collection object being built/created by the factory + # @param [Class] evaluator holding the transient properties for the current build/creation process + def self.process_with_solr_document(collection, evaluator) + return unless evaluator.with_solr_document + Hyrax::SolrService.add(solr_document_with_permissions(collection, evaluator), commit: true) + end + + # Return the collection's solr document with permissions added, such that... + # * permissions identified by with_permission_template, if any, are added to the solr fields + # @param [Collection] collection object being built/created by the factory + # @param [Class] evaluator holding the transient properties for the current build/creation process + # @returns the collection's solr document with permissions added + def self.solr_document_with_permissions(collection, evaluator) + collection.id ||= FactoryBot.generate(:object_id) + collection.edit_users = user_managers(evaluator.with_permission_template, evaluator.user) + collection.edit_groups = group_managers(evaluator.with_permission_template) + collection.read_users = user_viewers(evaluator.with_permission_template) + + user_depositors(evaluator.with_permission_template) + collection.read_groups = group_viewers(evaluator.with_permission_template) + + group_depositors(evaluator.with_permission_template) + collection.to_solr + end + private_class_method :solr_document_with_permissions + end +end diff --git a/spec/factories/collections_factory.rb b/spec/factories/collections_factory.rb new file mode 100644 index 00000000..febf05d7 --- /dev/null +++ b/spec/factories/collections_factory.rb @@ -0,0 +1,107 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :collection do + # DEPRECATION: This factory is being replaced by collection_lw defined in collections.rb. New tests should use the + # light weight collection factory. DO NOT ADD tests using this factory. + # + # rubocop:disable Layout/LineLength + # @example let(:collection) { build(:collection, collection_type_settings: [:not_nestable, :discoverable, :sharable, :allow_multiple_membership]) } + # rubocop:enable Layout/LineLength + + transient do + user { FactoryBot.create(:user) } + # allow defaulting to default user collection + collection_type_settings { nil } + with_permission_template { false } + create_access { false } + end + sequence(:title) { |n| ["Collection Title #{n}"] } + + after(:build) do |collection, evaluator| + collection.apply_depositor_metadata(evaluator.user.user_key) + if evaluator.collection_type_settings.present? + collection.collection_type = create(:collection_type, *evaluator.collection_type_settings) + elsif collection.collection_type_gid.nil? + collection.collection_type = create(:user_collection_type) + end + end + + after(:create) do |collection, evaluator| + # create the permission template if it was requested + if evaluator.with_permission_template || evaluator.create_access + attributes = { source_id: collection.id } + attributes[:manage_users] = CollectionFactoryHelper.user_managers(evaluator.with_permission_template, evaluator.user, evaluator.create_access) + attributes = evaluator.with_permission_template.merge(attributes) if evaluator.with_permission_template.respond_to?(:merge) + create(:permission_template, attributes) unless Hyrax::PermissionTemplate.find_by(source_id: collection.id) + collection.permission_template.reset_access_controls_for(collection: collection, interpret_visibility: true) + end + end + + factory :public_collection, traits: [:public] + + trait :public do + visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC } + end + + factory :private_collection do + visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE } + end + + factory :institution_collection do + visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED } + end + + factory :named_collection do + title { ['collection title'] } + description { ['collection description'] } + end + end + + factory :user_collection, class: Collection do + transient do + user { FactoryBot.create(:user) } + collection_type { create(:user_collection_type) } + end + + sequence(:title) { |n| ["User Collection Title #{n}"] } + + after(:build) do |collection, evaluator| + collection.apply_depositor_metadata(evaluator.user.user_key) + end + end + + factory :typeless_collection, class: Collection do + # To create a pre-Hyrax 2.1.0 collection without a collection type gid... + # col = build(:typeless_collection, ...) + # col.save(validate: false) + transient do + user { FactoryBot.create(:user) } + with_permission_template { false } + create_access { false } + do_save { false } + end + + sequence(:title) { |n| ["Typeless Collection Title #{n}"] } + + after(:build) do |collection, evaluator| + collection.apply_depositor_metadata(evaluator.user.user_key) + collection.save(validate: false) if evaluator.do_save || evaluator.with_permission_template + if evaluator.with_permission_template + attributes = { source_id: collection.id } + attributes[:manage_users] = [evaluator.user] if evaluator.create_access + attributes = evaluator.with_permission_template.merge(attributes) if evaluator.with_permission_template.respond_to?(:merge) + create(:permission_template, attributes) unless Hyrax::PermissionTemplate.find_by(source_id: collection.id) + end + end + end + + class CollectionFactoryHelper + def self.user_managers(permission_template_attributes, creator_user, include_creator = false) + managers = [] + managers << creator_user.user_key if include_creator + return managers unless permission_template_attributes.respond_to?(:merge) + return managers unless permission_template_attributes.key?(:manage_users) + managers + permission_template_attributes[:manage_users] + end + end +end diff --git a/spec/factories/content_blocks.rb b/spec/factories/content_blocks.rb new file mode 100644 index 00000000..6e498fe0 --- /dev/null +++ b/spec/factories/content_blocks.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :content_block do |_cb| + end +end diff --git a/spec/factories/counter_metrics.rb b/spec/factories/counter_metrics.rb new file mode 100644 index 00000000..2706ad14 --- /dev/null +++ b/spec/factories/counter_metrics.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :counter_metric, class: "Hyrax::CounterMetric" do + worktype { "Generic Work" } + resource_type { "Book" } + work_id { "12345678" } + date { Date.new(2023, 7, 17) } + total_item_investigations { 10 } + total_item_requests { 5 } + end +end diff --git a/spec/factories/featured_works.rb b/spec/factories/featured_works.rb new file mode 100644 index 00000000..2db9307d --- /dev/null +++ b/spec/factories/featured_works.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :featured_work do |_u| + end +end diff --git a/spec/factories/file_sets.rb b/spec/factories/file_sets.rb new file mode 100644 index 00000000..3d02612c --- /dev/null +++ b/spec/factories/file_sets.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :file_set do + transient do + user { FactoryBot.create(:user) } + content { nil } + end + after(:build) do |fs, evaluator| + fs.apply_depositor_metadata evaluator.user.user_key + end + + after(:create) do |file, evaluator| + Hydra::Works::UploadFileToFileSet.call(file, evaluator.content) if evaluator.content + end + + trait :public do + read_groups { ["public"] } + end + + trait :registered do + read_groups { ["registered"] } + end + + trait :image do + # content { File.open(Hyrax::Engine.root + 'spec/fixtures/world.png') } + # overriding to just load from scholarspace path + content { File.open(Rails.root + 'spec/fixtures/world.png') } + end + + trait :with_original_file do + after(:create) do |file_set, _evaluator| + Hydra::Works::AddFileToFileSet + # overriding to just load from scholarspace path + # .call(file_set, File.open(Hyrax::Engine.root + 'spec/fixtures/world.png'), :original_file) + .call(file_set, File.open(Rails.root + 'spec/fixtures/world.png'), :original_file) + end + end + + factory :file_with_work do + after(:build) do |file, _evaluator| + file.title = ['testfile'] + end + after(:create) do |file, evaluator| + Hydra::Works::UploadFileToFileSet.call(file, evaluator.content) if evaluator.content + create(:work, user: evaluator.user).members << file + end + end + end +end diff --git a/spec/factories/gw_etds.rb b/spec/factories/gw_etds.rb new file mode 100644 index 00000000..b720f5dd --- /dev/null +++ b/spec/factories/gw_etds.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :etd, aliases: [:gw_etd, :private_etd], class: 'GwEtd' do + transient do + user { FactoryBot.create(:user) } + # Set to true (or a hash) if you want to create an admin set + with_admin_set { false } + end + + # It is reasonable to assume that a work has an admin set; However, we don't want to + # go through the entire rigors of creating that admin set. + before(:create) do |work, evaluator| + if evaluator.with_admin_set + attributes = {} + attributes[:id] = work.admin_set_id if work.admin_set_id.present? + attributes = evaluator.with_admin_set.merge(attributes) if evaluator.with_admin_set.respond_to?(:merge) + admin_set = create(:admin_set, attributes) + work.admin_set_id = admin_set.id + end + end + + after(:create) do |work, _evaluator| + work.save! if work.try(:member_of_collections) && work.member_of_collections.present? + end + + title { ["Test title"] } + + after(:build) do |work, evaluator| + work.apply_depositor_metadata(evaluator.user.user_key) if work.try(:apply_depositor_metadata, evaluator.user.user_key) + end + + factory :public_etd, traits: [:public] + + trait :public do + visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC } + end + + factory :authenticated_etd, traits: [:authenticated] + + trait :authenticated do + visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED } + end + end +end diff --git a/spec/factories/gw_journal_issues.rb b/spec/factories/gw_journal_issues.rb new file mode 100644 index 00000000..2b83a0e9 --- /dev/null +++ b/spec/factories/gw_journal_issues.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :journal_issue, aliases: [:gw_journal_issue, :private_journal_issue], class: 'GwJournalIssue' do + transient do + user { FactoryBot.create(:user) } + # Set to true (or a hash) if you want to create an admin set + with_admin_set { false } + end + + # It is reasonable to assume that a work has an admin set; However, we don't want to + # go through the entire rigors of creating that admin set. + before(:create) do |work, evaluator| + if evaluator.with_admin_set + attributes = {} + attributes[:id] = work.admin_set_id if work.admin_set_id.present? + attributes = evaluator.with_admin_set.merge(attributes) if evaluator.with_admin_set.respond_to?(:merge) + admin_set = create(:admin_set, attributes) + work.admin_set_id = admin_set.id + end + end + + after(:create) do |work, _evaluator| + work.save! if work.try(:member_of_collections) && work.member_of_collections.present? + end + + title { ["Test title"] } + + after(:build) do |work, evaluator| + work.apply_depositor_metadata(evaluator.user.user_key) if work.try(:apply_depositor_metadata, evaluator.user.user_key) + end + + factory :public_journal_issue, traits: [:public] + + trait :public do + visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC } + end + + factory :authenticated_journal_issue, traits: [:authenticated] + + trait :authenticated do + visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED } + end + + factory :invalid_journal_issue do + title { nil } + end + end +end diff --git a/spec/factories/gw_works.rb b/spec/factories/gw_works.rb index 3f0dc88b..92e5aad0 100644 --- a/spec/factories/gw_works.rb +++ b/spec/factories/gw_works.rb @@ -1,17 +1,206 @@ -FactoryBot.define do - factory :gw_work do - id { Noid::Rails::Service.new.mint } - title { [Faker::Book.title] } +# frozen_string_literal: true +FactoryBot.define do + factory :work, aliases: [:generic_work, :private_generic_work], class: 'GwWork' do transient do - visibility { "public" } - user { nil } + user { FactoryBot.create(:user) } + # Set to true (or a hash) if you want to create an admin set + with_admin_set { false } + end + + # It is reasonable to assume that a work has an admin set; However, we don't want to + # go through the entire rigors of creating that admin set. + before(:create) do |work, evaluator| + if evaluator.with_admin_set + attributes = {} + attributes[:id] = work.admin_set_id if work.admin_set_id.present? + attributes = evaluator.with_admin_set.merge(attributes) if evaluator.with_admin_set.respond_to?(:merge) + admin_set = create(:admin_set, attributes) + work.admin_set_id = admin_set.id + end + end + + after(:create) do |work, _evaluator| + work.save! if work.try(:member_of_collections) && work.member_of_collections.present? + end + + title { ["Test title"] } + + after(:build) do |work, evaluator| + work.apply_depositor_metadata(evaluator.user.user_key) if work.try(:apply_depositor_metadata, evaluator.user.user_key) + end + + factory :public_generic_work, aliases: [:public_work], traits: [:public] + + trait :public do + visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC } + end + + factory :authenticated_generic_work, aliases: [:authenticated_work], traits: [:authenticated] + + trait :authenticated do + visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED } + end + + factory :invalid_generic_work do + title { nil } + end + + factory :private_work do + # private is default + # visibility { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE } + end + + factory :registered_generic_work do + read_groups { ["registered"] } + end + + factory :work_with_one_file do + before(:create) do |work, evaluator| + work.ordered_members << create(:file_set, user: evaluator.user, title: ['A Contained FileSet'], label: 'filename.pdf') + end end - after :create do |work, options| - work.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC if options.visibility == "public" - work.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE if options.visibility == "private" - work.visibility = Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED if options.visibility == "authenticated" + factory :work_with_files do + before(:create) { |work, evaluator| 2.times { work.ordered_members << create(:file_set, user: evaluator.user) } } end + + factory :work_with_image_files do + before(:create) { |work, evaluator| 2.times { work.ordered_members << create(:file_set, :image, user: evaluator.user) } } + end + + factory :work_with_ordered_files do + before(:create) do |work, evaluator| + work.ordered_members << create(:file_set, user: evaluator.user) + work.ordered_member_proxies.insert_target_at(0, create(:file_set, user: evaluator.user)) + end + end + + factory :work_with_one_child do + before(:create) do |work, evaluator| + work.ordered_members << create(:work, user: evaluator.user, title: ['A Contained Work']) + end + end + + factory :work_with_two_children do + before(:create) do |work, evaluator| + work.ordered_members << create(:work, user: evaluator.user, title: ['A Contained Work'], id: "BlahBlah1") + work.ordered_members << create(:work, user: evaluator.user, title: ['Another Contained Work'], id: "BlahBlah2") + end + end + + factory :work_with_representative_file do + before(:create) do |work, evaluator| + work.ordered_members << create(:file_set, user: evaluator.user, title: ['A Contained FileSet']) + work.representative_id = work.members[0].id + end + end + + factory :work_with_file_and_work do + before(:create) do |work, evaluator| + work.ordered_members << create(:file_set, user: evaluator.user) + work.ordered_members << create(:work, user: evaluator.user) + end + end + + factory :with_embargo_date do + # build with defaults: + # let(:work) { create(:embargoed_work) } + + # build with specific values: + # let(:embargo_attributes) do + # { embargo_date: Date.tomorrow.to_s, + # current_state: Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE, + # future_state: Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC } + # end + # let(:work) { create(:embargoed_work, with_embargo_attributes: embargo_attributes) } + + transient do + with_embargo_attributes { false } + embargo_date { Date.tomorrow.to_s } + current_state { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE } + future_state { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC } + end + factory :embargoed_work do + after(:build) do |work, evaluator| + if evaluator.with_embargo_attributes + work.apply_embargo(evaluator.with_embargo_attributes[:embargo_date], + evaluator.with_embargo_attributes[:current_state], + evaluator.with_embargo_attributes[:future_state]) + else + work.apply_embargo(evaluator.embargo_date, + evaluator.current_state, + evaluator.future_state) + end + end + end + factory :embargoed_work_with_files do + after(:build) do |work, evaluator| + if evaluator.with_embargo_attributes + work.apply_embargo(evaluator.with_embargo_attributes[:embargo_date], + evaluator.with_embargo_attributes[:current_state], + evaluator.with_embargo_attributes[:future_state]) + else + work.apply_embargo(evaluator.embargo_date, + evaluator.current_state, + evaluator.future_state) + end + end + after(:create) { |work, evaluator| 2.times { work.ordered_members << create(:file_set, user: evaluator.user) } } + end + end + + factory :with_lease_date do + # build with defaults: + # let(:work) { create(:leased_work) } + + # build with specific values: + # let(:lease_attributes) do + # { lease_date: Date.tomorrow.to_s, + # current_state: Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC, + # future_state: Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED } + # end + # let(:work) { create(:leased_work, with_lease_attributes: lease_attributes) } + + transient do + with_lease_attributes { false } + lease_date { Date.tomorrow.to_s } + current_state { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC } + future_state { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PRIVATE } + end + factory :leased_work do + after(:build) do |work, evaluator| + if evaluator.with_lease_attributes + work.apply_lease(evaluator.with_lease_attributes[:lease_date], + evaluator.with_lease_attributes[:current_state], + evaluator.with_lease_attributes[:future_state]) + else + work.apply_lease(evaluator.lease_date, + evaluator.current_state, + evaluator.future_state) + end + end + end + factory :leased_work_with_files do + after(:build) do |work, evaluator| + if evaluator.with_lease_attributes + work.apply_lease(evaluator.with_lease_attributes[:lease_date], + evaluator.with_lease_attributes[:current_state], + evaluator.with_lease_attributes[:future_state]) + else + work.apply_lease(evaluator.lease_date, + evaluator.current_state, + evaluator.future_state) + end + end + after(:create) { |work, evaluator| 2.times { work.ordered_members << create(:file_set, user: evaluator.user) } } + end + end + end + + # Doesn't set up any edit_users + factory :work_without_access, class: 'GenericWork' do + title { ['Test title'] } + depositor { create(:user).user_key } end -end \ No newline at end of file +end diff --git a/spec/factories/hyrax_collection.rb b/spec/factories/hyrax_collection.rb new file mode 100644 index 00000000..97334f38 --- /dev/null +++ b/spec/factories/hyrax_collection.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +## +# Use this factory for generic Hyrax/HydraWorks Collections in valkyrie. +# +# This factory creates a Valkyrized collection set; by default a Hyrax::PcdmCollection +# +# Why the antics around the class? Because of the Hyrax needs and potential downstream +# applciation needs. +# +# Downstream applications might implement a different collection class and the downstream +# application might leverage other Hyrax factories that create a `:hyrax_collection` +FactoryBot.define do + factory :hyrax_collection, class: (Hyrax.config.collection_class < Valkyrie::Resource ? Hyrax.config.collection_class : 'CollectionResource'), aliases: [:collection_resource] do + sequence(:title) { |n| ["The Tove Jansson Collection #{n}"] } + collection_type_gid { Hyrax::CollectionType.find_or_create_default_collection_type.to_global_id.to_s } + + transient do + with_permission_template { true } + collection_type { nil } + with_index { true } + user { FactoryBot.create(:user) } + edit_groups { [] } + edit_users { [] } + read_groups { [] } + read_users { [] } + members { nil } + access_grants { [] } + end + + after(:build) do |collection, evaluator| + collection.depositor ||= evaluator.user.user_key + collection.collection_type_gid = evaluator.collection_type.to_global_id.to_s if evaluator.collection_type + end + + after(:create) do |collection, evaluator| + if evaluator.members.present? + evaluator.members.map do |member| + member.member_of_collection_ids += [collection.id] + member = Hyrax.persister.save(resource: member) + Hyrax.index_adapter.save(resource: member) if evaluator.with_index + end + end + if evaluator.with_permission_template + Hyrax::Collections::PermissionsCreateService.create_default(collection: collection, + creating_user: evaluator.user, + grants: evaluator.access_grants) + collection.permission_manager.edit_groups = collection.permission_manager.edit_groups.to_a + + evaluator.edit_groups + collection.permission_manager.edit_users = collection.permission_manager.edit_users.to_a + + evaluator.edit_users + collection.permission_manager.read_groups = collection.permission_manager.read_groups.to_a + + evaluator.read_groups + collection.permission_manager.read_users = collection.permission_manager.read_users.to_a + + evaluator.read_users + collection.permission_manager.acl.save + end + Hyrax.index_adapter.save(resource: collection) if evaluator.with_index + end + + trait :public do + read_groups { ['public'] } + end + + trait :with_member_works do + transient do + members { [valkyrie_create(:hyrax_work), valkyrie_create(:hyrax_work)] } + end + end + + trait :with_member_collections do + transient do + members { [valkyrie_create(:hyrax_collection), valkyrie_create(:hyrax_collection)] } + end + end + + trait :as_collection_member do + member_of_collection_ids { [valkyrie_create(:hyrax_collection).id] } + end + + trait :as_member_of_multiple_collections do + member_of_collection_ids do + [valkyrie_create(:hyrax_collection).id, + valkyrie_create(:hyrax_collection).id, + valkyrie_create(:hyrax_collection).id] + end + end + + factory :pcdm_collection, class: 'Hyrax::PcdmCollection' do + end + end +end diff --git a/spec/factories/hyrax_default_admin_set.rb b/spec/factories/hyrax_default_admin_set.rb new file mode 100644 index 00000000..fbb51d3a --- /dev/null +++ b/spec/factories/hyrax_default_admin_set.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :stored_default_admin_set_id, class: Hyrax::DefaultAdministrativeSet do + id { 1 } + default_admin_set_id { Hyrax::AdminSetCreateService::DEFAULT_ID } + end +end diff --git a/spec/factories/hyrax_embargo.rb b/spec/factories/hyrax_embargo.rb new file mode 100644 index 00000000..2111df52 --- /dev/null +++ b/spec/factories/hyrax_embargo.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :hyrax_embargo, class: "Hyrax::Embargo" do + embargo_release_date { (Time.zone.today + 10).to_datetime } + visibility_after_embargo { 'open' } + visibility_during_embargo { 'authenticated' } + + to_create do |instance| + saved_instance = Valkyrie.config.metadata_adapter.persister.save(resource: instance) + instance.id = saved_instance.id + saved_instance + end + + trait :expired do + embargo_release_date { (Time.zone.today - 1).to_datetime } + end + end +end diff --git a/spec/factories/hyrax_file_metadata.rb b/spec/factories/hyrax_file_metadata.rb new file mode 100644 index 00000000..22416cdd --- /dev/null +++ b/spec/factories/hyrax_file_metadata.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +## +# Use this factory for FileMetadata for Files in valkyrie. +FactoryBot.define do + factory :hyrax_file_metadata, class: 'Hyrax::FileMetadata', aliases: [:file_metadata] do + transient do + use { nil } + visibility_setting { nil } + end + + after(:build) do |file_metadata, evaluator| + if evaluator.visibility_setting + Hyrax::VisibilityWriter + .new(resource: file_metadata) + .assign_access_for(visibility: evaluator.visibility_setting) + end + file_metadata.pcdm_use = Hyrax::FileMetadata::Use.uri_for(use: evaluator.use) if evaluator.use + end + + after(:create) do |file_metadata, evaluator| + if evaluator.visibility_setting + writer = Hyrax::VisibilityWriter.new(resource: file_metadata) + writer.assign_access_for(visibility: evaluator.visibility_setting) + writer.permission_manager.acl.save + end + end + + trait :public do + transient do + visibility_setting { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC } + end + end + + trait :original_file do + use { Hyrax::FileMetadata::Use.uri_for(use: :original_file) } + end + + trait :thumbnail do + use { Hyrax::FileMetadata::Use.uri_for(use: :thumbnail_file) } + end + + trait :extracted_text do + use { Hyrax::FileMetadata::Use.uri_for(use: :extracted_file) } + end + + trait :service_file do + use { Hyrax::FileMetadata::Use.uri_for(use: :service_file) } + end + + trait :image do + mime_type { 'image/png' } + end + + trait :audio_file do + mime_type { 'audio/x-wave' } + end + + trait :video_file do + mime_type { 'video/mp4' } + end + + trait :with_file do + transient do + file { FactoryBot.create(:uploaded_file, file: File.open(Hyrax::Engine.root + 'spec/fixtures/world.png')) } + file_set { FactoryBot.valkyrie_create(:hyrax_file_set) } + user { FactoryBot.create(:user) } + end + + after(:build) do |file_metadata, evaluator| + file_metadata.label = evaluator.file.uploader.filename + file_metadata.mime_type = evaluator.file.uploader.content_type if file_metadata.mime_type == Hyrax::FileMetadata::GENERIC_MIME_TYPE + file_metadata.original_filename = evaluator.file.uploader.filename + file_metadata.recorded_size = evaluator.file.uploader.size + file_metadata.file_set_id = evaluator.file_set.id + end + + before(:create) do |file_metadata, evaluator| + saved = Hyrax.storage_adapter.upload(resource: evaluator.file_set, + file: evaluator.file.uploader.file, + original_filename: evaluator.file.uploader.filename) + file_metadata.file_identifier = saved.id + end + + after(:create) do |file_metadata, evaluator| + Hyrax::ValkyrieUpload.new.add_file_to_file_set(file_set: evaluator.file_set, + file_metadata: file_metadata, + user: evaluator.user) + end + end + end +end diff --git a/spec/factories/hyrax_file_set.rb b/spec/factories/hyrax_file_set.rb new file mode 100644 index 00000000..02fd3435 --- /dev/null +++ b/spec/factories/hyrax_file_set.rb @@ -0,0 +1,129 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :hyrax_file_set, class: 'Hyrax::FileSet' do + transient do + files { nil } + original_file { nil } + extracted_text { nil } + thumbnail { nil } + visibility_setting { nil } + edit_users { [] } + edit_groups { [] } + read_users { [] } + read_groups { [] } + with_index { true } + end + + after(:build) do |file_set, evaluator| + if evaluator.visibility_setting + Hyrax::VisibilityWriter + .new(resource: file_set) + .assign_access_for(visibility: evaluator.visibility_setting) + end + file_set.file_ids = evaluator.files.map(&:id) if evaluator.files + + file_set.permission_manager.edit_groups = file_set.permission_manager.edit_groups.to_a + evaluator.edit_groups + file_set.permission_manager.edit_users = file_set.permission_manager.edit_users.to_a + evaluator.edit_users + file_set.permission_manager.read_users = file_set.permission_manager.read_users.to_a + evaluator.read_users + file_set.permission_manager.read_groups = file_set.permission_manager.read_groups.to_a + evaluator.read_groups + end + + after(:create) do |file_set, evaluator| + if evaluator.visibility_setting + writer = Hyrax::VisibilityWriter.new(resource: file_set) + writer.assign_access_for(visibility: evaluator.visibility_setting) + writer.permission_manager.acl.save + end + + file_set.permission_manager.edit_groups = file_set.permission_manager.edit_groups.to_a + evaluator.edit_groups + file_set.permission_manager.edit_users = file_set.permission_manager.edit_users.to_a + evaluator.edit_users + file_set.permission_manager.read_users = file_set.permission_manager.read_users.to_a + evaluator.read_users + file_set.permission_manager.read_groups = file_set.permission_manager.read_groups.to_a + evaluator.read_groups + + file_set.permission_manager.acl.save + + Hyrax.index_adapter.save(resource: file_set) if evaluator.with_index + end + + trait :under_embargo do + association :embargo, factory: :hyrax_embargo + + after(:create) do |fs, _e| + Hyrax::EmbargoManager.new(resource: fs).apply + fs.permission_manager.acl.save + end + end + + trait :with_expired_enforced_embargo do + after(:build) do |fs, _evaluator| + fs.embargo = FactoryBot.valkyrie_create(:hyrax_embargo, :expired) + end + + after(:create) do |fs, _evaluator| + allow(Hyrax::TimeService).to receive(:time_in_utc).and_return(10.days.ago) + Hyrax::EmbargoManager.new(resource: fs).apply + fs.permission_manager.acl.save + allow(Hyrax::TimeService).to receive(:time_in_utc).and_call_original + end + end + + trait :under_lease do + association :lease, factory: :hyrax_lease + + after(:create) do |fs, _e| + Hyrax::LeaseManager.new(resource: fs).apply + fs.permission_manager.acl.save + end + end + + trait :with_expired_enforced_lease do + after(:build) do |fs, _evaluator| + fs.lease = FactoryBot.valkyrie_create(:hyrax_lease, :expired) + end + + after(:create) do |fs, _evaluator| + allow(Hyrax::TimeService).to receive(:time_in_utc).and_return(10.days.ago) + Hyrax::LeaseManager.new(resource: fs).apply + fs.permission_manager.acl.save + allow(Hyrax::TimeService).to receive(:time_in_utc).and_call_original + end + end + + trait :public do + transient do + visibility_setting { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC } + end + end + + trait :authenticated do + transient do + visibility_setting { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_AUTHENTICATED } + end + end + + trait :with_files do + transient do + ios { [File.open(Hyrax::Engine.root + 'spec/fixtures/image.png'), File.open(Hyrax::Engine.root + 'spec/fixtures/Example.ogg')] } + + after(:create) do |file_set, evaluator| + evaluator.ios.each do |file| + filename = File.basename(file.path).to_s + Hyrax::ValkyrieUpload.file(filename: filename, file_set: file_set, io: file) + end + end + end + end + + trait :in_work do + transient do + work { build(:hyrax_work) } + end + + after(:create) do |file_set, evaluator| + evaluator.work.member_ids += [file_set.id] + Hyrax.persister.save(resource: evaluator.work) + end + end + end +end diff --git a/spec/factories/hyrax_lease.rb b/spec/factories/hyrax_lease.rb new file mode 100644 index 00000000..f8cd7cea --- /dev/null +++ b/spec/factories/hyrax_lease.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :hyrax_lease, class: "Hyrax::Lease" do + lease_expiration_date { (Time.zone.today + 10).to_datetime } + visibility_after_lease { 'authenticated' } + visibility_during_lease { 'open' } + + to_create do |instance| + saved_instance = Valkyrie.config.metadata_adapter.persister.save(resource: instance) + instance.id = saved_instance.id + saved_instance + end + + trait :expired do + lease_expiration_date { (Time.zone.today - 2).to_datetime } + end + end +end diff --git a/spec/factories/hyrax_resource.rb b/spec/factories/hyrax_resource.rb new file mode 100644 index 00000000..14f73c09 --- /dev/null +++ b/spec/factories/hyrax_resource.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +## +# Use for generic Resources, with Hyrax assumptions. +FactoryBot.define do + factory :hyrax_resource, class: "Hyrax::Resource" do + trait :under_embargo do + embargo_id { FactoryBot.create(:hyrax_embargo).id } + end + + trait :under_lease do + lease_id { FactoryBot.create(:hyrax_lease).id } + end + end +end diff --git a/spec/factories/hyrax_work.rb b/spec/factories/hyrax_work.rb new file mode 100644 index 00000000..4c830827 --- /dev/null +++ b/spec/factories/hyrax_work.rb @@ -0,0 +1,239 @@ +# frozen_string_literal: true + +## +# Use this factory for generic Hyrax/HydraWorks Works in valkyrie. +FactoryBot.define do + factory :hyrax_work, class: 'Hyrax::Test::SimpleWork' do + trait :under_embargo do + association :embargo, factory: :hyrax_embargo + + after(:create) do |work, _e| + Hyrax::EmbargoManager.new(resource: work).apply + work.permission_manager.acl.save + end + end + + trait :with_expired_enforced_embargo do + after(:build) do |work, _evaluator| + work.embargo = FactoryBot.valkyrie_create(:hyrax_embargo, :expired) + end + + after(:create) do |work, _evaluator| + allow(Hyrax::TimeService).to receive(:time_in_utc).and_return(10.days.ago) + Hyrax::EmbargoManager.new(resource: work).apply + work.permission_manager.acl.save + allow(Hyrax::TimeService).to receive(:time_in_utc).and_call_original + end + end + + trait :under_lease do + association :lease, factory: :hyrax_lease + + after(:create) do |work, _e| + Hyrax::LeaseManager.new(resource: work).apply + work.permission_manager.acl.save + end + end + + trait :with_expired_enforced_lease do + after(:build) do |work, _evaluator| + work.lease = FactoryBot.valkyrie_create(:hyrax_lease, :expired) + end + + after(:create) do |work, _evaluator| + allow(Hyrax::TimeService).to receive(:time_in_utc).and_return(10.days.ago) + Hyrax::LeaseManager.new(resource: work).apply + work.permission_manager.acl.save + allow(Hyrax::TimeService).to receive(:time_in_utc).and_call_original + end + end + + transient do + edit_users { [] } + edit_groups { [] } + read_users { [] } + read_groups { [] } + members { nil } + visibility_setting { nil } + with_index { true } + uploaded_files { [] } + end + + after(:build) do |work, evaluator| + if evaluator.visibility_setting + Hyrax::VisibilityWriter + .new(resource: work) + .assign_access_for(visibility: evaluator.visibility_setting) + end + + if evaluator.respond_to?(:admin_set) && evaluator.admin_set.present? + template = Hyrax::PermissionTemplate.find_by(source_id: evaluator.admin_set.id) + Hyrax::PermissionTemplateApplicator.apply(template).to(model: work) if template + end + + work.permission_manager.edit_groups = work.permission_manager.edit_groups.to_a + evaluator.edit_groups + work.permission_manager.edit_users = work.permission_manager.edit_users.to_a + evaluator.edit_users + work.permission_manager.read_users = work.permission_manager.read_users.to_a + evaluator.read_users + work.permission_manager.read_groups = work.permission_manager.read_groups.to_a + evaluator.read_groups + + work.member_ids = evaluator.members.compact.map(&:id) if evaluator.members + end + + after(:create) do |work, evaluator| + if evaluator.visibility_setting + Hyrax::VisibilityWriter + .new(resource: work) + .assign_access_for(visibility: evaluator.visibility_setting) + end + + if evaluator.respond_to?(:admin_set) && evaluator.admin_set.present? + # We're likely going to want to apply permissions + template = Hyrax::PermissionTemplate.find_by(source_id: evaluator.admin_set.id) + if template + Hyrax::PermissionTemplateApplicator.apply(template).to(model: work) + if template.active_workflow.present? + user = User.find_by(Hydra.config.user_key_field => work.depositor) + Hyrax::Workflow::WorkflowFactory.create(work, {}, user) + end + end + end + + work.permission_manager.edit_groups = work.permission_manager.edit_groups.to_a + evaluator.edit_groups + work.permission_manager.edit_users = work.permission_manager.edit_users.to_a + evaluator.edit_users + work.permission_manager.read_users = work.permission_manager.read_users.to_a + evaluator.read_users + work.permission_manager.read_groups = work.permission_manager.read_groups.to_a + evaluator.read_groups + + # these are both no-ops if an active embargo/lease isn't present + Hyrax::EmbargoManager.new(resource: work).apply + Hyrax::LeaseManager.new(resource: work).apply + + work.permission_manager.acl.save + + # This has to happen after permissions for permissions to propagate. + if evaluator.uploaded_files.present? + allow(Hyrax.config.characterization_service).to receive(:run).and_return(true) + perform_enqueued_jobs(only: ValkyrieIngestJob) do + Hyrax::WorkUploadsHandler.new(work: Hyrax.query_service.find_by(id: work.id)).add(files: evaluator.uploaded_files).attach + end + # I'm not sure why, but Wings required this reload. + work.member_ids = Hyrax.query_service.find_by(id: work.id).member_ids + end + + Hyrax.index_adapter.save(resource: Hyrax.query_service.find_by(id: work.id)) if evaluator.with_index + end + + trait :public do + transient do + visibility_setting { Hydra::AccessControls::AccessRight::VISIBILITY_TEXT_VALUE_PUBLIC } + end + end + + trait :with_admin_set do + transient do + admin_set { valkyrie_create(:hyrax_admin_set) } + end + + after(:build) do |work, evaluator| + work.admin_set_id = evaluator.admin_set&.id + end + end + + trait :with_default_admin_set do + admin_set_id { Hyrax::EnsureWellFormedAdminSetService.call } + end + + trait :with_member_works do + transient do + members do + # If you set a depositor on the containing work, propogate that into these members + additional_attributes = {} + additional_attributes[:depositor] = depositor if depositor + [valkyrie_create(:hyrax_work, additional_attributes), valkyrie_create(:hyrax_work, additional_attributes)] + end + end + end + + trait :with_file_and_work do + transient do + members do + # If you set a depositor on the containing work, propogate that into these members + additional_attributes = {} + additional_attributes[:depositor] = depositor if depositor + [valkyrie_create(:hyrax_file_set, additional_attributes), valkyrie_create(:hyrax_work, additional_attributes)] + end + end + end + + trait :with_one_file_set do + transient do + members do + # If you set a depositor on the containing work, propogate that into this member + additional_attributes = {} + additional_attributes[:depositor] = depositor if depositor + [valkyrie_create(:hyrax_file_set, additional_attributes)] + end + end + end + + trait :with_member_file_sets do + transient do + members do + # If you set a depositor on the containing work, propogate that into these members + additional_attributes = {} + additional_attributes[:depositor] = depositor if depositor + [valkyrie_create(:hyrax_file_set, additional_attributes), valkyrie_create(:hyrax_file_set, additional_attributes)] + end + end + end + + trait :with_thumbnail do + thumbnail_id do + file_set = members.find(&:file_set?) || + valkyrie_create(:hyrax_file_set) + file_set.id + end + end + + trait :with_representative do + representative_id do + file_set = members&.find(&:file_set?) || + valkyrie_create(:hyrax_file_set) + file_set.id + end + end + + trait :with_renderings do + rendering_ids do + file_set = members.find(&:file_set?) || + valkyrie_create(:hyrax_file_set) + file_set.id + end + end + + trait :as_collection_member do + member_of_collection_ids { [valkyrie_create(:hyrax_collection).id] } + end + + trait :as_member_of_multiple_collections do + member_of_collection_ids do + [valkyrie_create(:hyrax_collection).id, + valkyrie_create(:hyrax_collection).id, + valkyrie_create(:hyrax_collection).id] + end + end + + factory :monograph, class: 'Monograph' do + factory :comet_in_moominland do + title { 'Comet in Moominland' } + creator { 'Tove Jansson' } + record_info { 'An example monograph with enough metadata fill in required fields.' } + end + + trait :with_member_works do + transient do + members { [valkyrie_create(:monograph), valkyrie_create(:monograph)] } + end + end + end + end +end diff --git a/spec/factories/object_id.rb b/spec/factories/object_id.rb new file mode 100644 index 00000000..a6209daa --- /dev/null +++ b/spec/factories/object_id.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true +# Defines a new sequence +FactoryBot.define do + sequence :object_id do |n| + "object_id_#{n}" + end +end diff --git a/spec/factories/operations.rb b/spec/factories/operations.rb new file mode 100644 index 00000000..19efbc6e --- /dev/null +++ b/spec/factories/operations.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :operation, class: Hyrax::Operation do + operation_type { "Test operation" } + + trait :failing do + status { Hyrax::Operation::FAILURE } + end + + trait :pending do + status { Hyrax::Operation::PENDING } + end + + trait :successful do + status { Hyrax::Operation::SUCCESS } + end + + factory :batch_create_operation, class: Hyrax::BatchCreateOperation do + operation_type { "Batch Create" } + end + end +end diff --git a/spec/factories/permission.rb b/spec/factories/permission.rb new file mode 100644 index 00000000..3d757898 --- /dev/null +++ b/spec/factories/permission.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :permission, class: "Hyrax::Permission" do + agent { create(:user).user_key.to_s } + mode { :read } + end +end diff --git a/spec/factories/permission_template_accesses.rb b/spec/factories/permission_template_accesses.rb new file mode 100644 index 00000000..781ea737 --- /dev/null +++ b/spec/factories/permission_template_accesses.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :permission_template_access, class: Hyrax::PermissionTemplateAccess do + permission_template + trait :manage do + access { 'manage' } + end + + trait :deposit do + access { 'deposit' } + end + + trait :view do + access { 'view' } + end + end +end diff --git a/spec/factories/permission_templates.rb b/spec/factories/permission_templates.rb index e5d20226..2b70ce4a 100644 --- a/spec/factories/permission_templates.rb +++ b/spec/factories/permission_templates.rb @@ -1,24 +1,22 @@ # frozen_string_literal: true -# From https://github.com/samvera/hyrax/blob/v2.9.6/spec/factories/permission_templates.rb FactoryBot.define do factory :permission_template, class: Hyrax::PermissionTemplate do # Given that there is a one to one strong relation between permission_template and admin_set, # with a unique index on the source_id, I don't want to have duplication in source_id - sequence(:source_id) { |n| format('%010d', n) } + sequence(:source_id) { |n| format("%010d", n) } + + trait :with_immediate_release do + release_period { Hyrax::PermissionTemplate::RELEASE_TEXT_VALUE_NO_DELAY } + end + + trait :with_delayed_release do + release_period { Hyrax::PermissionTemplate::RELEASE_TEXT_VALUE_6_MONTHS } + end before(:create) do |permission_template, evaluator| if evaluator.with_admin_set source_id = permission_template.source_id - admin_set = - if source_id.present? - begin - AdminSet.find(source_id) - rescue ActiveFedora::ObjectNotFoundError - create(:admin_set, id: source_id) - end - else - create(:admin_set) - end + admin_set = SourceFinder.find_or_create_admin_set(source_id) permission_template.source_id = admin_set.id elsif evaluator.with_collection source_id = permission_template.source_id @@ -39,7 +37,7 @@ after(:create) do |permission_template, evaluator| if evaluator.with_workflows Hyrax::Workflow::WorkflowImporter.load_workflow_for(permission_template: permission_template) - Sipity::Workflow.activate!(permission_template: permission_template, workflow_id: permission_template.available_workflows.pluck(:id).first) + Sipity::Workflow.activate!(permission_template: permission_template, workflow_id: permission_template.available_workflows.pick(:id)) end if evaluator.with_active_workflow workflow = create(:workflow, active: true, permission_template: permission_template) @@ -67,22 +65,6 @@ end end - factory :permission_template_access, class: Hyrax::PermissionTemplateAccess do - permission_template - trait :manage do - access { 'manage' } - end - - trait :deposit do - access { 'deposit' } - end - - trait :view do - access { 'view' } - end - end - - # rubocop:disable Lint/ConstantDefinitionInBlock class AccessHelper def self.create_access(permission_template_id, agent_type, access, agent_ids) agent_ids.each do |agent_id| @@ -94,5 +76,36 @@ def self.create_access(permission_template_id, agent_type, access, agent_ids) end end end - # rubocop:enable Lint/ConstantDefinitionInBlock -end \ No newline at end of file + + class SourceFinder + def self.find_or_create_admin_set(source_id) + Hyrax.config.use_valkyrie? ? find_or_create_admin_set_valkyrie(source_id) : find_or_create_admin_set_active_fedora(source_id) + end + + def self.find_or_create_admin_set_active_fedora(source_id) + if source_id.present? + begin + AdminSet.find(source_id) + rescue ActiveFedora::ObjectNotFoundError + FactoryBot.create(:admin_set, id: source_id) + end + else + FactoryBot.create(:admin_set) + end + end + + def self.find_or_create_admin_set_valkyrie(source_id) + if source_id.present? + begin + Hyrax.query_service.find_by(id: source_id) + rescue Valkyrie::Persistence::ObjectNotFoundError + # Creating an Administrative set with a pre-determined id will not work for all adapters + # so we're letting the adapter assign the id + FactoryBot.valkyrie_create(:hyrax_admin_set) + end + else + FactoryBot.valkyrie_create(:hyrax_admin_set) + end + end + end +end diff --git a/spec/factories/proxy_deposit_requests.rb b/spec/factories/proxy_deposit_requests.rb new file mode 100644 index 00000000..442575f1 --- /dev/null +++ b/spec/factories/proxy_deposit_requests.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true +# Read about factories at https://github.com/thoughtbot/factory_bot + +FactoryBot.define do + factory :proxy_deposit_request do + end +end diff --git a/spec/factories/single_use_links.rb b/spec/factories/single_use_links.rb new file mode 100644 index 00000000..7e25cea0 --- /dev/null +++ b/spec/factories/single_use_links.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :single_use_link do + factory :show_link do + item_id { 'fs-id' } + path { '/concerns/generic_work/1234' } + end + + factory :download_link do + item_id { 'fs-id' } + path { '/downloads/1234' } + end + end +end diff --git a/spec/factories/sipity_entities.rb b/spec/factories/sipity_entities.rb new file mode 100644 index 00000000..e19284ef --- /dev/null +++ b/spec/factories/sipity_entities.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :sipity_entity, class: Sipity::Entity do + transient do + proxy_for { nil } + end + + proxy_for_global_id { 'gid://internal/Mock/1' } + workflow { workflow_state.workflow } + workflow_state + + after(:build) do |entity, evaluator| + entity.proxy_for_global_id = Hyrax::GlobalID(evaluator.proxy_for).to_s if + evaluator.proxy_for + end + end +end diff --git a/spec/factories/strategies/json_strategy.rb b/spec/factories/strategies/json_strategy.rb new file mode 100644 index 00000000..4a63c88a --- /dev/null +++ b/spec/factories/strategies/json_strategy.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +class JsonStrategy + def initialize + @strategy = FactoryBot.strategy_by_name(:create).new + end + + delegate :association, to: :@strategy + + def result(evaluation) + @strategy.result(evaluation).to_json + end + + def to_sym + :json + end +end diff --git a/spec/factories/strategies/valkyrie_resource.rb b/spec/factories/strategies/valkyrie_resource.rb new file mode 100644 index 00000000..66cf8f14 --- /dev/null +++ b/spec/factories/strategies/valkyrie_resource.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true +# @see https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#custom-strategies +# @example +# let(:resource) { FactoryBot.valkyrie_create(:hyrax_work) } +class ValkyrieCreateStrategy + def initialize + @strategy = FactoryBot.strategy_by_name(:create).new + end + + delegate :association, to: :@strategy + + def result(evaluation) + evaluation.notify(:after_build, evaluation.object) + evaluation.notify(:before_create, evaluation.object) + + result = persister.save(resource: evaluation.object) + + evaluation.notify(:after_create, result) + result + end + + def to_sym + :valkyrie_create + end + + private + + def persister + Hyrax.persister + end +end diff --git a/spec/factories/uploaded_files.rb b/spec/factories/uploaded_files.rb new file mode 100644 index 00000000..d2ab9096 --- /dev/null +++ b/spec/factories/uploaded_files.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :uploaded_file, class: Hyrax::UploadedFile do + user + file { File.open(Hyrax::Engine.root.join('spec', 'fixtures', 'image.jp2').to_s) } + + trait :audio do + file { File.open(Hyrax::Engine.root.join('spec', 'fixtures', 'sample_mpeg4.mp4').to_s) } + end + end +end diff --git a/spec/factories/users.rb b/spec/factories/users.rb index f7d84aaa..435adb40 100644 --- a/spec/factories/users.rb +++ b/spec/factories/users.rb @@ -1,21 +1,63 @@ +# frozen_string_literal: true + FactoryBot.define do factory :user do - email { Faker::Internet.email } - password { Faker::Internet.password } - #display_name { Faker::Name.name } - - factory :admin_user do - after :create do |user| - admin_role = Role.find_or_create_by(name: 'admin') - admin_role.users << user + sequence(:email) { |n| "user#{n}@example.com" } + password { 'password' } + + transient do + # Allow for custom groups when a user is instantiated. + # @example create(:user, groups: 'avacado') + groups { [] } + end + + after(:build) do |user, evaluator| + evaluator.groups.each do |group| + user.roles << Role.find_or_create_by(name: group) end + # This line below is directly from hyrax, but was unable to get it to + # work with the creating admin/content-admin users. Above seems to work though. + + # User.group_service.add(user: user, groups: evaluator.groups) + end + + factory :admin do + groups { ['admin'] } end - factory :content_admin_user do - after :create do |user| - content_admin_role = Role.find_or_create_by(name: 'content-admin') - content_admin_role.users << user + factory :content_admin do + groups { ['content-admin'] } + end + + factory :user_with_mail do + after(:create) do |user| + # Create examples of single file successes and failures + (1..10).each do |number| + file = MockFile.new(number.to_s, "Single File #{number}") + User.batch_user.send_message(user, 'File 1 could not be updated. You do not have sufficient privileges to edit it.', file.to_s, false) + User.batch_user.send_message(user, 'File 1 has been saved', file.to_s, false) + end + + # Create examples of mulitple file successes and failures + files = [] + (1..50).each do |number| + files << MockFile.new(number.to_s, "File #{number}") + end + User.batch_user.send_message(user, 'These files could not be updated. You do not have sufficient privileges to edit them.', 'Batch upload permission denied', false) + User.batch_user.send_message(user, 'These files have been saved', 'Batch upload complete', false) end end end -end \ No newline at end of file + + trait :guest do + guest { true } + end +end + +class MockFile + attr_accessor :to_s, :id + def initialize(id, string) + self.id = id + self.to_s = string + end +end diff --git a/spec/factories/workflow_actions.rb b/spec/factories/workflow_actions.rb new file mode 100644 index 00000000..9446e635 --- /dev/null +++ b/spec/factories/workflow_actions.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :workflow_action, class: Sipity::WorkflowAction do + workflow + name { 'submit' } + end +end diff --git a/spec/factories/workflow_states.rb b/spec/factories/workflow_states.rb new file mode 100644 index 00000000..ae4d0a58 --- /dev/null +++ b/spec/factories/workflow_states.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :workflow_state, class: Sipity::WorkflowState do + workflow + name { 'initial' } + end +end diff --git a/spec/factories/workflows.rb b/spec/factories/workflows.rb new file mode 100644 index 00000000..24c60689 --- /dev/null +++ b/spec/factories/workflows.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true +FactoryBot.define do + factory :workflow, class: Sipity::Workflow do + sequence(:name) { |n| "generic_work-#{n}" } + permission_template + end +end diff --git a/spec/features/dashboard_spec.rb b/spec/features/dashboard_spec.rb index d2a87bb1..8a1ffb09 100644 --- a/spec/features/dashboard_spec.rb +++ b/spec/features/dashboard_spec.rb @@ -29,7 +29,7 @@ it 'allows authenticated admin user to visit /notifications' do - admin_user = FactoryBot.create(:admin_user) + admin_user = FactoryBot.create(:admin) sign_in_user(admin_user) @@ -53,7 +53,7 @@ it 'allows authenticated admin user to visit /importers' do - admin_user = FactoryBot.create(:admin_user) + admin_user = FactoryBot.create(:admin) sign_in_user(admin_user) @@ -77,7 +77,7 @@ it 'allows authenticated admin user to visit /exporters' do - admin_user = FactoryBot.create(:admin_user) + admin_user = FactoryBot.create(:admin) sign_in_user(admin_user) @@ -88,7 +88,7 @@ end it 'displays all admin controls when logged in as an admin user' do - admin_user = FactoryBot.create(:admin_user) + admin_user = FactoryBot.create(:admin) sign_in_user(admin_user) @@ -122,7 +122,7 @@ end it 'displays all content-admin controls when logged in as a content-admin user' do - content_admin_user = FactoryBot.create(:content_admin_user) + content_admin_user = FactoryBot.create(:content_admin) sign_in_user(content_admin_user) diff --git a/spec/features/deposit_pdf_spec.rb b/spec/features/deposit_pdf_spec.rb index 1c1630f8..ab6d5fb5 100644 --- a/spec/features/deposit_pdf_spec.rb +++ b/spec/features/deposit_pdf_spec.rb @@ -3,7 +3,7 @@ RSpec.describe "Deposit a PDF through dashboard" do let(:admin_set) { FactoryBot.create(:admin_set) } - let(:admin_user) { FactoryBot.create(:admin_user) } + let(:admin_user) { FactoryBot.create(:admin) } let(:user) { FactoryBot.create(:user) } let(:pdf_path) { "#{Rails.root}/spec/fixtures/fixture_dummy.pdf" } let(:solr) { Blacklight.default_index.connection } diff --git a/spec/features/gw_indexer_spec.rb b/spec/features/gw_indexer_spec.rb index 1d7f0c72..bb0c57fb 100644 --- a/spec/features/gw_indexer_spec.rb +++ b/spec/features/gw_indexer_spec.rb @@ -2,12 +2,11 @@ RSpec.describe "GwIndexer" do - let(:admin_user) { FactoryBot.create(:admin_user) } + let(:admin_user) { FactoryBot.create(:admin) } let(:admin_set) { FactoryBot.create(:admin_set) } let(:solr) { Blacklight.default_index.connection } - let(:gw_work) { FactoryBot.create(:gw_work, + let(:gw_work) { FactoryBot.create(:public_work, admin_set: admin_set, - visibility: "public", user: admin_user) } let(:solr_doc) { gw_work.to_solr } @@ -58,9 +57,8 @@ context "date_created_isim field" do it 'has a date_created_isim field containing a four-digit year, when date_created is filled with four digit year' do - gw_work_good_year = FactoryBot.create(:gw_work, + gw_work_good_year = FactoryBot.create(:public_work, admin_set: admin_set, - visibility: "public", date_created: ["2001"]) expect(gw_work_good_year.to_solr['date_created_isim']).to eq(2001) @@ -69,9 +67,8 @@ it 'chooses the minimum valid four-digit year if multiple date_created values' do - gw_work_multiple_date_created_values = FactoryBot.create(:gw_work, + gw_work_multiple_date_created_values = FactoryBot.create(:public_work, admin_set: admin_set, - visibility: "public", date_created: ["august", "4", "2009", "2005", "1999"]) expect(gw_work_multiple_date_created_values.to_solr['date_created_isim']).to eq(1999) @@ -80,9 +77,8 @@ it 'has a nil value if no convertable dates' do - gw_work_no_good_values = FactoryBot.create(:gw_work, + gw_work_no_good_values = FactoryBot.create(:public_work, admin_set: admin_set, - visibility: "public", date_created: ["august", "4", "garbanzo"]) expect(gw_work_no_good_values.to_solr['date_created_isim']).to eq(nil) diff --git a/spec/features/sidekiq_dashboard_spec.rb b/spec/features/sidekiq_dashboard_spec.rb index 14770119..b43dfc8f 100644 --- a/spec/features/sidekiq_dashboard_spec.rb +++ b/spec/features/sidekiq_dashboard_spec.rb @@ -3,7 +3,7 @@ RSpec.describe "Sidekiq Dashboard Access" do it 'loads sidekiq dashboard for a logged in admin user' do - admin_user = FactoryBot.create(:admin_user) + admin_user = FactoryBot.create(:admin) visit "/users/sign_in" diff --git a/spec/features/sign_in_spec.rb b/spec/features/sign_in_spec.rb index ee1e92e7..e5372068 100644 --- a/spec/features/sign_in_spec.rb +++ b/spec/features/sign_in_spec.rb @@ -2,8 +2,8 @@ RSpec.describe 'user sign-in' do - let(:admin_user) { FactoryBot.create(:admin_user) } - let(:content_admin_user) { FactoryBot.create(:content_admin_user) } + let(:admin_user) { FactoryBot.create(:admin) } + let(:content_admin_user) { FactoryBot.create(:content_admin) } it 'has link to login page on homepage' do visit root_path diff --git a/spec/features/sort_catalog_spec.rb b/spec/features/sort_catalog_spec.rb index 67e8e244..8d809c20 100644 --- a/spec/features/sort_catalog_spec.rb +++ b/spec/features/sort_catalog_spec.rb @@ -4,7 +4,7 @@ # let(:solr) { Blacklight.default_index.connection } # let(:admin_set) { FactoryBot.create(:admin_set) } -# let(:admin_user) { FactoryBot.create(:admin_user) } +# let(:admin_user) { FactoryBot.create(:admin) } # let(:earliest_work) { FactoryBot.create(:gw_work, admin_set: admin_set, # date_uploaded: "2000-01-01", # date_modified: "2010-01-01") } diff --git a/spec/features/visibility_spec.rb b/spec/features/visibility_spec.rb index df994575..5a151345 100644 --- a/spec/features/visibility_spec.rb +++ b/spec/features/visibility_spec.rb @@ -6,20 +6,17 @@ let(:admin_set) { FactoryBot.create(:admin_set) } let(:basic_user) { FactoryBot.create(:user) } - let(:admin_user) { FactoryBot.create(:admin_user) } - let(:content_admin_user) { FactoryBot.create(:content_admin_user) } + let(:admin_user) { FactoryBot.create(:admin) } + let(:content_admin_user) { FactoryBot.create(:content_admin) } - let(:public_work) { FactoryBot.create(:gw_work, + let(:public_work) { FactoryBot.create(:public_work, admin_set: admin_set, - visibility: "public", user: admin_user) } - let(:auth_only_work) { FactoryBot.create(:gw_work, + let(:auth_only_work) { FactoryBot.create(:authenticated_work, admin_set: admin_set, - visibility: "authenticated", user: admin_user) } - let(:private_work) { FactoryBot.create(:gw_work, + let(:private_work) { FactoryBot.create(:private_work, admin_set: admin_set, - visibility: "private", user: admin_user) } diff --git a/spec/fixtures/1.5mb-avatar.jpg b/spec/fixtures/1.5mb-avatar.jpg new file mode 100644 index 00000000..4846008c Binary files /dev/null and b/spec/fixtures/1.5mb-avatar.jpg differ diff --git a/spec/fixtures/4-20.png b/spec/fixtures/4-20.png new file mode 100644 index 00000000..26f43f7d Binary files /dev/null and b/spec/fixtures/4-20.png differ diff --git a/spec/fixtures/Example.ogg b/spec/fixtures/Example.ogg new file mode 100644 index 00000000..0d7f43eb Binary files /dev/null and b/spec/fixtures/Example.ogg differ diff --git a/spec/fixtures/charter.docx b/spec/fixtures/charter.docx new file mode 100644 index 00000000..ce3dceb8 Binary files /dev/null and b/spec/fixtures/charter.docx differ diff --git a/spec/fixtures/countdown.avi b/spec/fixtures/countdown.avi new file mode 100644 index 00000000..6927e44d Binary files /dev/null and b/spec/fixtures/countdown.avi differ diff --git a/spec/fixtures/docx_fits.xml b/spec/fixtures/docx_fits.xml new file mode 100644 index 00000000..1e38e905 --- /dev/null +++ b/spec/fixtures/docx_fits.xml @@ -0,0 +1,21 @@ + + + + + + + + + 2012:04:19 15:49:11-04:00 + /home/mjg/workspace/scholarsphere/spec/fixtures/scholarsphere/scholarsphere_test2.docx + scholarsphere_test2.docx + 11065 + d2a13c821c6f707bfc4decbcc17241d5 + 1334864951000 + + + + + + + diff --git a/spec/fixtures/dublin_core_rdf_descMetadata.nt b/spec/fixtures/dublin_core_rdf_descMetadata.nt new file mode 100644 index 00000000..8dfa748e --- /dev/null +++ b/spec/fixtures/dublin_core_rdf_descMetadata.nt @@ -0,0 +1,13 @@ + "This is a work by JD in the field of biology." . + "Penn State" . + "Department of Bioinformatics" . + "2010-12-31"^^ . + "Title of work" . + "Biology" . + "en" . + "2009-12-31"^^ . + "insert rights statement here" . + . + "image/jpeg" . + "John Doe" . + "old:identifier:7779" . diff --git a/spec/fixtures/geonames.json b/spec/fixtures/geonames.json new file mode 100644 index 00000000..f538d5e5 --- /dev/null +++ b/spec/fixtures/geonames.json @@ -0,0 +1,577 @@ +{ + "__license__": "https://creativecommons.org/licenses/by/4.0/ https://www.geonames.org/", + "timezone": { + "gmtOffset": -6, + "timeZoneId": "America/Chicago", + "dstOffset": -5 + }, + "bbox": { + "east": -93.19402300000002, + "south": 44.889787, + "north": 45.051249999999996, + "west": -93.329163, + "accuracyLevel": 0 + }, + "asciiName": "Minneapolis", + "astergdem": 275, + "countryId": "6252001", + "fcl": "P", + "srtm3": 262, + "adminId2": "5029877", + "adminId3": "5037657", + "countryCode": "US", + "adminCodes1": { + "ISO3166_2": "MN" + }, + "adminId1": "5037779", + "lat": "44.97997", + "fcode": "PPLA2", + "continentCode": "NA", + "elevation": 253, + "adminCode2": "053", + "adminCode3": "43000", + "adminCode1": "MN", + "lng": "-93.26384", + "geonameId": 5037649, + "toponymName": "Minneapolis", + "population": 410939, + "wikipediaURL": "en.wikipedia.org/wiki/Minneapolis", + "adminName5": "", + "adminName4": "", + "adminName3": "City of Minneapolis", + "alternateNames": [ + { + "name": "미니애폴리스", + "lang": "ko" + }, + { + "name": "55401", + "lang": "post" + }, + { + "name": "55402", + "lang": "post" + }, + { + "name": "55403", + "lang": "post" + }, + { + "name": "55404", + "lang": "post" + }, + { + "name": "55405", + "lang": "post" + }, + { + "name": "55406", + "lang": "post" + }, + { + "name": "55407", + "lang": "post" + }, + { + "name": "55408", + "lang": "post" + }, + { + "name": "55409", + "lang": "post" + }, + { + "name": "55410", + "lang": "post" + }, + { + "name": "55411", + "lang": "post" + }, + { + "name": "55412", + "lang": "post" + }, + { + "name": "55413", + "lang": "post" + }, + { + "name": "55414", + "lang": "post" + }, + { + "name": "55415", + "lang": "post" + }, + { + "name": "55416", + "lang": "post" + }, + { + "name": "55417", + "lang": "post" + }, + { + "name": "55418", + "lang": "post" + }, + { + "name": "55419", + "lang": "post" + }, + { + "name": "55420", + "lang": "post" + }, + { + "name": "55422", + "lang": "post" + }, + { + "name": "55423", + "lang": "post" + }, + { + "name": "55424", + "lang": "post" + }, + { + "name": "55425", + "lang": "post" + }, + { + "name": "55426", + "lang": "post" + }, + { + "name": "55427", + "lang": "post" + }, + { + "name": "55428", + "lang": "post" + }, + { + "name": "55429", + "lang": "post" + }, + { + "name": "55430", + "lang": "post" + }, + { + "name": "55431", + "lang": "post" + }, + { + "name": "55435", + "lang": "post" + }, + { + "name": "55436", + "lang": "post" + }, + { + "name": "55437", + "lang": "post" + }, + { + "name": "55438", + "lang": "post" + }, + { + "name": "55439", + "lang": "post" + }, + { + "name": "55440", + "lang": "post" + }, + { + "name": "55441", + "lang": "post" + }, + { + "name": "55442", + "lang": "post" + }, + { + "name": "55443", + "lang": "post" + }, + { + "name": "55444", + "lang": "post" + }, + { + "name": "55445", + "lang": "post" + }, + { + "name": "55446", + "lang": "post" + }, + { + "name": "55447", + "lang": "post" + }, + { + "name": "55450", + "lang": "post" + }, + { + "name": "55454", + "lang": "post" + }, + { + "name": "55455", + "lang": "post" + }, + { + "name": "55458", + "lang": "post" + }, + { + "name": "55459", + "lang": "post" + }, + { + "name": "55460", + "lang": "post" + }, + { + "name": "55467", + "lang": "post" + }, + { + "name": "55470", + "lang": "post" + }, + { + "name": "55472", + "lang": "post" + }, + { + "name": "55474", + "lang": "post" + }, + { + "name": "55478", + "lang": "post" + }, + { + "name": "55479", + "lang": "post" + }, + { + "name": "55480", + "lang": "post" + }, + { + "name": "55483", + "lang": "post" + }, + { + "name": "55484", + "lang": "post" + }, + { + "name": "55485", + "lang": "post" + }, + { + "name": "55486", + "lang": "post" + }, + { + "name": "55487", + "lang": "post" + }, + { + "name": "55488", + "lang": "post" + }, + { + "name": "City of Minneapolis" + }, + { + "name": "Gakaabikaang" + }, + { + "name": "https://en.wikipedia.org/wiki/Minneapolis", + "lang": "link" + }, + { + "name": "https://ru.wikipedia.org/wiki/%D0%9C%D0%B8%D0%BD%D0%BD%D0%B5%D0%B0%D0%BF%D0%BE%D0%BB%D0%B8%D1%81", + "lang": "link" + }, + { + "name": "Mineapoli", + "lang": "haw" + }, + { + "name": "Mineapolis", + "lang": "lt" + }, + { + "name": "Mineápolis", + "lang": "es" + }, + { + "name": "Mineapolisa", + "lang": "lv" + }, + { + "name": "Minneapolis", + "lang": "ca" + }, + { + "name": "Minneapolis", + "lang": "da" + }, + { + "name": "Minneapolis", + "lang": "de" + }, + { + "isPreferredName": true, + "name": "Minneapolis", + "lang": "en" + }, + { + "name": "Minneapolis", + "lang": "eo" + }, + { + "name": "Minneapolis", + "lang": "fi" + }, + { + "name": "Minneapolis", + "lang": "fr" + }, + { + "name": "Minneapolis", + "lang": "ga" + }, + { + "name": "Minneapolis", + "lang": "gl" + }, + { + "name": "Minneapolis", + "lang": "hu" + }, + { + "name": "Minneapolis", + "lang": "id" + }, + { + "name": "Minneapolis", + "lang": "io" + }, + { + "name": "Minneapolis", + "lang": "it" + }, + { + "name": "Minneapolis", + "lang": "la" + }, + { + "name": "Minneapolis", + "lang": "nl" + }, + { + "name": "Minneapolis", + "lang": "nn" + }, + { + "name": "Minneapolis", + "lang": "no" + }, + { + "name": "Minneapolis", + "lang": "pl" + }, + { + "name": "Minneapolis", + "lang": "pt" + }, + { + "name": "Minneapolis", + "lang": "sk" + }, + { + "name": "Minneapolis", + "lang": "sv" + }, + { + "name": "Minneapolis", + "lang": "tr" + }, + { + "name": "Minneapòlis", + "lang": "oc" + }, + { + "name": "Minnéapolis", + "lang": "ug" + }, + { + "name": "Mìn-nì-â-pô-li-sṳ̂", + "lang": "hak" + }, + { + "name": "Minyapolis", + "lang": "tl" + }, + { + "name": "MSP", + "lang": "iata" + }, + { + "name": "Q36091", + "lang": "wkdt" + }, + { + "name": "USMES", + "lang": "unlc" + }, + { + "name": "Μινεάπολη", + "lang": "el" + }, + { + "name": "Минеаполис", + "lang": "bg" + }, + { + "name": "Минеаполис", + "lang": "mk" + }, + { + "name": "Минеаполис", + "lang": "sr" + }, + { + "name": "Миннеаполис", + "lang": "kk" + }, + { + "name": "Миннеаполис", + "lang": "ky" + }, + { + "name": "Миннеаполис", + "lang": "mrj" + }, + { + "name": "Миннеаполис", + "lang": "os" + }, + { + "name": "Миннеаполис", + "lang": "ru" + }, + { + "name": "Миннеаполис", + "lang": "sah" + }, + { + "name": "Миннеаполис", + "lang": "tg" + }, + { + "name": "Мінеапаліс", + "lang": "be" + }, + { + "name": "Міннеаполіс", + "lang": "uk" + }, + { + "name": "მინეაპოლისი", + "lang": "ka" + }, + { + "name": "Մինեապոլիս", + "lang": "hy" + }, + { + "name": "מיניאפוליס", + "lang": "he" + }, + { + "name": "منیاپولس", + "lang": "ur" + }, + { + "name": "مينيابولس", + "lang": "ar" + }, + { + "name": "مینیاپولیس", + "lang": "fa" + }, + { + "name": "मिनियापोलिस", + "lang": "hi" + }, + { + "name": "मिनीयापोलिस", + "lang": "mr" + }, + { + "name": "মিনিয়াপোলিস", + "lang": "bn" + }, + { + "name": "મિનેપોલિસ", + "lang": "gu" + }, + { + "name": "மினியாப்பொலிஸ்", + "lang": "ta" + }, + { + "name": "మిన్నియాపోలిస్", + "lang": "te" + }, + { + "name": "ಮಿನ್ನಿಯಾಪೋಲಿಸ್", + "lang": "kn" + }, + { + "name": "มินนีแอโพลิส", + "lang": "th" + }, + { + "name": "ミネアポリス", + "lang": "ja" + }, + { + "name": "明尼亞波利斯", + "lang": "yue" + }, + { + "name": "明尼阿波利斯", + "lang": "lzh" + }, + { + "name": "明尼阿波利斯", + "lang": "wuu" + }, + { + "name": "明尼阿波利斯", + "lang": "zh" + } + ], + "adminName2": "Hennepin", + "name": "Minneapolis", + "fclName": "city, village,...", + "countryName": "United States", + "fcodeName": "seat of a second-order administrative division", + "adminName1": "Minnesota" +} \ No newline at end of file diff --git a/spec/fixtures/hyrax_generic_stub.txt b/spec/fixtures/hyrax_generic_stub.txt new file mode 100644 index 00000000..8ecc7bbc --- /dev/null +++ b/spec/fixtures/hyrax_generic_stub.txt @@ -0,0 +1 @@ +This is a test fixture for hyrax: <%= @id %>. diff --git a/spec/fixtures/icons.zip b/spec/fixtures/icons.zip new file mode 100644 index 00000000..f1a23121 Binary files /dev/null and b/spec/fixtures/icons.zip differ diff --git a/spec/fixtures/image.jp2 b/spec/fixtures/image.jp2 new file mode 100644 index 00000000..3549ca63 Binary files /dev/null and b/spec/fixtures/image.jp2 differ diff --git a/spec/fixtures/image.jpg b/spec/fixtures/image.jpg new file mode 100644 index 00000000..1de2a82b Binary files /dev/null and b/spec/fixtures/image.jpg differ diff --git a/spec/fixtures/image.png b/spec/fixtures/image.png new file mode 100644 index 00000000..0a05f192 Binary files /dev/null and b/spec/fixtures/image.png differ diff --git a/spec/fixtures/jp2_fits.xml b/spec/fixtures/jp2_fits.xml new file mode 100644 index 00000000..4f0d4572 --- /dev/null +++ b/spec/fixtures/jp2_fits.xml @@ -0,0 +1,36 @@ + + + + + + + + + 11043 + 2012:04:19 15:49:11-04:00 + /home/mjg/workspace/scholarsphere/spec/fixtures/scholarsphere/scholarsphere_test6.jp2 + scholarsphere_test6.jp2 + 8ff299eda08d7c506273840d52a03bf3 + 1334864951000 + + + true + true + + + + big endian + JPEG 2000 Lossless + 512 + 465 + sRGB + 512 + 465 + 1 + 3 + 8 8 8 + 3 + + + + diff --git a/spec/fixtures/jpg_fits.xml b/spec/fixtures/jpg_fits.xml new file mode 100644 index 00000000..7e89ec5b --- /dev/null +++ b/spec/fixtures/jpg_fits.xml @@ -0,0 +1,43 @@ + + + + + + + + + + 1.02 + fmt/44 + + + + 1792 + 2012:04:24 21:00:53-04:00 + /home/mjg/workspace/scholarsphere/spec/fixtures/scholarsphere/bg_header.jpg + bg_header.jpg + 76958714b002451273f5b43752d67f77 + 1335315653000 + + + true + true + + + + big endian + JPEG (old-style) + 520 + 35 + YCbCr + 1 1 + no absolute unit of measurement + 100 + 100 + 8 8 8 + 3 + unknown + + + + diff --git a/spec/fixtures/mp3_fits.xml b/spec/fixtures/mp3_fits.xml new file mode 100644 index 00000000..330d3792 --- /dev/null +++ b/spec/fixtures/mp3_fits.xml @@ -0,0 +1,32 @@ + + + + + + + + + 1 + fmt/134 + + + + 2012:04:19 15:49:11-04:00 + /home/mjg/workspace/scholarsphere/spec/fixtures/scholarsphere/scholarsphere_test5.mp3 + scholarsphere_test5.mp3 + 366464 + d98da8d92c397294164b02a0382eb0e6 + 1334864951000 + + + + + + + diff --git a/spec/fixtures/pdf_fits.xml b/spec/fixtures/pdf_fits.xml new file mode 100644 index 00000000..6902cef5 --- /dev/null +++ b/spec/fixtures/pdf_fits.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + 1.4 + fmt/18 + + + + 218882 + GPL Ghostscript 8.15/PScript5.dll Version 5.2.2 + 2012:04:19 15:49:11-04:00 + 2010:10:09 10:29:55 + /home/mjg/workspace/scholarsphere/spec/fixtures/scholarsphere/scholarsphere_test4.pdf + scholarsphere_test4.pdf + 5a2d761cab7c15b2b3bb3465ce64586d + 1334864951000 + + + true + true + + + + Microsoft Word - sample.pdf.docx + carlos + 1 + no + no + no + no + no + no + + + + diff --git a/spec/fixtures/piano_note.wav b/spec/fixtures/piano_note.wav new file mode 100644 index 00000000..6697c57a Binary files /dev/null and b/spec/fixtures/piano_note.wav differ diff --git a/spec/fixtures/png_fits.xml b/spec/fixtures/png_fits.xml new file mode 100644 index 00000000..a0bb4635 --- /dev/null +++ b/spec/fixtures/png_fits.xml @@ -0,0 +1,29 @@ + + + + + + + + 1.0 + fmt/11 + + + + 2013:05:13 11:02:08-04:00 + /Users/jfriesen/Repositories/hyrax/spec/fixtures/world.png + spec/fixtures/world.png + 4218 + 28da6259ae5707c68708192a40b3e85c + 1368457328000 + + + + + Deflate/Inflate + 50 + 50 + + + + diff --git a/spec/fixtures/sample-file.pdf b/spec/fixtures/sample-file.pdf new file mode 100644 index 00000000..21d6a39c Binary files /dev/null and b/spec/fixtures/sample-file.pdf differ diff --git a/spec/fixtures/sample_mpeg4.mp4 b/spec/fixtures/sample_mpeg4.mp4 new file mode 100644 index 00000000..a05d9356 Binary files /dev/null and b/spec/fixtures/sample_mpeg4.mp4 differ diff --git a/spec/fixtures/small_file.txt b/spec/fixtures/small_file.txt new file mode 100644 index 00000000..ac790413 --- /dev/null +++ b/spec/fixtures/small_file.txt @@ -0,0 +1 @@ +small diff --git a/spec/fixtures/spoken-text.m4a b/spec/fixtures/spoken-text.m4a new file mode 100644 index 00000000..1b0d85cb Binary files /dev/null and b/spec/fixtures/spoken-text.m4a differ diff --git a/spec/fixtures/txt_fits.xml b/spec/fixtures/txt_fits.xml new file mode 100644 index 00000000..96395bec --- /dev/null +++ b/spec/fixtures/txt_fits.xml @@ -0,0 +1,29 @@ + + + + + + + + x-fmt/111 + + + + 1039 + /home/mjg/workspace/scholarsphere/spec/fixtures/scholarsphere/scholarsphere_test1.descMeta.txt + scholarsphere_test1.descMeta.txt + b283ff56a57716154cd4deb827964009 + 1334864951000 + + + true + true + + + + LF + US-ASCII + + + + diff --git a/spec/fixtures/updated-file.txt b/spec/fixtures/updated-file.txt new file mode 100644 index 00000000..5f213fb0 --- /dev/null +++ b/spec/fixtures/updated-file.txt @@ -0,0 +1 @@ +some updated content diff --git a/spec/fixtures/world.png b/spec/fixtures/world.png new file mode 100644 index 00000000..efbe348d Binary files /dev/null and b/spec/fixtures/world.png differ diff --git a/spec/fixtures/xls_fits.xml b/spec/fixtures/xls_fits.xml new file mode 100644 index 00000000..256f75c2 --- /dev/null +++ b/spec/fixtures/xls_fits.xml @@ -0,0 +1,18 @@ + + + + + + + + + /home/mjg/workspace/scholarsphere/spec/fixtures/scholarsphere/scholarsphere_test3.xls + scholarsphere_test3.xls + 22016 + bbe9cf68879e42241a1d71e78a5f630b + 1334864951000 + + + + + diff --git a/spec/fixtures/xml_fits.xml b/spec/fixtures/xml_fits.xml new file mode 100644 index 00000000..3ce25a72 --- /dev/null +++ b/spec/fixtures/xml_fits.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + 1.0 + fmt/101 + + + + 4000 + 2012:04:24 20:07:24-04:00 + /home/mjg/workspace/scholarsphere/spec/fixtures/scholarsphere/scholarsphere_test1.foxml.xml + scholarsphere_test1.foxml.xml + 1b5cfeeca9ddecd1a4cf30256bac6bdd + 1335312444000 + + + true + true + + + + UTF-8 + XML + 1.0 + http://www.fedora.info/definitions/1/0/foxml1-1.xsd + + + + diff --git "a/spec/fixtures/\344\270\226\347\225\214.png" "b/spec/fixtures/\344\270\226\347\225\214.png" new file mode 100644 index 00000000..efbe348d Binary files /dev/null and "b/spec/fixtures/\344\270\226\347\225\214.png" differ