Skip to content

Commit

Permalink
Feature: add Annotator UI tests (#627)
Browse files Browse the repository at this point in the history
* setup annotator page UI tests

* check if all the inputs and filters are present in annotator page test

* add annotator http requests to test fixtures

* test annotator results and count them

* test annotator empty illustration

* add comments in annotator page tests

* use dynamic api in recommender tests

* test that we have the exact correct annotations in the annotator test

* undo adding ids for elements to run annotator tests

* add a default ANNOTATOR_URL value for test config

---------

Co-authored-by: Syphax bouazzouni <[email protected]>
  • Loading branch information
Bilelkihal and syphax-bouazzouni committed Jun 14, 2024
1 parent a4417a7 commit e80cf79
Show file tree
Hide file tree
Showing 7 changed files with 299 additions and 9 deletions.
2 changes: 1 addition & 1 deletion app/controllers/annotator_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def annotator_results(uri)
else
@results_table_header.push(t('annotator.score'))
end
annotations = LinkedData::Client::HTTP.get(uri, api_params)
annotations = LinkedData::Client::HTTP.get(uri.dup.to_s, api_params)
@ontologies = get_simplified_ontologies_hash
@semantic_types = get_semantic_types
@results = []
Expand Down
1 change: 1 addition & 0 deletions app/views/annotator/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
= render Input::SelectComponent.new(label: t('annotator.include_ancestors'), id: 'ancestors_level', name: 'class_hierarchy_max_level', value: @ancestors_levels, selected: params[:class_hierarchy_max_level])
.filters_line
- include_score_helper = 'Score annotations following previous NCBO 2009 measure (old) or Score annotations following C-Value measure (cvalue) or Score annotations following C-Value measure with hierarchy expansion (cvalueh).'

= render Input::SelectComponent.new(label: t('annotator.include_score'), id: 'include_score', name: 'score', value: @include_score, tooltip: include_score_helper, selected: params[:score])
= render Input::NumberComponent.new(label: t('annotator.score_threshold'), name: "score_threshold", value: params[:score_threshold] || 0, tooltip: 'Specify minimum score value for annotations.')
= render Input::NumberComponent.new(label: t('annotator.confidence_threshold'), name: 'confidence_threshold', value: params[:confidence_threshold] || 0, tooltip: 'Specify the minimum position in the score distribution (between 1 and 100).')
Expand Down
7 changes: 2 additions & 5 deletions config/bioportal_config_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
$API_KEY = ENV['API_KEY']
$REST_URL = ENV['API_URL']
$BIOMIXER_URL = ENV['BIOMIXER_URL']
$ANNOTATOR_URL = $PROXY_URL = ENV['ANNOTATOR_URL']
$ANNOTATOR_URL = $PROXY_URL = ENV['ANNOTATOR_URL'].blank? ? "https://services.tesportal.lirmm.fr/annotator" : ENV['ANNOTATOR_URL']
$FAIRNESS_URL = ENV['FAIRNESS_URL']

# Resource term
Expand Down Expand Up @@ -218,7 +218,4 @@
}
]

$UI_THEME = :stageportal
if File.exist?('config/bioportal_config_development_testportal.lirmm.fr.rb')
require_relative 'bioportal_config_development_testportal.lirmm.fr' # local credentials
end
$UI_THEME = :stageportal
7 changes: 4 additions & 3 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,10 @@ services:
chrome-server:
image: selenium/standalone-chrome:112.0-chromedriver-112.0-grid-4.9.0-20230421
shm_size: 2g
ports:
- "4444:4444"
- "7900:7900"
network_mode: 'host'
# ports:
# - "4444:4444"
# - "7900:7900"

