Skip to content

Commit

Permalink
Merge pull request #4577 from pvannierop/sv_table_in_study_view
Browse files Browse the repository at this point in the history
RFC68: Impl. structural variants table in Study View
  • Loading branch information
alisman authored Aug 2, 2023
2 parents d0285e9 + cf2dca8 commit 2683037
Show file tree
Hide file tree
Showing 29 changed files with 2,846 additions and 247 deletions.
176 changes: 176 additions & 0 deletions end-to-end-test/local/specs/struct-var-table.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
var assert = require('assert');
var goToUrlAndSetLocalStorage = require('../../shared/specUtils')
.goToUrlAndSetLocalStorage;
var waitForStudyView = require('../../shared/specUtils').waitForStudyView;

const CBIOPORTAL_URL = process.env.CBIOPORTAL_URL.replace(/\/$/, '');
// TODO remove feature flag after merge.
const studyViewUrl = `${CBIOPORTAL_URL}/study/summary?id=study_es_0&featureFlags=STUDY_VIEW_STRUCT_VAR_TABLE`;
const structVarTable = '//*[@data-test="structural variant pairs-table"]';
const filterCheckBox = '[data-test=labeledCheckbox]';
const structVarFilterPillTag = '[data-test=pill-tag]';
const uncheckedSvIcon = '[data-test=structVarQueryCheckboxUnchecked]';
const checkedSvIcon = '[data-test=structVarQueryCheckboxChecked]';
const structVarNameCell = '[data-test=structVarNameCell]';
const toast = '.Toastify div[role=alert]';

describe('study view structural variant table', function() {
beforeEach(() => {
goToUrlAndSetLocalStorage(studyViewUrl, true);
waitForStudyView();
showSvPane();
});

it('adds structural variant to study view filter', () => {
$(structVarTable)
.$(filterCheckBox)
.click();
$('[data-test=selectSamplesButton]').waitForExist();
$('[data-test=selectSamplesButton]').click();
assert($(structVarFilterPillTag).isExisting());
});

it.skip('shows all checkboxes when row is hovered', () => {
$(structVarNameCell).waitForExist();
const firstSvRowCell = $$(structVarNameCell)[0];
assert.equal($$(structVarNameCell)[1].getText(), 'SND1');
assert.equal($$(structVarNameCell)[2].getText(), 'BRAF');

movePointerWithRetry(firstSvRowCell, () =>
$(uncheckedSvIcon).waitForDisplayed()
);
assert.equal($$(uncheckedSvIcon).length, 3);
});

it.skip('shows only checked checkboxes when row is not hovered', () => {
$(structVarNameCell).waitForExist();
const gene1Cell = $$(structVarNameCell)[1];
movePointerWithRetry(gene1Cell, () =>
$(uncheckedSvIcon).waitForDisplayed()
);
assert.equal($$(uncheckedSvIcon).length, 3);

gene1Cell.waitForClickable();
gene1Cell.click();

// hover somewhere else:
movePointerWithRetry($('span=Gene 2'), $(checkedSvIcon).waitForExist());

assert.equal($$(uncheckedSvIcon).length, 0);
assert.equal($$(checkedSvIcon).length, 1);
});

it.skip('adds gene1::gene2 to Results View query', () => {
$(structVarNameCell).waitForExist();
const firstSvRowCell = $$(structVarNameCell)[0];

movePointerWithRetry(firstSvRowCell, () => {
$$(uncheckedSvIcon)[0].waitForClickable();
});
const gene1And2Checkbox = $$(uncheckedSvIcon)[0];
gene1And2Checkbox.click();
$(toast).waitForDisplayed();
clearToast();

const resultsViewQueryBox = openResultViewQueryBox();
assert.equal('SND1: FUSION::BRAF;', resultsViewQueryBox.getValue());
});

it.skip('adds gene1::* to Results View query', () => {
$(structVarNameCell).waitForExist();
const gene1Cell = $$(structVarNameCell)[1];
movePointerWithRetry(gene1Cell, () =>
$(uncheckedSvIcon).waitForDisplayed()
);
gene1Cell.waitForClickable();
gene1Cell.click();
$(toast).waitForDisplayed();
clearToast();

const resultsViewQueryBox = openResultViewQueryBox();
assert.equal('SND1: FUSION::;', resultsViewQueryBox.getValue());
});

it.skip('adds *::gene2 to Results View query', () => {
$(structVarNameCell).waitForExist();
const gene2Cell = $$(structVarNameCell)[2];
movePointerWithRetry(gene2Cell, () =>
$(uncheckedSvIcon).waitForDisplayed()
);
gene2Cell.waitForClickable();
gene2Cell.click();
$(toast).waitForDisplayed();
clearToast();

const resultsViewQueryBox = openResultViewQueryBox();
assert.equal('BRAF: ::FUSION;', resultsViewQueryBox.getValue());
});
});

