Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce cypress-image-diff for visual testing #517

Merged
merged 18 commits into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/jbrowse-plugin-apollo/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
cypress/videos
cypress/screenshots
cypress/downloads
cypress/cypress-image-diff-html-report
cypress/cypress-image-diff-screenshots/comparison
cypress/cypress-image-diff-screenshots/diff
5 changes: 5 additions & 0 deletions packages/jbrowse-plugin-apollo/cypress-image-diff.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const config = {
ROOT_DIR: 'cypress',
}

module.exports = config
4 changes: 4 additions & 0 deletions packages/jbrowse-plugin-apollo/cypress.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
const { defineConfig } = require('cypress')

const { configurePlugin } = require('cypress-mongodb')
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const getCompareSnapshotsPlugin = require('cypress-image-diff-js/plugin')

const fs = require('node:fs')

Expand All @@ -27,6 +29,8 @@ module.exports = defineConfig({
e2e: {
baseUrl: 'http://localhost:8999',
setupNodeEvents(on, config) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
getCompareSnapshotsPlugin(on, config)
configurePlugin(on)
on('task', {
readdirSync(path) {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
58 changes: 58 additions & 0 deletions packages/jbrowse-plugin-apollo/cypress/e2e/showWarnings.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
describe('Warning signs', () => {
beforeEach(() => {
cy.loginAsGuest()
})
afterEach(() => {
cy.deleteAssemblies()
})
it('FIXME Show warnings', () => {
cy.addAssemblyFromGff(
'stopcodon.gff3',
'test_data/cdsChecks/stopcodon.gff3',
)
cy.selectAssemblyToView('stopcodon.gff3')
cy.searchFeatures('gene07', 1)

// Here it would be nice to check that there are no ErrorIcons yet.
// For this we need to make sure that the gene model is actually on the canvas,
// which is not obvious how to do.

cy.get('button[data-testid="track_menu_icon"]').click()
cy.contains('Appearance').trigger('mouseover')
cy.contains('Show both graphical and table display').click()
cy.contains('cds07').rightclick()
cy.contains('Edit feature details').click()
cy.contains('Basic information')
.parent()
.within(() => {
cy.get('input[value="16"]').type('{selectall}{backspace}4{enter}')
cy.get('input[value="27"]').type('{selectall}{backspace}24{enter}')
})
cy.get('button[data-testid="zoom_out"]').click()

// FIXME: There should be 2 ErrorIcons not 3
cy.get('[data-testid="ErrorIcon"]', { timeout: 5000 }).should(
'have.length',
3,
)
cy.get('[data-testid="ErrorIcon"]', { timeout: 5000 })
.last()
.trigger('mouseover')
cy.contains(/(internal stop codon)|(missing stop codon)/)

// Fix the missing stop codon. Internal stop still expected
cy.contains('Basic information')
.parent()
.within(() => {
cy.get('input[value="24"]').type('{selectall}{backspace}27{enter}')
})
cy.get('button[data-testid="zoom_out"]').click()
cy.reload()

// FIXME: There should be 1 error icon not 4
cy.get('[data-testid="ErrorIcon"]', { timeout: 5000 }).should(
'have.length',
4,
)
})
})
31 changes: 31 additions & 0 deletions packages/jbrowse-plugin-apollo/cypress/e2e/visualGeneModel.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* eslint-disable cypress/no-unnecessary-waiting */
describe('Simple tests for visuals', () => {
beforeEach(() => {
cy.loginAsGuest()
})
afterEach(() => {
cy.deleteAssemblies()
})
it('Shows correct gene model', () => {
cy.addAssemblyFromGff('so_types.gff3', 'test_data/so_types.gff3')
cy.selectAssemblyToView('so_types.gff3')
cy.searchFeatures('TGGT1_200010', 1)
cy.wait(5000) // Wait for gene model to render

cy.get('body').then(($body) => {
if ($body.find('button[aria-label="Close drawer"]').length > 0) {
cy.get('button[aria-label="Close drawer"]').click()
}
})

cy.searchFeatures('TGGT1_200010', 1)
cy.wait(5000)

// NB: The size of the image differs between headless and interactive execution of cypress.
// In headless mode (including github workflow) use this:
cy.get('canvas[data-testid="overlayCanvas"]').compareSnapshot('gene-model')

// For local testing use this (comment out when pushing to github):
// cy.get('canvas[data-testid="overlayCanvas"]').compareSnapshot('gene-model-local')
})
})
4 changes: 4 additions & 0 deletions packages/jbrowse-plugin-apollo/cypress/support/e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
// https://on.cypress.io/configuration
// ***********************************************************

// For Cypress v12.17.3 and older:
import compareSnapshotCommand from 'cypress-image-diff-js'
compareSnapshotCommand()

// Import commands.js using ES2015 syntax:
import './commands'

Expand Down
1 change: 1 addition & 0 deletions packages/jbrowse-plugin-apollo/cypress/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"lib": ["es5", "dom"],
"types": ["cypress", "node"],
"strict": true,
"esModuleInterop": true,
},
"include": ["**/*.ts", "../cypress.config.js"],
}
2 changes: 2 additions & 0 deletions packages/jbrowse-plugin-apollo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@
"@types/react": "^18.3.4",
"@types/react-dom": "^18",
"cypress": "12.17.3",
"cypress-image-diff-html-report": "^2.2.0",
"cypress-image-diff-js": "^2.3.0",
"cypress-mongodb": "^6.2.0",
"fake-indexeddb": "^4.0.2",
"jest": "^29.6.2",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,34 @@
refSeqId: string
}

// TODO: Integrate SO
const isGeneOrTranscript = (annotationFeature: AnnotationFeatureSnapshot) => {
const isGeneOrTranscript = (
annotationFeature: AnnotationFeatureSnapshot,
apolloSessionModel: ApolloSessionModel,
) => {

Check warning on line 40 in packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx

View check run for this annotation

Codecov / codecov/patch

packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx#L40

Added line #L40 was not covered by tests
const { featureTypeOntology } =
apolloSessionModel.apolloDataStore.ontologyManager

Check warning on line 42 in packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx

View check run for this annotation

Codecov / codecov/patch

packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx#L42

Added line #L42 was not covered by tests
if (!featureTypeOntology) {
throw new Error('featureTypeOntology is undefined')

Check warning on line 44 in packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx

View check run for this annotation

Codecov / codecov/patch

packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx#L44

Added line #L44 was not covered by tests
}
return (
annotationFeature.type === 'gene' ||
annotationFeature.type === 'mRNA' ||
annotationFeature.type === 'transcript'
featureTypeOntology.isTypeOf(annotationFeature.type, 'gene') ||
featureTypeOntology.isTypeOf(annotationFeature.type, 'mRNA') ||
featureTypeOntology.isTypeOf(annotationFeature.type, 'transcript')

Check warning on line 49 in packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx

View check run for this annotation

Codecov / codecov/patch

packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx#L48-L49

Added lines #L48 - L49 were not covered by tests
)
}

// TODO: Integrate SO
const isTranscript = (annotationFeature: AnnotationFeatureSnapshot) => {
const isTranscript = (
annotationFeature: AnnotationFeatureSnapshot,
apolloSessionModel: ApolloSessionModel,
) => {

Check warning on line 56 in packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx

View check run for this annotation

Codecov / codecov/patch

packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx#L56

Added line #L56 was not covered by tests
const { featureTypeOntology } =
apolloSessionModel.apolloDataStore.ontologyManager

Check warning on line 58 in packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx

View check run for this annotation

Codecov / codecov/patch

packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx#L58

Added line #L58 was not covered by tests
if (!featureTypeOntology) {
throw new Error('featureTypeOntology is undefined')

Check warning on line 60 in packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx

View check run for this annotation

Codecov / codecov/patch

packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx#L60

Added line #L60 was not covered by tests
}
return (
annotationFeature.type === 'mRNA' || annotationFeature.type === 'transcript'
featureTypeOntology.isTypeOf(annotationFeature.type, 'mRNA') ||
featureTypeOntology.isTypeOf(annotationFeature.type, 'transcript')

Check warning on line 64 in packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx

View check run for this annotation

Codecov / codecov/patch

packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx#L64

Added line #L64 was not covered by tests
)
}

Expand Down Expand Up @@ -109,7 +124,7 @@
const checkedAnnotationFeatureChildren = Object.values(
annotationFeature.children,
)
.filter((child) => isTranscript(child))
.filter((child) => isTranscript(child, apolloSessionModel))

Check warning on line 127 in packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx

View check run for this annotation

Codecov / codecov/patch

packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx#L127

Added line #L127 was not covered by tests
.filter((child) => checkedChildrens.includes(child._id))
const mins = checkedAnnotationFeatureChildren.map((f) => f.min)
const maxes = checkedAnnotationFeatureChildren.map((f) => f.max)
Expand Down Expand Up @@ -202,7 +217,7 @@
</DialogTitle>
<DialogContent>
<Box sx={{ ml: 3 }}>
{isGeneOrTranscript(annotationFeature) && (
{isGeneOrTranscript(annotationFeature, apolloSessionModel) && (
<FormControlLabel
control={
<Checkbox
Expand All @@ -217,7 +232,7 @@
{annotationFeature.children && (
<Box sx={{ display: 'flex', flexDirection: 'column', ml: 3 }}>
{Object.values(annotationFeature.children)
.filter((child) => isTranscript(child))
.filter((child) => isTranscript(child, apolloSessionModel))

Check warning on line 235 in packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx

View check run for this annotation

Codecov / codecov/patch

packages/jbrowse-plugin-apollo/src/components/CreateApolloAnnotation.tsx#L235

Added line #L235 was not covered by tests
.map((child) => (
<FormControlLabel
key={child._id}
Expand Down
16 changes: 16 additions & 0 deletions packages/jbrowse-plugin-apollo/test_data/cdsChecks/stopcodon.gff3
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ chr4 . CDS 1 30 . - 0 ID=cds04.1;Parent=mrna04
chr6 . gene 1 30 . + . ID=gene06
chr6 . mRNA 1 30 . + . ID=mrna06;Parent=gene06
chr6 . CDS 1 10 . + 0 ID=cds06.1;Parent=mrna06
#
chr7 . gene 4 27 . + . ID=gene07
chr7 . mRNA 4 27 . + . ID=mrna07;Parent=gene07
chr7 . exon 4 27 . + 0 ID=exon07;Parent=mrna07
chr7 . CDS 16 27 . + 0 ID=cds07;Parent=mrna07
#
chr8 . gene 1 32 . + . ID=gene08
chr8 . mRNA 1 32 . + . ID=mrna08;Parent=gene08
chr8 . exon 1 12 . + 0 ID=exon08.1;Parent=mrna08
chr8 . exon 16 32 . + 0 ID=exon08.2;Parent=mrna08
chr8 . CDS 4 12 . + 0 ID=cds08;Parent=mrna08
chr8 . CDS 16 27 . + 0 ID=cds08;Parent=mrna08
##FASTA
>chr1
ATGGTGCCGCAAAGTACTGGTGGGGGTTAAnnnnnnnnnnnnnnnnnnnnn
Expand All @@ -35,3 +47,7 @@ TTActaCCCACCAGTACTTTGCGGtcaCATnnnnnnnnnnnnnnnnnnnnn
ATGGTGtagCAAAGTACTGTTAGGGGTTAAnnnnnnnnnnnnnnnnnnnnn
>chr6
ATGGTGtagCAAAGTACTGTTAGGGGTTAAnnnnnnnnnnnnnnnnnnnnn
>chr7
ATGGTGtagCAAAGTATGGTTAGGtagTAAnnnnnnnnnnnnnnnnnnnnn
>chr8
ATGATGTATCAAAGTATGGTTAGGTAGTAACTGCTCAGCAATCTATCTTTA
3 changes: 2 additions & 1 deletion packages/jbrowse-plugin-apollo/test_data/so_types.gff3
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ chr1 VEuPathDB protein_coding_gene 1 200 . - . ID=TGGT1_200010
chr1 VEuPathDB mRNA_with_frameshift 1 200 . - . ID=TGGT1_200010-t26_1;Parent=TGGT1_200010
chr1 VEuPathDB interior_exon 1 50 . - . ID=exon_TGGT1_200010-t26_1-E2;Parent=TGGT1_200010-t26_1
chr1 VEuPathDB interior_exon 70 100 . - . ID=exon_TGGT1_200010-t26_1-E1;Parent=TGGT1_200010-t26_1
chr1 VEuPathDB CDS 1 50 . - 1 ID=TGGT1_200010-t26_1-p1-CDS2;Parent=TGGT1_200010-t26_1
chr1 VEuPathDB CDS 1 50 . - 1 ID=TGGT1_200010-t26_1-p1-CDS1;Parent=TGGT1_200010-t26_1
chr1 VEuPathDB CDS 70 100 . - 0 ID=TGGT1_200010-t26_1-p1-CDS1;Parent=TGGT1_200010-t26_1
chr1 VEuPathDB five_prime_UTR 160 200 . - 0 ID=UTR;Parent=TGGT1_200010-t26_1
##FASTA
>chr1
cattgttgcggagttgaacaacggcattacgaacacttccgtctctcacttttatacgat
Expand Down
Loading
Loading