mirror of
https://github.com/overleaf/overleaf.git
synced 2024-12-22 21:13:34 +00:00
Merge pull request #19631 from overleaf/jpa-e2e-emails
[server-pro] add e2e test for accepting project invite via email GitOrigin-RevId: c8391b57c1ee882499cfe5dc02817b5fadcd7ff4
This commit is contained in:
parent
bd2a99aca7
commit
8748ac7475
8 changed files with 124 additions and 10 deletions
1
server-ce/test/.gitignore
vendored
1
server-ce/test/.gitignore
vendored
|
@ -1 +1,2 @@
|
|||
data/
|
||||
docker-mailtrap/
|
||||
|
|
|
@ -12,14 +12,14 @@ export IMAGE_TAG_PRO ?= quay.io/sharelatex/sharelatex-pro:latest
|
|||
export CYPRESS_SHARD ?=
|
||||
export COMPOSE_PROJECT_NAME ?= test
|
||||
|
||||
test-e2e-native:
|
||||
test-e2e-native: build_mailtrap
|
||||
docker compose -f docker-compose.yml -f docker-compose.native.yml up --build --no-log-prefix sharelatex host-admin -d
|
||||
CYPRESS_ADMIN_CLIENT_URL='http://localhost:8081' CYPRESS_GIT_BRIDGE_PUBLIC_HOST='localhost' CYPRESS_SAML_PUBLIC_HOST='localhost:8082' CYPRESS_OVERLEAF_PUBLIC_HOST='localhost:8082' npm run cypress:open
|
||||
|
||||
test-e2e:
|
||||
docker compose up --build --no-log-prefix --exit-code-from=e2e e2e
|
||||
|
||||
test-e2e-open:
|
||||
test-e2e-open: build_mailtrap
|
||||
docker compose up --build --no-log-prefix --exit-code-from=e2e-open e2e-open
|
||||
|
||||
clean:
|
||||
|
@ -32,7 +32,7 @@ prefetch_default_compose:
|
|||
|
||||
prefetch_default: prefetch_default_compose_build
|
||||
prefetch_default_compose_build:
|
||||
docker compose build
|
||||
docker compose build host-admin
|
||||
|
||||
prefetch: prefetch_custom
|
||||
prefetch_custom: prefetch_custom_compose_pull
|
||||
|
@ -50,4 +50,11 @@ prefetch_old:
|
|||
docker pull $(IMAGE_TAG_PRO:latest=5.0.1-RC1)
|
||||
docker pull $(IMAGE_TAG_PRO:latest=5.0)
|
||||
|
||||
# Google Cloud Build runs on a very ancient Docker version that does not support the subdir flag.
|
||||
# Use services -> mailtrap -> build -> context = https://github.com/dbck/docker-mailtrap.git#v1.5.0:build in docker-compose.yml eventually.
|
||||
prefetch_default_compose_build: build_mailtrap
|
||||
build_mailtrap:
|
||||
git clone https://github.com/dbck/docker-mailtrap.git || true && cd docker-mailtrap && git checkout v1.5.0
|
||||
docker build -t mailtrap docker-mailtrap/build
|
||||
|
||||
.PHONY: test-e2e test-e2e-open
|
||||
|
|
|
@ -2,6 +2,11 @@ import '@testing-library/cypress/add-commands'
|
|||
|
||||
Cypress.on('uncaught:exception', (err, runnable) => {
|
||||
if (err.message.includes('ResizeObserver')) {
|
||||
// spurious error from PDF preview
|
||||
return false
|
||||
}
|
||||
if (err.message.includes('rcube_webmail')) {
|
||||
// spurious error from mailtrap
|
||||
return false
|
||||
}
|
||||
})
|
||||
|
|
|
@ -11,12 +11,18 @@ services:
|
|||
host-admin:
|
||||
# The host-admin service initiates the mongo replica set
|
||||
condition: service_healthy
|
||||
mailtrap:
|
||||
condition: service_started
|
||||
environment:
|
||||
OVERLEAF_SITE_URL: 'http://sharelatex'
|
||||
OVERLEAF_APP_NAME: Overleaf Community Edition
|
||||
OVERLEAF_MONGO_URL: mongodb://mongo/sharelatex?directConnection=true
|
||||
OVERLEAF_REDIS_HOST: redis
|
||||
REDIS_HOST: redis
|
||||
OVERLEAF_EMAIL_FROM_ADDRESS: 'welcome@example.com'
|
||||
OVERLEAF_EMAIL_SMTP_HOST: 'mailtrap'
|
||||
OVERLEAF_EMAIL_SMTP_PORT: '25'
|
||||
OVERLEAF_EMAIL_SMTP_IGNORE_TLS: 'true'
|
||||
ENABLED_LINKED_FILE_TYPES: 'project_file,project_output_file'
|
||||
ENABLE_CONVERSIONS: 'true'
|
||||
EMAIL_CONFIRMATION_DISABLED: 'true'
|
||||
|
@ -26,6 +32,11 @@ services:
|
|||
timeout: 3s
|
||||
retries: 30
|
||||
|
||||
mailtrap:
|
||||
image: mailtrap
|
||||
environment:
|
||||
MAILTRAP_PASSWORD: 'password-for-mailtrap'
|
||||
|
||||
mongo:
|
||||
image: mongo:5.0.17
|
||||
command: '--replSet overleaf'
|
||||
|
|
|
@ -4,7 +4,7 @@ import { ensureUserExists, login } from './helpers/login'
|
|||
import {
|
||||
createProject,
|
||||
enableLinkSharing,
|
||||
shareProjectByEmailAndAcceptInvite,
|
||||
shareProjectByEmailAndAcceptInviteViaDash,
|
||||
} from './helpers/project'
|
||||
|
||||
import git from 'isomorphic-git'
|
||||
|
@ -134,7 +134,7 @@ describe('git-bridge', function () {
|
|||
})
|
||||
|
||||
it('should expose r/w interface to invited r/w collaborator', () => {
|
||||
shareProjectByEmailAndAcceptInvite(
|
||||
shareProjectByEmailAndAcceptInviteViaDash(
|
||||
projectName,
|
||||
'collaborator-rw@example.com',
|
||||
'Can edit'
|
||||
|
@ -146,7 +146,7 @@ describe('git-bridge', function () {
|
|||
})
|
||||
|
||||
it('should expose r/o interface to invited r/o collaborator', () => {
|
||||
shareProjectByEmailAndAcceptInvite(
|
||||
shareProjectByEmailAndAcceptInviteViaDash(
|
||||
projectName,
|
||||
'collaborator-ro@example.com',
|
||||
'Read only'
|
||||
|
|
36
server-ce/test/helpers/email.ts
Normal file
36
server-ce/test/helpers/email.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Helper function for opening an email in Roundcube based mailtrap.
|
||||
* We need to cross an origin boundary, which complicates the use of variables.
|
||||
* Any variables need to be explicitly defined and the "runner" may only reference these and none from its scope.
|
||||
* It is not possible to use Cypress helper functions, e.g. from the testing library inside the "runner".
|
||||
* REF: https://github.com/testing-library/cypress-testing-library/issues/221
|
||||
*/
|
||||
export function openEmail<T>(
|
||||
subject: string | RegExp,
|
||||
runner: (frame: Cypress.Chainable<JQuery<any>>, args?: T) => void,
|
||||
args?: T
|
||||
) {
|
||||
const runnerS = runner.toString()
|
||||
cy.origin(
|
||||
'http://mailtrap',
|
||||
{ args: { args, runnerS, subject } },
|
||||
({ args, runnerS, subject }) => {
|
||||
cy.visit('/')
|
||||
cy.get('input[name="_user"]').type('mailtrap')
|
||||
cy.get('input[name="_pass"]').type('password-for-mailtrap')
|
||||
cy.get('button[type="submit"]').click()
|
||||
cy.log('mailtrap login is flaky in cypress, submit again')
|
||||
cy.get('input[name="_pass"]').type('password-for-mailtrap')
|
||||
cy.get('button[type="submit"]').click()
|
||||
// Use force as the subject is partially hidden
|
||||
cy.contains(subject).click({ force: true })
|
||||
cy.log('wait for iframe loading')
|
||||
cy.wait(1000)
|
||||
cy.get('iframe[id="messagecontframe"]').then(frame => {
|
||||
// runnerS='(frame, args) => { runner body }'. Extract the runnable function.
|
||||
const runner = new Function('return ' + runnerS)()
|
||||
runner(cy.wrap(frame.prop('contentWindow').document.body), args)
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
import { login } from './login'
|
||||
import { openEmail } from './email'
|
||||
|
||||
export function createProject(
|
||||
name: string,
|
||||
|
@ -23,7 +24,7 @@ export function createProject(
|
|||
.then(url => url.split('/').pop())
|
||||
}
|
||||
|
||||
export function shareProjectByEmailAndAcceptInvite(
|
||||
function shareProjectByEmail(
|
||||
projectName: string,
|
||||
email: string,
|
||||
level: 'Read only' | 'Can edit'
|
||||
|
@ -38,6 +39,14 @@ export function shareProjectByEmailAndAcceptInvite(
|
|||
.within(() => cy.findByText('Can edit').parent().select(level))
|
||||
cy.findByText('Share').click({ force: true })
|
||||
})
|
||||
}
|
||||
|
||||
export function shareProjectByEmailAndAcceptInviteViaDash(
|
||||
projectName: string,
|
||||
email: string,
|
||||
level: 'Read only' | 'Can edit'
|
||||
) {
|
||||
shareProjectByEmail(projectName, email, level)
|
||||
|
||||
login(email)
|
||||
cy.visit('/project')
|
||||
|
@ -49,6 +58,29 @@ export function shareProjectByEmailAndAcceptInvite(
|
|||
})
|
||||
}
|
||||
|
||||
export function shareProjectByEmailAndAcceptInviteViaEmail(
|
||||
projectName: string,
|
||||
email: string,
|
||||
level: 'Read only' | 'Can edit'
|
||||
) {
|
||||
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()
|
||||
}
|
||||
|
||||
export function enableLinkSharing() {
|
||||
let linkSharingReadOnly: string
|
||||
let linkSharingReadAndWrite: string
|
||||
|
|
|
@ -4,7 +4,8 @@ import { ensureUserExists, login } from './helpers/login'
|
|||
import {
|
||||
createProject,
|
||||
enableLinkSharing,
|
||||
shareProjectByEmailAndAcceptInvite,
|
||||
shareProjectByEmailAndAcceptInviteViaDash,
|
||||
shareProjectByEmailAndAcceptInviteViaEmail,
|
||||
} from './helpers/project'
|
||||
import { throttledRecompile } from './helpers/compile'
|
||||
import { beforeWithReRunOnTestRetry } from './helpers/beforeWithReRunOnTestRetry'
|
||||
|
@ -143,13 +144,34 @@ describe('Project Sharing', function () {
|
|||
.should('contain.text', author) // might have other edits in the same group
|
||||
}
|
||||
|
||||
describe('via email', function () {
|
||||
const email = 'collaborator-email@example.com'
|
||||
ensureUserExists({ email })
|
||||
|
||||
beforeEach(function () {
|
||||
login('user@example.com')
|
||||
shareProjectByEmailAndAcceptInviteViaEmail(
|
||||
projectName,
|
||||
email,
|
||||
'Read only'
|
||||
)
|
||||
})
|
||||
|
||||
it('should grant the collaborator read access', () => {
|
||||
cy.visit('/project')
|
||||
cy.findByText(projectName).click()
|
||||
expectFullReadOnlyAccess()
|
||||
expectProjectDashboardEntry()
|
||||
})
|
||||
})
|
||||
|
||||
describe('read only', () => {
|
||||
const email = 'collaborator-ro@example.com'
|
||||
ensureUserExists({ email })
|
||||
|
||||
beforeWithReRunOnTestRetry(function () {
|
||||
login('user@example.com')
|
||||
shareProjectByEmailAndAcceptInvite(projectName, email, 'Read only')
|
||||
shareProjectByEmailAndAcceptInviteViaDash(projectName, email, 'Read only')
|
||||
})
|
||||
|
||||
it('should grant the collaborator read access', () => {
|
||||
|
@ -167,7 +189,7 @@ describe('Project Sharing', function () {
|
|||
|
||||
beforeWithReRunOnTestRetry(function () {
|
||||
login('user@example.com')
|
||||
shareProjectByEmailAndAcceptInvite(projectName, email, 'Can edit')
|
||||
shareProjectByEmailAndAcceptInviteViaDash(projectName, email, 'Can edit')
|
||||
})
|
||||
|
||||
it('should grant the collaborator write access', () => {
|
||||
|
|
Loading…
Reference in a new issue