volumes:
mysql-data:
Expand Down
181 changes: 181 additions & 0 deletions test/fixtures/annotator.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
yaml_structure: regular
sample_response:
- annotatedClass:
prefLabel: Melanom
synonym:
- cilt kanseri
"@id": http://aims.fao.org/aos/agrovoc/c_4713
"@type": http://www.w3.org/2002/07/owl#Class
links:
self: https://data.stageportal.lirmm.fr/ontologies/AGROVOC/classes/http%3A%2F%2Faims.fao.org%2Faos%2Fagrovoc%2Fc_4713
ontology: http://localhost:9393/ontologies/STY
children: https://data.stageportal.lirmm.fr/ontologies/AGROVOC/classes/http%3A%2F%2Faims.fao.org%2Faos%2Fagrovoc%2Fc_4713/children
parents: https://data.stageportal.lirmm.fr/ontologies/AGROVOC/classes/http%3A%2F%2Faims.fao.org%2Faos%2Fagrovoc%2Fc_4713/parents
descendants: https://data.stageportal.lirmm.fr/ontologies/AGROVOC/classes/http%3A%2F%2Faims.fao.org%2Faos%2Fagrovoc%2Fc_4713/descendants
ancestors: https://data.stageportal.lirmm.fr/ontologies/AGROVOC/classes/http%3A%2F%2Faims.fao.org%2Faos%2Fagrovoc%2Fc_4713/ancestors
instances: https://data.stageportal.lirmm.fr/ontologies/AGROVOC/classes/http%3A%2F%2Faims.fao.org%2Faos%2Fagrovoc%2Fc_4713/instances
tree: https://data.stageportal.lirmm.fr/ontologies/AGROVOC/classes/http%3A%2F%2Faims.fao.org%2Faos%2Fagrovoc%2Fc_4713/tree
notes: https://data.stageportal.lirmm.fr/ontologies/AGROVOC/classes/http%3A%2F%2Faims.fao.org%2Faos%2Fagrovoc%2Fc_4713/notes
mappings: https://data.stageportal.lirmm.fr/ontologies/AGROVOC/classes/http%3A%2F%2Faims.fao.org%2Faos%2Fagrovoc%2Fc_4713/mappings
ui: http://stageportal.lirmm.fr/ontologies/AGROVOC?p=classes&conceptid=http%3A%2F%2Faims.fao.org%2Faos%2Fagrovoc%2Fc_4713
"@context":
self: http://www.w3.org/2002/07/owl#Class
ontology: http://localhost:9393/ontologies/STY
children: http://www.w3.org/2002/07/owl#Class
parents: http://www.w3.org/2002/07/owl#Class
descendants: http://www.w3.org/2002/07/owl#Class
ancestors: http://www.w3.org/2002/07/owl#Class
instances: http://data.bioontology.org/metadata/Instance
tree: http://www.w3.org/2002/07/owl#Class
notes: http://data.bioontology.org/metadata/Note
mappings: http://data.bioontology.org/metadata/Mapping
ui: http://www.w3.org/2002/07/owl#Class
"@context":
"@vocab": http://data.bioontology.org/metadata/
prefLabel: http://www.w3.org/2004/02/skos/core#prefLabel
synonym: http://www.w3.org/2004/02/skos/core#altLabel
"@language": en
hierarchy: []
annotations:
- from: 1
to: 8
matchType: PREF
text: MELANOMA
mappings: []
- annotatedClass:
prefLabel: Melanom
synonym:
- malignant melanoma
- melanoma patient
- melanocytes
"@id": http://data.europa.eu/8mn/euroscivoc/276b8c99-a318-48df-aa31-1f9f3e0ba910
"@type": http://www.w3.org/2002/07/owl#Class
links:
self: https://data.stageportal.lirmm.fr/ontologies/EUROSCIVOC/classes/http%3A%2F%2Fdata.europa.eu%2F8mn%2Feuroscivoc%2F276b8c99-a318-48df-aa31-1f9f3e0ba910
ontology: http://localhost:9393/ontologies/STY
children: https://data.stageportal.lirmm.fr/ontologies/EUROSCIVOC/classes/http%3A%2F%2Fdata.europa.eu%2F8mn%2Feuroscivoc%2F276b8c99-a318-48df-aa31-1f9f3e0ba910/children
parents: https://data.stageportal.lirmm.fr/ontologies/EUROSCIVOC/classes/http%3A%2F%2Fdata.europa.eu%2F8mn%2Feuroscivoc%2F276b8c99-a318-48df-aa31-1f9f3e0ba910/parents
descendants: https://data.stageportal.lirmm.fr/ontologies/EUROSCIVOC/classes/http%3A%2F%2Fdata.europa.eu%2F8mn%2Feuroscivoc%2F276b8c99-a318-48df-aa31-1f9f3e0ba910/descendants
ancestors: https://data.stageportal.lirmm.fr/ontologies/EUROSCIVOC/classes/http%3A%2F%2Fdata.europa.eu%2F8mn%2Feuroscivoc%2F276b8c99-a318-48df-aa31-1f9f3e0ba910/ancestors
instances: https://data.stageportal.lirmm.fr/ontologies/EUROSCIVOC/classes/http%3A%2F%2Fdata.europa.eu%2F8mn%2Feuroscivoc%2F276b8c99-a318-48df-aa31-1f9f3e0ba910/instances
tree: https://data.stageportal.lirmm.fr/ontologies/EUROSCIVOC/classes/http%3A%2F%2Fdata.europa.eu%2F8mn%2Feuroscivoc%2F276b8c99-a318-48df-aa31-1f9f3e0ba910/tree
notes: https://data.stageportal.lirmm.fr/ontologies/EUROSCIVOC/classes/http%3A%2F%2Fdata.europa.eu%2F8mn%2Feuroscivoc%2F276b8c99-a318-48df-aa31-1f9f3e0ba910/notes
mappings: https://data.stageportal.lirmm.fr/ontologies/EUROSCIVOC/classes/http%3A%2F%2Fdata.europa.eu%2F8mn%2Feuroscivoc%2F276b8c99-a318-48df-aa31-1f9f3e0ba910/mappings
ui: http://stageportal.lirmm.fr/ontologies/EUROSCIVOC?p=classes&conceptid=http%3A%2F%2Fdata.europa.eu%2F8mn%2Feuroscivoc%2F276b8c99-a318-48df-aa31-1f9f3e0ba910
"@context":
self: http://www.w3.org/2002/07/owl#Class
ontology: http://localhost:9393/ontologies/STY
children: http://www.w3.org/2002/07/owl#Class
parents: http://www.w3.org/2002/07/owl#Class
descendants: http://www.w3.org/2002/07/owl#Class
ancestors: http://www.w3.org/2002/07/owl#Class
instances: http://data.bioontology.org/metadata/Instance
tree: http://www.w3.org/2002/07/owl#Class
notes: http://data.bioontology.org/metadata/Note
mappings: http://data.bioontology.org/metadata/Mapping
ui: http://www.w3.org/2002/07/owl#Class
"@context":
"@vocab": http://data.bioontology.org/metadata/
prefLabel: http://www.w3.org/2004/02/skos/core#prefLabel
synonym: http://www.w3.org/2004/02/skos/core#altLabel
"@language": en
hierarchy: []
annotations:
- from: 1
to: 8
matchType: PREF
text: MELANOMA
- from: 34
to: 44
matchType: SYN
text: MELANOCYTES
mappings: []
- annotatedClass:
definition:
- http://opendata.inrae.fr/thesaurusINRAE/note_f18c0fe1
prefLabel: mélanome
synonym:
- malignant melanoma
- mélanome malin
"@id": http://opendata.inrae.fr/thesaurusINRAE/c_11970
"@type": http://www.w3.org/2002/07/owl#Class
links:
self: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11970
ontology: http://localhost:9393/ontologies/STY
children: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11970/children
parents: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11970/parents
descendants: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11970/descendants
ancestors: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11970/ancestors
instances: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11970/instances
tree: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11970/tree
notes: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11970/notes
mappings: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11970/mappings
ui: http://stageportal.lirmm.fr/ontologies/INRAETHES?p=classes&conceptid=http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11970
"@context":
self: http://www.w3.org/2002/07/owl#Class
ontology: http://localhost:9393/ontologies/STY
children: http://www.w3.org/2002/07/owl#Class
parents: http://www.w3.org/2002/07/owl#Class
descendants: http://www.w3.org/2002/07/owl#Class
ancestors: http://www.w3.org/2002/07/owl#Class
instances: http://data.bioontology.org/metadata/Instance
tree: http://www.w3.org/2002/07/owl#Class
notes: http://data.bioontology.org/metadata/Note
mappings: http://data.bioontology.org/metadata/Mapping
ui: http://www.w3.org/2002/07/owl#Class
"@context":
"@vocab": http://data.bioontology.org/metadata/
prefLabel: http://www.w3.org/2004/02/skos/core#prefLabel
synonym: http://www.w3.org/2004/02/skos/core#altLabel
definition: http://www.w3.org/2004/02/skos/core#definition
"@language": en
hierarchy: []
annotations:
- from: 1
to: 8
matchType: PREF
text: MELANOMA
mappings: []
- annotatedClass:
prefLabel: tumeur
synonym:
- néoplasme
- néoplasie
"@id": http://opendata.inrae.fr/thesaurusINRAE/c_11887
"@type": http://www.w3.org/2002/07/owl#Class
links:
self: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11887
ontology: http://localhost:9393/ontologies/STY
children: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11887/children
parents: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11887/parents
descendants: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11887/descendants
ancestors: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11887/ancestors
instances: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11887/instances
tree: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11887/tree
notes: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11887/notes
mappings: https://data.stageportal.lirmm.fr/ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11887/mappings
ui: http://stageportal.lirmm.fr/ontologies/INRAETHES?p=classes&conceptid=http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11887
"@context":
self: http://www.w3.org/2002/07/owl#Class
ontology: http://localhost:9393/ontologies/STY
children: http://www.w3.org/2002/07/owl#Class
parents: http://www.w3.org/2002/07/owl#Class
descendants: http://www.w3.org/2002/07/owl#Class
ancestors: http://www.w3.org/2002/07/owl#Class
instances: http://data.bioontology.org/metadata/Instance
tree: http://www.w3.org/2002/07/owl#Class
notes: http://data.bioontology.org/metadata/Note
mappings: http://data.bioontology.org/metadata/Mapping
ui: http://www.w3.org/2002/07/owl#Class
"@context":
"@vocab": http://data.bioontology.org/metadata/
prefLabel: http://www.w3.org/2004/02/skos/core#prefLabel
synonym: http://www.w3.org/2004/02/skos/core#altLabel
"@language": en
hierarchy: []
annotations:
- from: 25
to: 29
matchType: PREF
text: TUMOR
mappings: []
108 changes: 108 additions & 0 deletions test/system/annotator_page_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
require "application_system_test_case"
require 'webmock/minitest'

