- <% if plan.template.org == plan.funder %>
- <%# If the plan's funder is the same as the template owner then just
- display the identifiers %>
-
- <%= form.label(:funder_name, _('Funder'), class: 'control-label') %>
+<% if Rails.configuration.x.madmp.enable_ethical_issues %>
+
+
-
- <%= plan.funder.name %>:
+
- <% else %>
- <%# Otherwise display the Org typeahead for funders %>
+
+
+<% end %>
+
+
+
+
-
+
diff --git a/app/views/shared/export/_plan_coversheet.erb b/app/views/shared/export/_plan_coversheet.erb
index 3a50c75dcd..df16331646 100644
--- a/app/views/shared/export/_plan_coversheet.erb
+++ b/app/views/shared/export/_plan_coversheet.erb
@@ -41,8 +41,8 @@
<%= _("Last modified: ") %><%= l(@plan.updated_at.to_date, formats: :short) %>
- <% if @plan.grant_number.present? %>
-
<%= _("Grant number / URL: ") %><%= @plan.grant_number %>
+ <% if @plan.grant.present? %>
+
<%= _("Grant number / URL: ") %><%= @plan.grant.value %>
<% end %>
<% if @public_plan %>
diff --git a/config/initializers/_dmproadmap.rb b/config/initializers/_dmproadmap.rb
index 1b1fff6ed9..0d44e72c5f 100644
--- a/config/initializers/_dmproadmap.rb
+++ b/config/initializers/_dmproadmap.rb
@@ -204,6 +204,12 @@ class Application < Rails::Application
# ------------------------------------------------------------------------ #
config.x.recaptcha.enabled = false
+ # --------------------------------------------------- #
+ # Machine Actionable / Networked DMP Features (maDMP) #
+ # --------------------------------------------------- #
+ config.x.madmp.enable_ethical_issues = false
+ config.x.madmp.enable_research_domain = false
+
end
end
diff --git a/db/migrate/20210729204238_create_research_domains.rb b/db/migrate/20210729204238_create_research_domains.rb
new file mode 100644
index 0000000000..3cb6414b0c
--- /dev/null
+++ b/db/migrate/20210729204238_create_research_domains.rb
@@ -0,0 +1,12 @@
+class CreateFos < ActiveRecord::Migration[5.2]
+ def change
+ create_table :research_domains do |t|
+ t.string :identifier, null: false
+ t.string :label, null: false
+ t.references :parent, foreign_key: { to_table: :research_domains }
+ t.timestamps
+ end
+
+ add_reference :plans, :research_domain, index: true
+ end
+end
diff --git a/db/migrate/20210729204412_add_ethical_issues_and_funding_status_to_plans.rb b/db/migrate/20210729204412_add_ethical_issues_and_funding_status_to_plans.rb
new file mode 100644
index 0000000000..a1432822e0
--- /dev/null
+++ b/db/migrate/20210729204412_add_ethical_issues_and_funding_status_to_plans.rb
@@ -0,0 +1,9 @@
+class AddEthicalIssuesAndFundingStatusToPlans < ActiveRecord::Migration[5.2]
+ def change
+ add_column :plans, :ethical_issues, :boolean
+ add_column :plans, :ethical_issues_description, :text
+ add_column :plans, :ethical_issues_report, :string
+
+ add_column :plans, :funding_status, :integer, null: true
+ end
+end
diff --git a/db/migrate/20210729204611_madmp_cleanup.rb b/db/migrate/20210729204611_madmp_cleanup.rb
new file mode 100644
index 0000000000..bfea82c298
--- /dev/null
+++ b/db/migrate/20210729204611_madmp_cleanup.rb
@@ -0,0 +1,34 @@
+class MadmpCleanup < ActiveRecord::Migration[5.2]
+ def change
+
+ # Decided not to ask users for the mime type when defining research outputs
+ drop_table :mime_types
+ remove_column :research_outputs, :mime_type_id
+
+ # Remove attributes found in the RDA common standard that we decided not to use
+ remove_column :research_outputs, :mandatory_attribution
+ remove_column :research_outputs, :coverage_region
+ remove_column :research_outputs, :coverage_start
+ remove_column :research_outputs, :coverage_end
+
+ # We're going to move towards a different solution allowing multiple api_clients
+ # to have an interest in a plan
+ remove_column :plans, :api_client_id
+
+ # Remove the old principal_investigator and data_contact fields since they now
+ # live in the contributors table
+ remove_column :plans, :data_contact
+ remove_column :plans, :data_contact_email
+ remove_column :plans, :data_contact_phone
+
+ remove_column :plans, :principal_investigator
+ remove_column :plans, :principal_investigator_email
+ remove_column :plans, :principal_investigator_identifier
+ remove_column :plans, :principal_investigator_phone
+
+
+ # Remove the old funder and grant fields since they have been replaced by associations
+ remove_column :plans, :funder_name
+ remove_column :plans, :grant_number
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index afeebf74be..e36701b4ce 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema.define(version: 2020_12_16_140226) do
+ActiveRecord::Schema.define(version: 2021_07_29_204611) do
create_table "annotations", id: :integer, force: :cascade do |t|
t.integer "question_id"
@@ -157,15 +157,6 @@
t.boolean "default_language"
end
- create_table "mime_types", force: :cascade do |t|
- t.string "description", null: false
- t.string "category", null: false
- t.string "value", null: false
- t.datetime "created_at", null: false
- t.datetime "updated_at", null: false
- t.index ["value"], name: "index_mime_types_on_value"
- end
-
create_table "notes", id: :integer, force: :cascade do |t|
t.integer "user_id"
t.text "text"
@@ -257,18 +248,9 @@
t.integer "template_id"
t.datetime "created_at"
t.datetime "updated_at"
- t.string "grant_number"
t.string "identifier"
t.text "description"
- t.string "principal_investigator"
- t.string "principal_investigator_identifier"
- t.string "data_contact"
- t.string "funder_name"
t.integer "visibility", default: 3, null: false
- t.string "data_contact_email"
- t.string "data_contact_phone"
- t.string "principal_investigator_email"
- t.string "principal_investigator_phone"
t.boolean "feedback_requested", default: false
t.boolean "complete", default: false
t.integer "org_id"
@@ -276,11 +258,16 @@
t.integer "grant_id"
t.datetime "start_date"
t.datetime "end_date"
- t.integer "api_client_id"
+ t.boolean "ethical_issues"
+ t.text "ethical_issues_description"
+ t.string "ethical_issues_report"
+ t.integer "funding_status"
+ t.bigint "research_domain_id"
t.index ["funder_id"], name: "index_plans_on_funder_id"
t.index ["grant_id"], name: "index_plans_on_grant_id"
t.index ["org_id"], name: "index_plans_on_org_id"
t.index ["template_id"], name: "index_plans_on_template_id"
+ t.index ["research_domain_id"], name: "index_plans_on_research_domain_id"
end
create_table "plans_guidance_groups", id: :integer, force: :cascade do |t|
@@ -355,6 +342,15 @@
t.integer "super_region_id"
end
+ create_table "research_domains", force: :cascade do |t|
+ t.string "identifier", null: false
+ t.string "label", null: false
+ t.bigint "parent_id"
+ t.datetime "created_at", null: false
+ t.datetime "updated_at", null: false
+ t.index ["parent_id"], name: "index_research_domains_on_parent_id"
+ end
+
create_table "research_outputs", force: :cascade do |t|
t.integer "plan_id"
t.integer "output_type", default: 3, null: false
@@ -364,16 +360,11 @@
t.integer "display_order"
t.boolean "is_default"
t.text "description"
- t.integer "mime_type_id"
t.integer "access", default: 0, null: false
t.datetime "release_date"
t.boolean "personal_data"
t.boolean "sensitive_data"
t.bigint "byte_size"
- t.text "mandatory_attribution"
- t.datetime "coverage_start"
- t.datetime "coverage_end"
- t.string "coverage_region"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["output_type"], name: "index_research_outputs_on_output_type"
diff --git a/lib/tasks/utils/external_api.rake b/lib/tasks/utils/external_api.rake
index f74986d977..7b363831f5 100644
--- a/lib/tasks/utils/external_api.rake
+++ b/lib/tasks/utils/external_api.rake
@@ -1,60 +1,101 @@
# frozen_string_literal: true
-require "httparty"
-
-# rubocop:disable Metrics/BlockLength
+# rubocop:disable Metrics/BlockLength, Layout/LineLength
namespace :external_api do
- # MIME Types
- # -------------------------------------
- desc "Fetch all of the latest MIME types and load into the DB"
- task load_mime_types: :environment do
- %w[application.csv audio.csv font.csv image.csv message.csv model.csv
- multipart.csv text.csv video.csv].each do |file_name|
- url = "https://www.iana.org/assignments/media-types"
- fetch_and_process_mime_type_file(url: "#{url}/#{file_name}")
- end
- end
-
- private
-
- # MIME Types
- # -------------------------------------
- def fetch_and_process_mime_type_file(url:)
- p "Processing #{url}"
- body = fetch_mime_type_csv_file(url: url)
- p " Unable to process the specified URL" unless body.present?
-
- csv = CSV.parse(body, headers: true, force_quotes: true, encoding: "iso-8859-1:utf-8")
- # rubocop:disable Layout/LineLength
- p " Invalid CSV format. Expecting a 'Name' and 'Template' column" unless csv.headers.include?("Name") &&
- csv.headers.include?("Template")
- # rubocop:enable Layout/LineLength
- process_mime_type_file(csv: csv)
- p " Done"
- rescue StandardError => e
- p " Error processing CSV content - #{e.message}"
- end
+ desc "Seed the Research Domain table with Field of Science categories"
+ task add_field_of_science_to_research_domains: :environment do
+ # TODO: If we can identify an external API authority for this information we should switch
+ # to fetch the list from there instead of the hard-coded list below which was derived from:
+ # https://www.oecd.org/science/inno/38235147.pdf
+ [
+ {
+ identifier: "1",
+ label: "Natural sciences",
+ children: [
+ { identifier: "1.1", label: "Mathematics" },
+ { identifier: "1.2", label: "Computer and information sciences" },
+ { identifier: "1.3", label: "Physical sciences" },
+ { identifier: "1.4", label: "Chemical sciences" },
+ { identifier: "1.5", label: "Earth and related environmental sciences" },
+ { identifier: "1.6", label: "Biological sciences" },
+ { identifier: "1.7", label: "Other natural sciences" }
+ ]
+ },
+ {
+ identifier: "2",
+ label: "Engineering and Technology",
+ children: [
+ { identifier: "2.1", label: "Civil engineering" },
+ { identifier: "2.2", label: "Electrical engineering, electronic engineering, information engineering" },
+ { identifier: "2.3", label: "Mechanical engineering" },
+ { identifier: "2.4", label: "Chemical engineering" },
+ { identifier: "2.5", label: "Materials engineering" },
+ { identifier: "2.6", label: "Medical engineering" },
+ { identifier: "2.7", label: "Environmental engineering" },
+ { identifier: "2.8", label: "Environmental biotechnology" },
+ { identifier: "2.9", label: "Industrial Biotechnology" },
+ { identifier: "2.10", label: "Nano-technology" },
+ { identifier: "2.11", label: "Other engineering and technologies" }
+ ]
+ },
+ {
+ identifier: "3",
+ label: "Medical and Health Sciences",
+ children: [
+ { identifier: "3.1", label: "Basic medicine" },
+ { identifier: "3.2", label: "Clinical medicine" },
+ { identifier: "3.3", label: "Health sciences" },
+ { identifier: "3.4", label: "Health biotechnology" },
+ { identifier: "3.5", label: "Other medical sciences" }
+ ]
+ },
+ {
+ identifier: "4",
+ label: "Agricultural Sciences",
+ children: [
+ { identifier: "4.1", label: "Agriculture, forestry, and fisheries" },
+ { identifier: "4.2", label: "Animal and dairy science" },
+ { identifier: "4.3", label: "Veterinary science" },
+ { identifier: "4.4", label: "Agricultural biotechnology" },
+ { identifier: "4.5", label: "Other agricultural sciences" }
+ ]
+ },
+ {
+ identifier: "5",
+ label: "Social Sciences",
+ children: [
+ { identifier: "5.1", label: "Psychology" },
+ { identifier: "5.2", label: "Economics and business" },
+ { identifier: "5.3", label: "Educational sciences" },
+ { identifier: "5.4", label: "Sociology" },
+ { identifier: "5.5", label: "Law" },
+ { identifier: "5.6", label: "Political science" },
+ { identifier: "5.7", label: "Social and economic geography" },
+ { identifier: "5.8", label: "Media and communications" },
+ { identifier: "5.7", label: "Other social sciences" }
+ ]
+ },
+ {
+ identifier: "6",
+ label: "Humanities",
+ children: [
+ { identifier: "6.1", label: "History and archaeology" },
+ { identifier: "6.2", label: "Languages and literature" },
+ { identifier: "6.3", label: "Philosophy, ethics and religion" },
+ { identifier: "6.4", label: "Art (arts, history of arts, performing arts, music)" },
+ { identifier: "6.5", label: "Other humanities" }
+ ]
+ }
+ ].each do |fos|
+ p "#{fos[:identifier]} - #{fos[:label]}"
+ parent = ResearchDomain.find_or_create_by(identifier: fos[:identifier], label: fos[:label])
- def process_mime_type_file(csv:)
- return unless csv.is_a?(CSV::Table)
-
- csv.each do |line|
- next unless line["Template"].present? && line["Name"].present?
-
- type = MimeType.find_or_initialize_by(value: line["Template"].downcase)
- type.description = line["Name"]
- type.category = line["Template"].split("/").first.downcase
- type.save
+ fos[:children].each do |child|
+ child[:parent_id] = parent.id
+ p " #{child[:identifier]} - #{child[:label]}"
+ ResearchDomain.find_or_create_by(child)
+ end
end
end
-
- def fetch_mime_type_csv_file(url:)
- return nil unless url.present?
-
- payload = HTTParty.get(url, debug: false)
- return nil unless payload.code == 200
-
- payload.body
- end
end
-# rubocop:enable Metrics/BlockLength
+# rubocop:enable Metrics/BlockLength, Layout/LineLength
diff --git a/spec/factories/plans.rb b/spec/factories/plans.rb
index ebd56acf16..20bfbdd9a3 100644
--- a/spec/factories/plans.rb
+++ b/spec/factories/plans.rb
@@ -6,18 +6,13 @@
#
# id :integer not null, primary key
# complete :boolean default(FALSE)
-# data_contact :string
-# data_contact_email :string
-# data_contact_phone :string
# description :text
+# ethical_issues :boolean
+# ethical_issues_description :text
+# ethical_issues_report :string
# feedback_requested :boolean default(FALSE)
-# funder_name :string
-# grant_number :string
+# funding_status :integer
# identifier :string
-# principal_investigator :string
-# principal_investigator_email :string
-# principal_investigator_identifier :string
-# principal_investigator_phone :string
# title :string
# visibility :integer default(3), not null
# created_at :datetime
@@ -26,7 +21,7 @@
# org_id :integer
# funder_id :integer
# grant_id :integer
-# api_client_id :integer
+# research_domain_id :bigint
#
# Indexes
#
@@ -39,6 +34,7 @@
#
# fk_rails_... (template_id => templates.id)
# fk_rails_... (org_id => orgs.id)
+# fk_rails_... (research_domain_id => research_domains.id)
#
FactoryBot.define do
@@ -46,21 +42,16 @@
title { Faker::Company.bs }
template
org
- # TODO: Drop this column once the funder_id has been back filled
- # and we're removing the is_other org stuff
- grant_number { SecureRandom.rand(1_000) }
identifier { SecureRandom.hex }
description { Faker::Lorem.paragraph }
- principal_investigator { Faker::Name.name }
- # TODO: Drop this column once the funder_id has been back filled
- # and we're removing the is_other org stuff
- funder_name { Faker::Company.name }
- data_contact_email { Faker::Internet.safe_email }
- principal_investigator_email { Faker::Internet.safe_email }
feedback_requested { false }
complete { false }
start_date { Time.now }
end_date { start_date + 2.years }
+ ethical_issues { [true, false].sample }
+ ethical_issues_description { Faker::Lorem.paragraph }
+ ethical_issues_report { Faker::Internet.url }
+ funding_status { Plan.funding_statuses.keys.sample }
transient do
phases { 0 }
diff --git a/spec/factories/research_domains.rb b/spec/factories/research_domains.rb
new file mode 100644
index 0000000000..7d4017f924
--- /dev/null
+++ b/spec/factories/research_domains.rb
@@ -0,0 +1,28 @@
+# frozen_string_literal: true
+
+# == Schema Information
+#
+# Table name: research_domains
+#
+# id :bigint(8) not null, primary key
+# identifier :string(255) not null
+# label :string(255) not null
+# created_at :datetime not null
+# updated_at :datetime not null
+# parent_id :bigint(8)
+#
+# Indexes
+#
+# index_research_domain_on_parent_id (parent_id)
+#
+# Foreign Keys
+#
+# fk_rails_... (parent_id => research_domains.id)
+#
+FactoryBot.define do
+ factory :research_domain do
+ identifier { SecureRandom.uuid }
+ label { Faker::Lorem.unique.word }
+ uri { Faker::Internet.url }
+ end
+end
diff --git a/spec/factories/research_outputs.rb b/spec/factories/research_outputs.rb
index ccc7204d83..807ecd8ad4 100644
--- a/spec/factories/research_outputs.rb
+++ b/spec/factories/research_outputs.rb
@@ -8,13 +8,9 @@
# abbreviation :string
# access :integer default(0), not null
# byte_size :bigint
-# coverage_end :datetime
-# coverage_region :string
-# coverage_start :datetime
# description :text
# display_order :integer
# is_default :boolean default("false")
-# mandatory_attribution :text
# output_type :integer default(3), not null
# output_type_description :string
# personal_data :boolean
@@ -36,11 +32,8 @@
abbreviation { Faker::Lorem.unique.word }
access { ResearchOutput.accesses.keys.sample }
byte_size { Faker::Number.number }
- coverage_end { Time.now + 2.years }
- coverage_start { Time.now + 1.month }
description { Faker::Lorem.paragraph }
is_default { [nil, true, false].sample }
- mandatory_attribution { Faker::Music::PearlJam.musician }
display_order { Faker::Number.between(from: 1, to: 20) }
output_type { ResearchOutput.output_types.keys.sample }
output_type_description { Faker::Lorem.sentence }
@@ -51,7 +44,6 @@
trait :complete do
after(:create) do |research_output|
- research_output.mime_type = create(:mime_type)
# add a license identifier
# add a repository identifier
# add a metadata_standard identifier
diff --git a/spec/models/api_client_spec.rb b/spec/models/api_client_spec.rb
index b33c87d4ad..68fe7089f2 100644
--- a/spec/models/api_client_spec.rb
+++ b/spec/models/api_client_spec.rb
@@ -34,7 +34,6 @@
context "Associations" do
it { is_expected.to belong_to(:org).optional }
- it { is_expected.to have_many(:plans) }
end
context "Instance Methods" do
diff --git a/spec/models/mime_type_spec.rb b/spec/models/mime_type_spec.rb
deleted file mode 100644
index c6c826c0f1..0000000000
--- a/spec/models/mime_type_spec.rb
+++ /dev/null
@@ -1,38 +0,0 @@
-# frozen_string_literal: true
-
-require "rails_helper"
-
-RSpec.describe MimeType, type: :model do
-
- context "associations" do
- it { is_expected.to have_many :research_outputs }
- end
-
- context "validations" do
- it { is_expected.to validate_presence_of(:category) }
- it { is_expected.to validate_presence_of(:description) }
- it { is_expected.to validate_presence_of(:value) }
- end
-
- it "factory builds a valid model" do
- expect(build(:mime_type).valid?).to eql(true)
- end
-
- context "scopes" do
- describe ":categories" do
- before(:each) do
- @categories = [Faker::Lorem.unique.word, Faker::Lorem.unique.word]
- @categories.each { |category| 2.times { create(:mime_type, category: category) } }
- @results = described_class.categories
- end
-
- it "returns a unique list of categories" do
- expect(@results.first).not_to eql(@results.last)
- end
- it "returns a sorted list of categories" do
- expect(@results).to eql(@categories.sort { |a, b| a <=> b })
- end
- end
- end
-
-end
diff --git a/spec/models/plan_spec.rb b/spec/models/plan_spec.rb
index aedf054f2c..2f8f38c2de 100644
--- a/spec/models/plan_spec.rb
+++ b/spec/models/plan_spec.rb
@@ -4,6 +4,7 @@
describe Plan do
+ include IdentifierHelper
include RolesHelper
include TemplateHelper
@@ -50,6 +51,8 @@
it { is_expected.to belong_to :org }
+ it { is_expected.to belong_to(:research_domain).optional }
+
it { is_expected.to belong_to(:funder).optional }
it { is_expected.to have_many :phases }
@@ -529,12 +532,11 @@
end
- # TODO: Add this one in once we are able to easily do LEFT JOINs in Rails 5
context "when Contributor name matches term" do
let!(:plan) { create(:plan, :creator, description: "foolike desc") }
let!(:contributor) { create(:contributor, plan: plan, name: "Dr. Foo Bar") }
- xit "returns contributor name" do
+ it "returns contributor name" do
expect(subject).to include(plan)
end
end
@@ -1542,7 +1544,6 @@
plan.grant = id
plan.save
plan2 = create(:plan, grant: id)
- expect(plan2.grant).to eql(plan.grant)
expect(plan2.grant.value).to eql(plan.grant.value)
# Make sure that deleting the plan does not delete the shared grant!
plan.destroy
@@ -1550,4 +1551,32 @@
end
end
+ describe "#grant association sanity checks" do
+ let!(:plan) { create(:plan, :creator) }
+
+ it "allows a grant identifier to be associated" do
+ plan.grant = { value: build(:identifier, identifier_scheme: nil).value }
+ plan.save
+ expect(plan.grant.new_record?).to eql(false)
+ end
+ it "allows a grant identifier to be deleted" do
+ plan.grant = { value: build(:identifier, identifier_scheme: nil).value }
+ plan.save
+ plan.grant = { value: nil }
+ plan.save
+ expect(plan.grant).to eql(nil)
+ expect(Identifier.last).to eql(nil)
+ end
+ it "does not allow multiple grants on a single plan" do
+ plan.grant = { value: build(:identifier, identifier_scheme: nil).value }
+ plan.save
+ val = SecureRandom.uuid
+ plan.grant = { value: build(:identifier, identifier_scheme: nil, value: val).value }
+ plan.save
+ expect(plan.grant.new_record?).to eql(false)
+ expect(plan.grant.value).to eql(val)
+ expect(Identifier.all.length).to eql(1)
+ end
+ end
+
end
diff --git a/spec/models/research_domain_spec.rb b/spec/models/research_domain_spec.rb
new file mode 100644
index 0000000000..a9294fa69c
--- /dev/null
+++ b/spec/models/research_domain_spec.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+require "rails_helper"
+
+describe ResearchDomain do
+
+ context "associations" do
+ it { is_expected.to have_many :sub_fields }
+ it { is_expected.to belong_to(:parent).optional }
+ end
+
+end
diff --git a/spec/models/research_output_spec.rb b/spec/models/research_output_spec.rb
index 221f974fd5..d948f6c206 100644
--- a/spec/models/research_output_spec.rb
+++ b/spec/models/research_output_spec.rb
@@ -6,7 +6,6 @@
context "associations" do
it { is_expected.to belong_to(:plan).optional }
- it { is_expected.to belong_to(:mime_type).optional }
end
# rubocop:disable Layout/LineLength
@@ -32,22 +31,6 @@
@subject.dataset!
expect(@subject).not_to validate_presence_of(:output_type_description)
end
-
- describe ":coverage_start and :coverage_end" do
- it "allows coverage_start to be nil" do
- @subject.coverage_start = nil
- expect(@subject.valid?).to eql(true)
- end
- it "allows end_date to be nil" do
- @subject.coverage_end = nil
- expect(@subject.valid?).to eql(true)
- end
- it "does not allow end_date to come before start_date" do
- @subject.coverage_end = Time.now
- @subject.coverage_start = Time.now + 2.days
- expect(@subject.valid?).to eql(false)
- end
- end
end
# rubocop:enable Layout/LineLength
@@ -63,64 +46,9 @@
model.destroy
expect(Plan.last).to eql(plan)
end
- it "does not delete associated mime_type" do
- model = create(:research_output, :complete, plan: create(:plan))
- mime_type = model.mime_type
- model.destroy
- expect(MimeType.last).to eql(mime_type)
- end
end
context "instance methods" do
- describe ":available_mime_types" do
- before(:each) do
- @audiovisuals = %w[audio video].map do |cat|
- create(:mime_type, category: cat)
- end
- @audiovisuals = @audiovisuals.sort { |a, b| a.description <=> b.description }
- @images = [create(:mime_type, category: "image")]
- @texts = [create(:mime_type, category: "text")]
- @models = [create(:mime_type, category: "model")]
- @subject = build(:research_output)
- end
- it "returns an empty array if no :output_type is present" do
- @subject.output_type = nil
- expect(@subject.available_mime_types.to_a).to eql([])
- end
- it "returns an empty array if :output_type has no mime_types defined" do
- @subject.physical_object!
- expect(@subject.available_mime_types.to_a).to eql([])
- end
- it "returns the correct mime_types for :output_type == :audiovisual" do
- @subject.audiovisual!
- expect(@subject.available_mime_types.to_a).to eql(@audiovisuals)
- end
- it "returns the correct mime_types for :output_type == :sound" do
- @subject.sound!
- expect(@subject.available_mime_types.to_a).to eql(@audiovisuals)
- end
- it "returns the correct mime_types for :output_type == :image" do
- @subject.image!
- expect(@subject.available_mime_types.to_a).to eql(@images)
- end
- it "returns the correct mime_types for :output_type == :data_paper" do
- @subject.data_paper!
- expect(@subject.available_mime_types.to_a).to eql(@texts)
- end
- it "returns the correct mime_types for :output_type == :dataset" do
- @subject.dataset!
- expect(@subject.available_mime_types.to_a).to eql(@texts)
- end
- it "returns the correct mime_types for :output_type == :text" do
- @subject.text!
- expect(@subject.available_mime_types.to_a).to eql(@texts)
- end
- it "returns the correct mime_types for :output_type == :model_representation" do
- @subject.model_representation!
- expect(@subject.available_mime_types.to_a).to eql(@models)
- end
- end
-
xit "licenses should have tests once implemented" do
true
end
diff --git a/spec/presenters/api/v1/funding_presenter_spec.rb b/spec/presenters/api/v1/funding_presenter_spec.rb
index feb6dde3d6..2216ace28c 100644
--- a/spec/presenters/api/v1/funding_presenter_spec.rb
+++ b/spec/presenters/api/v1/funding_presenter_spec.rb
@@ -1,21 +1,32 @@
# frozen_string_literal: true
-require "rails_helper"
+module Api
-RSpec.describe Api::V1::FundingPresenter do
+ module V1
+
+ class FundingPresenter
+
+ class << self
+
+ # If the plan has a grant number then it has been awarded/granted
+ # otherwise it is 'planned'
+ def status(plan:)
+ return "planned" unless plan.present?
+
+ case plan.funding_status
+ when "funded"
+ "granted"
+ when "denied"
+ "rejected"
+ else
+ "planned"
+ end
+ end
+
+ end
- describe "#status(plan:)" do
- it "returns `planned` if the plan is nil" do
- expect(described_class.status(plan: nil)).to eql("planned")
- end
- it "returns `planned` if the plan's grant_number is nil" do
- plan = build(:plan, grant_number: nil)
- expect(described_class.status(plan: plan)).to eql("planned")
- end
- it "returns `granted` if the plan has a grant_number" do
- plan = build(:plan, grant_number: Faker::Lorem.word)
- expect(described_class.status(plan: plan)).to eql("granted")
end
+
end
end
diff --git a/spec/presenters/api/v1/plan_presenter_spec.rb b/spec/presenters/api/v1/plan_presenter_spec.rb
index ea5fb9071e..83ffb43180 100644
--- a/spec/presenters/api/v1/plan_presenter_spec.rb
+++ b/spec/presenters/api/v1/plan_presenter_spec.rb
@@ -25,7 +25,13 @@
expect(presenter.data_contact).to eql(nil)
expect(presenter.contributors).to eql([])
end
- it "sets data_contact" do
+ it "sets data_contact to the owner" do
+ # Plan.owner stupidly requires that the record be persisted, so need to create here
+ plan = create(:plan, :creator)
+ presenter = described_class.new(plan: plan)
+ expect(presenter.data_contact).to eql(plan.owner)
+ end
+ it "sets data_contact to the data_curation contributor if there is no owner" do
expect(@presenter.data_contact).to eql(@data_contact)
end
it "sets other contributors (including the data_contact)" do
diff --git a/spec/services/api/v1/contextual_error_service_spec.rb b/spec/services/api/v1/contextual_error_service_spec.rb
index 235135557f..529b9f28c3 100644
--- a/spec/services/api/v1/contextual_error_service_spec.rb
+++ b/spec/services/api/v1/contextual_error_service_spec.rb
@@ -10,7 +10,7 @@
@plan.contributors << build(:contributor, org: build(:org), investigation: true)
@plan.contributors.first.identifiers << build(:identifier)
@plan.funder = build(:org)
- @plan.grant = build(:identifier)
+ @plan.grant = { value: build(:identifier).value }
end
describe "process_plan_errors(plan:)" do
@@ -38,9 +38,6 @@
it "contextualizes the :plan funder errors" do
expect(@results.include?("Funding name can't be blank")).to eql(true)
end
- it "contextualizes the :plan grant errors" do
- expect(@results.include?("Grant value can't be blank")).to eql(true)
- end
end
describe "contextualize(errors:)" do
@@ -106,13 +103,6 @@
expect(result.length).to eql(1)
expect(result.first.start_with?("Funding name ")).to eql(true)
end
- it "returns errors if a Grant is invalid" do
- @plan.grant.value = nil
- @plan.grant.valid?
- result = described_class.contextualize(errors: @plan.grant.errors, context: "Grant")
- expect(result.length).to eql(1)
- expect(result.first.start_with?("Grant value ")).to eql(true)
- end
end
describe "valid_plan?(plan:)" do
@@ -124,13 +114,9 @@
@plan.funder.name = nil
expect(described_class.valid_plan?(plan: @plan)).to eql(false)
end
- it "return false if :plan grant is not valid" do
- @plan.grant.value = nil
- expect(described_class.valid_plan?(plan: @plan)).to eql(false)
- end
it "does not require :plan funder and grant to be present" do
@plan.funder = nil
- @plan.grant = nil
+ @plan.grant = {}
expect(described_class.valid_plan?(plan: @plan)).to eql(true)
end
it "returns true when everything is valid" do
diff --git a/spec/support/helpers/identifier_helper.rb b/spec/support/helpers/identifier_helper.rb
new file mode 100644
index 0000000000..8a199a8a48
--- /dev/null
+++ b/spec/support/helpers/identifier_helper.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+module IdentifierHelper
+
+ def create_orcid(user:, val: SecureRandom.uuid)
+ scheme = orcid_scheme
+ val = append_prefix(scheme: scheme, val: val)
+ create(:identifier, identifiable: user, identifier_scheme: scheme, value: val)
+ end
+
+ def orcid_scheme
+ name = Rails.configuration.x.orcid.name || "orcid"
+ landing_page = Rails.configuration.x.orcid.landing_page_url || "https://orcid.org/"
+ scheme = IdentifierScheme.find_by(name: name)
+ scheme.update(identifier_prefix: landing_page) if scheme.present?
+ return scheme if scheme.present?
+
+ create(:identifier_scheme, :for_identification, :for_users, name: name,
+ identifier_prefix: landing_page)
+ end
+
+ def append_prefix(scheme:, val:)
+ val = val.start_with?("/") ? val[1..val.length] : val
+ url = landing_page_for(scheme: scheme)
+ val.start_with?(url) ? val : "#{url}#{val}"
+ end
+
+ def remove_prefix(scheme:, val:)
+ val.gsub(landing_page_for(scheme: scheme), "")
+ end
+
+ def landing_page_for(scheme:)
+ url = scheme.identifier_prefix
+ unless url.present?
+ url = Rails.configuration.x.send(:"#{scheme.name.downcase}")&.landing_page_url
+ end
+ return nil unless url.present?
+
+ %w[/ : & ?].include?(url.last) ? url : "#{url}/"
+ end
+
+end
diff --git a/spec/views/api/v1/plans/_funding.json.jbuilder_spec.rb b/spec/views/api/v1/plans/_funding.json.jbuilder_spec.rb
index 3f200f6274..69dba26ac9 100644
--- a/spec/views/api/v1/plans/_funding.json.jbuilder_spec.rb
+++ b/spec/views/api/v1/plans/_funding.json.jbuilder_spec.rb
@@ -9,7 +9,9 @@
create(:identifier, identifiable: @funder,
identifier_scheme: create(:identifier_scheme, name: "fundref"))
@funder.reload
- @plan = create(:plan, funder: @funder)
+ @plan = create(:plan, funder: @funder, org: create(:org), identifier: SecureRandom.uuid)
+ create(:identifier, identifiable: @plan.org,
+ identifier_scheme: create(:identifier_scheme, name: "ror"))
@grant = create(:identifier, identifiable: @plan)
@plan.update(grant_id: @grant.id)
@plan.reload
@@ -31,10 +33,23 @@
expect(@json[:funder_id][:type]).to eql(id.identifier_format)
expect(@json[:funder_id][:identifier]).to eql(id.value)
end
+ it "includes :dmproadmap_funding_opportunity_identifier" do
+ identifier = @plan.identifier
+ expect(@json[:dmproadmap_funding_opportunity_id][:type]).to eql("other")
+ expect(@json[:dmproadmap_funding_opportunity_id][:identifier]).to eql(identifier)
+ end
it "includes :grant_ids" do
expect(@json[:grant_id][:type]).to eql(@grant.identifier_format)
expect(@json[:grant_id][:identifier]).to eql(@grant.value)
end
+ it "includes :dmproadmap_funded_affiliations" do
+ org = @plan.org
+ expect(@json[:dmproadmap_funded_affiliations].any?).to eql(true)
+ affil = @json[:dmproadmap_funded_affiliations].last
+ expect(affil[:name]).to eql(org.name)
+ expect(affil[:affiliation_id][:type]).to eql(org.identifiers.last.identifier_format)
+ expect(affil[:affiliation_id][:identifier]).to eql(org.identifiers.last.value)
+ end
end
end
diff --git a/spec/views/api/v1/plans/_show.json.jbuilder_spec.rb b/spec/views/api/v1/plans/_show.json.jbuilder_spec.rb
index 2bf3068212..7f800c9d91 100644
--- a/spec/views/api/v1/plans/_show.json.jbuilder_spec.rb
+++ b/spec/views/api/v1/plans/_show.json.jbuilder_spec.rb
@@ -38,6 +38,16 @@
it "includes the :modified" do
expect(@json[:modified]).to eql(@plan.updated_at.to_formatted_s(:iso8601))
end
+ it "includes :ethical_issues" do
+ expected = Api::V1::ConversionService.boolean_to_yes_no_unknown(@plan.ethical_issues)
+ expect(@json[:ethical_issues_exist]).to eql(expected)
+ end
+ it "includes :ethical_issues_description" do
+ expect(@json[:ethical_issues_description]).to eql(@plan.ethical_issues_description)
+ end
+ it "includes :ethical_issues_report" do
+ expect(@json[:ethical_issues_report]).to eql(@plan.ethical_issues_report)
+ end
it "returns the URL of the plan as the :dmp_id if no DOI is defined" do
expected = Rails.application.routes.url_helpers.api_v1_plan_url(@plan)