require_relative 'test_helper' module MESH class HeadingTest < TestBase def test_have_the_correct_unique_id mh = @mesh_tree.find_heading_by_unique_id('D000001') assert_equal 'D000001', mh.unique_id end def test_have_the_correct_tree_number mh = @mesh_tree.find_heading_by_unique_id('D000001') assert_equal 1, mh.tree_numbers.length assert_includes mh.tree_numbers, 'D03.438.221.173' end def test_have_the_correct_tree_numbers mh = @mesh_tree.find_heading_by_unique_id('D000224') assert_equal 2, mh.tree_numbers.length assert_includes mh.tree_numbers, 'C19.053.500.263' assert_includes mh.tree_numbers, 'C20.111.163' end def test_have_the_correct_root_letters mh = @mesh_tree.find_heading_by_unique_id('D000224') assert_equal ['C'], mh.roots mh = @mesh_tree.find_heading_by_unique_id('D064946') assert_equal ['H', 'N'], mh.roots end def test_have_the_correct_descriptor_class mh = @mesh_tree.find_heading_by_unique_id('D000224') assert_equal :topical_descriptor, mh.descriptor_class mh = @mesh_tree.find_heading_by_unique_id('D005260') assert_equal :check_tag, mh.descriptor_class end def test_have_the_correct_semantic_type mh = @mesh_tree.find_heading_by_unique_id('D000224') assert_equal ['Disease or Syndrome'], mh.semantic_types mh = @mesh_tree.find_heading_by_unique_id('D005260') assert_equal ['Organism Attribute'], mh.semantic_types mh = @mesh_tree.find_heading_by_unique_id('D014148') assert_equal ['Organic Chemical', 'Pharmacologic Substance'], mh.semantic_types end def test_have_the_correct_original_heading mh = @mesh_tree.find_heading_by_unique_id('D000224') assert_equal 'Addison Disease', mh.original_heading mh = @mesh_tree.find_heading_by_unique_id('D000014') assert_equal 'Abnormalities, Drug-Induced', mh.original_heading end def test_have_anglicised_original_heading mh = @mesh_tree.find_heading_by_unique_id('D001471') assert_equal 'Barrett Esophagus', mh.original_heading assert_equal 'Barrett Oesophagus', mh.original_heading(:en_gb) end def test_have_natural_language_name mh = @mesh_tree.find_heading_by_unique_id('D000224') assert_equal 'Addison Disease', mh.natural_language_name mh = @mesh_tree.find_heading_by_unique_id('D000014') assert_equal 'Drug-Induced Abnormalities', mh.natural_language_name end def test_have_anglicised_natural_language_name mh = @mesh_tree.find_heading_by_unique_id('D001471') assert_equal 'Barrett Esophagus', mh.natural_language_name assert_equal 'Barrett Oesophagus', mh.natural_language_name(:en_gb) end def test_have_the_correct_summary mh = @mesh_tree.find_heading_by_unique_id('D000238') assert_equal 'A benign tumor of the anterior pituitary in which the cells do not stain with acidic or basic dyes.', mh.summary end def test_have_anglicised_summary mh = @mesh_tree.find_heading_by_unique_id('D001471') assert_equal 'A condition with damage to the lining of the lower ESOPHAGUS resulting from chronic acid reflux (ESOPHAGITIS, REFLUX). Through the process of metaplasia, the squamous cells are replaced by a columnar epithelium with cells resembling those of the INTESTINE or the salmon-pink mucosa of the STOMACH. Barrett\'s columnar epithelium is a marker for severe reflux and precursor to ADENOCARCINOMA of the esophagus.', mh.summary assert_equal 'A condition with damage to the lining of the lower OESOPHAGUS resulting from chronic acid reflux (OESOPHAGITIS, REFLUX). Through the process of metaplasia, the squamous cells are replaced by a columnar epithelium with cells resembling those of the INTESTINE or the salmon-pink mucosa of the STOMACH. Barrett\'s columnar epithelium is a marker for severe reflux and precursor to ADENOCARCINOMA of the oesophagus.', mh.summary(:en_gb) end def test_linkify_summary mh = @mesh_tree.find_heading_by_unique_id('D001471') original_summary = 'A condition with damage to the lining of the lower ESOPHAGUS resulting from chronic acid reflux (ESOPHAGITIS, REFLUX). Through the process of metaplasia, the squamous cells are replaced by a columnar epithelium with cells resembling those of the INTESTINE or the salmon-pink mucosa of the STOMACH. Barrett\'s columnar epithelium is a marker for severe reflux and precursor to ADENOCARCINOMA of the esophagus.' assert_equal original_summary, mh.summary found = { 'ESOPHAGUS' => false, 'ESOPHAGITIS, REFLUX' => false, 'INTESTINE' => false, 'STOMACH' => false, 'ADENOCARCINOMA' => false } linkified_summary = mh.linkify_summary do |text, entry| found[text] = entry "#{text.downcase}" end assert_equal 5, found.length found.each do |text, found_entry| refute_nil found_entry, "Linkify found '#{text}' but entry was nil" assert found_entry, "Linkify failed to find '#{text}'" end assert_equal original_summary, mh.summary assert_equal 'A condition with damage to the lining of the lower esophagus resulting from chronic acid reflux (esophagitis, reflux). Through the process of metaplasia, the squamous cells are replaced by a columnar epithelium with cells resembling those of the intestine or the salmon-pink mucosa of the stomach. Barrett\'s columnar epithelium is a marker for severe reflux and precursor to adenocarcinoma of the esophagus.', linkified_summary end def test_linkifies_another_summary mh = @mesh_tree.find_heading_by_main_heading('Diabetic Nephropathies') linkified_summary = mh.linkify_summary do |text, entry| "#{text.downcase}" end expected_summary = 'KIDNEY injuries associated with diabetes mellitus and affecting KIDNEY GLOMERULUS; ARTERIOLES; KIDNEY TUBULES; and the interstitium. Clinical signs include persistent PROTEINURIA, from microalbuminuria progressing to ALBUMINURIA of greater than 300 mg/24 h, leading to reduced GLOMERULAR FILTRATION RATE and END-STAGE RENAL DISEASE.' expected_linkified = 'kidney injuries associated with diabetes mellitus and affecting kidney glomerulus; arterioles; kidney tubules; and the interstitium. Clinical signs include persistent proteinuria, from microalbuminuria progressing to albuminuria of greater than 300 mg/24 h, leading to reduced glomerular filtration rate and end-stage renal disease.' assert_equal expected_summary, mh.summary assert_equal expected_linkified, linkified_summary end def test_to_s mh = @mesh_tree.find_heading_by_unique_id('D001471') assert_equal 'D001471, Barrett Esophagus, [C06.198.102,C06.405.117.102]', mh.to_s end def test_have_the_correct_entries expected_terms = ['Activity Cycles', 'Ultradian Cycles', 'Activity Cycle', 'Cycle, Activity', 'Cycle, Ultradian', 'Cycles, Activity', 'Cycles, Ultradian', 'Ultradian Cycle'] mh = @mesh_tree.find_heading_by_unique_id('D000204') actual_terms = mh.structured_entries.map { |entry| entry.term } assert_equal expected_terms.sort, actual_terms.sort end def test_have_anglicised_entries expected_entries = ["Barrett Epithelium", "Barrett Esophagus", "Barrett Metaplasia", "Barrett Oesophagus", "Barrett Syndrome", "Barrett's Esophagus", "Barrett's Oesophagus", "Barrett's Syndrome", "Barretts Esophagus", "Barretts Oesophagus", "Barretts Syndrome", "Epithelium, Barrett", "Esophagus, Barrett", "Esophagus, Barrett's", "Oesophagus, Barrett", "Oesophagus, Barrett's", "Syndrome, Barrett", "Syndrome, Barrett's"] expected_entries_en = ['Barrett Oesophagus', 'Barrett Syndrome', 'Oesophagus, Barrett', 'Barrett Epithelium', 'Barrett Metaplasia', 'Barrett\'s Oesophagus', 'Barrett\'s Syndrome', 'Barretts Oesophagus', 'Barretts Syndrome', 'Epithelium, Barrett', 'Oesophagus, Barrett\'s', 'Syndrome, Barrett', 'Syndrome, Barrett\'s'] expected_entries.sort! expected_entries_en.sort! mh = @mesh_tree.find_heading_by_unique_id('D001471') actual_entry_terms_all = mh.structured_entries.map { |entry| entry.term } en_gb_entries = mh.structured_entries.select { |entry| entry.locales.include? :en_gb } en_gb_terms = en_gb_entries.map { |entry| entry.term } assert_equal expected_entries.sort, actual_entry_terms_all.sort assert_equal expected_entries_en.sort, en_gb_terms.sort end def test_structured_entries_have_duplicates_with_MH skip #todo for test_has_structured_entries #ideally shouldn't have Acetominophen duplicated. end def test_has_structured_entries mh = @mesh_tree.find_heading_by_main_heading('Acetaminophen') expected_terms = ['APAP', 'Acamol', 'Acephen', 'Acetaco', 'Acetamidophenol', 'Acetaminophen', 'Acetominophen', 'Algotropyl', 'Anacin 3', 'Anacin-3', 'Anacin3', 'Datril', 'Hydroxyacetanilide', 'N-(4-Hydroxyphenyl)acetanilide', 'N-Acetyl-p-aminophenol', 'Panadol', 'Paracetamol', 'Tylenol', 'p-Acetamidophenol', 'p-Hydroxyacetanilide'] actual_terms = mh.structured_entries.map { |tn| tn.term } assert_equal expected_terms.sort, actual_terms.sort end def test_has_entries_by_term mh = @mesh_tree.find_heading_by_main_heading('Acetaminophen') expected_terms = ['Acetamidophenol', 'Hydroxyacetanilide', 'Paracetamol', 'APAP', 'Acamol', 'Acephen', 'Acetaco', 'Acetominophen', 'Acetominophen', 'Algotropyl', 'Anacin-3', 'Datril', 'N-(4-Hydroxyphenyl)acetanilide', 'N-Acetyl-p-aminophenol', 'Panadol', 'Tylenol', 'p-Acetamidophenol', 'p-Hydroxyacetanilide', 'Anacin 3', 'Anacin3'] entries_by_term = mh.entries_by_term assert_equal expected_terms.length, entries_by_term.length expected_terms.each do |expected_term| assert_equal expected_term, entries_by_term[expected_term].term end end def test_have_a_single_wikipedia_link expected = { 'D000001' => 'http://en.wikipedia.org/wiki/A23187', 'D000005' => 'http://en.wikipedia.org/wiki/Abdomen', 'D000082' => 'http://en.wikipedia.org/wiki/Paracetamol' } expected.each do |id, expected_link| mh = @mesh_tree.find_heading_by_unique_id(id) assert_equal 1, mh.wikipedia_links.length assert_equal expected_link, mh.wikipedia_links[0][:link] end end def test_have_a_single_wikipedia_score expected = { 'D000001' => 0.5, 'D000005' => 1.0, 'D000082' => 0.35 } expected.each do |id, expected_score| mh = @mesh_tree.find_heading_by_unique_id(id) assert_equal 1, mh.wikipedia_links.length assert_equal expected_score, mh.wikipedia_links[0][:score] end end def test_have_a_single_wikipedia_image expected = { 'D000001' => 'http://upload.wikimedia.org/wikipedia/commons/thumb/1/17/A23187.png/220px-A23187.png', 'D000005' => 'http://upload.wikimedia.org/wikipedia/commons/thumb/3/3b/Abdomen_%28PSF%29.jpg/250px-Abdomen_%28PSF%29.jpg', 'D000082' => 'http://upload.wikimedia.org/wikipedia/commons/thumb/2/29/Paracetamol-skeletal.svg/150px-Paracetamol-skeletal.svg.png' } expected.each do |id, expected_image| mh = @mesh_tree.find_heading_by_unique_id(id) assert_equal 1, mh.wikipedia_links.length assert_equal expected_image, mh.wikipedia_links[0][:image] end end def test_have_a_single_wikipedia_abstract expected = { 'D000001' => '| CAS_number = 52665-69-7', 'D000005' => 'The abdomen (less formally called the belly, stomach, or tummy), in vertebrates such as mammals, constitutes the part of the body between the thorax (chest) and pelvis. The region enclosed by the abdomen is termed the abdominal cavity.', 'D000082' => '| MedlinePlus = a681004' } expected.each do |id, expected_abstract| mh = @mesh_tree.find_heading_by_unique_id(id) assert_equal 1, mh.wikipedia_links.length assert_equal expected_abstract, mh.wikipedia_links[0][:abstract] end end def test_have_more_than_one_wikipedia_link mh = @mesh_tree.find_heading_by_unique_id('D000100') expected = %w( http://en.wikipedia.org/wiki/Sodium_acetrizoate http://en.wikipedia.org/wiki/Acetrizoic_acid ) assert_equal expected, mh.wikipedia_links.map { |l| l[:link] } end def test_have_more_than_one_wikipedia_score mh = @mesh_tree.find_heading_by_unique_id('D000100') expected = [0.09, 0.09] assert_equal expected, mh.wikipedia_links.map { |l| l[:score] } end def test_have_more_than_one_wikipedia_image mh = @mesh_tree.find_heading_by_unique_id('D000100') expected = %w( http://upload.wikimedia.org/wikipedia/commons/thumb/4/4d/Sodium_acetrizoate.svg/150px-Sodium_acetrizoate.svg.png http://upload.wikimedia.org/wikipedia/commons/thumb/2/26/Acetrizoic_acid.png/220px-Acetrizoic_acid.png ) assert_equal expected, mh.wikipedia_links.map { |l| l[:image] } end def test_have_more_than_one_wikipedia_abstract mh = @mesh_tree.find_heading_by_unique_id('D000100') expected = ['| CAS_number = 129-63-5', '| CAS_number = 85-36-9'] assert_equal expected, mh.wikipedia_links.map { |l| l[:abstract] } end def test_have_the_correct_parent mh = @mesh_tree.find_heading_by_unique_id('D000001') assert_equal 1, mh.parents.length assert_equal 'D001583', mh.parents[0].unique_id end def test_have_the_correct_parents mh = @mesh_tree.find_heading_by_unique_id('D000224') p1 = @mesh_tree.find_heading_by_unique_id('D000309') p2 = @mesh_tree.find_heading_by_unique_id('D001327') assert_equal 2, mh.parents.length assert_includes mh.parents, p1 assert_includes mh.parents, p2 end def test_have_the_correct_parents_again child = @mesh_tree.find_heading_by_main_heading('Questionnaires') assert_equal 1, child.parents.length expected_parent = @mesh_tree.find_heading_by_main_heading('Data Collection') assert_includes child.parents, expected_parent end def test_have_the_correct_children parent = @mesh_tree.find_heading_by_tree_number('C19.053.500') child1 = @mesh_tree.find_heading_by_tree_number('C19.053.500.263') child2 = @mesh_tree.find_heading_by_tree_number('C19.053.500.270') child3 = @mesh_tree.find_heading_by_tree_number('C19.053.500.480') child4 = @mesh_tree.find_heading_by_tree_number('C19.053.500.740') assert_equal 4, parent.children.length assert_includes parent.children, child1 assert_includes parent.children, child2 assert_includes parent.children, child3 assert_includes parent.children, child4 end def test_have_the_correct_children_again parent = @mesh_tree.find_heading_by_main_heading('Data Collection') expected_children = [ 'Health Surveys', 'Interviews as Topic', 'Questionnaires', 'Records as Topic', 'Registries', 'Vital Statistics', 'Geriatric Assessment', 'Nutrition Assessment', 'Health Care Surveys', 'Narration', 'Lot Quality Assurance Sampling', 'Checklist', 'Health Impact Assessment', 'Crowdsourcing' ].map { |oh| @mesh_tree.find_heading_by_main_heading(oh) } assert_equal expected_children.length, parent.children.length expected_children.each do |ec| assert_includes parent.children, ec end end def test_has_one_forward_reference mh = @mesh_tree.find_heading_by_main_heading('Abdominal Muscles') fx = @mesh_tree.find_heading_by_main_heading('Abdominal Wall') assert_equal [fx], mh.forward_references end def test_has_several_forward_references mh = @mesh_tree.find_heading_by_main_heading('Acquired Immunodeficiency Syndrome') fx1 = @mesh_tree.find_heading_by_main_heading('AIDS Arteritis, Central Nervous System') fx2 = @mesh_tree.find_heading_by_main_heading('AIDS Dementia Complex') fx3 = @mesh_tree.find_heading_by_main_heading('AIDS Serodiagnosis') fx4 = @mesh_tree.find_heading_by_main_heading('HIV Seropositivity') fx5 = @mesh_tree.find_heading_by_main_heading('HIV Seroprevalence') fx6 = @mesh_tree.find_heading_by_main_heading('Lymphoma, AIDS-Related') assert_equal [fx1, fx2, fx3, fx4, fx5, fx6], mh.forward_references end def test_have_the_correct_siblings skip end def test_match_on_conditions_for_original_heading mh = @mesh_tree.find_heading_by_unique_id('D001471') assert mh.matches(original_heading: /^Barrett Esophagus$/) end def test_not_match_on_incorrect_condition_for_original_heading mh = @mesh_tree.find_heading_by_unique_id('D001471') refute mh.matches(original_heading: /^Foo$/) end def test_match_on_conditions_for_entries mh = @mesh_tree.find_heading_by_unique_id('D001471') assert mh.matches(entries: /Metaplasia/) end def test_not_match_on_incorrect_conditions_for_entries mh = @mesh_tree.find_heading_by_unique_id('D001471') refute mh.matches(entries: /Foo/) end def test_match_on_descriptor_class mh = @mesh_tree.find_heading_by_unique_id('D000224') assert mh.matches(descriptor_class: :topical_descriptor) refute mh.matches(descriptor_class: :check_tag) mh = @mesh_tree.find_heading_by_unique_id('D005260') assert mh.matches(descriptor_class: :check_tag) refute mh.matches(descriptor_class: :topical_descriptor) end def test_match_on_conditions_for_tree_numbers mh = @mesh_tree.find_heading_by_unique_id('D001471') assert mh.matches(tree_numbers: /C06\.198\.102/) assert mh.matches(tree_numbers: /^C06\.198\.102$/) assert mh.matches(tree_numbers: /^C06/) assert mh.matches(tree_numbers: /\.198\./) assert mh.matches(tree_numbers: /^C06\.405\.117\.102$/) end def test_not_match_on_incorrect_conditions_for_tree_numbers mh = @mesh_tree.find_heading_by_unique_id('D001471') refute mh.matches(tree_numbers: /Foo/) end def test_match_on_conditions_for_summary mh = @mesh_tree.find_heading_by_unique_id('D001471') assert mh.matches(summary: /the lower ESOPHAGUS resulting from chronic acid reflux \(ESOPHAGITIS, REFLUX\)\./) end def test_not_match_on_incorrect_conditions_for_summary mh = @mesh_tree.find_heading_by_unique_id('D001471') refute mh.matches(summary: /Foo/) end def test_match_on_conditions_for_useful mh = @mesh_tree.find_heading_by_unique_id('D001471') begin mh.useful = true assert mh.matches(useful: true) refute mh.matches(useful: false) mh.useful = false assert mh.matches(useful: false) refute mh.matches(useful: true) ensure mh.useful = true end end def test_match_on_multiple_conditions mh = @mesh_tree.find_heading_by_unique_id('D001471') assert mh.matches(original_heading: /^Barrett Esophagus$/, summary: /the lower ESOPHAGUS/) end def test_not_match_on_incorrect_multiple_conditions mh = @mesh_tree.find_heading_by_unique_id('D001471') refute mh.matches(original_heading: /^Barrett Esophagus$/, summary: /Foo/) refute mh.matches(original_heading: /^Foo/, summary: /the lower ESOPHAGUS/) end def test_allow_headings_to_be_marked_as_not_useful mh = @mesh_tree.find_heading_by_unique_id('D055550') mh.useful = true assert mh.useful mh.useful = false refute mh.useful mh.useful = true assert mh.useful end def test_know_its_deepest_position_in_the_tree #single tree numbers assert_equal 1, @mesh_tree.find_heading_by_unique_id('D002319').deepest_position assert_equal 2, @mesh_tree.find_heading_by_unique_id('D001808').deepest_position assert_equal 3, @mesh_tree.find_heading_by_unique_id('D001158').deepest_position assert_equal 4, @mesh_tree.find_heading_by_unique_id('D001981').deepest_position end def test_know_its_shallowest_position_in_the_tree #single tree numbers assert_equal 1, @mesh_tree.find_heading_by_unique_id('D002319').shallowest_position assert_equal 2, @mesh_tree.find_heading_by_unique_id('D001808').shallowest_position assert_equal 3, @mesh_tree.find_heading_by_unique_id('D001158').shallowest_position assert_equal 4, @mesh_tree.find_heading_by_unique_id('D001981').shallowest_position end def test_know_if_one_heading_is_the_descendant_of_another parent = @mesh_tree.find_heading_by_unique_id('D002319') child = @mesh_tree.find_heading_by_unique_id('D001808') grandchild = @mesh_tree.find_heading_by_unique_id('D001158') great_grandchild = @mesh_tree.find_heading_by_unique_id('D001981') unrelated = @mesh_tree.find_heading_by_unique_id('D008091') refute parent.has_descendant(parent), 'should not consider itself a desecendant' assert parent.has_descendant(child), "should consider child #{child.inspect} a descendant of #{parent.inspect} in #{parent.children}" assert parent.has_descendant(grandchild), "should consider grandchild #{grandchild.inspect} a descendant #{parent.inspect}" assert parent.has_descendant(great_grandchild), "should consider great grandchild #{great_grandchild.inspect} a descendant #{parent.inspect}" refute parent.has_descendant(unrelated), 'should not consider an unrelated heading a descendant' end def test_know_if_one_heading_is_the_ancestor_of_another child = @mesh_tree.find_heading_by_unique_id('D001981') parent = @mesh_tree.find_heading_by_unique_id('D001158') grandparent = @mesh_tree.find_heading_by_unique_id('D001808') great_grandparent = @mesh_tree.find_heading_by_unique_id('D002319') unrelated = @mesh_tree.find_heading_by_unique_id('D008091') refute child.has_ancestor(child), 'should not consider itself an ancestor' assert child.has_ancestor(parent), "should consider parent #{parent.inspect} an ancestor of #{child.inspect} in #{child.parents}" assert child.has_ancestor(grandparent), "should consider grandparent #{grandparent.inspect} an ancestor #{child.inspect}" assert child.has_ancestor(great_grandparent), "should consider great grandparent #{great_grandparent.inspect} an ancestor #{child.inspect}" refute child.has_ancestor(unrelated), 'should not consider an unrelated heading an ancestor' end def test_know_if_headings_are_siblings_at_the_same_level_below_a_common_parent parent = @mesh_tree.find_heading_by_tree_number('C19.053.500') child1 = @mesh_tree.find_heading_by_tree_number('C19.053.500.263') child2 = @mesh_tree.find_heading_by_tree_number('C19.053.500.270') child3 = @mesh_tree.find_heading_by_tree_number('C19.053.500.480') child4 = @mesh_tree.find_heading_by_tree_number('C19.053.500.740') unrelated = @mesh_tree.find_heading_by_unique_id('D008091') children = [child1, child2, child3, child4] children.each { |c| refute parent.sibling?(c) } children.each { |c| refute c.sibling?(parent) } children.each { |c| assert child1.sibling?(c) unless c == child1 } children.each { |c| assert c.sibling?(child1) unless c == child1 } children.each { |c| refute unrelated.sibling?(c) } children.each { |c| refute c.sibling?(unrelated) } end def test_override_inspect_to_prevent_issues_in_test_diagnostics mh = @mesh_tree.find_heading_by_unique_id('D001471') expected = "#{mh.unique_id}, #{mh.original_heading}, [#{mh.tree_numbers.join(',')}]" assert_equal expected, mh.inspect end def setup @mesh_tree = @@mesh_tree end end end