preview-logs-pane.test.js 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import React from 'react'
  2. import { screen, render, fireEvent } from '@testing-library/react'
  3. import PreviewLogsPane from '../../../../../frontend/js/features/preview/components/preview-logs-pane'
  4. import sinon from 'sinon'
  5. const { expect } = require('chai')
  6. describe('<PreviewLogsPane />', function() {
  7. const sampleError1 = {
  8. content: 'error 1 content',
  9. file: 'main.tex',
  10. level: 'error',
  11. line: 17,
  12. message: 'Misplaced alignment tab character &.'
  13. }
  14. const sampleError2 = {
  15. content: 'error 1 content',
  16. file: 'main.tex',
  17. level: 'error',
  18. line: 22,
  19. message: 'Extra alignment tab has been changed to cr.'
  20. }
  21. const sampleWarning = {
  22. file: 'main.tex',
  23. level: 'warning',
  24. line: 30,
  25. message: "Reference `idontexist' on page 1 undefined on input line 30."
  26. }
  27. const sampleTypesettingIssue = {
  28. file: 'main.tex',
  29. level: 'typesetting',
  30. line: 12,
  31. message: "Reference `idontexist' on page 1 undefined on input line 30."
  32. }
  33. const sampleRawLog = `
  34. This is pdfTeX, Version 3.14159265-2.6-1.40.21 (TeX Live 2020) (preloaded format=pdflatex 2020.9.10) 6 NOV 2020 15:23
  35. entering extended mode
  36. \\write18 enabled.
  37. %&-line parsing enabled.
  38. **main.tex
  39. (/compile/main.tex
  40. LaTeX2e <2020-02-02> patch level 5
  41. L3 programming layer <2020-07-17> (/usr/local/texlive/2020/texmf-dist/tex/latex
  42. /base/article.cls
  43. Document Class: article 2019/12/20 v1.4l Standard LaTeX document class
  44. (/usr/local/texlive/2020/texmf-dist/tex/latex/base/size10.clo
  45. File: size10.clo 2019/12/20 v1.4l Standard LaTeX file (size option)
  46. )`
  47. const errors = [sampleError1, sampleError2]
  48. const warnings = [sampleWarning]
  49. const typesetting = [sampleTypesettingIssue]
  50. const logEntries = {
  51. all: [...errors, ...warnings, ...typesetting],
  52. errors,
  53. warnings,
  54. typesetting
  55. }
  56. const onLogEntryLocationClick = sinon.stub()
  57. const noOp = () =>
  58. describe('with logs', function() {
  59. beforeEach(function() {
  60. render(
  61. <PreviewLogsPane
  62. logEntries={logEntries}
  63. rawLog={sampleRawLog}
  64. onLogEntryLocationClick={onLogEntryLocationClick}
  65. onClearCache={noOp}
  66. />
  67. )
  68. })
  69. it('renders all log entries with appropriate labels', function() {
  70. const errorEntries = screen.getAllByLabelText(
  71. `Log entry with level: error`
  72. )
  73. const warningEntries = screen.getAllByLabelText(
  74. `Log entry with level: warning`
  75. )
  76. const typesettingEntries = screen.getAllByLabelText(
  77. `Log entry with level: typesetting`
  78. )
  79. expect(errorEntries).to.have.lengthOf(errors.length)
  80. expect(warningEntries).to.have.lengthOf(warnings.length)
  81. expect(typesettingEntries).to.have.lengthOf(typesetting.length)
  82. })
  83. it('renders the raw log', function() {
  84. screen.getByLabelText('Raw logs from the LaTeX compiler')
  85. })
  86. it('renders a link to location button for every error and warning log entry', function() {
  87. logEntries.all.forEach((entry, index) => {
  88. const linkToSourceButton = screen.getByRole('button', {
  89. name: `Navigate to log position in source code: ${entry.file}, ${
  90. entry.line
  91. }`
  92. })
  93. fireEvent.click(linkToSourceButton)
  94. expect(onLogEntryLocationClick).to.have.callCount(index + 1)
  95. const call = onLogEntryLocationClick.getCall(index)
  96. expect(
  97. call.calledWith({
  98. file: entry.file,
  99. line: entry.line,
  100. column: entry.column
  101. })
  102. ).to.be.true
  103. })
  104. })
  105. it(' does not render a link to location button for the raw log entry', function() {
  106. const rawLogEntry = screen.getByLabelText(
  107. 'Raw logs from the LaTeX compiler'
  108. )
  109. expect(rawLogEntry.querySelector('.log-entry-header-link')).to.not.exist
  110. })
  111. })
  112. describe('with validation issues', function() {
  113. const sampleValidationIssues = {
  114. sizeCheck: {
  115. resources: [
  116. { path: 'foo/bar', kbSize: 76221 },
  117. { path: 'bar/baz', kbSize: 2342 }
  118. ]
  119. },
  120. mainFile: true
  121. }
  122. it('renders a validation entry for known issues', function() {
  123. render(
  124. <PreviewLogsPane
  125. validationIssues={sampleValidationIssues}
  126. onLogEntryLocationClick={onLogEntryLocationClick}
  127. onClearCache={noOp}
  128. />
  129. )
  130. const validationEntries = screen.getAllByLabelText(
  131. 'A validation issue which prevented this project from compiling'
  132. )
  133. expect(validationEntries).to.have.lengthOf(
  134. Object.keys(sampleValidationIssues).length
  135. )
  136. })
  137. it('ignores unknown issues', function() {
  138. render(
  139. <PreviewLogsPane
  140. validationIssues={{ unknownIssue: true }}
  141. onLogEntryLocationClick={onLogEntryLocationClick}
  142. onClearCache={noOp}
  143. />
  144. )
  145. const validationEntries = screen.queryAllByLabelText(
  146. 'A validation issue prevented this project from compiling'
  147. )
  148. expect(validationEntries).to.have.lengthOf(0)
  149. })
  150. })
  151. describe('with compilation errors', function() {
  152. const sampleErrors = {
  153. clsiMaintenance: true,
  154. tooRecentlyCompiled: true,
  155. compileTerminated: true
  156. }
  157. it('renders an error entry for known errors', function() {
  158. render(
  159. <PreviewLogsPane
  160. errors={sampleErrors}
  161. onLogEntryLocationClick={onLogEntryLocationClick}
  162. onClearCache={noOp}
  163. />
  164. )
  165. const errorEntries = screen.getAllByLabelText(
  166. 'An error which prevented this project from compiling'
  167. )
  168. expect(errorEntries).to.have.lengthOf(Object.keys(sampleErrors).length)
  169. })
  170. it('ignores unknown errors', function() {
  171. render(
  172. <PreviewLogsPane
  173. errors={{ unknownIssue: true }}
  174. onLogEntryLocationClick={onLogEntryLocationClick}
  175. onClearCache={noOp}
  176. />
  177. )
  178. const errorEntries = screen.queryAllByLabelText(
  179. 'There was an error compiling this project'
  180. )
  181. expect(errorEntries).to.have.lengthOf(0)
  182. })
  183. })
  184. })