Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions infra/dataform-service/src/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import functions from '@google-cloud/functions-framework'

import { BigQueryExport } from './bigquery.js'
import { callRunJob } from './cloud_run.js'
import * as cloud_run from './cloud_run.js'
import { getCompilationResults, runWorkflow } from './dataform.js'
import { StorageUpload } from './storage.js'

Expand Down Expand Up @@ -101,7 +101,7 @@ async function handleExport (req, res) {
} else if (destination === 'firestore') {
console.info('Firestore export')
const jobName = `projects/${projectId}/locations/${location}/jobs/${jobId}`
await callRunJob(jobName, payload)
await internals.callRunJob(jobName, payload)
} else {
throw new Error('Bad Request: destination unknown')
}
Expand Down Expand Up @@ -191,7 +191,7 @@ async function handleTrigger (req, res) {
async function executeAction (actionName, actionArgs) {
if (actionName === 'runDataformRepo') {
console.info(`Executing action: ${actionName}`)
await runDataformRepo(actionArgs)
await internals.runDataformRepo(actionArgs)
}
}

Expand Down Expand Up @@ -241,6 +241,13 @@ async function mainHandler (req, res) {
}
}

const internals = {
callRunJob: cloud_run.callRunJob,
runDataformRepo
}

export { internals, handleExport, mainHandler }

/**
* Main entry point for the combined Dataform service.
* Handles both trigger and export operations based on the request path.
Expand Down
134 changes: 134 additions & 0 deletions infra/dataform-service/src/index.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import test, { mock } from 'node:test'
import assert from 'node:assert'
import { internals, handleExport } from './index.js'

test('handleExport handles export job error', async () => {
const req = {
body: {
calls: [[{
destination: 'firestore',
config: {},
query: 'SELECT 1'
}]]
}
}

let statusCode = null
let responseData = null

const res = {
status: (code) => {
statusCode = code
return {
json: (data) => {
responseData = data
}
}
}
}

const expectedError = new Error('Mocked error')
mock.method(internals, 'callRunJob', async () => {
throw expectedError
})

await handleExport(req, res)

assert.strictEqual(statusCode, 400)
assert.deepStrictEqual(responseData.replies, [400])
assert.strictEqual(responseData.errorMessage, expectedError)

mock.restoreAll()
})

test('handleExport handles missing payload error', async () => {
const req = {
body: {
calls: [[null]]
}
}

let statusCode = null
let responseData = null

const res = {
status: (code) => {
statusCode = code
return {
json: (data) => {
responseData = data
}
}
}
}

await handleExport(req, res)

assert.strictEqual(statusCode, 400)
assert.deepStrictEqual(responseData.replies, [400])
assert.strictEqual(responseData.errorMessage, 'Bad Request: no payload received, expected JSON object')
})

test('handleExport handles missing required keys error', async () => {
const req = {
body: {
calls: [[{
destination: 'firestore'
// missing config and query
}]]
}
}

let statusCode = null
let responseData = null

const res = {
status: (code) => {
statusCode = code
return {
json: (data) => {
responseData = data
}
}
}
}

await handleExport(req, res)

assert.strictEqual(statusCode, 400)
assert.deepStrictEqual(responseData.replies, [400])
assert.strictEqual(responseData.errorMessage, 'Bad Request: unexpected payload structure, required keys: destination, config, query')
})

test('handleExport handles unknown destination error', async () => {
const req = {
body: {
calls: [[{
destination: 'unknown',
config: {},
query: 'SELECT 1'
}]]
}
}

let statusCode = null
let responseData = null

const res = {
status: (code) => {
statusCode = code
return {
json: (data) => {
responseData = data
}
}
}
}

await handleExport(req, res)

assert.strictEqual(statusCode, 400)
assert.deepStrictEqual(responseData.replies, [400])
assert.ok(responseData.errorMessage instanceof Error)
assert.strictEqual(responseData.errorMessage.message, 'Bad Request: destination unknown')
})
3 changes: 2 additions & 1 deletion infra/dataform-service/src/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"scripts": {
"start": "npx functions-framework --target=dataform-service --signature-type=http --port=${PORT:-8080}",
"start_dev": "npx functions-framework --target=dataform-service --signature-type=http --port=8080 --debug",
"build": "docker build -t dataform-service ."
"build": "docker build -t dataform-service .",
"test": "node --test"
},
"engines": {
"node": ">=22.0.0"
Expand Down
Loading
Loading