diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb index 821b8082b6..2b7d204b9b 100644 --- a/app/controllers/templates_controller.rb +++ b/app/controllers/templates_controller.rb @@ -107,7 +107,7 @@ def populate_template begin running! - PopulateTemplatesJob.new.queue_job + PopulateTemplatesJob.perform_later(@current_user) rescue StandardError done! end diff --git a/app/jobs/populate_templates_job.rb b/app/jobs/populate_templates_job.rb index e9b8afc086..aac040d90c 100644 --- a/app/jobs/populate_templates_job.rb +++ b/app/jobs/populate_templates_job.rb @@ -2,9 +2,9 @@ class PopulateTemplatesJob < ApplicationJob queue_with_priority 1 queue_as QueueNames::TEMPLATES - def perform + def perform(user) return unless Seek::Config.isa_json_compliance_enabled - Seek::IsaTemplates::TemplateExtractor.extract_templates + Seek::IsaTemplates::TemplateExtractor.extract_templates(user) end end diff --git a/lib/seek/isa_templates/template_attributes_schema.json b/lib/seek/isa_templates/template_attributes_schema.json index ceed37ba58..334f831d7c 100644 --- a/lib/seek/isa_templates/template_attributes_schema.json +++ b/lib/seek/isa_templates/template_attributes_schema.json @@ -1,112 +1,140 @@ { - "$schema": "http://json-schema.org/draft-04/schema", - "title": "ISA tempalte attribute schema", - "description": "JSON-schema representing an ISA template attribute in DataHub", - "type": "object", - "properties": { - "iri": { - "anyOf": [ - { - "type": "string", - "format": "uri" - }, - { - "type": "null" - } - ] - }, - "name": { "type": "string" }, - "description": { "type": "string" }, - "required": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "ontology": { - "anyOf": [ - { - "type": "object", - "properties": { - "name": { "type": "string" }, - "version": { - "anyOf": [{ "type": "string" }, { "type": "number" }] - }, - "description": { "type": "string" }, - "rootTermURI": { "type": "string", "format": "uri" } - } - }, - { - "type": "null" - } - ] - }, - "dataType": { - "type": "string", - "enum": [ - "Date time", - "Date", - "Real number", - "Integer", - "Web link", - "Email address", - "Text", - "String", - "Boolean", - "Registered Sample", - "Registered Sample List", - "Controlled Vocabulary", - "URI", - "Registered Data file", - "ENA custom date" - ] - }, - "CVList": { - "anyOf": [ - { - "type": "array" - }, - { - "type": "null" - } - ] - }, - "isaTag": { - "anyOf": [ - { - "type": "string", - "enum": [ - "source", - "sample", - "protocol", - "source_characteristic", - "sample_characteristic", - "other_material", - "other_material_characteristic", - "data_file", - "data_file_comment", - "parameter_value" - ] - }, - { - "type": "null" - } - ] - }, - "title": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - } - }, - "additionalProperties": false + "$schema": "http://json-schema.org/draft-04/schema", + "title": "ISA tempalte attribute schema", + "description": "JSON-schema representing an ISA template attribute in DataHub", + "type": "object", + "properties": { + "iri": { + "anyOf": [ + { + "type": "string", + "format": "uri" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "required": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ] + }, + "ontology": { + "anyOf": [ + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + }, + "description": { + "type": "string" + }, + "rootTermURI": { + "type": "string", + "format": "uri" + } + } + }, + { + "type": "null" + } + ] + }, + "dataType": { + "type": "string", + "enum": [ + "Date time", + "Date", + "Real number", + "Integer", + "Web link", + "Email address", + "Text", + "String", + "Boolean", + "Registered Sample", + "Registered Sample List", + "Controlled Vocabulary", + "URI", + "Registered Data file", + "ENA custom date" + ] + }, + "allowCVFreeText": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ] + }, + "CVList": { + "anyOf": [ + { + "type": "array" + }, + { + "type": "null" + } + ] + }, + "isaTag": { + "anyOf": [ + { + "type": "string", + "enum": [ + "source", + "sample", + "protocol", + "source_characteristic", + "sample_characteristic", + "other_material", + "other_material_characteristic", + "data_file", + "data_file_comment", + "parameter_value" + ] + }, + { + "type": "null" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false } diff --git a/lib/seek/isa_templates/template_attributes_schema_test.json b/lib/seek/isa_templates/template_attributes_schema_test.json index 23528693ba..b2d16f4092 100644 --- a/lib/seek/isa_templates/template_attributes_schema_test.json +++ b/lib/seek/isa_templates/template_attributes_schema_test.json @@ -1,99 +1,152 @@ { - "$schema": "http://json-schema.org/draft-04/schema", - "title": "ISA tempalte attribute schema", - "description": "JSON-schema representing an ISA template attribute in DataHub", - "type": "object", - "properties": { - "iri": { - "anyOf": [ - { - "type": "string", - "format": "uri" - }, - { - "type": "null" - } - ] - }, - "name": { "type": "string" }, - "description": { "type": "string" }, - "required": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - }, - "ontology": { - "anyOf": [ - { - "type": "object", - "properties": { - "name": { "type": "string" }, - "version": { - "anyOf": [{ "type": "string" }, { "type": "number" }] - }, - "description": { "type": "string" }, - "rootTermURI": { "type": "string", "format": "uri" } - } - }, - { - "type": "null" - } - ] - }, - "dataType": { - "type": "string", - "enum": [ - "String attribute type 1", - "Sample multi attribute type 1" - ] - }, - "CVList": { - "anyOf": [ - { - "type": "array" - }, - { - "type": "null" - } - ] - }, - "isaTag": { - "anyOf": [ - { - "type": "string", - "enum": [ - "source", - "sample", - "protocol", - "source_characteristic", - "sample_characteristic", - "other_material", - "other_material_characteristic", - "data_file", - "data_file_comment", - "parameter_value" - ] - }, - { - "type": "null" - } - ] - }, - "title": { - "anyOf": [ - { - "type": "boolean" - }, - { - "type": "null" - } - ] - } - }, - "additionalProperties": false + "$schema": "http://json-schema.org/draft-04/schema", + "title": "ISA template attribute schema", + "description": "JSON-schema representing an ISA template attribute in DataHub", + "type": "object", + "properties": { + "iri": { + "anyOf": [ + { + "type": "string", + "format": "uri" + }, + { + "type": "null" + } + ] + }, + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "required": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ] + }, + "ontology": { + "anyOf": [ + { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "version": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + } + ] + }, + "description": { + "type": "string" + }, + "rootTermURI": { + "type": "string", + "format": "uri" + } + } + }, + { + "type": "null" + } + ] + }, + "dataType": { + "type": "string", + "enum": [ + "Date time", + "Date", + "Real number", + "Integer", + "Web link", + "Email address", + "Text", + "String", + "ChEBI", + "ECN", + "MetaNetX chemical", + "MetaNetX reaction", + "MetaNetX compartment", + "InChI", + "ENA custom date", + "Boolean", + "Registered Strain", + "Registered Sample", + "Registered Sample List", + "Controlled Vocabulary", + "Controlled Vocabulary List", + "URI", + "DOI", + "NCBI ID", + "Registered Data file", + "Linked Extended Metadata", + "Linked Extended Metadata (multiple)" + ] + }, + "allowCVFreeText": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ] + }, + "CVList": { + "anyOf": [ + { + "type": "array" + }, + { + "type": "null" + } + ] + }, + "isaTag": { + "anyOf": [ + { + "type": "string", + "enum": [ + "source", + "sample", + "protocol", + "source_characteristic", + "sample_characteristic", + "other_material", + "other_material_characteristic", + "data_file", + "data_file_comment", + "parameter_value" + ] + }, + { + "type": "null" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ] + } + }, + "additionalProperties": false } diff --git a/lib/seek/isa_templates/template_extractor.rb b/lib/seek/isa_templates/template_extractor.rb index 4f11d633db..6e0c80c0bf 100644 --- a/lib/seek/isa_templates/template_extractor.rb +++ b/lib/seek/isa_templates/template_extractor.rb @@ -3,13 +3,12 @@ module Seek module IsaTemplates module TemplateExtractor - def self.extract_templates + def self.extract_templates(user) FileUtils.touch(resultfile) result = StringIO.new seed_isa_tags - disable_authorization_checks do - client = Ebi::OlsClient.new + User.with_current_user(user) do project = Project.find_or_create_by(title: 'Default Project') directory = Seek::Config.append_filestore_path('source_types') @directory_files = Dir.exist?(directory) ? Dir.glob("#{directory}/*.json") : [] @@ -38,54 +37,16 @@ def self.extract_templates current_template_attributes = [] item['data'].each_with_index do |attribute, j| - is_ontology = attribute['ontology'].present? - is_cv = attribute['CVList'].present? - if is_ontology || is_cv - scv = - SampleControlledVocab.new( - { - title: attribute['name'], - source_ontology: is_ontology ? attribute['ontology']['name'] : nil, - ols_root_term_uris: is_ontology ? attribute['ontology']['rootTermURI'] : nil - } - ) - end - - if is_ontology - if attribute['ontology']['rootTermURI'].present? - begin - terms = client.all_descendants(attribute['ontology']['name'], - attribute['ontology']['rootTermURI']) - rescue StandardError => e - scv.save(validate: false) - next - end - terms.each_with_index do |term, i| - puts "#{j}) #{i + 1} FROM #{terms.length}" - if i.zero? - # Skip the parent name - des = term[:description] - scv[:description] = des.is_a?(Array) ? des[0] : des - elsif term[:label].present? && term[:iri].present? - cvt = - SampleControlledVocabTerm.new( - { label: term[:label], iri: term[:iri], parent_iri: term[:parent_iri] } - ) - scv.sample_controlled_vocab_terms << cvt - end - end - end - elsif is_cv - # the CV terms - if attribute['CVList'].present? - attribute['CVList'].each do |term| - cvt = SampleControlledVocabTerm.new({ label: term }) - scv.sample_controlled_vocab_terms << cvt - end - end + is_cv = attribute['dataType'].include? 'Controlled Vocabulary' + allow_cv_free_text = false + if is_cv + is_ontology = attribute['ontology'].present? + cv_exists = !SampleControlledVocab.find_by(title: attribute['name']).nil? + allow_cv_free_text = attribute['allowCVFreeText'].present? ? attribute['allowCVFreeText'] : false + + scv = cv_exists ? SampleControlledVocab.find_by(title: attribute['name']) : initialize_sample_controlled_vocab(template_details, attribute, is_ontology) end - - p scv.errors if (is_ontology || is_cv) && !scv.save(validate: false) + p scv.errors if is_cv && !scv.save(validate: false) ta = TemplateAttribute.new(is_title: (attribute['title'] || 0), isa_tag_id: get_isa_tag_id(attribute['isaTag']), @@ -95,12 +56,13 @@ def self.extract_templates sample_controlled_vocab_id: scv&.id, pid: attribute['pid'], sample_attribute_type_id: get_sample_attribute_type(attribute['dataType']), - allow_cv_free_text: attribute['ontology'].present?, + allow_cv_free_text: allow_cv_free_text, title: attribute['name']) current_template_attributes.append ta end template.template_attributes << current_template_attributes + template.contributor = nil template.save! unless @errors.present? end @@ -118,6 +80,51 @@ def self.extract_templates FileUtils.rm_f(@directory_files) unless @directory_files.blank? end + def self.initialize_sample_controlled_vocab(template_details, attribute, is_ontology = false) + scv = SampleControlledVocab.new( + { + title: attribute['name'], + source_ontology: is_ontology ? attribute['ontology']['name'] : nil, + ols_root_term_uris: is_ontology ? attribute['ontology']['rootTermURI'] : nil + } + ) + + if is_ontology + client = Ebi::OlsClient.new + if attribute['ontology']['rootTermURI'].present? + begin + terms = client.all_descendants(attribute['ontology']['name'], + attribute['ontology']['rootTermURI']) + rescue StandardError => e + add_log(template_details, "Failed to fetch terms from OLS for attribute '#{attribute['name']}'. Please add terms manually!") + Rails.logger.debug("Failed to fetch terms from OLS for attribute '#{attribute['name']}'. Error: #{e}") + terms = [] + end + terms.each_with_index do |term, i| + puts "#{j}) #{i + 1} FROM #{terms.length}" + if i.zero? + # Skip the parent name + des = term[:description] + scv[:description] = des.is_a?(Array) ? des[0] : des + elsif term[:label].present? && term[:iri].present? + cvt = + SampleControlledVocabTerm.new( + { label: term[:label], iri: term[:iri], parent_iri: term[:parent_iri] } + ) + scv.sample_controlled_vocab_terms << cvt + end + end + end + else + # the CV terms + attribute['CVList'].each do |term| + cvt = SampleControlledVocabTerm.new({ label: term }) + scv.sample_controlled_vocab_terms << cvt + end + end + scv + end + def self.init_template(metadata) { title: metadata['name'], @@ -169,7 +176,7 @@ def self.valid_isa_json?(json) end def self.get_sample_attribute_type(title) - sa = SampleAttributeType.find_by(title:) + sa = SampleAttributeType.find_by(title: title) @errors.append "
  • Could not find a Sample Attribute Type named '#{title}'
  • " if sa.nil? return if sa.nil? @@ -180,10 +187,10 @@ def self.get_sample_attribute_type(title) def self.get_isa_tag_id(title) return nil if title.blank? - it = IsaTag.find_by(title:) + it = IsaTag.find_by(title: title) @errors.append "
  • Could not find an ISA Tag named '#{title}'
  • " if it.nil? - it.id + it&.id end def self.seed_isa_tags diff --git a/test/fixtures/files/upload_json_sample_type_template/test_apple_cv_template.json b/test/fixtures/files/upload_json_sample_type_template/test_apple_cv_template.json new file mode 100644 index 0000000000..4eaef0dd67 --- /dev/null +++ b/test/fixtures/files/upload_json_sample_type_template/test_apple_cv_template.json @@ -0,0 +1,102 @@ +{ + "data": [ + { + "metadata": { + "name": "Test Apple CV Template", + "group": "SEEK Test", + "group_order": 1, + "temporary_name": "1_test_apple_cv_template", + "version": "1.0.0", + "isa_config": null, + "isa_measurement_type": null, + "isa_technology_type": null, + "isa_protocol_type": null, + "repo_schema_id": null, + "organism": "any", + "level": "study source" + }, + "data": [ + { + "iri": null, + "name": "Source Name", + "description": "Sources are considered as the starting biological material used in a study.", + "dataType": "String", + "title": true, + "required": true, + "isaTag": "source" + }, + { + "iri": null, + "name": "Source Characteristic 1", + "description": "A characteristic of the source", + "dataType": "String", + "required": true, + "ontology": null, + "allowCVFreeText": null, + "CVList": null, + "isaTag": "source_characteristic" + }, + { + "iri": null, + "name": "apples controlled vocab for template", + "description": "", + "dataType": "Controlled Vocabulary", + "required": false, + "ontology": null, + "allowCVFreeText": true, + "CVList": [ + "Granny Smith", + "Golden Delicious", + "Bramley", + "Cox's Orange Pippin" + ], + "isaTag": "source_characteristic" + }, + { + "iri": null, + "name": "physics ontology", + "description": "", + "dataType": "Controlled Vocabulary List", + "required": false, + "ontology": { + "name": "edam", + "version": "", + "description": "The study of matter, space and time, and related concepts such as energy and force.", + "rootTermURI": "http://edamontology.org/topic_3318" + }, + "allowCVFreeText": false, + "CVList": null, + "isaTag": "source_characteristic" + }, + { + "iri": null, + "name": "New CV List", + "description": "", + "dataType": "Controlled Vocabulary List", + "required": false, + "ontology": null, + "CVList": [ + "term 1", + "term 2" + ], + "isaTag": "source_characteristic" + }, + { + "iri": null, + "name": "New ontology List", + "description": "", + "dataType": "Controlled Vocabulary List", + "required": false, + "ontology": { + "name": "FBbi", + "version": "", + "description": "Imaging method", + "rootTermURI": "http://purl.obolibrary.org/obo/FBbi_00000222" + }, + "CVList": null, + "isaTag": "source_characteristic" + } + ] + } + ] +} \ No newline at end of file diff --git a/test/fixtures/files/upload_json_sample_type_template/test_templates.json b/test/fixtures/files/upload_json_sample_type_template/test_templates.json index ce4e2f20cc..0643aee1af 100644 --- a/test/fixtures/files/upload_json_sample_type_template/test_templates.json +++ b/test/fixtures/files/upload_json_sample_type_template/test_templates.json @@ -20,7 +20,7 @@ "iri": null, "name": "Source Name", "description": "Sources are considered as the starting biological material used in a study.", - "dataType": "String attribute type 1", + "dataType": "String", "title": true, "required": true, "isaTag": "source" @@ -29,7 +29,7 @@ "iri": null, "name": "Source Characteristic 1", "description": "A characteristic of the source.", - "dataType": "String attribute type 1", + "dataType": "String", "required": true, "ontology": null, "CVList": null, @@ -57,7 +57,7 @@ "iri": null, "name": "Input", "description": "Registered Samples in the platform used as input for this protocol.", - "dataType": "Sample multi attribute type 1", + "dataType": "Registered Sample List", "required": true, "isaTag": null }, @@ -65,7 +65,7 @@ "iri": null, "name": "Name of a protocol with samples as outputs", "description": "Type of experimental step that generates samples as outputs from the study sources.", - "dataType": "String attribute type 1", + "dataType": "String", "required": true, "ontology": null, "CVList": null, @@ -75,7 +75,7 @@ "iri": null, "name": "Name of protocol parameter 1", "description": "A parameter for the protocol.", - "dataType": "String attribute type 1", + "dataType": "String", "required": true, "ontology": null, "CVList": null, @@ -85,7 +85,7 @@ "iri": null, "name": "Sample Name", "description": "Samples are considered as biological material sampled from sources and used in the study.", - "dataType": "String attribute type 1", + "dataType": "String", "title": true, "required": true, "isaTag": "sample" @@ -94,7 +94,7 @@ "iri": null, "name": "Sample Characteristic 1", "description": "A characteristic of the sample.", - "dataType": "String attribute type 1", + "dataType": "String", "required": true, "ontology": null, "CVList": null, @@ -122,7 +122,7 @@ "iri": null, "name": "Input", "description": "Registered Samples in the platform used as input for this protocol.", - "dataType": "Sample multi attribute type 1", + "dataType": "Registered Sample List", "required": true, "isaTag": null }, @@ -130,7 +130,7 @@ "iri": null, "name": "Name of a protocol with material output", "description": "Type of assay or experimental step performed that generates a material output.", - "dataType": "String attribute type 1", + "dataType": "String", "required": true, "ontology": null, "CVList": null, @@ -140,7 +140,7 @@ "iri": null, "name": "Name of protocol parameter 1", "description": "A parameter for the protocol.", - "dataType": "String attribute type 1", + "dataType": "String", "required": true, "ontology": null, "CVList": null, @@ -150,7 +150,7 @@ "iri": null, "name": "Output material Name", "description": "Name of the major material output resulting from the application of the protocol.", - "dataType": "String attribute type 1", + "dataType": "String", "title": true, "required": true, "isaTag": "other_material" @@ -159,7 +159,7 @@ "iri": null, "name": "Output material characteristic 1", "description": "Characteristic 1 of the output material.", - "dataType": "String attribute type 1", + "dataType": "String", "required": true, "ontology": null, "CVList": null, @@ -187,7 +187,7 @@ "iri": null, "name": "Input", "description": "Registered Samples in the platform used as input for this protocol.", - "dataType": "Sample multi attribute type 1", + "dataType": "Registered Sample List", "required": true, "isaTag": null }, @@ -195,7 +195,7 @@ "iri": null, "name": "Name of a protocol with data file output", "description": "Type of assay or experimental step performed that generates a data file output.", - "dataType": "String attribute type 1", + "dataType": "String", "required": true, "ontology": null, "CVList": null, @@ -205,7 +205,7 @@ "iri": null, "name": "Name of protocol parameter 1", "description": "A parameter for the protocol.", - "dataType": "String attribute type 1", + "dataType": "String", "required": true, "ontology": null, "CVList": null, @@ -215,7 +215,7 @@ "iri": null, "name": "Data file Name", "description": "Name of the major data file output resulting from the application of the protocol.", - "dataType": "String attribute type 1", + "dataType": "String", "title": true, "required": true, "isaTag": "data_file" @@ -224,7 +224,7 @@ "iri": null, "name": "Data file characteristic 1", "description": "Characteristic 1 of the data file output.", - "dataType": "String attribute type 1", + "dataType": "String", "required": true, "ontology": null, "CVList": null, diff --git a/test/functional/templates_controller_test.rb b/test/functional/templates_controller_test.rb index 566f16496f..9673aeab8d 100644 --- a/test/functional/templates_controller_test.rb +++ b/test/functional/templates_controller_test.rb @@ -14,17 +14,18 @@ class TemplatesControllerTest < ActionController::TestCase FactoryBot.create(:person) # to prevent person being first person and therefore admin @person = FactoryBot.create(:project_administrator) + @admin = FactoryBot.create(:admin) @project = @person.projects.first @project_ids = [@project.id] refute_nil @project login_as(@person) @template = FactoryBot.create(:min_template, project_ids: @project_ids, contributor: @person) - @string_type = FactoryBot.create(:string_sample_attribute_type) - @int_type = FactoryBot.create(:integer_sample_attribute_type) - @registered_sample_attribute_type = FactoryBot.create(:sample_sample_attribute_type) - @registered_sample_multi_attribute_type = FactoryBot.create(:sample_multi_sample_attribute_type) - @controlled_vocab_type = FactoryBot.create(:controlled_vocab_attribute_type) - @controlled_vocab_list_type = FactoryBot.create(:cv_list_attribute_type) + @string_type = SampleAttributeType.find_by(title: "String").nil? ? FactoryBot.create(:string_sample_attribute_type, title: "string") : SampleAttributeType.find_by(title: "String") + @int_type = SampleAttributeType.find_by(title: "Integer").nil? ? FactoryBot.create(:integer_sample_attribute_type) : SampleAttributeType.find_by(title: "Integer") + @registered_sample_attribute_type = SampleAttributeType.find_by(title: "Registered Sample").nil? ? FactoryBot.create(:sample_sample_attribute_type) : SampleAttributeType.find_by(title: "Registered Sample") + @registered_sample_multi_attribute_type = SampleAttributeType.find_by(title: "Registered Sample List").nil? ? FactoryBot.create(:sample_multi_sample_attribute_type) : SampleAttributeType.find_by(title: "Registered Sample List") + @controlled_vocab_type = SampleAttributeType.find_by(title: "Controlled Vocabulary").nil? ? FactoryBot.create(:controlled_vocab_attribute_type) : SampleAttributeType.find_by(title: "Controlled Vocabulary") + @controlled_vocab_list_type = SampleAttributeType.find_by(title: "Controlled Vocabulary List").nil? ? FactoryBot.create(:cv_list_attribute_type) : SampleAttributeType.find_by(title: "Controlled Vocabulary List") @default_isa_tag = FactoryBot.create(:default_isa_tag) end @@ -650,6 +651,72 @@ class TemplatesControllerTest < ActionController::TestCase assert_select 'script#project-selector-possibilities-json', text: /#{options}/, count: 1 end + test 'should reuse existing controlled vocabularies' do + apples_cv = FactoryBot.create(:apples_sample_controlled_vocab, title: "apples controlled vocab for template", ) + physics_ontology = FactoryBot.create(:sample_controlled_vocab, title: "physics ontology", source_ontology: "edam", ols_root_term_uris: "http://edamontology.org/topic_3318") + assert_equal SampleControlledVocab.count, 2 + + login_as(@admin) + #################################################################################################################### + # This file contains the JSON definition for 1 template with 6 template attributes: + # 1. Source Name (Sting) => New + # 2. Source Characteristic 1 (String) => New + # 3. apples controlled (CV) vocab for template => Reuse + # 4. physics ontology (CV, ontology) => Reuse + # 5. New CV (CV List) List => New + # 6. New ontology List (CV List, ontology) => New + # New template attributes should be 6 + # New sample controlled vocabs should be 2 + #################################################################################################################### + template_json = fixture_file_upload('upload_json_sample_type_template/test_apple_cv_template.json', 'application/json') + + assert_enqueued_jobs 1, only: PopulateTemplatesJob do + post :populate_template, params: { template_json_file: template_json } + end + + + assert_difference('Template.count', 1) do + assert_difference('TemplateAttribute.count', 6) do + assert_difference('SampleControlledVocab.count', 2) do + perform_enqueued_jobs(only: PopulateTemplatesJob) + end + end + end + registered_template = Template.last + assert_equal registered_template.template_attributes.detect { |ta| ta.title == 'apples controlled vocab for template' }.sample_controlled_vocab, apples_cv + assert_equal registered_template.template_attributes.detect { |ta| ta.title == 'physics ontology' }.sample_controlled_vocab, physics_ontology + end + + test 'should allow controlled vocab attributes to have free text in instance-wide templates' do + login_as(@admin) + #################################################################################################################### + # This file contains the JSON definition for 1 template with 6 template attribute: + # 1. Source Name (Sting) => allowCVFreeText: null (not present) + # 2. Source Characteristic 1 (String) => allowCVFreeText: null + # 3. apples controlled vocab for template => allowCVFreeText: true + # 4. physics ontology (CV, ontology) => allowCVFreeText: false + # 5. New CV List (CV List) => allowCVFreeText: null => Should resolve to false + # 6. New ontology (CV List, ontology) => allowCVFreeText: null => Should resolve to false + #################################################################################################################### + template_json = fixture_file_upload('upload_json_sample_type_template/test_apple_cv_template.json', 'application/json') + assert_enqueued_jobs 1, only: PopulateTemplatesJob do + post :populate_template, params: { template_json_file: template_json } + end + assert_difference('Template.count', 1) do + assert_difference('TemplateAttribute.count', 6) do + perform_enqueued_jobs(only: PopulateTemplatesJob) + end + end + + registered_template = Template.last + refute registered_template.template_attributes.detect { |ta| ta.title == 'Source Name' }.allow_cv_free_text + refute registered_template.template_attributes.detect { |ta| ta.title == 'Source Characteristic 1' }.allow_cv_free_text + assert registered_template.template_attributes.detect { |ta| ta.title == 'apples controlled vocab for template' }.allow_cv_free_text + refute registered_template.template_attributes.detect { |ta| ta.title == 'physics ontology' }.allow_cv_free_text + refute registered_template.template_attributes.detect { |ta| ta.title == 'New CV List' }.allow_cv_free_text + refute registered_template.template_attributes.detect { |ta| ta.title == 'New ontology List' }.allow_cv_free_text + end + def create_template_from_parent_template(parent_template, person= @person, linked_sample_type= nil) child_template_attributes = parent_template.template_attributes.map do |ta| FactoryBot.create(:template_attribute, parent_attribute_id: ta.id, title: ta.title, isa_tag_id: ta.isa_tag_id, sample_attribute_type: ta.sample_attribute_type, is_title: ta.is_title, required: ta.required, sample_controlled_vocab: ta.sample_controlled_vocab, pos: ta.pos) diff --git a/test/unit/jobs/populate_templates_job_test.rb b/test/unit/jobs/populate_templates_job_test.rb index 0558063667..8b91d8c7df 100644 --- a/test/unit/jobs/populate_templates_job_test.rb +++ b/test/unit/jobs/populate_templates_job_test.rb @@ -4,8 +4,8 @@ class PopulateTemplatesJobTest < ActiveSupport::TestCase def setup # Create the SampleAttributeTypes # The title MUST be set manually! - FactoryBot.create(:string_sample_attribute_type, title: 'String attribute type 1') - FactoryBot.create(:sample_multi_sample_attribute_type, title: 'Sample multi attribute type 1') + FactoryBot.create(:string_sample_attribute_type, title: 'String') if SampleAttributeType.find_by(title: 'String').nil? + FactoryBot.create(:sample_multi_sample_attribute_type, title: 'Registered Sample List') if SampleAttributeType.find_by(title: 'Registered Sample List').nil? # Create the ISA Tags %i[source_isa_tag sample_isa_tag protocol_isa_tag source_characteristic_isa_tag sample_characteristic_isa_tag @@ -16,6 +16,7 @@ def setup # Set isa_json_compliance_enabled to true Seek::Config.isa_json_compliance_enabled = true + @admin = FactoryBot.create(:admin) end def teardown @@ -31,7 +32,7 @@ def teardown assert_nothing_raised do assert_difference('Template.count', 4) do - PopulateTemplatesJob.perform_now + PopulateTemplatesJob.perform_now(@admin) end end end @@ -44,8 +45,8 @@ def teardown assert_no_difference('Template.count') do assert_raises(RuntimeError, -'') do - PopulateTemplatesJob.perform_now +'