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,
-'
The property \'#/data/0/data/1/dataType\' value \"Invalid String attribute type 1\" did not match one of the following values: String attribute type 1, Sample multi attribute type 1 in schema file:///home/kepel/projects/seek/lib/seek/isa_templates/template_attributes_schema_test.json#
Could not find a Sample Attribute Type named \'Invalid String attribute type 1\'
') do
- PopulateTemplatesJob.perform_now
+'
The property \'#/data/0/data/1/dataType\' value \"Invalid String attribute type 1\" did not match one of the following values: ') do
+ PopulateTemplatesJob.perform_now(@admin)
end
end
end