class AnnotatorPageTest < ApplicationSystemTestCase
def setup
WebMock.disable!
@apikey = LinkedData::Client.settings.apikey
@annotator_api = $ANNOTATOR_URL
@host = "#{@annotator_api.split('/')[-2]}:443"
@annotator_text_area = ".annotator-page-text-area > textarea"
@sample_response = fixtures(:annotator)["sample_response"]
end

def teardown
WebMock.disable!
end

test "go to annotator page and check if all the inputs and filters are there" do
visit root_url
click_link(href: '/annotator')
assert_selector @annotator_text_area
assert_selector 'div.insert-sample-text-button'
# Check if there are the annotator's options
assert_selector 'label[for="chips-whole_word_only-check"]'
assert_selector 'label[for="chips-longest_only-check"]'
assert_selector 'label[for="chips-expand_mappings-check"]'
assert_selector 'label[for="chips-exclude_numbers-check"]'
assert_selector 'label[for="chips-exclude_synonyms-check"]'
assert_selector 'div.select-ontologies'

# Open the advanced options
find('div.advanced-options-button').click

# Check if there are the advanced options
assert_selector 'input#select_umls_semantic_types-ts-control', visible: :all
assert_selector 'input#select_umls_semantic_groups-ts-control', visible: :all
assert_selector 'input#select_ancestors_level-ts-control', visible: :all
assert_selector 'input#select_include_score-ts-control', visible: :all
assert_selector 'input[name="score_threshold"]'
assert_selector 'input[name="confidence_threshold"]'
assert_selector 'label[for="chips-fast_context-check"]'
assert_selector 'label[for="chips-lemmatize-check"]'
end