function showSvPane() {
const $chartsBtn = $('[data-test=add-charts-button]');
$chartsBtn.waitForExist();
$chartsBtn.waitForClickable();
$chartsBtn.click();
const $chartsGenomicTab = $('.tabAnchor_Genomic');
$chartsGenomicTab.waitForExist();
$chartsGenomicTab.waitForClickable();
$chartsGenomicTab.click();
const $svChartCheckbox = $(
'[data-test="add-chart-option-structural-variants"]'
).$('[data-test="labeledCheckbox"]');
$svChartCheckbox.waitForExist();
$svChartCheckbox.waitForClickable();
if (!$svChartCheckbox.isSelected()) {
$svChartCheckbox.click();
}
$chartsBtn.click();
waitForStudyView();
}

function openResultViewQueryBox() {
const resultsViewQueryBox = $('[data-test=geneSet]');
resultsViewQueryBox.waitForClickable();
resultsViewQueryBox.click();
return resultsViewQueryBox;
}

function clearToast() {
const toastify = $('.Toastify button');
toastify.waitForClickable();
toastify.click();
browser.pause(100);
}

function movePointerTo(element) {
element.waitForDisplayed();
element.scrollIntoView();
const x = element.getLocation('x');
const y = element.getLocation('y');
browser.performActions([
{
type: 'pointer',
parameters: { pointerType: 'mouse' },
actions: [
{ type: 'pointerMove', duration: 0, x, y },
{ type: 'pointerMove', duration: 0, x, y },
],
},
]);
}

