const assert = require('node:assert/strict') const fs = require('node:fs') const path = require('node:path') const { pathToFileURL } = require('node:url') const vm = require('node:vm') const rules = require('../utils/teamBackgroundFile') assert.equal(rules.validateEnterpriseWebsite(' 无 '), '') assert.equal(rules.validateEnterpriseWebsite('https://example.com'), '') assert.match(rules.validateEnterpriseWebsite('ftp://example.com'), /http/) assert.equal(rules.validateBackgroundFile({ name: 'brief.PDF', size: 1 }), '') assert.match(rules.validateBackgroundFile({ name: 'brief.zip', size: 1 }), /类型/) assert.match(rules.validateBackgroundFile({ name: 'brief.pdf', size: 50 * 1024 * 1024 + 1 }), /50MB/) assert.equal(rules.validateBackgroundFile({ name: 'brief.pdf', size: 50 * 1024 * 1024 }), '') assert.equal(rules.validateBackgroundFile({ name: `${'a'.repeat(251)}.pdf`, size: 1 }), '') assert.match(rules.validateBackgroundFile({ name: `${'a'.repeat(252)}.pdf`, size: 1 }), /255/) assert.match(rules.validateBackgroundFile({ name: 'empty.pdf', size: 0 }), /非空/) console.log('team background rules: PASS') const transportPath = path.join(__dirname, '../http/teamBackgroundFile.js') async function loadTransport({ api = {}, uni = {}, wx = {} } = {}) { const source = fs.readFileSync(transportPath, 'utf8') const context = vm.createContext({ uni, wx }) const baseApiModule = new vm.SyntheticModule(['BaseApi'], function () { this.setExport('BaseApi', 'https://api.example.test/app') }, { context, identifier: 'test:baseApi' }) const apiModule = new vm.SyntheticModule(['default'], function () { this.setExport('default', api) }, { context, identifier: 'test:api' }) const transportModule = new vm.SourceTextModule(source, { context, identifier: pathToFileURL(transportPath).href }) await transportModule.link(specifier => { if (specifier === './baseApi.js') return baseApiModule if (specifier === './index.js') return apiModule throw new Error(`unexpected transport import: ${specifier}`) }) await transportModule.evaluate() return transportModule.namespace } function assertNoIdentityFields(value) { if (!value || typeof value !== 'object') return for (const [key, child] of Object.entries(value)) { assert.ok(!['source', 'coachId', 'uploaderId'].includes(key), `unexpected identity field: ${key}`) assertNoIdentityFields(child) } } async function createUploadHarness(response, progress = 37) { let request const progressValues = [] const uni = { getStorageSync(key) { assert.equal(key, 'token') return 'token-123' }, uploadFile(options) { request = options return { onProgressUpdate(callback) { callback({ progress }) setImmediate(() => options.success(response)) } } } } const transport = await loadTransport({ uni }) return { request: () => request, progressValues, promise: transport.uploadTeamBackgroundFile(12, '/tmp/brief.pdf', value => progressValues.push(value)) } } async function testUploadTransport() { const stringHarness = await createUploadHarness({ statusCode: 200, data: JSON.stringify({ code: 0, data: { id: 7 } }) }) assert.equal((await stringHarness.promise).id, 7) assert.equal(stringHarness.request().url, 'https://api.example.test/app/core/user/team/12/background-files') assert.equal(stringHarness.request().filePath, '/tmp/brief.pdf') assert.equal(stringHarness.request().name, 'file') assert.equal(stringHarness.request().header.token, 'token-123') assert.deepEqual(stringHarness.progressValues, [37]) assertNoIdentityFields(stringHarness.request()) const objectHarness = await createUploadHarness({ statusCode: 200, data: { code: 0, data: { id: 8 } } }) assert.equal((await objectHarness.promise).id, 8) const statusHarness = await createUploadHarness({ statusCode: 500, data: { code: 0 } }) await assert.rejects(statusHarness.promise, /上传失败,请重试/) const codeHarness = await createUploadHarness({ statusCode: 200, data: { code: 9, msg: '上传业务失败' } }) await assert.rejects(codeHarness.promise, /上传业务失败/) const invalidJsonHarness = await createUploadHarness({ statusCode: 200, data: '' }) await assert.rejects(invalidJsonHarness.promise, /上传失败,请重试/) } async function testApiTransport() { const calls = [] const api = { get(...args) { calls.push(['get', ...args]) return Promise.resolve({ data: { code: 0, data: [{ id: 1 }] } }) }, del(...args) { calls.push(['del', ...args]) return Promise.resolve({ data: { code: 0, data: true } }) }, post(...args) { calls.push(['post', ...args]) return Promise.resolve({ data: { code: 0, data: { sessionId: 'session-1' } } }) } } const transport = await loadTransport({ api }) assert.deepEqual(await transport.listTeamBackgroundFiles(12), [{ id: 1 }]) assert.equal(await transport.disableTeamBackgroundFile(12, 34), true) assert.deepEqual(await transport.createTeamBackgroundSession(12), { sessionId: 'session-1' }) assert.equal(calls[0][0], 'get') assert.equal(calls[0][1], '/core/user/team/12/background-files') assert.equal(calls[1][0], 'del') assert.equal(calls[1][1], '/core/user/team/12/background-files/34') assert.equal(calls[2][0], 'post') assert.equal(calls[2][1], '/core/user/team/12/background-upload-session') for (const call of calls) { assert.equal(Object.keys(call[2]).length, 0) assert.equal(call[3], false) assertNoIdentityFields(call) } const failingTransport = await loadTransport({ api: { get: () => Promise.resolve({ data: { code: 3, msg: '列表业务失败' } }) } }) await assert.rejects(failingTransport.listTeamBackgroundFiles(12), /列表业务失败/) assert.equal(transport.uploadTeamBackgroundFile.length, 2) assert.equal(transport.listTeamBackgroundFiles.length, 1) assert.equal(transport.disableTeamBackgroundFile.length, 2) assert.equal(transport.createTeamBackgroundSession.length, 1) assert.equal(transport.downloadTeamBackgroundFile.length, 2) } async function createDownloadHarness({ result, responseHeaders, downloadError, openError, withHeadersListener = true } = {}) { let request let openRequest const uni = { getStorageSync(key) { assert.equal(key, 'token') return 'token-456' }, downloadFile(options) { request = options setImmediate(() => { if (downloadError) options.fail(downloadError) else options.success(result) }) if (!withHeadersListener) return {} return { onHeadersReceived(callback) { if (responseHeaders) callback({ header: responseHeaders }) } } } } const wx = { openDocument(options) { openRequest = options setImmediate(() => { if (openError) options.fail(openError) else options.success('opened') }) } } const transport = await loadTransport({ uni, wx }) return { request: () => request, openRequest: () => openRequest, promise: transport.downloadTeamBackgroundFile(12, 34) } } async function testDownloadTransport() { const successHarness = await createDownloadHarness({ result: { statusCode: 200, tempFilePath: '/tmp/download.pdf' }, responseHeaders: { 'cOnTeNt-TyPe': 'application/pdf', 'CONTENT-disPOSITION': 'attachment; filename="download.pdf"' } }) assert.equal(await successHarness.promise, 'opened') assert.equal(successHarness.request().url, 'https://api.example.test/app/core/user/team/12/background-files/34/download') assert.equal(successHarness.request().header.token, 'token-456') assert.equal(successHarness.openRequest().filePath, '/tmp/download.pdf') assert.equal(successHarness.openRequest().showMenu, true) assertNoIdentityFields(successHarness.request()) const resultHeaderHarness = await createDownloadHarness({ result: { statusCode: 200, tempFilePath: '/tmp/result-header.docx', header: { 'content-type': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'content-disposition': 'attachment; filename="result-header.docx"' } }, withHeadersListener: false }) assert.equal(await resultHeaderHarness.promise, 'opened') const resultHeadersHarness = await createDownloadHarness({ result: { statusCode: 200, tempFilePath: '/tmp/result-headers.txt', headers: { 'Content-Type': 'text/plain; charset=UTF-8', 'Content-Disposition': 'attachment; filename="result-headers.txt"' } }, withHeadersListener: false }) assert.equal(await resultHeadersHarness.promise, 'opened') const jsonHarness = await createDownloadHarness({ result: { statusCode: 200, tempFilePath: '/tmp/error.json' }, responseHeaders: { 'Content-Type': 'application/json;charset=UTF-8', 'Content-Disposition': 'attachment; filename="error.json"' } }) await assert.rejects(jsonHarness.promise, /下载失败,请重试/) assert.equal(jsonHarness.openRequest(), undefined) const htmlHarness = await createDownloadHarness({ result: { statusCode: 200, tempFilePath: '/tmp/error.html' }, responseHeaders: { 'content-type': 'text/html; charset=UTF-8' } }) await assert.rejects(htmlHarness.promise, /下载失败,请重试/) assert.equal(htmlHarness.openRequest(), undefined) const missingHeadersHarness = await createDownloadHarness({ result: { statusCode: 200, tempFilePath: '/tmp/unknown.pdf' }, withHeadersListener: false }) await assert.rejects(missingHeadersHarness.promise, /下载失败,请重试/) assert.equal(missingHeadersHarness.openRequest(), undefined) const statusHarness = await createDownloadHarness({ result: { statusCode: 500 } }) await assert.rejects(statusHarness.promise, /下载失败,请重试/) assert.equal(statusHarness.openRequest(), undefined) const downloadError = new Error('download network error') const downloadFailureHarness = await createDownloadHarness({ downloadError }) await assert.rejects(downloadFailureHarness.promise, /download network error/) const openError = new Error('open document error') const openFailureHarness = await createDownloadHarness({ result: { statusCode: 200, tempFilePath: '/tmp/download.pdf' }, responseHeaders: { 'Content-Type': 'application/pdf', 'Content-Disposition': 'attachment; filename="download.pdf"' }, openError }) await assert.rejects(openFailureHarness.promise, /open document error/) } async function main() { const loadedTransport = await loadTransport() assert.equal(typeof loadedTransport.downloadTeamBackgroundFile, 'function') await testUploadTransport() await testApiTransport() await testDownloadTransport() console.log('team background transport: PASS') } main().catch(error => { console.error(error) process.exitCode = 1 })