test "go to annotator page insert sample text and get annotations" do
visit root_url
click_link(href: '/annotator')

# Fill the annotator's text area input by a sample text
find(@annotator_text_area).fill_in(with: 'Melanoma is a malignant tumor of melanocytes found mainly')

# Mock the api call for the annotator with the entered text
WebMock.enable!
stub_request(:get, "#{@annotator_api}?class_hierarchy_max_level=None&confidence_threshold=0&score_threshold=0&text=Melanoma%20is%20a%20malignant%20tumor%20of%20melanocytes%20found%20mainly&whole_word_only=true")
.with(
headers: {
'Accept'=>'application/json',
'Authorization'=>"apikey token=#{@apikey}",
'Host'=> @host,
'User-Agent'=>'NCBO API Ruby Client v0.1.0'
})
.to_return(status: 200, body: @sample_response.to_json, headers: {})


find(".annotator-page-button #annotator").click

# Check if we get the table of annotations
assert_selector 'table#annotator-table'

# Check if the number of annotations is 4
assert_equal 5, page.all('tr').count

# Check if we got the correct annotations
assert_selector 'a[href="ontologies/AGROVOC/classes/http%3A%2F%2Faims.fao.org%2Faos%2Fagrovoc%2Fc_4713"]', text: 'Melanom'
assert_selector 'a[href="ontologies/EUROSCIVOC/classes/http%3A%2F%2Fdata.europa.eu%2F8mn%2Feuroscivoc%2F276b8c99-a318-48df-aa31-1f9f3e0ba910"]', text: 'Melanom'
assert_selector 'a[href="ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11970"]', text: 'mélanome'
assert_selector 'a[href="ontologies/INRAETHES/classes/http%3A%2F%2Fopendata.inrae.fr%2FthesaurusINRAE%2Fc_11887"]', text: 'tumeur'