/**
* When scrolling to the new location, some tooltips might pop up and interfere.
* A retry solves this problem: the second time the pointer is already near/at the desired location
*/
function movePointerWithRetry(element, isOk) {
movePointerTo(element);
try {
if (isOk()) {
return;
}
} catch (e) {
// retry
movePointerTo(element);
}
}
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,17 @@
"buildBootstrap": "sass --style :compressed src/globalStyles/bootstrap-entry.scss src/globalStyles/prefixed-bootstrap.min.css",
"heroku-postbuild": "yarn run build && yarn add [email protected] -g",
"updateAPI": "yarn run fetchAPI && yarn run buildAPI && yarn run updateOncoKbAPI && yarn run updateGenomeNexusAPI",
"fetchAPILocal": "export CBIOPORTAL_URL=http://localhost:8090 && curl -L -k ${CBIOPORTAL_URL}/api/api-docs | json | grep -v basePath | grep -v termsOfService | grep -v host > packages/cbioportal-ts-api-client/src/generated/CBioPortalAPI-docs.json && curl -L -k ${CBIOPORTAL_URL}/api/api-docs?group=internal | json | grep -v host | grep -v basePath | grep -v termsOfService > packages/cbioportal-ts-api-client/src/generated/CBioPortalAPIInternal-docs.json",
"fetchAPI": "./scripts/env_vars.sh && eval \"$(./scripts/env_vars.sh)\" && curl -L -k ${CBIOPORTAL_URL}/api/api-docs | json | grep -v basePath | grep -v termsOfService | grep -v host > packages/cbioportal-ts-api-client/src/generated/CBioPortalAPI-docs.json && curl -L -k ${CBIOPORTAL_URL}/api/api-docs?group=internal | json | grep -v host | grep -v basePath | grep -v termsOfService > packages/cbioportal-ts-api-client/src/generated/CBioPortalAPIInternal-docs.json",
"fetchAPILocal": "export CBIOPORTAL_URL=http://localhost:8090 && curl -s -L -k ${CBIOPORTAL_URL}/api/api-docs | json | grep -v basePath | grep -v termsOfService | grep -v host > packages/cbioportal-ts-api-client/src/generated/CBioPortalAPI-docs.json && curl -s -L -k ${CBIOPORTAL_URL}/api/api-docs?group=internal | json | grep -v host | grep -v basePath | grep -v termsOfService > packages/cbioportal-ts-api-client/src/generated/CBioPortalAPIInternal-docs.json",
"fetchAPI": "./scripts/env_vars.sh && eval \"$(./scripts/env_vars.sh)\" && curl -s -L -k ${CBIOPORTAL_URL}/api/api-docs | json | grep -v basePath | grep -v termsOfService | grep -v host > packages/cbioportal-ts-api-client/src/generated/CBioPortalAPI-docs.json && curl -s -L -k ${CBIOPORTAL_URL}/api/api-docs?group=internal | json | grep -v host | grep -v basePath | grep -v termsOfService > packages/cbioportal-ts-api-client/src/generated/CBioPortalAPIInternal-docs.json",
"buildAPI": "node scripts/generate-api.js packages/cbioportal-ts-api-client/src/generated CBioPortalAPI CBioPortalAPIInternal",
"updateOncoKbAPI": "yarn run fetchOncoKbAPI && yarn run buildOncoKbAPI",
"fetchOncoKbAPI": "curl -k https://www.oncokb.org/api/v1/v2/api-docs?group=Public%20APIs | json | grep -v basePath | grep -v termsOfService | grep -v host > packages/oncokb-ts-api-client/src/generated/OncoKbAPI-docs.json",
"fetchOncoKbAPI": "curl -s -k https://www.oncokb.org/api/v1/v2/api-docs?group=Public%20APIs | json | grep -v basePath | grep -v termsOfService | grep -v host > packages/oncokb-ts-api-client/src/generated/OncoKbAPI-docs.json",
"buildOncoKbAPI": "node scripts/generate-api.js packages/oncokb-ts-api-client/src/generated OncoKbAPI",
"updateG2SAPI": "yarn run fetchG2SAPI && yarn run buildG2SAPI",
"fetchG2SAPI": "curl -k http://g2s.genomenexus.org/v2/api-docs?group=api > packages/genome-nexus-ts-api-client/src/generated/Genome2StructureAPI-docs.json",
"fetchG2SAPI": "curl -s -k http://g2s.genomenexus.org/v2/api-docs?group=api > packages/genome-nexus-ts-api-client/src/generated/Genome2StructureAPI-docs.json",
"buildG2SAPI": "node scripts/generate-api.js packages/genome-nexus-ts-api-client/src/generated Genome2StructureAPI",
"updateGenomeNexusAPI": "yarn run fetchGenomeNexusAPI && yarn run buildGenomeNexusAPI",
"fetchGenomeNexusAPI": "./scripts/env_vars.sh && eval \"$(./scripts/env_vars.sh)\" && curl -k ${GENOME_NEXUS_URL}/v2/api-docs | json | grep -v basePath | grep -v termsOfService | grep -v host > packages/genome-nexus-ts-api-client/src/generated/GenomeNexusAPI-docs.json && curl -k ${GENOME_NEXUS_URL}/v2/api-docs?group=internal | json | grep -v basePath | grep -v termsOfService | grep -v host > packages/genome-nexus-ts-api-client/src/generated/GenomeNexusAPIInternal-docs.json",
"fetchGenomeNexusAPI": "./scripts/env_vars.sh && eval \"$(./scripts/env_vars.sh)\" && curl -s -k ${GENOME_NEXUS_URL}/v2/api-docs | json | grep -v basePath | grep -v termsOfService | grep -v host > packages/genome-nexus-ts-api-client/src/generated/GenomeNexusAPI-docs.json && curl -s -k ${GENOME_NEXUS_URL}/v2/api-docs?group=internal | json | grep -v basePath | grep -v termsOfService | grep -v host > packages/genome-nexus-ts-api-client/src/generated/GenomeNexusAPIInternal-docs.json",
"buildGenomeNexusAPI": "node scripts/generate-api.js packages/genome-nexus-ts-api-client/src/generated GenomeNexusAPI GenomeNexusAPIInternal",
"updateHotspotGenes": "./scripts/get_hotspot_genes.sh > src/shared/static-data/hotspotGenes.json",
"compileOqlParser": "cd src/shared/lib/oql && pegjs oql-parser.pegjs",
Expand Down
163 changes: 163 additions & 0 deletions src/pages/studyView/StructVarUtils.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import { assert } from 'chai';
import * as React from 'react';
import {
STRUCTVARAnyGeneStr,
STRUCTVARNullGeneStr,
STUCTVARDownstreamFusionStr,
STUCTVARUpstreamFusionStr,
} from 'shared/lib/oql/oqlfilter';
import { SingleGeneQuery } from 'shared/lib/oql/oql-parser';
import {
oqlQueryToStructVarGenePair,
StructVarGenePair,
} from 'pages/studyView/StructVarUtils';

