import React from 'react' import { screen, render, fireEvent } from '@testing-library/react' import PreviewPane from '../../../../../frontend/js/features/preview/components/preview-pane' const { expect } = require('chai') describe('', function () { const sampleError1 = { content: 'error 1 content', file: 'main.tex', level: 'error', line: 17, message: 'Misplaced alignment tab character &.', } const sampleError2 = { content: 'error 1 content', file: 'main.tex', level: 'error', line: 22, message: 'Extra alignment tab has been changed to cr.', } const sampleWarning = { file: 'main.tex', level: 'warning', line: 30, message: "Reference `idontexist' on page 1 undefined on input line 30.", } describe('first error pop-up', function () { it('renders a first error pop-up with the first error', function () { const propsAfterCompileWithErrors = getProps(false, { errors: [sampleError1, sampleError2], warnings: [sampleWarning], }) render() screen.getByRole('alertdialog', { name: 'This project has errors. This is the first one.', }) screen.getByText(sampleError1.message) }) it('does not render a first error pop-up when there are only warnings', function () { const propsAfterCompileWithWarningsOnly = getProps(false, { errors: [], warnings: [sampleWarning], }) render() expect( screen.queryByRole('alertdialog', { name: 'This project has errors. This is the first one.', }) ).to.not.exist }) it('does not render a first error pop-up when a compile is ongoing', function () { const propsWhileCompiling = getProps(true, { errors: [sampleError1, sampleError2], warnings: [sampleWarning], }) render() expect( screen.queryByRole('alertdialog', { name: 'This project has errors. This is the first one.', }) ).to.not.exist }) it('does not render a first error pop-up when viewing logs', function () { const propsWithErrorsViewingLogs = getProps( false, { errors: [sampleError1, sampleError2], warnings: [sampleWarning], }, Date.now(), true ) render() expect( screen.queryByRole('alertdialog', { name: 'This project has errors. This is the first one.', }) ).to.not.exist }) it('does not render a first error pop-up when going back to the PDF view after viewing logs', function () { const nowTimestamp = Date.now() const propsWithErrorsViewingLogs = getProps( false, { errors: [sampleError1, sampleError2], warnings: [sampleWarning], }, nowTimestamp, true ) const propsWithErrorsAfterViewingLogs = getProps( false, { errors: [sampleError1, sampleError2], warnings: [sampleWarning], }, nowTimestamp, false ) const { rerender } = render( ) rerender() expect( screen.queryByRole('alertdialog', { name: 'This project has errors. This is the first one.', }) ).to.not.exist }) it('renders a first error pop-up with updated errors after recompiling', function () { const nowTimestamp = Date.now() const laterTimestamp = Date.now() + 1000 const propsWithErrorsAfterFirstCompile = getProps( false, { errors: [sampleError1, sampleError2], warnings: [sampleWarning], }, nowTimestamp, true ) const propsWithErrorsAfterSecondCompile = getProps( false, { errors: [sampleError2], warnings: [sampleWarning], }, laterTimestamp, false ) const { rerender } = render( ) rerender() screen.getByRole('alertdialog', { name: 'This project has errors. This is the first one.', }) screen.getByText(sampleError2.message) }) it('allows dismissing the first error pop-up', function () { const propsWithErrors = getProps(false, { errors: [sampleError1, sampleError2], warnings: [sampleWarning], }) render() const dismissPopUpButton = screen.getByRole('button', { name: 'Dismiss first error alert', }) fireEvent.click(dismissPopUpButton) expect( screen.queryByRole('alertdialog', { name: 'This project has errors. This is the first one.', }) ).to.not.exist }) it('does not render the first error pop-up with new recompiles after it being dismissed once', function () { const nowTimestamp = Date.now() const laterTimestamp = Date.now() + 1000 const propsWithErrorsForFirstCompile = getProps( false, { errors: [sampleError1, sampleError2], warnings: [sampleWarning], }, nowTimestamp ) const propsWithErrorsForSecondCompile = getProps( false, { errors: [sampleError2], warnings: [sampleWarning], }, laterTimestamp ) const { rerender } = render( ) const dismissPopUpButton = screen.getByRole('button', { name: 'Dismiss first error alert', }) fireEvent.click(dismissPopUpButton) rerender() expect( screen.queryByRole('alertdialog', { name: 'This project has errors. This is the first one.', }) ).to.not.exist }) }) describe('accessible description of the compile result', function () { it('renders an accessible description with the errors and warnings count', function () { const errors = [sampleError1, sampleError2] const warnings = [sampleWarning] const propsWithErrorsAndWarnings = getProps(false, { errors, warnings, }) render() screen.getByText(`${errors.length} error${errors.length > 1 ? 's' : ''}`) screen.getByText( `${warnings.length} warning${warnings.length > 1 ? 's' : ''}` ) }) it('renders an accessible description for failed compiles with CLSI errors', function () { const sampleCLSIError = { clsiMaintenance: true, } const propsWithCLSIError = getProps( false, {}, Date.now(), false, true, {}, sampleCLSIError ) render() screen.getByText('This project did not compile because of an error') }) it('renders an accessible description for failed compiles with validation issues', function () { const sampleValidationIssue = { clsiMaintenance: true, } const propsWithValidationIssue = getProps( false, {}, Date.now(), false, true, sampleValidationIssue, {} ) render() screen.getByText( 'This project did not compile because of a validation issue' ) }) }) function getProps( isCompiling = false, logEntries = {}, lastCompileTimestamp = Date.now(), isShowingLogs = false, compileFailed = false, validationIssues = {}, errors = {} ) { const logEntriesWithDefaults = { errors: [], warnings: [], typesetting: [], ...logEntries, } logEntriesWithDefaults.all = [ ...logEntriesWithDefaults.errors, ...logEntriesWithDefaults.warnings, ...logEntriesWithDefaults.typesetting, ] return { compilerState: { autoCompileHasChanges: false, isAutoCompileOn: false, isCompiling: isCompiling, isClearingCache: false, isDraftModeOn: false, isSyntaxCheckOn: false, lastCompileTimestamp, logEntries: logEntriesWithDefaults, compileFailed, validationIssues, errors, }, onClearCache: () => {}, onLogEntryLocationClick: () => {}, onRecompile: () => {}, onRecompileFromScratch: () => {}, onRunSyntaxCheckNow: () => {}, onSetAutoCompile: () => {}, onSetDraftMode: () => {}, onSetSyntaxCheck: () => {}, onToggleLogs: () => {}, onSetSplitLayout: () => {}, onSetFullLayout: () => {}, onStopCompilation: () => {}, showLogs: isShowingLogs, splitLayout: true, } } })