templates.spec.ts 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. import { startWith } from './helpers/config'
  2. import { ensureUserExists, login } from './helpers/login'
  3. import { createProject } from './helpers/project'
  4. const WITHOUT_PROJECTS_USER = 'user-without-projects@example.com'
  5. const ADMIN_USER = 'admin@example.com'
  6. const REGULAR_USER = 'user@example.com'
  7. const TEMPLATES_USER = 'templates@example.com'
  8. describe('Templates', () => {
  9. ensureUserExists({ email: TEMPLATES_USER })
  10. ensureUserExists({ email: WITHOUT_PROJECTS_USER })
  11. let OVERLEAF_TEMPLATES_USER_ID: string
  12. before(function () {
  13. login(TEMPLATES_USER)
  14. cy.visit('/')
  15. cy.get('meta[name="ol-user_id"]').then(el => {
  16. OVERLEAF_TEMPLATES_USER_ID = el.attr('content')!
  17. })
  18. })
  19. function varsFn() {
  20. return {
  21. OVERLEAF_TEMPLATES_USER_ID,
  22. OVERLEAF_NEW_PROJECT_TEMPLATE_LINKS:
  23. '[{"name":"All Templates","url":"/templates/all"}]',
  24. }
  25. }
  26. describe('enabled in Server Pro', () => {
  27. startWith({
  28. pro: true,
  29. varsFn,
  30. })
  31. ensureUserExists({ email: REGULAR_USER })
  32. ensureUserExists({ email: ADMIN_USER, isAdmin: true })
  33. it('should show templates link on welcome page', () => {
  34. login(WITHOUT_PROJECTS_USER)
  35. cy.visit('/')
  36. cy.findByText('Browse templates').click()
  37. cy.url().should('match', /\/templates$/)
  38. })
  39. it('should have templates feature', () => {
  40. const resumeTemplatesUserSession = login(TEMPLATES_USER)
  41. const name = `Template ${Date.now()}`
  42. const description = `Template Description ${Date.now()}`
  43. cy.visit('/')
  44. createProject(name).as('templateProjectId')
  45. cy.get('header').findByText('Menu').click()
  46. cy.findByText('Manage Template').click()
  47. cy.findByText('Template Description')
  48. .click()
  49. .parent()
  50. .get('textarea')
  51. .type(description)
  52. cy.findByText('Publish').click()
  53. cy.findByText('Publishing…').should('be.disabled')
  54. cy.findByText('Publish').should('not.exist')
  55. cy.findByText('Unpublish', { timeout: 10_000 })
  56. cy.findByText('Republish')
  57. cy.findByText('View it in the template gallery').click()
  58. cy.url()
  59. .should('match', /\/templates\/[a-f0-9]{24}$/)
  60. .as('templateURL')
  61. cy.findAllByText(name).first().should('exist')
  62. cy.findByText(description)
  63. cy.findByText('Open as Template')
  64. cy.findByText('Unpublish')
  65. cy.findByText('Republish')
  66. cy.get('img')
  67. .should('have.attr', 'src')
  68. .and('match', /\/v\/0\//)
  69. cy.findByText('Republish').click()
  70. cy.findByText('Publishing…').parent().should('be.disabled')
  71. cy.findByText('Republish', { timeout: 10_000 })
  72. cy.get('img', { timeout: 10_000 })
  73. .should('have.attr', 'src')
  74. .and('match', /\/v\/1\//)
  75. // custom tag
  76. const tagName = `${Date.now()}`
  77. cy.visit('/')
  78. cy.findByText(name)
  79. .parent()
  80. .parent()
  81. .within(() => cy.get('input[type="checkbox"]').first().check())
  82. cy.get('.project-list-sidebar-react').within(() => {
  83. cy.findAllByText('New Tag').first().click()
  84. })
  85. cy.focused().type(tagName)
  86. cy.findByText('Create').click()
  87. cy.get('.project-list-sidebar-react').within(() => {
  88. cy.findByText(tagName)
  89. .parent()
  90. .within(() => cy.get('.name').should('have.text', `${tagName} (1)`))
  91. })
  92. // Check listing
  93. cy.visit('/templates')
  94. cy.findByText(tagName)
  95. cy.visit('/templates/all')
  96. cy.findByText(name)
  97. cy.visit(`/templates/${tagName}`)
  98. cy.findByText(name)
  99. // Unpublish via template page
  100. cy.get('@templateURL').then(url => cy.visit(`${url}`))
  101. cy.findByText('Unpublish').click()
  102. cy.url().should('match', /\/templates$/)
  103. cy.get('@templateURL').then(url =>
  104. cy.visit(`${url}`, {
  105. failOnStatusCode: false,
  106. })
  107. )
  108. cy.findByText('Not found')
  109. cy.visit('/templates/all')
  110. cy.findByText(name).should('not.exist')
  111. cy.visit(`/templates/${tagName}`)
  112. cy.findByText(name).should('not.exist')
  113. // Publish again
  114. cy.get('@templateProjectId').then(projectId =>
  115. cy.visit(`/project/${projectId}`)
  116. )
  117. cy.get('header').findByText('Menu').click()
  118. cy.findByText('Manage Template').click()
  119. cy.findByText('Publish').click()
  120. cy.findByText('Unpublish', { timeout: 10_000 })
  121. // Should assign a new template id
  122. cy.findByText('View it in the template gallery').click()
  123. cy.url()
  124. .should('match', /\/templates\/[a-f0-9]{24}$/)
  125. .as('newTemplateURL')
  126. cy.get('@newTemplateURL').then(newURL => {
  127. cy.get('@templateURL').then(prevURL => {
  128. expect(newURL).to.match(/\/templates\/[a-f0-9]{24}$/)
  129. expect(prevURL).to.not.equal(newURL)
  130. })
  131. })
  132. // Open project from template
  133. login(REGULAR_USER)
  134. cy.visit('/templates')
  135. cy.findByText(tagName).click()
  136. cy.findByText(name).click()
  137. cy.findByText('Open as Template').click()
  138. cy.url().should('match', /\/project\/[a-f0-9]{24}$/)
  139. cy.get('.project-name').findByText(name)
  140. cy.get('header').findByText('Menu').click()
  141. cy.findByText('Word Count') // wait for lazy loading
  142. cy.findByText('Manage Template').should('not.exist')
  143. // Check management as regular user
  144. cy.get('@newTemplateURL').then(url => cy.visit(`${url}`))
  145. cy.findByText('Open as Template')
  146. cy.findByText('Unpublish').should('not.exist')
  147. cy.findByText('Republish').should('not.exist')
  148. // Check management as admin user
  149. login(ADMIN_USER)
  150. cy.get('@newTemplateURL').then(url => cy.visit(`${url}`))
  151. cy.findByText('Open as Template')
  152. cy.findByText('Unpublish')
  153. cy.findByText('Republish')
  154. cy.get('@templateProjectId').then(projectId =>
  155. cy.visit(`/project/${projectId}`)
  156. )
  157. cy.get('header').findByText('Menu').click()
  158. cy.findByText('Manage Template').click()
  159. cy.findByText('Unpublish')
  160. resumeTemplatesUserSession()
  161. // Unpublish via editor
  162. cy.get('@templateProjectId').then(projectId =>
  163. cy.visit(`/project/${projectId}`)
  164. )
  165. cy.get('header').findByText('Menu').click()
  166. cy.findByText('Manage Template').click()
  167. cy.findByText('Unpublish').click()
  168. cy.findByText('Publish')
  169. cy.visit('/templates/all')
  170. cy.findByText(name).should('not.exist')
  171. // check for template links, after creating the first project
  172. cy.visit('/')
  173. cy.findAllByRole('button')
  174. .contains(/new project/i)
  175. .click()
  176. cy.findAllByText('All Templates')
  177. .first()
  178. .should('have.attr', 'href', '/templates/all')
  179. })
  180. })
  181. function checkDisabled() {
  182. it('should not have templates feature', () => {
  183. login(TEMPLATES_USER)
  184. cy.visit('/')
  185. createProject('maybe templates')
  186. cy.get('header').findByText('Menu').click()
  187. cy.findByText('Word Count') // wait for lazy loading
  188. cy.findByText('Manage Template').should('not.exist')
  189. cy.visit('/templates', { failOnStatusCode: false })
  190. cy.findByText('Not found')
  191. cy.visit('/templates/all', { failOnStatusCode: false })
  192. cy.findByText('Not found')
  193. // check for template links, after creating the first project
  194. cy.visit('/')
  195. cy.findAllByRole('button')
  196. .contains(/new project/i)
  197. .click()
  198. cy.findAllByText('All Templates').should('not.exist')
  199. })
  200. it('should not show templates link on welcome page', () => {
  201. login(WITHOUT_PROJECTS_USER)
  202. cy.visit('/')
  203. cy.findByText(/new project/i) // wait for lazy loading
  204. cy.findByText('Browse templates').should('not.exist')
  205. })
  206. }
  207. describe('disabled Server Pro', () => {
  208. startWith({ pro: true })
  209. checkDisabled()
  210. })
  211. describe('unavailable in CE', () => {
  212. startWith({
  213. pro: false,
  214. varsFn,
  215. })
  216. checkDisabled()
  217. })
  218. })