Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 49 additions & 49 deletions cypress/e2e/api/SessionApi.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,20 @@ describe('The session Api', function() {
})

it('returns connection', function() {
cy.createTextSession(fileId).then(connection => {
cy.openConnection({ fileId }).then(({ connection }) => {
cy.wrap(connection)
.its('document.id')
.its('documentId')
.should('equal', fileId)
cy.destroySession(connection)
cy.closeConnection(connection)
})
})

it('provides initial content', function() {
cy.createTextSession(fileId, { filePath }).then(connection => {
cy.wrap(connection)
.its('state.documentSource')
cy.openConnection({fileId, filePath }).then(({ connection, data }) => {
cy.wrap(data)
.its('content')
.should('eql', '## Hello world\n')
cy.destroySession(connection)
cy.closeConnection(connection)
})
})

Expand All @@ -74,14 +74,14 @@ describe('The session Api', function() {

beforeEach(function() {
cy.uploadTestFile()
.then(cy.createTextSession)
.then(con => {
.then((fileId) => cy.openConnection({ fileId }))
.then(({ connection: con }) => {
connection = con
})
})

afterEach(function() {
cy.destroySession(connection)
cy.closeConnection(connection)
})

// Echoes all message types but queries
Expand Down Expand Up @@ -135,9 +135,9 @@ describe('The session Api', function() {
cy.uploadTestFile()
.then(id => {
fileId = id
return cy.createTextSession(fileId, { filePath })
return cy.openConnection({ fileId, filePath })
})
.then(con => {
.then(({ connection: con }) => {
connection = con
})
})
Expand Down Expand Up @@ -169,18 +169,18 @@ describe('The session Api', function() {
documentState,
manualSave: true,
})
cy.createTextSession(fileId, { filePath })
.then(con => {
cy.openConnection({ fileId, filePath })
.then(({ connection: con, data }) => {
joining = con
return joining
return data
})
.its('state.documentState')
.its('documentState')
.should('eql', documentState)
.then(() => joining.close())
cy.closeConnection(joining)
})

afterEach(function() {
cy.destroySession(connection)
cy.closeConnection(connection)
})
})

Expand All @@ -204,15 +204,15 @@ describe('The session Api', function() {
})
.then(() => cy.clearCookies())
.then(() => {
return cy.createTextSession(undefined, { filePath: '', shareToken })
.then(con => {
return cy.openConnection({ filePath: '', token: shareToken })
.then(({ connection: con }) => {
connection = con
})
})
})

afterEach(function() {
cy.destroySession(connection)
cy.closeConnection(connection)
})

it('starts empty public', function() {
Expand Down Expand Up @@ -243,14 +243,14 @@ describe('The session Api', function() {
documentState,
manualSave: true,
})
cy.createTextSession(undefined, { filePath: '', shareToken })
.then(con => {
cy.openConnection({ filePath: '', token: shareToken })
.then(({ connection: con, data }) => {
joining = con
return con
return data
})
.its('state.documentState')
.its('documentState')
.should('eql', documentState)
.then(() => joining.close())
cy.closeConnection(joining)
})

})
Expand All @@ -269,49 +269,48 @@ describe('The session Api', function() {
cy.log(token)
shareToken = token
cy.clearCookies()
cy.createTextSession(undefined, { filePath: '', shareToken })
.then(con => {
cy.openConnection({ filePath: '', token: shareToken })
.then(({ connection: con }) => {
connection = con
})
})
})

it('does not send initial content if other session is alive but did not push any steps', function() {
let joining
cy.createTextSession(undefined, { filePath: '', shareToken })
.then(con => {
cy.openConnection({ filePath: '', token: shareToken })
.then(({ connection: con, data }) => {
joining = con
return con
return data
})
.its('state.documentSource')
.its('content')
.should('eql', '## Hello world\n')
.then(() => cy.destroySession(joining))
cy.destroySession(connection)
.then(() => cy.closeConnection(joining))
cy.closeConnection(connection)
})

it('does not send initial content if session is alive even without saved state', function() {
let joining
cy.pushSteps({ connection, steps: [messages.update], version })
.its('version')
.should('be.at.least', 1)
cy.createTextSession(undefined, { filePath: '', shareToken })
.then(con => {
cy.openConnection({ filePath: '', token: shareToken })
.then(({ connection: con, data }) => {
joining = con
return con
return data
})
.its('state.documentSource')
.its('content')
.should('eql', '## Hello world\n')
.then(() => cy.destroySession(joining))
cy.destroySession(connection)
.then(() => cy.closeConnection(joining))
cy.closeConnection(connection)
})

it('refuses create,push,sync,save with non-matching baseVersionEtag', function() {
cy.failToCreateTextSession(undefined, 'wrongBaseVersionEtag', { filePath: '', token: shareToken })
.its('status')
.should('eql', 412)

connection.setBaseVersionEtag('wrongBaseVersionEtag')
connection.connection.baseVersionEtag = 'wrongBaseVersionEtag'
connection.baseVersionEtag = 'wrongBaseVersionEtag'

cy.failToPushSteps({ connection, steps: [messages.update], version })
.its('status')
Expand All @@ -325,7 +324,7 @@ describe('The session Api', function() {
.its('status')
.should('equal', 412)

cy.destroySession(connection)
cy.closeConnection(connection)
})

it('recovers session even if last person leaves right after create', function() {
Expand All @@ -335,12 +334,12 @@ describe('The session Api', function() {
.its('version')
.should('be.at.least', 1)
cy.log('Other user creates session')
cy.createTextSession(undefined, { filePath: '', shareToken })
.then(con => {
cy.openConnection({ filePath: '', token: shareToken })
.then(({ connection: con }) => {
joining = con
})
cy.log('Initial user closes session')
cy.destroySession(connection)
cy.closeConnection(connection)
cy.log('Other user still finds the steps')
.then(() => {
cy.syncSteps(joining, {
Expand All @@ -354,11 +353,12 @@ describe('The session Api', function() {
// Skipped for now since the behaviour chanced by not cleaning up the state on close/create
it.skip('ignores steps stored after close cleaned up', function() {
cy.pushAndClose({ connection, steps: [messages.update], version })
cy.createTextSession(undefined, { filePath: '', shareToken })
.then(con => {
cy.openConnection({ filePath: '', token: shareToken })
.then(({ connection: con, data }) => {
connection = con
return data
})
.its('state.documentSource')
.its('content')
.should('eql', '## Hello world\n')
})

Expand Down
15 changes: 8 additions & 7 deletions cypress/e2e/api/UsersApi.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,22 @@ describe('The user mention API', function() {
beforeEach(function() {
cy.login(user)
cy.uploadTestFile('test.md').as('fileId')
.then(cy.createTextSession).as('connection')
})

afterEach(function() {
cy.get('@connection').then(c => c.closed || c.close())
.then((fileId) => cy.openConnection({ fileId }))
.its('connection')
.as('connection')
})

it('has a valid connection', function() {
cy.get('@connection')
.its('document.id')
.its('documentId')
.should('equal', this.fileId)
cy.closeConnection(this.connection)
})

it('fetches users with valid session', function() {
cy.sessionUsers(this.connection)
.its('status').should('eq', 200)
cy.closeConnection(this.connection)
})

it('rejects invalid sessions', function() {
Expand All @@ -41,10 +41,11 @@ describe('The user mention API', function() {
.its('status').should('eq', 403)
cy.sessionUsers(this.connection, { documentId: 0 })
.its('status').should('eq', 403)
cy.closeConnection(this.connection)
})

it('rejects closed sessions', function() {
cy.destroySession(this.connection)
cy.closeConnection(this.connection)
cy.sessionUsers(this.connection)
.its('status').should('eq', 403)
})
Expand Down
77 changes: 31 additions & 46 deletions cypress/support/sessions.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,15 @@
*/

import axios from '@nextcloud/axios'
import { SessionConnection } from '../../src/services/SessionConnection.js'
import { open, close } from '../../src/apis/Connect.ts'
import { push } from '../../src/apis/Sync.ts'
import { save } from '../../src/apis/Save.ts'
import { open, close } from '../../src/apis/connect.ts'
import { push, sync } from '../../src/apis/sync.ts'
import { save } from '../../src/apis/save.ts'

const url = Cypress.config('baseUrl').replace(/\/index.php\/?$/g, '')

Cypress.Commands.add('createTextSession', async (fileId, options = {}) => {
const { connection, data } = await open({ fileId, token: options.shareToken, ...options })
return new SessionConnection(data, connection)
})
Cypress.Commands.add('openConnection', open)

Cypress.Commands.add('destroySession', async (sessionConnection) => {
const { documentId, id, token } = sessionConnection.session
await close({ documentId, sessionId: id, sessionToken: token })
sessionConnection.close()
})
Cypress.Commands.add('closeConnection', close)

Cypress.Commands.add('failToCreateTextSession', (fileId, baseVersionEtag = null, options = {}) => {
return open({ fileId, ...options, baseVersionEtag })
Expand All @@ -29,55 +21,48 @@ Cypress.Commands.add('failToCreateTextSession', (fileId, baseVersionEtag = null,
}, (err) => err.response)
})

Cypress.Commands.add('pushSteps', ({ connection: sessionConnection, steps, version, awareness = '' }) => {
return push(
sessionConnection.connection,
{ steps, version, awareness }
).then(response => response.data)
Cypress.Commands.add('pushSteps', ({ connection, steps, version, awareness = '' }) => {
return push(connection, { steps, version, awareness })
.then(response => response.data)
})

Cypress.Commands.add('failToPushSteps', ({ connection: sessionConnection, steps, version, awareness = '' }) => {
return push(
sessionConnection.connection,
{ steps, version, awareness }
).then((_response) => {
throw new Error('Expected request to fail - but it succeeded!')
}, (err) => err.response)
Cypress.Commands.add('failToPushSteps', ({ connection, steps, version, awareness = '' }) => {
return push( connection, { steps, version, awareness })
.then((_response) => {
throw new Error('Expected request to fail - but it succeeded!')
}, (err) => err.response)
})

Cypress.Commands.add('syncSteps', (connection, options = { version: 0 }) => {
return connection.sync(options)
return sync(connection, options)
.then(response => response.data)
})

Cypress.Commands.add('failToSyncSteps', (connection, options = { version: 0 }) => {
return connection.sync(options)
.then((response) => {
return sync(connection, options)
.then((_response) => {
throw new Error('Expected request to fail - but it succeeded!')
}, (err) => err.response)
})

Cypress.Commands.add('save', (sessionConnection, options = { version: 0 }) => {
return save(
sessionConnection.connection,
options
).then(response => response.data)
Cypress.Commands.add('save', (connection, options = { version: 0 }) => {
return save( connection, options)
.then(response => response.data)
})

Cypress.Commands.add('failToSave', (sessionConnection, options = { version: 0 }) => {
return save(
sessionConnection.connection,
options
).then((response) => {
throw new Error('Expected request to fail - but it succeeded!')
}, (err) => err.response)
Cypress.Commands.add('failToSave', (connection, options = { version: 0 }) => {
return save( connection, options)
.then((_response) => {
throw new Error('Expected request to fail - but it succeeded!')
}, (err) => err.response)
})

Cypress.Commands.add('sessionUsers', function(connection, bodyOptions = {}) {
const { documentId, sessionId, sessionToken } = connection
const data = {
documentId: connection.document.id,
sessionId: connection.session.id,
sessionToken: connection.session.token,
documentId,
sessionId,
sessionToken,
requesttoken: this.requesttoken,
...bodyOptions,
}
Expand All @@ -93,14 +78,14 @@ Cypress.Commands.add('sessionUsers', function(connection, bodyOptions = {}) {
Cypress.Commands.add('pushAndClose', ({ connection, steps, version, awareness = '' }) => {
cy.log('Race between push and close')
.then(() => {
const push = connection.push({ steps, version, awareness })
const pushed = push(connection, { steps, version, awareness })
.catch(error => {
// handle 403 gracefully
if (error.response?.status !== 403) {
throw error
}
})
const close = connection.close()
return Promise.all([push, close])
const closed = close(connection)
return Promise.all([pushed, closed])
})
})
Loading
Loading