Spaces:
Sleeping
Sleeping
| import { afterEach, beforeAll, describe, expect, it } from 'vitest'; | |
| import { getDocsClient, getDriveClient } from '../../clients.js'; | |
| import * as GDocsHelpers from '../../googleDocsApiHelpers.js'; | |
| import { buildInsertTableWithDataRequests } from './insertTableWithData.js'; | |
| import { extractTableSnapshot } from './structureHelpers.js'; | |
| import { register as registerCloneTable } from './cloneTable.js'; | |
| import { hexToRgbColor } from '../../types.js'; | |
| const runLive = process.env.GOOGLE_DOCS_LIVE_TESTS === '1'; | |
| const liveDescribe = runLive ? describe : describe.skip; | |
| const mockLog = { | |
| info: () => {}, | |
| warn: () => {}, | |
| error: () => {}, | |
| }; | |
| let toolExecute: (args: any, context: any) => Promise<string>; | |
| const TABLE_FIELDS = | |
| 'body(content(startIndex,endIndex,table(rows,columns,tableStyle(tableColumnProperties(width,widthType)),tableRows(startIndex,endIndex,tableRowStyle(minRowHeight,preventOverflow,tableHeader),tableCells(startIndex,endIndex,tableCellStyle(backgroundColor,borderTop(color,width,dashStyle),borderBottom(color,width,dashStyle),borderLeft(color,width,dashStyle),borderRight(color,width,dashStyle),contentAlignment,paddingTop,paddingBottom,paddingLeft,paddingRight,rowSpan,columnSpan),content(paragraph(elements(startIndex,endIndex,textRun(content,textStyle(bold))))))))))'; | |
| liveDescribe('cloneTable live integration', () => { | |
| const createdDocumentIds: string[] = []; | |
| beforeAll(() => { | |
| const fakeServer = { addTool: (config: any) => (toolExecute = config.execute) }; | |
| registerCloneTable(fakeServer as any); | |
| }); | |
| afterEach(async () => { | |
| const drive = await getDriveClient(); | |
| while (createdDocumentIds.length > 0) { | |
| const fileId = createdDocumentIds.pop()!; | |
| try { | |
| await drive.files.delete({ fileId, supportsAllDrives: true }); | |
| } catch { | |
| // Best-effort cleanup only. | |
| } | |
| } | |
| }); | |
| it('clones a formatted table into a target document and preserves core formatting', async () => { | |
| const drive = await getDriveClient(); | |
| const docs = await getDocsClient(); | |
| const sourceDoc = await drive.files.create({ | |
| requestBody: { | |
| name: `cloneTable-source-${Date.now()}`, | |
| mimeType: 'application/vnd.google-apps.document', | |
| }, | |
| fields: 'id', | |
| supportsAllDrives: true, | |
| }); | |
| const targetDoc = await drive.files.create({ | |
| requestBody: { | |
| name: `cloneTable-target-${Date.now()}`, | |
| mimeType: 'application/vnd.google-apps.document', | |
| }, | |
| fields: 'id', | |
| supportsAllDrives: true, | |
| }); | |
| const sourceDocumentId = sourceDoc.data.id!; | |
| const targetDocumentId = targetDoc.data.id!; | |
| createdDocumentIds.push(sourceDocumentId, targetDocumentId); | |
| const sourceData = [ | |
| ['No.', '課題名'], | |
| ['1', 'SHIN-2870 調査'], | |
| ]; | |
| await GDocsHelpers.executeBatchUpdateWithSplitting( | |
| docs, | |
| sourceDocumentId, | |
| buildInsertTableWithDataRequests(sourceData, 1, true), | |
| mockLog | |
| ); | |
| const sourceTableStart = 2; | |
| const styleRequests = [ | |
| GDocsHelpers.buildTableColumnWidthRequest(sourceTableStart, [0], 60), | |
| GDocsHelpers.buildTableColumnWidthRequest(sourceTableStart, [1], 180), | |
| GDocsHelpers.buildPinTableHeaderRowsRequest(sourceTableStart, 1), | |
| GDocsHelpers.buildTableRowStyleRequest(sourceTableStart, [0], 24, true), | |
| ].filter(Boolean); | |
| const headerBg = hexToRgbColor('#D9E2F3')!; | |
| const headerCellStyle = GDocsHelpers.buildTableCellStyleRequest(sourceTableStart, 0, 0, { | |
| rowSpan: 1, | |
| columnSpan: 2, | |
| backgroundColor: headerBg, | |
| contentAlignment: 'CENTER', | |
| paddingTopPt: 6, | |
| paddingBottomPt: 6, | |
| }); | |
| if (headerCellStyle) styleRequests.push(headerCellStyle.request); | |
| await GDocsHelpers.executeBatchUpdateWithSplitting( | |
| docs, | |
| sourceDocumentId, | |
| styleRequests, | |
| mockLog | |
| ); | |
| await toolExecute( | |
| { | |
| documentId: targetDocumentId, | |
| sourceDocumentId, | |
| sourceTableId: 'table:body:0', | |
| index: 1, | |
| }, | |
| { log: mockLog } | |
| ); | |
| const targetRes = await docs.documents.get({ | |
| documentId: targetDocumentId, | |
| fields: TABLE_FIELDS, | |
| }); | |
| const snapshot = extractTableSnapshot(targetRes.data, 'table:body:0'); | |
| expect(snapshot).not.toBeNull(); | |
| expect(snapshot!.data).toEqual(sourceData); | |
| expect(snapshot!.pinnedHeaderRowsCount).toBe(1); | |
| expect(snapshot!.columnStyles).toEqual([ | |
| { columnIndex: 0, widthPt: 60, widthType: 'FIXED_WIDTH' }, | |
| { columnIndex: 1, widthPt: 180, widthType: 'FIXED_WIDTH' }, | |
| ]); | |
| expect(snapshot!.rowStyles[0]).toMatchObject({ | |
| rowIndex: 0, | |
| minRowHeightPt: 24, | |
| preventOverflow: true, | |
| tableHeader: true, | |
| }); | |
| expect(snapshot!.cellStyles[0]).toMatchObject({ | |
| rowIndex: 0, | |
| columnIndex: 0, | |
| contentAlignment: 'CENTER', | |
| paddingTopPt: 6, | |
| paddingBottomPt: 6, | |
| hasBoldText: true, | |
| }); | |
| }, 120000); | |
| }); | |