Skip to content

Commit

Permalink
Merge pull request #32 from TranslatorSRI/add-filters-to-nodenorm-web…
Browse files Browse the repository at this point in the history
…site

Add filters to NodeNorm and NameRes website, turn NameRes into actual tests
  • Loading branch information
gaurav authored Jan 5, 2024
2 parents 9a9f67c + ccb943f commit 4518b73
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 37 deletions.
34 changes: 24 additions & 10 deletions website/src/components/TestResult.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,31 @@ export default {
data() { return {
testResult: null,
displayDetailed: false,
testR: null,
}},
created() {
const testR = this.test.test(this.endpoint);
if (!testR) {
console.log(`Unable to set up test Promise in ${this.description}`);
return;
}
console.log("Returned testR: ", testR);
this.testR = this.test.test(this.endpoint);
},
watch: {
test() {
this.testResult = null;
this.testR = this.test.test(this.endpoint);
},
testR() {
const testR = this.testR;
if (!testR) {
console.log(`Test Promise not set in ${this.description}`);
return;
}
console.log("Returned testR: ", testR);
testR.then(result => {
console.log("Got result:", result);
this.testResult = result;
});
this.testResult = null;
testR.then(result => {
console.log("Got result:", result);
this.testResult = result;
});
},
},
computed: {
testStatus() {
Expand All @@ -69,6 +81,8 @@ export default {
case 'json':
case 'NodeNorm':
return this.testResult.result;
case 'NameRes':
return this.testResult.result;
}
},
testResultAsJson() {
Expand Down
85 changes: 71 additions & 14 deletions website/src/models/NameResTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,16 @@ function convertPrevNameResFormatToCurrent(response) {

// A helper function that returns a Promise that evaluates to a JSON result object.
// TODO: cache this.
export function lookupNameRes(nameResEndpoint, query, limit=10) {
// TODO: once all current instances are upgraded to 1.3.2+, we can replace this with a GET request.
const url = nameResEndpoint + "/lookup?string=" + encodeURIComponent(query) + "&limit=" + encodeURIComponent(limit);
const request = new Request(
url, {
method: "POST"
}
);
export function lookupNameRes(nameResEndpoint, query, expectedID="", limit=10, includePrefixes=[], excludePrefixes=[]) {
const url = new URL(nameResEndpoint + '/lookup');
url.search = new URLSearchParams({
'string': query,
'limit': limit,
'only_prefixes': includePrefixes,
'exclude_prefixes': excludePrefixes,
})

const request = new Request(url);

return fetch(request).then(response => {
if (!response.ok) return TestResult.failure("Could not submit request to NameRes /lookup", 'text', response.statusText);
Expand All @@ -48,7 +50,25 @@ export function lookupNameRes(nameResEndpoint, query, limit=10) {
return TestResult.failure(`NameRes /lookup returned an unexpected response`, 'json', responseJson);
}

return TestResult.success(`NameRes /lookup returned ${results.length} results`, 'NameRes', results);
// Is the expectedID in the results?
if (!expectedID) {
return TestResult.success(`NameRes /lookup returned ${results.length} results, no expected ID`, 'NameRes', results);
}
if (results.length < 1) {
return TestResult.failure(`NameRes /lookup returned NO results`, 'NameRes', results);
}

const topID = results[0]['curie'];
if (topID === expectedID) {
return TestResult.success(`NameRes /lookup returned ${results.length} results with expected ID ${expectedID} at top`, 'NameRes', results);
}

const resultIDs = results.map(r => r['curie']);
if (resultIDs.includes(expectedID)) {
return TestResult.success(`NameRes /lookup returned ${results.length} results with expected ID ${expectedID} at position ${resultIDs.indexOf(expectedID) + 1}`, 'NameRes', results);
}

return TestResult.failure(`NameRes /lookup returned ${results.length} results but missed expected ID ${expectedID}`, 'NameRes', results);
});
});
}
Expand All @@ -62,7 +82,7 @@ export class NameResTest extends Test {
/**
* Convert a single row into zero or more tests.
*/
static convertRowToTests(row) {
static convertRowToTests(row, limit=10) {
const source = row['Source'];
const source_url = row['Source URL'];

Expand Down Expand Up @@ -168,19 +188,56 @@ export class NameResTest extends Test {
});
}

// Do we have a preferred ID?
let expectedID = '';
if ('Preferred ID' in row) {
expectedID = row['Preferred ID'];
}

// Are there prefixes to include or exclude?
const prefixes = (row['Prefixes'] ? row['Prefixes'] : "").split('|');
const includePrefixes = [];
const excludePrefixes = [];
prefixes.forEach(prefix => {
if (!prefix) return;
if (prefix.startsWith('^')) {
excludePrefixes.push(prefix.substring(1));
} else {
includePrefixes.push(prefix);
}
})

// Look for tests in this row.
const tests = [];
if('Query label' in row) { // || 'Preferred label' in row) {
const query_label = row['Query label'];
// const preferred_label = row.get('Preferred label', '');
if('Query Label' in row) { // || 'Preferred label' in row) {
const query_label = row['Query Label'];

if (query_label !== '') {
// To begin with, let's just return the results as-is.
tests.push(new NameResTest(`Lookup "${query_label}"`, {}, source, source_url, (nameResURL) => {
return lookupNameRes(nameResURL, query_label);
return lookupNameRes(nameResURL, query_label, expectedID, limit, includePrefixes, excludePrefixes);
}));
}

const preferred_label = row['Preferred Label'];
if (preferred_label !== '') {
// To begin with, let's just return the results as-is.
tests.push(new NameResTest(`Lookup "${preferred_label}"`, {}, source, source_url, (nameResURL) => {
return lookupNameRes(nameResURL, preferred_label, expectedID, limit, includePrefixes, excludePrefixes);
}));
}


const additional_labels = row['Additional Labels'].split('|');
additional_labels.forEach(additional_label => {
if (!additional_label) return;

// To begin with, let's just return the results as-is.
tests.push(new NameResTest(`Lookup "${additional_label}"`, {}, source, source_url, (nameResURL) => {
return lookupNameRes(nameResURL, additional_label, expectedID, limit, includePrefixes, excludePrefixes);
}));
});

} else {
tests.push(TestResult.failure(`Could not understand row`, 'json', row));
}
Expand Down
4 changes: 2 additions & 2 deletions website/src/models/NodeNormTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ export class NodeNormTest extends Test {
});
}

if(row['Biolink classes']) {
const biolink_classes = row['Biolink classes'].split(/\s*\|\s*/);
if(row['Biolink Classes']) {
const biolink_classes = row['Biolink Classes'].split(/\s*\|\s*/);
biolink_classes.forEach(biolink_class => {
tests.push(createBiolinkClassTest(query_id, biolink_class));
});
Expand Down
47 changes: 41 additions & 6 deletions website/src/views/NameResValidator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,21 @@
This page will test several instances of the Name Resolver.
</p>

<b-button @click="loadGoogleSheet()">Reload</b-button>
<b-card title="Filter">
<b-card-body>
<b-form-group label="Choose categories:" label-for="selected-categories">
<b-form-select id="selected-categories" multiple v-model="selectedCategories" :options="googleSheetCategories" />
</b-form-group>
</b-card-body>

<b-form-group label="Choose NodeNorm endpoints:" label-for="current-endpoints">
<b-form-select id="current-endpoints" multiple v-model="currentEndpoints" :options="nameResEndpointsAsList" />
</b-form-group>

<b-card-footer>
<b-button @click="loadGoogleSheet()">Reload Google Sheet</b-button>
</b-card-footer>
</b-card>

<h2>Tests</h2>

Expand All @@ -25,7 +39,7 @@
<tr>
<th>Test</th>
<th>Source</th>
<th v-for="endpoint in Object.keys(nameResEndpoints)">
<th v-for="endpoint in currentEndpoints">
<a target="_blank" :href="nameResEndpoints[endpoint] + '/docs'">{{endpoint}}</a>
</th>
</tr>
Expand All @@ -34,7 +48,7 @@
<tr v-for="test in tests">
<td><TextWithURLs :text="test.description" :urls="test.urls"></TextWithURLs></td>
<td><TextWithURLs :text="test.source" :urls="{'URL': test.source_url}"></TextWithURLs></td>
<td v-for="endpoint in Object.keys(nameResEndpoints)">
<td v-for="endpoint in currentEndpoints">
<TestResult :test="test" :endpoint="nameResEndpoints[endpoint]" :description="test.description + ':' + test.source + ':' + nameResEndpoints[endpoint]"></TestResult>
</td>
</tr>
Expand All @@ -50,19 +64,22 @@ import TextWithURLs from "@/components/TextWithURLs.vue";
import { NameResTest } from '@/models/NameResTest';
import TestResult from "@/components/TestResult.vue";
import {RouterLink} from "vue-router";
import {NodeNormTest} from "@/models/NodeNormTest";
export default {
components: {TestResult, BTable, TextWithURLs, RouterLink},
data () {
return {
nameResEndpoints: {
"NameRes-localhost": "http://localhost:8080",
"NameRes-localhost": "http://localhost:8080",
"NameRes-RENCI-exp": "https://name-lookup-dev.apps.renci.org",
"NameRes-RENCI-dev": "https://name-resolution-sri.renci.org",
"NameRes-ITRB-ci": "https://name-lookup.ci.transltr.io",
"NameRes-ITRB-test": "https://name-lookup.test.transltr.io",
"NameRes-ITRB-prod": "https://name-lookup.transltr.io"
},
currentEndpoints: ["NameRes-RENCI-dev", "NameRes-ITRB-test"],
selectedCategories: ["Unit Tests"],
testData: [],
testDataErrors: [],
testDataIncomplete: true,
Expand All @@ -75,9 +92,27 @@ export default {
tests() {
if (this.testDataIncomplete) return [];
return this.testData.flatMap(row => {
if(row['Ignore?'] && row['Ignore?'] == 'y') return [];
return NameResTest.convertRowToTests(row)
if ('Category' in row && this.selectedCategories.includes(row['Category'])) {
return NameResTest.convertRowToTests(row)
}
return [];
});
},
nameResEndpointsAsList() {
return Object.entries(this.nameResEndpoints).map(([name, endpointURL]) => ({ "value": name, "text": `${name} (${endpointURL})` }));
},
googleSheetCategories() {
const categories = this.testData.map(row => {
if ('Category' in row) return row['Category'];
return '(undefined)';
});
let counts = {};
categories.forEach(category => {
counts[category] = counts[category] ? counts[category] + 1 : 1;
});
return Object.entries(counts).map(([key, value]) => ({value: key, text: `${key} (${value})`}));
},
},
methods: {
Expand Down
44 changes: 39 additions & 5 deletions website/src/views/NodeNormValidator.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,21 @@
This page will test several instances of the Node Normalization service.
</p>

<b-button @click="loadGoogleSheet()">Reload</b-button>
<b-card title="Filter">
<b-card-body>
<b-form-group label="Choose categories:" label-for="selected-categories">
<b-form-select id="selected-categories" multiple v-model="selectedCategories" :options="googleSheetCategories" />
</b-form-group>
</b-card-body>

<b-form-group label="Choose NodeNorm endpoints:" label-for="current-endpoints">
<b-form-select id="current-endpoints" multiple v-model="currentEndpoints" :options="nodeNormEndpointsAsList" />
</b-form-group>

<b-card-footer>
<b-button @click="loadGoogleSheet()">Reload Google Sheet</b-button>
</b-card-footer>
</b-card>

<h2>Tests</h2>

Expand All @@ -24,7 +38,7 @@
<tr>
<th>Test</th>
<th>Source</th>
<th v-for="endpoint in Object.keys(nodeNormEndpoints)">
<th v-for="endpoint in currentEndpoints">
<a target="_blank" :href="nodeNormEndpoints[endpoint] + '/docs'">{{endpoint}}</a>
</th>
</tr>
Expand All @@ -33,7 +47,7 @@
<tr v-for="test in tests">
<td><TextWithURLs :text="test.description" :urls="test.urls"></TextWithURLs></td>
<td><TextWithURLs :text="test.source" :urls="{'URL': test.source_url}"></TextWithURLs></td>
<td v-for="endpoint in Object.keys(nodeNormEndpoints)">
<td v-for="endpoint in currentEndpoints">
<TestResult :test="test" :endpoint="nodeNormEndpoints[endpoint]" :description="test.description + ':' + test.source + ':' + nodeNormEndpoints[endpoint]"></TestResult>
</td>
</tr>
Expand Down Expand Up @@ -61,6 +75,8 @@ export default {
"NodeNorm-ITRB-test": "https://nodenorm.test.transltr.io",
"NodeNorm-ITRB-prod": "https://nodenorm.transltr.io"
},
currentEndpoints: ["NodeNorm-RENCI-dev", "NodeNorm-ITRB-test"],
selectedCategories: ["Unit Tests"],
testData: [],
testDataErrors: [],
testDataIncomplete: true,
Expand All @@ -73,9 +89,27 @@ export default {
tests() {
if (this.testDataIncomplete) return [];
return this.testData.flatMap(row => {
if(row['Ignore?'] && row['Ignore?'] == 'y') return [];
return NodeNormTest.convertRowToTests(row)
if ('Category' in row && this.selectedCategories.includes(row['Category'])) {
return NodeNormTest.convertRowToTests(row);
}
return [];
});
},
nodeNormEndpointsAsList() {
return Object.entries(this.nodeNormEndpoints).map(([name, endpointURL]) => ({ "value": name, "text": `${name} (${endpointURL})` }));
},
googleSheetCategories() {
const categories = this.testData.map(row => {
if ('Category' in row) return row['Category'];
return '(undefined)';
});
let counts = {};
categories.forEach(category => {
counts[category] = counts[category] ? counts[category] + 1 : 1;
});
return Object.entries(counts).map(([key, value]) => ({value: key, text: `${key} (${value})`}));
},
},
methods: {
Expand Down

0 comments on commit 4518b73

Please sign in to comment.