Docs to Google Sheets mock.
This commit is contained in:
parent
1bc84c1633
commit
1c5b50773f
|
@ -2,7 +2,10 @@ import { Datasource } from "@budibase/types"
|
||||||
import nock from "nock"
|
import nock from "nock"
|
||||||
import { GoogleSheetsConfig } from "../../googlesheets"
|
import { GoogleSheetsConfig } from "../../googlesheets"
|
||||||
|
|
||||||
|
// https://protobuf.dev/reference/protobuf/google.protobuf/#value
|
||||||
type Value = string | number | boolean
|
type Value = string | number | boolean
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/Dimension
|
||||||
type Dimension = "ROWS" | "COLUMNS"
|
type Dimension = "ROWS" | "COLUMNS"
|
||||||
|
|
||||||
interface Range {
|
interface Range {
|
||||||
|
@ -18,12 +21,14 @@ interface DimensionProperties {
|
||||||
// dataSourceColumnReference: DataSourceColumnReference
|
// dataSourceColumnReference: DataSourceColumnReference
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values#ValueRange
|
||||||
interface ValueRange {
|
interface ValueRange {
|
||||||
range: string
|
range: string
|
||||||
majorDimension: Dimension
|
majorDimension: Dimension
|
||||||
values: Value[][]
|
values: Value[][]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/UpdateValuesResponse
|
||||||
interface UpdateValuesResponse {
|
interface UpdateValuesResponse {
|
||||||
spreadsheetId: string
|
spreadsheetId: string
|
||||||
updatedRange: string
|
updatedRange: string
|
||||||
|
@ -33,6 +38,7 @@ interface UpdateValuesResponse {
|
||||||
updatedData: ValueRange
|
updatedData: ValueRange
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/response#AddSheetResponse
|
||||||
interface AddSheetResponse {
|
interface AddSheetResponse {
|
||||||
properties: SheetProperties
|
properties: SheetProperties
|
||||||
}
|
}
|
||||||
|
@ -41,12 +47,14 @@ interface Response {
|
||||||
addSheet?: AddSheetResponse
|
addSheet?: AddSheetResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/response
|
||||||
interface BatchUpdateResponse {
|
interface BatchUpdateResponse {
|
||||||
spreadsheetId: string
|
spreadsheetId: string
|
||||||
replies: Response[]
|
replies: Response[]
|
||||||
updatedSpreadsheet: Spreadsheet
|
updatedSpreadsheet: Spreadsheet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/sheets#GridProperties
|
||||||
interface GridProperties {
|
interface GridProperties {
|
||||||
rowCount: number
|
rowCount: number
|
||||||
columnCount: number
|
columnCount: number
|
||||||
|
@ -57,12 +65,14 @@ interface GridProperties {
|
||||||
columnGroupControlAfter: boolean
|
columnGroupControlAfter: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/sheets#SheetProperties
|
||||||
interface SheetProperties {
|
interface SheetProperties {
|
||||||
sheetId: number
|
sheetId: number
|
||||||
title: string
|
title: string
|
||||||
gridProperties: GridProperties
|
gridProperties: GridProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request#AddSheetRequest
|
||||||
interface AddSheetRequest {
|
interface AddSheetRequest {
|
||||||
properties: SheetProperties
|
properties: SheetProperties
|
||||||
}
|
}
|
||||||
|
@ -71,6 +81,7 @@ interface Request {
|
||||||
addSheet?: AddSheetRequest
|
addSheet?: AddSheetRequest
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request
|
||||||
interface BatchUpdateRequest {
|
interface BatchUpdateRequest {
|
||||||
requests: Request[]
|
requests: Request[]
|
||||||
includeSpreadsheetInResponse: boolean
|
includeSpreadsheetInResponse: boolean
|
||||||
|
@ -78,11 +89,13 @@ interface BatchUpdateRequest {
|
||||||
responseIncludeGridData: boolean
|
responseIncludeGridData: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/other#ErrorValue
|
||||||
interface ErrorValue {
|
interface ErrorValue {
|
||||||
type: string
|
type: string
|
||||||
message: string
|
message: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/other#ExtendedValue
|
||||||
interface ExtendedValue {
|
interface ExtendedValue {
|
||||||
stringValue?: string
|
stringValue?: string
|
||||||
numberValue?: number
|
numberValue?: number
|
||||||
|
@ -91,14 +104,17 @@ interface ExtendedValue {
|
||||||
errorValue?: ErrorValue
|
errorValue?: ErrorValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/cells#CellData
|
||||||
interface CellData {
|
interface CellData {
|
||||||
userEnteredValue: ExtendedValue
|
userEnteredValue: ExtendedValue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/sheets#RowData
|
||||||
interface RowData {
|
interface RowData {
|
||||||
values: CellData[]
|
values: CellData[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/sheets#GridData
|
||||||
interface GridData {
|
interface GridData {
|
||||||
startRow: number
|
startRow: number
|
||||||
startColumn: number
|
startColumn: number
|
||||||
|
@ -107,21 +123,61 @@ interface GridData {
|
||||||
columnMetadata: DimensionProperties[]
|
columnMetadata: DimensionProperties[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/sheets#Sheet
|
||||||
interface Sheet {
|
interface Sheet {
|
||||||
properties: SheetProperties
|
properties: SheetProperties
|
||||||
data: GridData[]
|
data: GridData[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets#SpreadsheetProperties
|
||||||
interface SpreadsheetProperties {
|
interface SpreadsheetProperties {
|
||||||
title: string
|
title: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets#Spreadsheet
|
||||||
interface Spreadsheet {
|
interface Spreadsheet {
|
||||||
properties: SpreadsheetProperties
|
properties: SpreadsheetProperties
|
||||||
spreadsheetId: string
|
spreadsheetId: string
|
||||||
sheets: Sheet[]
|
sheets: Sheet[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/ValueInputOption
|
||||||
|
type ValueInputOption =
|
||||||
|
| "USER_ENTERED"
|
||||||
|
| "RAW"
|
||||||
|
| "INPUT_VALUE_OPTION_UNSPECIFIED"
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/append#InsertDataOption
|
||||||
|
type InsertDataOption = "OVERWRITE" | "INSERT_ROWS"
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/ValueRenderOption
|
||||||
|
type ValueRenderOption = "FORMATTED_VALUE" | "UNFORMATTED_VALUE" | "FORMULA"
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/DateTimeRenderOption
|
||||||
|
type DateTimeRenderOption = "SERIAL_NUMBER" | "FORMATTED_STRING"
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/append#query-parameters
|
||||||
|
interface AppendParams {
|
||||||
|
valueInputOption?: ValueInputOption
|
||||||
|
insertDataOption?: InsertDataOption
|
||||||
|
includeValuesInResponse?: boolean
|
||||||
|
responseValueRenderOption?: ValueRenderOption
|
||||||
|
responseDateTimeRenderOption?: DateTimeRenderOption
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AppendRequest {
|
||||||
|
range: string
|
||||||
|
params: AppendParams
|
||||||
|
body: ValueRange
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/append#response-body
|
||||||
|
interface AppendResponse {
|
||||||
|
spreadsheetId: string
|
||||||
|
tableRange: string
|
||||||
|
updates: UpdateValuesResponse
|
||||||
|
}
|
||||||
|
|
||||||
export class GoogleSheetsMock {
|
export class GoogleSheetsMock {
|
||||||
private config: GoogleSheetsConfig
|
private config: GoogleSheetsConfig
|
||||||
private spreadsheet: Spreadsheet
|
private spreadsheet: Spreadsheet
|
||||||
|
@ -141,7 +197,38 @@ export class GoogleSheetsMock {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
private route(
|
||||||
|
method: "get" | "put" | "post",
|
||||||
|
path: string | RegExp,
|
||||||
|
handler: (uri: string, request: nock.Body) => nock.Body
|
||||||
|
): nock.Scope {
|
||||||
|
const headers = { reqheaders: { authorization: "Bearer test" } }
|
||||||
|
const scope = nock("https://sheets.googleapis.com/", headers)
|
||||||
|
return scope[method](path).reply(200, handler).persist()
|
||||||
|
}
|
||||||
|
|
||||||
|
private get(
|
||||||
|
path: string | RegExp,
|
||||||
|
handler: (uri: string, request: nock.Body) => nock.Body
|
||||||
|
): nock.Scope {
|
||||||
|
return this.route("get", path, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
private put(
|
||||||
|
path: string | RegExp,
|
||||||
|
handler: (uri: string, request: nock.Body) => nock.Body
|
||||||
|
): nock.Scope {
|
||||||
|
return this.route("put", path, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
private post(
|
||||||
|
path: string | RegExp,
|
||||||
|
handler: (uri: string, request: nock.Body) => nock.Body
|
||||||
|
): nock.Scope {
|
||||||
|
return this.route("post", path, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
private mockAuth() {
|
||||||
nock("https://www.googleapis.com/")
|
nock("https://www.googleapis.com/")
|
||||||
.post("/oauth2/v4/token")
|
.post("/oauth2/v4/token")
|
||||||
.reply(200, {
|
.reply(200, {
|
||||||
|
@ -164,50 +251,72 @@ export class GoogleSheetsMock {
|
||||||
scopes: "https://www.googleapis.com/auth/spreadsheets",
|
scopes: "https://www.googleapis.com/auth/spreadsheets",
|
||||||
})
|
})
|
||||||
.persist()
|
.persist()
|
||||||
|
}
|
||||||
|
|
||||||
nock("https://sheets.googleapis.com/", {
|
init() {
|
||||||
reqheaders: { authorization: "Bearer test" },
|
this.mockAuth()
|
||||||
})
|
|
||||||
.get(`/v4/spreadsheets/${this.config.spreadsheetId}/`)
|
|
||||||
.reply(200, () => this.handleGetSpreadsheet())
|
|
||||||
.persist()
|
|
||||||
|
|
||||||
nock("https://sheets.googleapis.com/", {
|
this.get(`/v4/spreadsheets/${this.config.spreadsheetId}/`, () =>
|
||||||
reqheaders: { authorization: "Bearer test" },
|
this.handleGetSpreadsheet()
|
||||||
})
|
)
|
||||||
.post(`/v4/spreadsheets/${this.config.spreadsheetId}/:batchUpdate`)
|
|
||||||
.reply(200, (_uri, request) =>
|
|
||||||
this.handleBatchUpdate(request as BatchUpdateRequest)
|
|
||||||
)
|
|
||||||
.persist()
|
|
||||||
|
|
||||||
nock("https://sheets.googleapis.com/", {
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/batchUpdate
|
||||||
reqheaders: { authorization: "Bearer test" },
|
this.post(
|
||||||
})
|
`/v4/spreadsheets/${this.config.spreadsheetId}/:batchUpdate`,
|
||||||
.put(
|
(_uri, request) => this.handleBatchUpdate(request as BatchUpdateRequest)
|
||||||
new RegExp(`/v4/spreadsheets/${this.config.spreadsheetId}/values/.*`)
|
)
|
||||||
)
|
|
||||||
.reply(200, (_uri, request) =>
|
|
||||||
this.handleValueUpdate(request as ValueRange)
|
|
||||||
)
|
|
||||||
.persist()
|
|
||||||
|
|
||||||
nock("https://sheets.googleapis.com/", {
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/update
|
||||||
reqheaders: { authorization: "Bearer test" },
|
this.put(
|
||||||
})
|
new RegExp(`/v4/spreadsheets/${this.config.spreadsheetId}/values/.*`),
|
||||||
.get(
|
(_uri, request) => this.handleValueUpdate(request as ValueRange)
|
||||||
new RegExp(`/v4/spreadsheets/${this.config.spreadsheetId}/values/.*`)
|
)
|
||||||
)
|
|
||||||
.reply(200, uri => {
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/get
|
||||||
|
this.get(
|
||||||
|
new RegExp(`/v4/spreadsheets/${this.config.spreadsheetId}/values/.*`),
|
||||||
|
uri => {
|
||||||
const range = uri.split("/").pop()
|
const range = uri.split("/").pop()
|
||||||
if (!range) {
|
if (!range) {
|
||||||
throw new Error("No range provided")
|
throw new Error("No range provided")
|
||||||
}
|
}
|
||||||
return this.handleGetValues(decodeURIComponent(range))
|
return this.handleGetValues(decodeURIComponent(range))
|
||||||
})
|
}
|
||||||
.persist()
|
)
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets.values/append
|
||||||
|
this.post(
|
||||||
|
new RegExp(
|
||||||
|
`/v4/spreadsheets/${this.config.spreadsheetId}/values/.*:append`
|
||||||
|
),
|
||||||
|
(_uri, request) => {
|
||||||
|
const url = new URL(_uri, "https://sheets.googleapis.com/")
|
||||||
|
const params: Record<string, any> = Object.fromEntries(
|
||||||
|
url.searchParams.entries()
|
||||||
|
)
|
||||||
|
|
||||||
|
if (params.includeValuesInResponse === "true") {
|
||||||
|
params.includeValuesInResponse = true
|
||||||
|
} else {
|
||||||
|
params.includeValuesInResponse = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const range = url.pathname.split("/").pop()
|
||||||
|
if (!range) {
|
||||||
|
throw new Error("No range provided")
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.handleValueAppend({
|
||||||
|
range,
|
||||||
|
params,
|
||||||
|
body: request as ValueRange,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private handleValueAppend(request: AppendRequest): AppendResponse {}
|
||||||
|
|
||||||
private handleGetValues(range: string): ValueRange {
|
private handleGetValues(range: string): ValueRange {
|
||||||
const { sheet, topLeft, bottomRight } = this.parseA1Notation(range)
|
const { sheet, topLeft, bottomRight } = this.parseA1Notation(range)
|
||||||
const valueRange: ValueRange = {
|
const valueRange: ValueRange = {
|
||||||
|
@ -415,6 +524,7 @@ export class GoogleSheetsMock {
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://developers.google.com/sheets/api/guides/concepts#cell
|
||||||
private parseA1Notation(range: string): {
|
private parseA1Notation(range: string): {
|
||||||
sheet: Sheet
|
sheet: Sheet
|
||||||
topLeft: Range
|
topLeft: Range
|
||||||
|
|
Loading…
Reference in New Issue