UNPKG

@dhlab/e2e-autogen

Version:

Google 스프레드시트 기반 시나리오를 Playwright 테스트 스텁 코드로 자동 생성하고, 테스트 실행 결과를 다시 시트에 업데이트하는 CLI 도구

242 lines (240 loc) 12.4 kB
'use strict'; var _SpreadsheetSheet_instances, _SpreadsheetSheet_gid, _SpreadsheetSheet_cachedSheetName, _SpreadsheetSheet_cachedColumnCount, _SpreadsheetSheet_rawSheets, _SpreadsheetSheet_dataRange, _SpreadsheetSheet_ensureColumnExists, _SpreadsheetSheet_columnCount, _SpreadsheetSheet_numberToColumnLetter, _SpreadsheetSheet_columnLetterToNumber; Object.defineProperty(exports, "__esModule", { value: true }); exports.SpreadsheetSheet = void 0; const tslib_1 = require("tslib"); class SpreadsheetSheet { constructor(spreadsheetId, gid, sheets, rawSheets) { _SpreadsheetSheet_instances.add(this); _SpreadsheetSheet_gid.set(this, void 0); _SpreadsheetSheet_cachedSheetName.set(this, null); _SpreadsheetSheet_cachedColumnCount.set(this, null); _SpreadsheetSheet_rawSheets.set(this, void 0); this.spreadsheetId = spreadsheetId; tslib_1.__classPrivateFieldSet(this, _SpreadsheetSheet_gid, gid, "f"); this.sheets = sheets; tslib_1.__classPrivateFieldSet(this, _SpreadsheetSheet_rawSheets, rawSheets || null, "f"); } get gid() { return tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_gid, "f"); } async rows() { const sheetName = await this.sheetName(); const res = await this.sheets.spreadsheets.values.get({ spreadsheetId: this.spreadsheetId, range: `'${sheetName}'`, }); return res.data.values ?? []; } /** * 지정된 셀에 comment를 추가합니다. * @param row 행 번호 (1-based) * @param col 열 번호 (1-based) * @param comment 추가할 comment 내용 */ async addComment(row, col, comment) { if (!comment.trim()) return; const sheetName = await this.sheetName(); const columnLetter = tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_instances, "m", _SpreadsheetSheet_numberToColumnLetter).call(this, col); const range = `'${sheetName}'!${columnLetter}${row}`; try { await this.sheets.spreadsheets.batchUpdate({ spreadsheetId: this.spreadsheetId, requestBody: { requests: [ { updateCells: { range: { sheetId: parseInt(tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_gid, "f")), startRowIndex: row - 1, endRowIndex: row, startColumnIndex: col - 1, endColumnIndex: col, }, rows: [ { values: [ { note: comment, }, ], }, ], fields: "note", }, }, ], }, }); } catch (error) { console.warn(`⚠️ Failed to add comment to ${range}: ${error}`); } } /** * values를 마지막 컬럼 다음에 세로 방향으로 추가한다. * @param values 추가할 데이터 * @param startRow 데이터가 시작되는 row (default: 1) */ async writeAfterLastColumn(values, startRow = 1) { if (values.length === 0) { console.warn("⚠️ 작성할 데이터가 없습니다. writeAfterLastColumn 스킵"); return; } const { nextColumnLetter: targetColumnLetter, lastRow } = await tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_instances, "m", _SpreadsheetSheet_dataRange).call(this); // 시트 컬럼 수가 부족하면 확장 const targetColumnNum = tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_instances, "m", _SpreadsheetSheet_columnLetterToNumber).call(this, targetColumnLetter); await tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_instances, "m", _SpreadsheetSheet_ensureColumnExists).call(this, targetColumnNum); const sheetName = await this.sheetName(); // 시트에 이미 존재하는 데이터 행 수 const existingDataRows = Math.max(0, lastRow - (startRow - 1)); const totalRows = Math.max(existingDataRows, values.length); // 부족한 행은 빈 셀로 패딩 const padded = values.map((v) => [...v]); while (padded.length < totalRows) padded.push([""]); const endRow = startRow + padded.length - 1; const range = `'${sheetName}'!${targetColumnLetter}${startRow}:${targetColumnLetter}${endRow}`; await this.sheets.spreadsheets.values.update({ spreadsheetId: this.spreadsheetId, range, valueInputOption: "RAW", requestBody: { values: padded }, }); console.log(`✅ ${values.length} rows written → ${range}`); } /** * values 를 마지막 행 다음(A열 기준) 에 가로 방향으로 추가한다. * @param values 추가할 데이터 */ async writeAfterLastRow(values) { if (values.length === 0) { console.warn("⚠️ 작성할 데이터가 없습니다. writeAfterLastRow 스킵"); return; } const sheetName = await this.sheetName(); const { lastRow } = await tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_instances, "m", _SpreadsheetSheet_dataRange).call(this); const startRow = lastRow + 1; const columnCount = Math.max(...values.map((v) => v.length)); const endColumnLetter = tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_instances, "m", _SpreadsheetSheet_numberToColumnLetter).call(this, columnCount); const range = `'${sheetName}'!A${startRow}:${endColumnLetter}${startRow + values.length - 1}`; await this.sheets.spreadsheets.values.update({ spreadsheetId: this.spreadsheetId, range, valueInputOption: "RAW", requestBody: { values: values }, }); } async applyStyle(requests) { if (!requests || requests.length === 0) return; await this.sheets.spreadsheets.batchUpdate({ spreadsheetId: this.spreadsheetId, requestBody: { requests }, }); } /** * gid를 이용해 시트 이름을 조회한다. */ async sheetName() { if (tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_cachedSheetName, "f")) { return tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_cachedSheetName, "f"); } if (tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_rawSheets, "f")) { const sheetsData = await tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_rawSheets, "f").call(this); const targetSheet = sheetsData.find((sheet) => String(sheet.properties?.sheetId) === tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_gid, "f")); if (targetSheet?.properties?.title) { tslib_1.__classPrivateFieldSet(this, _SpreadsheetSheet_cachedSheetName, targetSheet.properties.title, "f"); return tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_cachedSheetName, "f"); } } try { const response = await this.sheets.spreadsheets.get({ spreadsheetId: this.spreadsheetId, }); const targetSheet = response.data.sheets?.find((sheet) => String(sheet.properties?.sheetId) === tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_gid, "f")); const name = targetSheet?.properties?.title; if (!name) throw new Error(`gid(${tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_gid, "f")})에 해당하는 시트를 찾지 못했습니다.`); tslib_1.__classPrivateFieldSet(this, _SpreadsheetSheet_cachedSheetName, name, "f"); return name; } catch (error) { throw new Error(`시트 이름 조회 실패: ${error}`); } } invalidateCache() { tslib_1.__classPrivateFieldSet(this, _SpreadsheetSheet_cachedSheetName, null, "f"); tslib_1.__classPrivateFieldSet(this, _SpreadsheetSheet_cachedColumnCount, null, "f"); } } exports.SpreadsheetSheet = SpreadsheetSheet; _SpreadsheetSheet_gid = new WeakMap(), _SpreadsheetSheet_cachedSheetName = new WeakMap(), _SpreadsheetSheet_cachedColumnCount = new WeakMap(), _SpreadsheetSheet_rawSheets = new WeakMap(), _SpreadsheetSheet_instances = new WeakSet(), _SpreadsheetSheet_dataRange = /** * 시트의 데이터 범위를 감지한다. */ async function _SpreadsheetSheet_dataRange() { const rows = await this.rows(); const lastColumnNum = Math.max(1, ...rows.map((row) => row.length)); const lastRow = rows.length; const lastColumnLetter = tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_instances, "m", _SpreadsheetSheet_numberToColumnLetter).call(this, lastColumnNum); const nextColumnLetter = tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_instances, "m", _SpreadsheetSheet_numberToColumnLetter).call(this, lastColumnNum + 1); return { lastRow, lastColumnLetter, nextColumnLetter, }; }, _SpreadsheetSheet_ensureColumnExists = async function _SpreadsheetSheet_ensureColumnExists(columnNumber) { const columnCount = await tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_instances, "m", _SpreadsheetSheet_columnCount).call(this); if (columnCount >= columnNumber) return; const append = { appendDimension: { sheetId: Number(tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_gid, "f")), dimension: "COLUMNS", length: columnNumber - columnCount, }, }; await this.sheets.spreadsheets.batchUpdate({ spreadsheetId: this.spreadsheetId, requestBody: { requests: [append] }, }); this.invalidateCache(); console.log(`📐 시트 컬럼 확장: ${columnCount} → ${columnNumber}`); }, _SpreadsheetSheet_columnCount = async function _SpreadsheetSheet_columnCount() { if (tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_cachedColumnCount, "f") !== null) { return tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_cachedColumnCount, "f"); } if (tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_rawSheets, "f")) { const sheetsData = await tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_rawSheets, "f").call(this); const targetSheet = sheetsData.find((sheet) => String(sheet.properties?.sheetId) === tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_gid, "f")); const columnCount = targetSheet?.properties?.gridProperties?.columnCount; if (columnCount !== undefined && columnCount !== null) { tslib_1.__classPrivateFieldSet(this, _SpreadsheetSheet_cachedColumnCount, columnCount, "f"); return columnCount; } } const response = await this.sheets.spreadsheets.get({ spreadsheetId: this.spreadsheetId, includeGridData: false, }); const targetSheet = response.data.sheets?.find((sheet) => String(sheet.properties?.sheetId) === tslib_1.__classPrivateFieldGet(this, _SpreadsheetSheet_gid, "f")); const columnCount = targetSheet?.properties?.gridProperties?.columnCount ?? 0; tslib_1.__classPrivateFieldSet(this, _SpreadsheetSheet_cachedColumnCount, columnCount, "f"); return columnCount; }, _SpreadsheetSheet_numberToColumnLetter = function _SpreadsheetSheet_numberToColumnLetter(num) { let result = ""; while (num > 0) { num--; result = String.fromCharCode(65 + (num % 26)) + result; num = Math.floor(num / 26); } return result; }, _SpreadsheetSheet_columnLetterToNumber = function _SpreadsheetSheet_columnLetterToNumber(columnLetter) { let result = 0; for (let i = 0; i < columnLetter.length; i++) { result = result * 26 + (columnLetter.charCodeAt(i) - 64); } return result; };