preview-log-entry.test.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. import React from 'react'
  2. import { expect } from 'chai'
  3. import sinon from 'sinon'
  4. import { screen, render, fireEvent } from '@testing-library/react'
  5. import PreviewLogEntry from '../../../../../frontend/js/features/preview/components/preview-log-entry.js'
  6. describe('<PreviewLogEntry />', function() {
  7. const level = 'error'
  8. const noOp = () => {}
  9. describe('log entry description', function() {
  10. for (const level of ['error', 'warning', 'typesetting']) {
  11. it(`describes the log entry with ${level} information`, function() {
  12. render(<PreviewLogEntry level={level} onLogEntryLinkClick={noOp} />)
  13. screen.getByLabelText(`Log entry with level: "${level}"`)
  14. })
  15. }
  16. })
  17. describe('log location link', function() {
  18. const file = 'foo.tex'
  19. const line = 42
  20. const column = 21
  21. const onLogEntryLinkClick = sinon.stub()
  22. afterEach(function() {
  23. onLogEntryLinkClick.reset()
  24. })
  25. it('renders both file and line', function() {
  26. render(
  27. <PreviewLogEntry
  28. file={file}
  29. line={line}
  30. level={level}
  31. onLogEntryLinkClick={noOp}
  32. />
  33. )
  34. screen.getByRole('button', {
  35. name: `Navigate to log position in source code: ${file}, ${line}`
  36. })
  37. })
  38. it('renders only file when line information is not available', function() {
  39. render(
  40. <PreviewLogEntry file={file} level={level} onLogEntryLinkClick={noOp} />
  41. )
  42. screen.getByRole('button', {
  43. name: `Navigate to log position in source code: ${file}`
  44. })
  45. })
  46. it('does not render when file information is not available', function() {
  47. render(<PreviewLogEntry level={level} onLogEntryLinkClick={noOp} />)
  48. expect(
  49. screen.queryByRole('button', {
  50. name: `Navigate to log position in source code: `
  51. })
  52. ).to.not.exist
  53. })
  54. it('calls the callback with file, line and column on click', function() {
  55. render(
  56. <PreviewLogEntry
  57. file={file}
  58. line={line}
  59. column={column}
  60. level={level}
  61. onLogEntryLinkClick={onLogEntryLinkClick}
  62. />
  63. )
  64. const linkToSourceButton = screen.getByRole('button', {
  65. name: `Navigate to log position in source code: ${file}, ${line}`
  66. })
  67. fireEvent.click(linkToSourceButton)
  68. expect(onLogEntryLinkClick).to.be.calledOnce
  69. expect(onLogEntryLinkClick).to.be.calledWith({
  70. file,
  71. line: line,
  72. column: column
  73. })
  74. })
  75. })
  76. describe('log entry contents', function() {
  77. const logContent = 'foo bar latex error stuff baz'
  78. it('renders collapsed contents by default', function() {
  79. render(
  80. <PreviewLogEntry
  81. content={logContent}
  82. level={level}
  83. onLogEntryLinkClick={noOp}
  84. />
  85. )
  86. screen.getByText(logContent)
  87. screen.getByRole('button', {
  88. name: 'Expand'
  89. })
  90. })
  91. it('supports expanding contents', function() {
  92. render(
  93. <PreviewLogEntry
  94. content={logContent}
  95. level={level}
  96. onLogEntryLinkClick={noOp}
  97. />
  98. )
  99. screen.getByText(logContent)
  100. const expandCollapseBtn = screen.getByRole('button', {
  101. name: 'Expand'
  102. })
  103. fireEvent.click(expandCollapseBtn)
  104. screen.getByRole('button', {
  105. name: 'Collapse'
  106. })
  107. })
  108. it('should not render at all when there are no log contents', function() {
  109. const { container } = render(
  110. <PreviewLogEntry level={level} onLogEntryLinkClick={noOp} />
  111. )
  112. expect(container.querySelector('.log-entry-content')).to.not.exist
  113. })
  114. })
  115. describe('human-readable hints', function() {
  116. const logContent = 'foo bar latex error stuff baz'
  117. const logHintText = 'foo bar baz'
  118. const logHint = <>{logHintText}</>
  119. const infoURL = 'www.overleaf.com/learn/latex'
  120. it('renders the hint', function() {
  121. render(
  122. <PreviewLogEntry
  123. content={logContent}
  124. humanReadableHintComponent={logHint}
  125. extraInfoURL={infoURL}
  126. level={level}
  127. onLogEntryLinkClick={noOp}
  128. />
  129. )
  130. screen.getByText(logHintText)
  131. })
  132. it('renders the link to learn more', function() {
  133. render(
  134. <PreviewLogEntry
  135. content={logContent}
  136. humanReadableHintComponent={logHint}
  137. extraInfoURL={infoURL}
  138. level={level}
  139. onLogEntryLinkClick={noOp}
  140. />
  141. )
  142. screen.getByRole('link', { name: 'Learn more' })
  143. })
  144. it('does not render the link when it is not available', function() {
  145. render(
  146. <PreviewLogEntry
  147. content={logContent}
  148. humanReadableHintComponent={logHint}
  149. level={level}
  150. onLogEntryLinkClick={noOp}
  151. />
  152. )
  153. expect(screen.queryByRole('link', { name: 'Learn more' })).to.not.exist
  154. })
  155. })
  156. })