|
|
@@ -96,7 +96,8 @@ assert.deepEqual(creationState, {
|
|
|
completed: false,
|
|
|
teamPayloadSnapshot: '',
|
|
|
teamQuestionnaireId: '',
|
|
|
- publishResult: null
|
|
|
+ publishResult: null,
|
|
|
+ resumeStage: ''
|
|
|
})
|
|
|
const firstPayloadSnapshot = rules.createTeamPayloadSnapshot({
|
|
|
teamName: '团队', enterpriseWebsite: ' https://example.com ', coachId: 7
|
|
|
@@ -669,9 +670,17 @@ const teamEditPagePath = path.join(__dirname, '../pagesMy/teamEdit.vue')
|
|
|
const headerComponentPath = path.join(__dirname, '../components/CusHeader/index.vue')
|
|
|
|
|
|
async function testDeferredPcSelectionSurvivesSessionFailure() {
|
|
|
+ let createCalls = 0
|
|
|
+ const firstRequest = createDeferred()
|
|
|
const component = await loadVueComponent(backgroundComponentPath, {
|
|
|
http: {
|
|
|
- createTeamBackgroundSession: () => Promise.reject(new Error('session unavailable'))
|
|
|
+ createTeamBackgroundSession() {
|
|
|
+ createCalls += 1
|
|
|
+ if (createCalls === 1) return firstRequest.promise
|
|
|
+ return Promise.resolve({
|
|
|
+ code: '123456', uploadUrl: 'https://upload.example/retry', expiresAt: '2099-01-01 00:00:00'
|
|
|
+ })
|
|
|
+ }
|
|
|
}
|
|
|
})
|
|
|
const instance = instantiateComponent(component, {
|
|
|
@@ -682,10 +691,25 @@ async function testDeferredPcSelectionSurvivesSessionFailure() {
|
|
|
$showToast() {},
|
|
|
$emit() {}
|
|
|
})
|
|
|
- await assert.rejects(instance.waitForDeferredPcUpload(12), /session unavailable/)
|
|
|
+ const first = instance.waitForDeferredPcUpload(12)
|
|
|
+ const second = instance.waitForDeferredPcUpload(12)
|
|
|
+ assert.equal(first, second, 'the whole deferred flow must expose one shared waiter')
|
|
|
+ assert.equal(createCalls, 1)
|
|
|
+ firstRequest.reject(new Error('session unavailable'))
|
|
|
+ const failed = await Promise.allSettled([first, second])
|
|
|
+ assert.deepEqual(failed.map(result => result.status), ['rejected', 'rejected'])
|
|
|
+ assert.match(failed[0].reason.message, /session unavailable/)
|
|
|
assert.equal(instance.pcUploadDeferred, true)
|
|
|
assert.equal(instance.pcDialogVisible, false)
|
|
|
assert.equal(instance.deferredPcResolve, null)
|
|
|
+ assert.equal(instance.deferredPcWaitPromise, null)
|
|
|
+
|
|
|
+ const retry = instance.waitForDeferredPcUpload(12)
|
|
|
+ await flushPromises()
|
|
|
+ assert.equal(createCalls, 2, 'a failed shared waiter must be retryable')
|
|
|
+ assert.equal(typeof instance.deferredPcResolve, 'function')
|
|
|
+ instance.skipDeferredPcUpload()
|
|
|
+ await retry
|
|
|
}
|
|
|
|
|
|
async function testSessionRefreshFailureKeepsOldTimer() {
|
|
|
@@ -824,6 +848,39 @@ async function testDeferredPcFinishWaitsForListRefresh() {
|
|
|
await assert.rejects(waiting, /list refresh failed/)
|
|
|
}
|
|
|
|
|
|
+async function testDeferredPcWaiterSingleFlightFinishesAllCallers() {
|
|
|
+ let createCalls = 0
|
|
|
+ const sessionRequest = createDeferred()
|
|
|
+ const component = await loadVueComponent(backgroundComponentPath, {
|
|
|
+ http: {
|
|
|
+ createTeamBackgroundSession() {
|
|
|
+ createCalls += 1
|
|
|
+ return sessionRequest.promise
|
|
|
+ },
|
|
|
+ listTeamBackgroundFiles: () => Promise.resolve([])
|
|
|
+ }
|
|
|
+ })
|
|
|
+ const instance = instantiateComponent(component, {
|
|
|
+ teamId: '', editable: true, boundTeamId: 12, pcUploadDeferred: true,
|
|
|
+ $showToast() {}, $emit() {}
|
|
|
+ })
|
|
|
+ const first = instance.waitForDeferredPcUpload(12)
|
|
|
+ const second = instance.waitForDeferredPcUpload(12)
|
|
|
+ assert.equal(first, second)
|
|
|
+ assert.equal(createCalls, 1)
|
|
|
+ let settled = false
|
|
|
+ first.then(() => { settled = true })
|
|
|
+ sessionRequest.resolve({
|
|
|
+ code: '654321', uploadUrl: 'https://upload.example/', expiresAt: '2099-01-01 00:00:00'
|
|
|
+ })
|
|
|
+ await flushPromises()
|
|
|
+ assert.equal(settled, false, 'session creation must not settle the dialog waiter')
|
|
|
+ await instance.finishDeferredPcUpload()
|
|
|
+ await Promise.all([first, second])
|
|
|
+ assert.equal(settled, true)
|
|
|
+ assert.equal(instance.deferredPcWaitPromise, null)
|
|
|
+}
|
|
|
+
|
|
|
async function testTeamContextResetAndUploadIsolation() {
|
|
|
const uploads = []
|
|
|
const component = await loadVueComponent(backgroundComponentPath, {
|
|
|
@@ -1100,6 +1157,9 @@ async function testCreatedTeamNavigationIsAwaitableAndResumable() {
|
|
|
assert.equal(url, '/core/user/team')
|
|
|
assert.equal(payload.id, 88)
|
|
|
assert.equal(payload.enterpriseWebsite, 'https://new.example')
|
|
|
+ if (teamPutCalls === 1) {
|
|
|
+ return Promise.resolve({ data: { code: 9, msg: '官网更新失败' } })
|
|
|
+ }
|
|
|
return Promise.resolve({ data: { code: 0, data: true } })
|
|
|
}
|
|
|
},
|
|
|
@@ -1138,6 +1198,18 @@ async function testCreatedTeamNavigationIsAwaitableAndResumable() {
|
|
|
assert.ok(toasts.some(message => String(message).includes('页面跳转失败')))
|
|
|
|
|
|
navigationOptions = null
|
|
|
+ const failedUpdate = instance.handleConfirm({
|
|
|
+ teamName: '团队', enterpriseWebsite: 'https://new.example'
|
|
|
+ })
|
|
|
+ await failedUpdate
|
|
|
+ assert.equal(teamPostCalls, 1)
|
|
|
+ assert.equal(publishCalls, 1)
|
|
|
+ assert.equal(flushCalls, 1)
|
|
|
+ assert.equal(teamPutCalls, 1)
|
|
|
+ assert.equal(instance.creationState.stage, 'update')
|
|
|
+ assert.ok(toasts.some(message => String(message).includes('团队更新失败:官网更新失败')))
|
|
|
+ assert.equal(timers.count(), 0)
|
|
|
+
|
|
|
const retry = instance.handleConfirm({
|
|
|
teamName: '团队', enterpriseWebsite: 'https://new.example'
|
|
|
})
|
|
|
@@ -1145,7 +1217,7 @@ async function testCreatedTeamNavigationIsAwaitableAndResumable() {
|
|
|
assert.equal(teamPostCalls, 1, 'retry must reuse the created team id')
|
|
|
assert.equal(publishCalls, 1, 'retry after publish success must not publish again')
|
|
|
assert.equal(flushCalls, 1, 'navigate-stage retry must not repeat file processing')
|
|
|
- assert.equal(teamPutCalls, 1, 'changed sanitized payload must update the same team')
|
|
|
+ assert.equal(teamPutCalls, 2, 'changed sanitized payload must update the same team')
|
|
|
assert.equal(timers.count(), 1)
|
|
|
timers.runNext()
|
|
|
await flushPromises()
|
|
|
@@ -1207,13 +1279,18 @@ async function testTeamEditRedirectIsLockedAndResumable() {
|
|
|
}
|
|
|
const component = await loadVueComponent(teamEditPagePath, { uni, timers })
|
|
|
const instance = instantiateComponent(component, {
|
|
|
- submitDto: { id: 12, teamName: '团队' },
|
|
|
+ submitDto: { id: 12, teamName: '团队', enterpriseWebsite: 'https://old.example' },
|
|
|
show: true,
|
|
|
$api: {
|
|
|
put(url, payload) {
|
|
|
putCalls += 1
|
|
|
assert.equal(url, '/core/user/team')
|
|
|
assert.equal(payload.id, 12)
|
|
|
+ assert.equal(Object.hasOwn(payload, 'coachId'), false)
|
|
|
+ assert.equal(Object.hasOwn(payload, 'uploaderId'), false)
|
|
|
+ assert.equal(Object.hasOwn(payload, 'source'), false)
|
|
|
+ assert.equal(payload.enterpriseWebsite,
|
|
|
+ putCalls === 1 ? 'https://old.example' : 'https://new.example')
|
|
|
return Promise.resolve({ data: { code: 0, data: true } })
|
|
|
}
|
|
|
},
|
|
|
@@ -1251,9 +1328,30 @@ async function testTeamEditRedirectIsLockedAndResumable() {
|
|
|
timers.runNext()
|
|
|
await flushPromises()
|
|
|
assert.ok(redirectOptions)
|
|
|
- redirectOptions.success({})
|
|
|
+ redirectOptions.fail({ errMsg: 'redirectTo:fail still missing' })
|
|
|
await retry
|
|
|
assert.equal(putCalls, 1)
|
|
|
+
|
|
|
+ redirectOptions = null
|
|
|
+ instance.handleConfirm({
|
|
|
+ id: 12,
|
|
|
+ teamName: '团队',
|
|
|
+ enterpriseWebsite: ' https://new.example ',
|
|
|
+ coachId: 7,
|
|
|
+ uploaderId: 8,
|
|
|
+ source: 'WECHAT'
|
|
|
+ })
|
|
|
+ const changedRetry = instance.editConfirm()
|
|
|
+ await flushPromises()
|
|
|
+ assert.equal(putCalls, 2, 'a changed payload must update the saved team before redirect')
|
|
|
+ assert.equal(instance.saving, true)
|
|
|
+ assert.equal(timers.count(), 1)
|
|
|
+ timers.runNext()
|
|
|
+ await flushPromises()
|
|
|
+ assert.ok(redirectOptions)
|
|
|
+ redirectOptions.success({})
|
|
|
+ await changedRetry
|
|
|
+ assert.equal(putCalls, 2)
|
|
|
assert.equal(instance.saving, false)
|
|
|
}
|
|
|
|
|
|
@@ -1346,6 +1444,7 @@ async function main() {
|
|
|
await testPcSessionSingleFlightSurvivesSameTeamReset()
|
|
|
await testPcSessionFailureClearsSingleFlightForRetry()
|
|
|
await testDeferredPcFinishWaitsForListRefresh()
|
|
|
+ await testDeferredPcWaiterSingleFlightFinishesAllCallers()
|
|
|
await testTeamContextResetAndUploadIsolation()
|
|
|
await testFileActionsWaitForCurrentListAndDocumentContext()
|
|
|
await testTeamFillFlushesBeforeEmitAndLocks()
|