Skip to content

Commit d9c85bf

Browse files
committed
chore(refactor): split open api functions
Two api endpoints deserve two different functions in particular as they also expect different params. This also allows narrowing down the types a little more. Signed-off-by: Max <max@nextcloud.com>
1 parent 70d6b85 commit d9c85bf

6 files changed

Lines changed: 101 additions & 32 deletions

File tree

cypress/e2e/api/SessionApi.spec.js

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ describe('The session Api', function() {
3636
})
3737

3838
it('returns connection', function() {
39-
cy.openConnection({ fileId }).then(({ connection }) => {
39+
cy.openFileConnection({ fileId }).then(({ connection }) => {
4040
cy.wrap(connection).its('documentId').should('equal', fileId)
4141
cy.closeConnection(connection)
4242
})
4343
})
4444

4545
it('provides initial content', function() {
46-
cy.openConnection({ fileId, filePath }).then(({ connection, data }) => {
46+
cy.openFileConnection({ fileId, filePath }).then(({ connection, data }) => {
4747
cy.wrap(data).its('content').should('eql', '## Hello world\n')
4848
cy.closeConnection(connection)
4949
})
@@ -63,7 +63,7 @@ describe('The session Api', function() {
6363

6464
beforeEach(function() {
6565
cy.uploadTestFile()
66-
.then((fileId) => cy.openConnection({ fileId }))
66+
.then((fileId) => cy.openFileConnection({ fileId }))
6767
.then(({ connection: con }) => {
6868
connection = con
6969
})
@@ -116,7 +116,7 @@ describe('The session Api', function() {
116116
cy.uploadTestFile()
117117
.then((id) => {
118118
fileId = id
119-
return cy.openConnection({ fileId, filePath })
119+
return cy.openFileConnection({ fileId, filePath })
120120
})
121121
.then(({ connection: con }) => {
122122
connection = con
@@ -151,7 +151,7 @@ describe('The session Api', function() {
151151
documentState,
152152
manualSave: true,
153153
})
154-
cy.openConnection({ fileId, filePath })
154+
cy.openFileConnection({ fileId, filePath })
155155
.as('joining')
156156
.its('data.documentState')
157157
.should('eql', documentState)
@@ -183,7 +183,7 @@ describe('The session Api', function() {
183183
.then(() => cy.clearCookies())
184184
.then(() => {
185185
return cy
186-
.openConnection({ filePath: '', token: shareToken })
186+
.openShareConnection({ filePath: '', token: shareToken })
187187
.then(({ connection: con }) => {
188188
connection = con
189189
})
@@ -223,7 +223,7 @@ describe('The session Api', function() {
223223
documentState,
224224
manualSave: true,
225225
})
226-
cy.openConnection({ filePath: '', token: shareToken })
226+
cy.openShareConnection({ filePath: '', token: shareToken })
227227
.as('joining')
228228
.its('data.documentState')
229229
.should('eql', documentState)
@@ -247,15 +247,15 @@ describe('The session Api', function() {
247247
cy.log(token)
248248
shareToken = token
249249
cy.clearCookies()
250-
cy.openConnection({ filePath: '', token: shareToken }).then(({ connection: con }) => {
250+
cy.openShareConnection({ filePath: '', token: shareToken }).then(({ connection: con }) => {
251251
connection = con
252252
})
253253
})
254254
})
255255

256256
it('does not send initial content if other session is alive but did not push any steps', function() {
257257
let joining
258-
cy.openConnection({ filePath: '', token: shareToken })
258+
cy.openShareConnection({ filePath: '', token: shareToken })
259259
.then(({ connection: con, data }) => {
260260
joining = con
261261
return data
@@ -271,7 +271,7 @@ describe('The session Api', function() {
271271
cy.pushSteps({ connection, steps: [messages.update], version })
272272
.its('version')
273273
.should('eql', 0)
274-
cy.openConnection({ filePath: '', token: shareToken })
274+
cy.openShareConnection({ filePath: '', token: shareToken })
275275
.then(({ connection: con, data }) => {
276276
joining = con
277277
return data
@@ -312,7 +312,7 @@ describe('The session Api', function() {
312312
.its('version')
313313
.should('eql', 0)
314314
cy.log('Other user creates session')
315-
cy.openConnection({ filePath: '', token: shareToken }).then(({ connection: con }) => {
315+
cy.openShareConnection({ filePath: '', token: shareToken }).then(({ connection: con }) => {
316316
joining = con
317317
})
318318
cy.log('Initial user closes session')
@@ -330,7 +330,7 @@ describe('The session Api', function() {
330330
// Skipped for now since the behaviour chanced by not cleaning up the state on close/create
331331
it.skip('ignores steps stored after close cleaned up', function() {
332332
cy.pushAndClose({ connection, steps: [messages.update], version })
333-
cy.openConnection({ filePath: '', token: shareToken })
333+
cy.openShareConnection({ filePath: '', token: shareToken })
334334
.then(({ connection: con, data }) => {
335335
connection = con
336336
return data

cypress/e2e/api/UsersApi.spec.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ describe('The user mention API', function() {
1616
cy.login(user)
1717
cy.uploadTestFile('test.md')
1818
.as('fileId')
19-
.then((fileId) => cy.openConnection({ fileId }))
19+
.then((fileId) => cy.openFileConnection({ fileId }))
2020
.its('connection')
2121
.as('connection')
2222
})

cypress/support/sessions.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,21 @@
44
*/
55

66
import axios from '@nextcloud/axios'
7-
import { close, open } from '../../src/apis/connect.ts'
7+
import { close, openFile, openShare } from '../../src/apis/connect.ts'
88
import { save } from '../../src/apis/save.ts'
99
import { push, sync } from '../../src/apis/sync.ts'
1010

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

13-
Cypress.Commands.add('openConnection', open)
13+
Cypress.Commands.add('openFileConnection', openFile)
14+
Cypress.Commands.add('openShareConnection', openShare)
1415

1516
Cypress.Commands.add('closeConnection', close)
1617

1718
Cypress.Commands.add(
1819
'failToCreateTextSession',
1920
(fileId, baseVersionEtag = null, options = {}) => {
20-
return open({ fileId, ...options, baseVersionEtag }).then(
21+
return openFile({ fileId, ...options, baseVersionEtag }).then(
2122
() => {
2223
throw new Error('Expected request to fail - but it succeeded!')
2324
},

src/apis/connect.ts

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,15 @@ import axios from '@nextcloud/axios'
1010
import { generateUrl } from '@nextcloud/router'
1111

1212
export interface OpenParams {
13-
fileId?: number
13+
fileId: number
14+
filePath: string // not send to the api but included in the connection
1415
baseVersionEtag?: string
16+
}
17+
18+
export interface OpenShareParams {
19+
token: string
1520
filePath: string
16-
token?: string
21+
baseVersionEtag?: string
1722
guestName?: string
1823
}
1924

@@ -27,16 +32,31 @@ export interface OpenData {
2732
hasOwner: boolean
2833
}
2934

35+
/**
36+
* Open editing connection to a file when logged in
37+
*
38+
* @param params Parameters identifying the document
39+
*/
40+
export async function openFile(params: OpenParams): Promise<{ connection: Connection, data: OpenData }> {
41+
const url = generateUrl(`/apps/text/session/${params.fileId}/create`)
42+
const response = await axios.put(url, params)
43+
const { document, session } = response.data
44+
const connection = {
45+
documentId: document.id,
46+
sessionId: session.id,
47+
sessionToken: session.token,
48+
baseVersionEtag: document.baseVersionEtag,
49+
}
50+
return { connection, data: response.data }
51+
}
52+
3053
/**
3154
* Open editing connection to the document
3255
*
3356
* @param params Parameters identifying the document
3457
*/
35-
export async function open(params: OpenParams): Promise<{ connection: Connection, data: OpenData }> {
36-
const _baseUrl = params.token
37-
? generateUrl('/apps/text/public')
38-
: generateUrl('/apps/text')
39-
const url = `${_baseUrl}/session/${params.fileId}/create`
58+
export async function openShare(params: OpenShareParams): Promise<{ connection: Connection, data: OpenData }> {
59+
const url = generateUrl('/apps/text/public/session/123/create')
4060
const response = await axios.put(url, params)
4161
const { document, session } = response.data
4262
const connection = {

src/composables/useConnection.ts

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type { OpenData } from '../apis/connect.ts'
88
import type { Document, Session } from '../services/SyncService.ts'
99

1010
import { inject, provide, shallowRef } from 'vue'
11-
import { open } from '../apis/connect.ts'
11+
import * as api from '../apis/connect.ts'
1212

1313
export interface Connection {
1414
documentId: number
@@ -65,13 +65,8 @@ export function provideConnection(
6565
const guestName = localStorage.getItem('nick') ?? ''
6666
const { connection: opened, data }
6767
= openInitialSession(props, baseVersionEtag)
68-
|| (await open({
69-
fileId: props.fileId,
70-
guestName,
71-
token: props.shareToken,
72-
filePath: props.relativePath,
73-
baseVersionEtag,
74-
}))
68+
|| await openShare(props, baseVersionEtag, guestName)
69+
|| await openFile(props, baseVersionEtag)
7570
await setBaseVersionEtag(data.document.baseVersionEtag)
7671
connection.value = opened
7772
openData.value = data
@@ -134,3 +129,56 @@ function openInitialSession(
134129
return { connection, data: props.initialSession }
135130
}
136131
}
132+
133+
/**
134+
* Get the connection and additional data from the initial session if available.
135+
*
136+
* @param props Props of the editor component
137+
* @param props.relativePath Relative path to the file.
138+
* @param props.shareToken Share token of the file.
139+
* @param props.fileId id of the file
140+
* @param baseVersionEtag Etag from the last editing session.
141+
* @param guestName to be shown to other participants.
142+
*/
143+
async function openShare(
144+
props: {
145+
fileId: number
146+
relativePath: string
147+
shareToken?: string
148+
},
149+
baseVersionEtag: string | undefined,
150+
guestName: string | undefined,
151+
) {
152+
if (props.shareToken) {
153+
return api.openShare({
154+
guestName,
155+
token: props.shareToken,
156+
filePath: props.relativePath,
157+
fileId: props.fileId,
158+
baseVersionEtag,
159+
})
160+
}
161+
}
162+
163+
/**
164+
* Get the connection and additional data from the initial session if available.
165+
*
166+
* @param props Props of the editor component
167+
* @param props.fileId id of the file
168+
* @param props.relativePath Relative path to the file.
169+
* @param baseVersionEtag Etag from the last editing session.
170+
*/
171+
async function openFile(
172+
props: {
173+
fileId: number
174+
relativePath: string
175+
},
176+
baseVersionEtag: string | undefined,
177+
) {
178+
return api.openFile({
179+
type: 'file',
180+
id: props.fileId,
181+
filePath: props.relativePath,
182+
baseVersionEtag,
183+
})
184+
}

src/tests/services/SyncService.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ describe('Sync service', () => {
5454
setBaseVersionEtag,
5555
)
5656
vi.mock('../../apis/connect')
57-
vi.mocked(connect.open).mockResolvedValue(openResult)
57+
vi.mocked(connect.openFile).mockResolvedValue(openResult)
5858
const openHandler = vi.fn()
5959
const service = new SyncService({ connection, openConnection })
6060
service.bus.on('opened', openHandler)

0 commit comments

Comments
 (0)