describe('StructVarUtils', () => {
describe('oqlQueryToStructVarGenePair', () => {
it.each([
[{ gene: 'A', alterations: [] }, []],
[
{
gene: 'A',
alterations: [
{
gene: undefined,
alteration_type: STUCTVARDownstreamFusionStr,
modifiers: [],
},
],
},
[],
],
[
{
gene: 'A',
alterations: [
{
gene: 'B',
alteration_type: STUCTVARDownstreamFusionStr,
modifiers: [],
},
],
},
[{ gene1HugoSymbolOrOql: 'A', gene2HugoSymbolOrOql: 'B' }],
],
[
{
gene: 'A',
alterations: [
{
gene: STRUCTVARAnyGeneStr,
alteration_type: STUCTVARDownstreamFusionStr,
modifiers: [],
},
],
},
[
{
gene1HugoSymbolOrOql: 'A',
gene2HugoSymbolOrOql: STRUCTVARAnyGeneStr,
},
],
],
[
{
gene: 'A',
alterations: [
{
gene: STRUCTVARNullGeneStr,
alteration_type: STUCTVARDownstreamFusionStr,
modifiers: [],
},
],
},
[
{
gene1HugoSymbolOrOql: 'A',
gene2HugoSymbolOrOql: STRUCTVARNullGeneStr,
},
],
],
[
{
gene: 'A',
alterations: [
{
gene: 'B',
alteration_type: STUCTVARUpstreamFusionStr,
modifiers: [],
},
],
},
[{ gene1HugoSymbolOrOql: 'B', gene2HugoSymbolOrOql: 'A' }],
],
[
{
gene: 'A',
alterations: [
{
gene: STRUCTVARAnyGeneStr,
alteration_type: STUCTVARUpstreamFusionStr,
modifiers: [],
},
],
},
[
{
gene1HugoSymbolOrOql: STRUCTVARAnyGeneStr,
gene2HugoSymbolOrOql: 'A',
},
],
],
[
{
gene: 'A',
alterations: [
{
gene: STRUCTVARNullGeneStr,
alteration_type: STUCTVARUpstreamFusionStr,
modifiers: [],
},
],
},
[
{
gene1HugoSymbolOrOql: STRUCTVARNullGeneStr,
gene2HugoSymbolOrOql: 'A',
},
],
],
[
{
gene: 'A',
alterations: [
{
gene: 'B',
alteration_type: STUCTVARDownstreamFusionStr,
modifiers: [],
},
{
gene: 'C',
alteration_type: STUCTVARDownstreamFusionStr,
modifiers: [],
},
],
},
[
{ gene1HugoSymbolOrOql: 'A', gene2HugoSymbolOrOql: 'B' },
{ gene1HugoSymbolOrOql: 'A', gene2HugoSymbolOrOql: 'C' },
],
],
])(
'converts %p into %p',
(singleGeneQuery, expected: StructVarGenePair[]) => {
assert.deepEqual(
oqlQueryToStructVarGenePair(
singleGeneQuery as SingleGeneQuery
),
expected
);
}
);
});
});
Loading

0 comments on commit 2683037

Please sign in to comment.