| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- import { login } from './login'
- import { openEmail } from './email'
- import { v4 as uuid } from 'uuid'
- export function createProject(
- name: string,
- {
- type = 'Blank Project',
- newProjectButtonMatcher = /new project/i,
- open = true,
- }: {
- type?: 'Blank Project' | 'Example Project'
- newProjectButtonMatcher?: RegExp
- open?: boolean
- } = {}
- ): Cypress.Chainable<string> {
- cy.url().then(url => {
- if (!url.endsWith('/project')) {
- cy.visit('/project')
- }
- })
- const interceptId = uuid()
- let projectId = ''
- if (!open) {
- cy.then(() => {
- // Register intercept just before creating the project, otherwise we might
- // intercept a request from a prior createProject invocation.
- cy.intercept(
- { method: 'GET', url: /\/project\/[a-fA-F0-9]{24}$/, times: 1 },
- req => {
- projectId = req.url.split('/').pop()!
- // Redirect back to the project dashboard, effectively reload the page.
- req.redirect('/project')
- }
- ).as(interceptId)
- })
- }
- cy.findAllByRole('button').contains(newProjectButtonMatcher).click()
- // FIXME: This should only look in the left menu
- cy.findAllByText(type).first().click()
- cy.findByRole('dialog').within(() => {
- cy.get('input').type(name)
- cy.findByText('Create').click()
- })
- if (open) {
- cy.url().should('match', /\/project\/[a-fA-F0-9]{24}/)
- waitForMainDocToLoad()
- return cy
- .url()
- .should('match', /\/project\/[a-fA-F0-9]{24}/)
- .then(url => url.split('/').pop())
- } else {
- const alias = `@${interceptId}` // IDEs do not like computed values in cy.wait().
- cy.wait(alias)
- return cy.then(() => projectId)
- }
- }
- export function openProjectByName(projectName: string) {
- cy.visit('/project')
- cy.findByText(projectName).click()
- waitForMainDocToLoad()
- }
- export function openProjectById(projectId: string) {
- cy.visit(`/project/${projectId}`)
- waitForMainDocToLoad()
- }
- export function openProjectViaLinkSharingAsAnon(url: string) {
- cy.visit(url)
- waitForMainDocToLoad()
- }
- export function openProjectViaLinkSharingAsUser(
- url: string,
- projectName: string,
- email: string
- ) {
- cy.visit(url)
- cy.findByText(projectName) // wait for lazy loading
- cy.contains(`as ${email}`)
- cy.findByText('OK, join project').click()
- waitForMainDocToLoad()
- }
- export function openProjectViaInviteNotification(projectName: string) {
- cy.visit('/project')
- cy.findByText(projectName)
- .parent()
- .parent()
- .within(() => {
- cy.findByText('Join Project').click()
- })
- cy.findByText('Open Project').click()
- cy.url().should('match', /\/project\/[a-fA-F0-9]{24}/)
- waitForMainDocToLoad()
- }
- function shareProjectByEmail(
- projectName: string,
- email: string,
- level: 'Viewer' | 'Editor'
- ) {
- openProjectByName(projectName)
- cy.findByText('Share').click()
- cy.findByRole('dialog').within(() => {
- cy.findByLabelText('Add people', { selector: 'input' }).type(`${email},`)
- cy.findByLabelText('Add people', { selector: 'input' })
- .parents('form')
- .within(() => {
- cy.findByTestId('add-collaborator-select')
- .click()
- .then(() => {
- cy.findByText(level).click()
- })
- })
- cy.findByText('Invite').click({ force: true })
- cy.findByText('Invite not yet accepted.')
- })
- }
- export function shareProjectByEmailAndAcceptInviteViaDash(
- projectName: string,
- email: string,
- level: 'Viewer' | 'Editor'
- ) {
- shareProjectByEmail(projectName, email, level)
- login(email)
- openProjectViaInviteNotification(projectName)
- }
- export function shareProjectByEmailAndAcceptInviteViaEmail(
- projectName: string,
- email: string,
- level: 'Viewer' | 'Editor'
- ) {
- shareProjectByEmail(projectName, email, level)
- login(email)
- openEmail(projectName, frame => {
- frame.contains('View project').then(a => {
- cy.log(
- 'bypass target=_blank and navigate current browser tab/cypress-iframe to project invite'
- )
- cy.visit(a.attr('href')!)
- })
- })
- cy.url().should('match', /\/project\/[a-f0-9]+\/invite\/token\/[a-f0-9]+/)
- cy.findByText(/user would like you to join/)
- cy.contains(new RegExp(`You are accepting this invite as ${email}`))
- cy.findByText('Join Project').click()
- waitForMainDocToLoad()
- }
- export function enableLinkSharing() {
- let linkSharingReadOnly: string
- let linkSharingReadAndWrite: string
- const origin = new URL(Cypress.config().baseUrl!).origin
- waitForMainDocToLoad()
- cy.findByText('Share').click()
- cy.findByText('Turn on link sharing').click()
- cy.findByText('Anyone with this link can view this project')
- .next()
- .should('contain.text', origin + '/read')
- .then(el => {
- linkSharingReadOnly = el.text()
- })
- cy.findByText('Anyone with this link can edit this project')
- .next()
- .should('contain.text', origin + '/')
- .then(el => {
- linkSharingReadAndWrite = el.text()
- })
- return cy.then(() => {
- return { linkSharingReadOnly, linkSharingReadAndWrite }
- })
- }
- export function waitForMainDocToLoad() {
- cy.log('Wait for main doc to load; it will steal the focus after loading')
- cy.get('.cm-content').should('contain.text', 'Introduction')
- }
- export function openFile(fileName: string, waitFor: string) {
- // force: The file-tree pane is too narrow to display the full name.
- cy.findByTestId('file-tree').findByText(fileName).click({ force: true })
- // wait until we've switched to the selected file
- cy.findByText('Loading…').should('not.exist')
- cy.findByText(waitFor)
- }
- export function createNewFile() {
- const fileName = `${uuid()}.tex`
- cy.log('create new project file')
- cy.get('button').contains('New file').click({ force: true })
- cy.findByRole('dialog').within(() => {
- cy.get('input').clear()
- cy.get('input').type(fileName)
- cy.findByText('Create').click()
- })
- // force: The file-tree pane is too narrow to display the full name.
- cy.findByTestId('file-tree').findByText(fileName).click({ force: true })
- // wait until we've switched to the newly created empty file
- cy.findByText('Loading…').should('not.exist')
- cy.get('.cm-line').should('have.length', 1)
- return fileName
- }
- export function toggleTrackChanges(state: boolean) {
- cy.findByText('Review').click()
- cy.get('.track-changes-menu-button').then(el => {
- // when the menu is expanded renders the `expand_more` icon,
- // and the `chevron_right` icon when it's collapsed
- if (!el.text().includes('expand_more')) {
- el.click()
- }
- })
- cy.findByText('Everyone')
- .parent()
- .within(() => {
- cy.get('.form-check-input').then(el => {
- if (el.prop('checked') === state) return
- const id = uuid()
- const alias = `@${id}`
- cy.intercept({
- method: 'POST',
- url: '**/track_changes',
- times: 1,
- }).as(id)
- if (state) {
- cy.get('.form-check-input').check()
- } else {
- cy.get('.form-check-input').uncheck()
- }
- cy.wait(alias)
- })
- })
- cy.contains('.toolbar-item', 'Review').click()
- }
|