# Check if the action buttons below the table are there (json, rdf, cite us and api doc buttons)
assert_selector '#annotator_json'
assert_selector '#annotator_rdf'
assert_selector '#annotator_cite_us'
assert_selector '#annotator_api_doc'

# Clear the sample text in the annotator text area
find(@annotator_text_area).native.clear

# Fill it with a text that will return an empty state
find(@annotator_text_area).fill_in(with: 'mainly')

# Mock the api call of the annotator to get and return an empty result
stub_request(:get, "#{@annotator_api}?class_hierarchy_max_level=None&confidence_threshold=0&score_threshold=0&text=mainly&whole_word_only=true")
.with(
headers: {
'Accept'=>'application/json',
'Authorization'=>"apikey token=#{@apikey}",
'Host'=> @host,
'User-Agent'=>'NCBO API Ruby Client v0.1.0'
})
.to_return(status: 200, body: ([]).to_json, headers: {})

find(".annotator-page-button #annotator").click

# Check if we got the empty state correctly
assert_selector 'div.browse-empty-illustration'
end

end
2 changes: 2 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require_relative '../config/environment'
require 'rails/test_help'
require 'simplecov'
require 'webmock/minitest'

SimpleCov.start 'rails' do
add_filter '/bin/'
Expand All @@ -16,6 +17,7 @@ class ActiveSupport::TestCase

# Add more helper methods to be used by all tests here...

WebMock.allow_net_connect!

Capybara.server_host = "0.0.0.0"
Capybara.app_host = "http://#{Socket.gethostname}:#{Capybara.server_port}"
Expand Down

0 comments on commit e80cf79

Please sign in to comment.