Skip to content

Commit

Permalink
Merge pull request #783 from sanger/x1249-xenium-metrics
Browse files Browse the repository at this point in the history
xenium metrics workflow altered to stop issues with duplicate region names for repeat runs occurring
  • Loading branch information
khelwood authored Oct 24, 2024
2 parents 966c5b0 + 7ec05fe commit 993e670
Show file tree
Hide file tree
Showing 6 changed files with 2,664 additions and 2,564 deletions.
66 changes: 52 additions & 14 deletions cypress/e2e/pages/xeniumMetrics.cy.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import {
GetRegionsOfInterestQuery,
GetRegionsOfInterestQueryVariables,
GetRunNamesQuery,
GetRunNamesQueryVariables,
GetRunRoisQuery,
GetRunRoisQueryVariables,
RecordMetricsMutation,
RecordMetricsMutationVariables
} from '../../../src/types/sdk';
import { HttpResponse } from 'msw';
import { selectSGPNumber } from '../shared/customReactSelect.cy';
import { selectOption, selectSGPNumber } from '../shared/customReactSelect.cy';

describe('Xenium Metrics', () => {
before(() => {
Expand All @@ -24,13 +26,13 @@ describe('Xenium Metrics', () => {
});
});

describe('When a labware with registered regions of interest is scanned', () => {
describe('When a labware with registered run names is scanned', () => {
before(() => {
cy.get('#labwareScanInput').type('STAN-3111{enter}');
});
it('displays the region of interest table', () => {
cy.findByRole('table').should('be.visible');
});
// it('displays the region of interest table', () => {
// cy.findByRole('table').should('be.visible');
// });
it('displays the sgp number selector', () => {
cy.findByTestId('workNumber').should('be.visible');
});
Expand All @@ -41,14 +43,14 @@ describe('Xenium Metrics', () => {
cy.findByTestId('input').should('be.disabled');
});
});
describe('When a labware with no regions of interest is scanned', () => {
describe('When a labware with no run names is scanned', () => {
before(() => {
cy.msw().then(({ worker, graphql }) => {
worker.use(
graphql.query<GetRegionsOfInterestQuery, GetRegionsOfInterestQueryVariables>('GetRegionsOfInterest', () => {
graphql.query<GetRunNamesQuery, GetRunNamesQueryVariables>('GetRunNames', () => {
return HttpResponse.json({
data: {
rois: []
runRois: []
}
});
})
Expand All @@ -58,17 +60,52 @@ describe('Xenium Metrics', () => {
cy.get('#labwareScanInput').type('STAN-3111{enter}');
});
it('displays a message error', () => {
cy.findByText('No regions of interest recorded for the labware STAN-3111').should('be.visible');
cy.findByText('No run names found for the labware STAN-3111').should('be.visible');
});
it('keeps the labware scanner enabled', () => {
cy.findByTestId('input').should('be.enabled');
});
it('doe snot display the metrics details', () => {
cy.findByTestId('runName').should('not.exist');
cy.findByTestId('workNumber').should('not.exist');
it('does not display the metrics details', () => {
cy.findByRole('table').should('not.exist');
});
});

describe('On run name selection update', () => {
describe('When a run name is selected with roi registered', () => {
before(() => {
cy.get('#labwareScanInput').type('STAN-3111{enter}');
selectOption('runName', 'Run Name 1');
});
it('displays the region of interest table', () => {
cy.findByRole('table').should('be.visible');
});
});
describe('When a run name is selected with no roi registered', () => {
before(() => {
cy.msw().then(({ worker, graphql }) => {
worker.use(
graphql.query<GetRunRoisQuery, GetRunRoisQueryVariables>('GetRunRois', () => {
return HttpResponse.json({
data: {
runRois: []
}
});
})
);
});
cy.reload();
cy.get('#labwareScanInput').type('STAN-3111{enter}');
selectOption('runName', 'Run Name 1');
});

it('displays an error message', () => {
cy.findByText('No regions of interest are recorded for the scanned labware and the selected run name.').should(
'be.visible'
);
});
});
});

describe('When a metric file is uploaded and sgp number is selected', () => {
before(() => {
cy.reload();
Expand Down Expand Up @@ -118,6 +155,7 @@ describe('Xenium Metrics', () => {

const fillInForm = () => {
cy.get('#labwareScanInput').type('STAN-3111{enter}');
selectOption('runName', 'Run Name 1');
selectSGPNumber('SGP1008');
cy.get('#file-0')
.scrollIntoView()
Expand Down
5 changes: 5 additions & 0 deletions src/graphql/queries/GetRunRois.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
query GetRunRois($barcode: String!, $run: String!) {
runRois(barcode: $barcode, run: $run) {
...RoiFields
}
}
14 changes: 14 additions & 0 deletions src/mocks/handlers/regionOfInterestHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { graphql, HttpResponse } from 'msw';
import {
GetRegionsOfInterestQuery,
GetRegionsOfInterestQueryVariables,
GetRunRoisQuery,
GetRunRoisQueryVariables,
LabwareRoi,
RecordMetricsMutation,
RecordMetricsMutationVariables
Expand Down Expand Up @@ -35,6 +37,18 @@ const regionOfInterestHandlers = [
}
),

graphql.query<GetRunRoisQuery, GetRunRoisQueryVariables>('GetRunRois', ({ variables }) => {
const labware = createLabware(variables.barcode);
const rois = labware.slots.flatMap((slot) =>
slot.samples.map((sample) => ({
sample,
address: slot.address,
roi: faker.helpers.arrayElement(['top left', 'top right', 'bottom left', 'bottom right', 'center'])
}))
);
return HttpResponse.json({ data: { runRois: rois } }, { status: 200 });
}),

graphql.mutation<RecordMetricsMutation, RecordMetricsMutationVariables>('RecordMetrics', () => {
return HttpResponse.json({ data: { recordSampleMetrics: { operations: [{ id: 1 }] } } }, { status: 200 });
})
Expand Down
6 changes: 1 addition & 5 deletions src/mocks/handlers/xeniumHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,7 @@ const xeniumHandlers = [
graphql.query<GetRunNamesQuery, GetAnalyserScanDataQueryVariables>('GetRunNames', () => {
return HttpResponse.json({
data: {
runNames: [
faker.string.alphanumeric({ length: { min: 5, max: 8 } }),
faker.string.alphanumeric({ length: { min: 5, max: 8 } }),
faker.string.alphanumeric({ length: { min: 5, max: 8 } })
]
runNames: ['Run Name 1', 'Run Name 2', 'Run Name 3']
}
});
})
Expand Down
66 changes: 41 additions & 25 deletions src/pages/XeniumMetrics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,20 +83,39 @@ const validationSchema = Yup.object().shape({
const XeniumMetrics = () => {
const stanCore = useContext(StanCoreContext);

const getMetricOperationDetails = useCallback(
const getRunNames = useCallback(
async (
foundLabware: LabwareFlaggedFieldsFragment,
barcode: string,
setValues: (values: SetStateAction<XeniumMetricsForm>, shouldValidate?: boolean) => {}
): Promise<string[]> => {
try {
const response = await stanCore.GetRegionsOfInterest({
barcodes: [foundLabware.barcode]
});
if (response.rois.length > 0 && response.rois[0].rois.length > 0) {
const groupedByRoi = groupByRoi(response.rois[0]!.rois!);
const response = await stanCore.GetRunNames({
barcode: barcode
});
if (response.runNames) {
setValues((prev) => ({
...prev,
runNames: response.runNames
}));
return [];
} else {
return ['No run names found for the labware ' + barcode];
}
},
[stanCore]
);

const getRois = useCallback(
async (
labware: LabwareFlaggedFieldsFragment,
runName: string,
setValues: (values: SetStateAction<XeniumMetricsForm>, shouldValidate?: boolean) => {}
) => {
stanCore.GetRunRois({ barcode: labware.barcode, run: runName }).then((response) => {
if (response.runRois) {
const groupedByRoi = groupByRoi(response.runRois);
setValues((prev) => ({
...prev,
labware: foundLabware,
labware: labware,
sampleMetricData: Object.keys(groupedByRoi).map((roi) => {
return {
externalIdAddress: groupedByRoi[roi].map((data) => {
Expand All @@ -107,22 +126,8 @@ const XeniumMetrics = () => {
};
})
}));

const runNames = await stanCore.GetRunNames({
barcode: foundLabware.barcode
});
if (runNames.runNames) {
setValues((prev) => ({
...prev,
runNames: runNames.runNames
}));
}
return [];
}
return ['No regions of interest recorded for the labware ' + foundLabware.barcode];
} catch (error) {
return ['Error fetching the regions of interests related to the labware ' + foundLabware.barcode];
}
});
},
[stanCore]
);
Expand Down Expand Up @@ -151,6 +156,7 @@ const XeniumMetrics = () => {
runName: ''
}));
};

return (
<AppShell>
<AppShell.Header>
Expand Down Expand Up @@ -191,7 +197,7 @@ const XeniumMetrics = () => {
labwares: LabwareFlaggedFieldsFragment[],
foundLabware: LabwareFlaggedFieldsFragment
) => {
return getMetricOperationDetails(foundLabware, setValues);
return getRunNames(foundLabware.barcode, setValues);
}}
>
{({ labwares, removeLabware }) =>
Expand All @@ -214,6 +220,11 @@ const XeniumMetrics = () => {
value: runName
};
})}
onChange={async (val) => {
const runName = (val as OptionType).label;
await setFieldValue('runName', runName);
await getRois(labware, runName, setValues);
}}
/>
</div>
<Panel key={labware.barcode}>
Expand Down Expand Up @@ -252,6 +263,11 @@ const XeniumMetrics = () => {
/>
</div>
)}
{values.runName && values.sampleMetricData.length === 0 && (
<div>
<Warning message="No regions of interest are recorded for the scanned labware and the selected run name."></Warning>
</div>
)}
</Panel>
</div>
))
Expand Down
Loading

0 comments on commit 993e670

Please sign in to comment.