undefined} size="lg" toggled />
+ )
+
+ expect(loader).toContain('class="spin"')
+ expect(loader).toContain('style="height: 18px; width: 18px"')
+ expect(toggle).toContain('h-7.5 w-12.5')
+ expect(toggle).toContain('translate-x-full')
+ })
+})
From a85df987d4bf675e7c9bff5476791b8817d8386e Mon Sep 17 00:00:00 2001
From: taherd <183945978+taherdhanera@users.noreply.github.com>
Date: Wed, 13 May 2026 23:34:01 +0530
Subject: [PATCH 3/5] test: cover input primitive states
---
.../interface/components/primitives.test.tsx | 35 +++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/plugins/interface/components/primitives.test.tsx b/plugins/interface/components/primitives.test.tsx
index d701376..12ec5fc 100644
--- a/plugins/interface/components/primitives.test.tsx
+++ b/plugins/interface/components/primitives.test.tsx
@@ -3,6 +3,7 @@ import { describe, expect, it } from 'vitest'
import { Avatar } from './avatar'
import { Card } from './card'
+import { Input } from './input/Input'
import { Label } from './label/Label'
import { Loader } from './loader/Loader'
import { Toggle } from './toggle'
@@ -95,4 +96,38 @@ describe('interface primitive components', () => {
expect(toggle).toContain('h-7.5 w-12.5')
expect(toggle).toContain('translate-x-full')
})
+
+ it('renders input wrappers with prefix, suffix, and invalid state', () => {
+ const wrapped = renderToString(
+ undefined}
+ placeholder="Filter"
+ preText="$"
+ postText="USD"
+ size="sm"
+ />
+ )
+ const plain = renderToString(
+ undefined}
+ size="lg"
+ />
+ )
+
+ expect(wrapped).toContain('$')
+ expect(wrapped).toContain('>USD')
+ expect(wrapped).toContain('placeholder="Filter"')
+ expect(wrapped).toContain('text-ob-destructive')
+
+ expect(plain).toContain('
Date: Thu, 14 May 2026 00:07:25 +0530
Subject: [PATCH 4/5] test: cover public package entrypoints
---
src/public-entrypoints.test.ts | 54 ++++++++++++++++++++++++++++++++++
1 file changed, 54 insertions(+)
create mode 100644 src/public-entrypoints.test.ts
diff --git a/src/public-entrypoints.test.ts b/src/public-entrypoints.test.ts
new file mode 100644
index 0000000..cdd5b46
--- /dev/null
+++ b/src/public-entrypoints.test.ts
@@ -0,0 +1,54 @@
+import { describe, expect, it, vi } from 'vitest'
+
+import { ChangeDataCapturePlugin } from '../plugins/cdc'
+import { ClerkPlugin } from '../plugins/clerk'
+import { QueryLogPlugin } from '../plugins/query-log'
+import { ResendPlugin } from '../plugins/resend'
+import { SqlMacrosPlugin } from '../plugins/sql-macros'
+import { StripeSubscriptionPlugin } from '../plugins/stripe'
+import { StudioPlugin } from '../plugins/studio'
+import { WebSocketPlugin } from '../plugins/websocket'
+import * as publicApi from '../dist'
+import * as pluginApi from '../dist/plugins'
+import { StarbaseDBDurableObject } from './do'
+import { StarbaseDB } from './handler'
+
+vi.mock('cloudflare:workers', () => {
+ return {
+ DurableObject: class MockDurableObject {},
+ }
+})
+
+describe('public package entrypoints', () => {
+ it('exposes runtime APIs from the root package export', () => {
+ expect(publicApi.StarbaseDB).toBe(StarbaseDB)
+ expect(publicApi.StarbaseDBDurableObject).toBe(StarbaseDBDurableObject)
+ expect(Object.keys(publicApi).sort()).toEqual([
+ 'StarbaseDB',
+ 'StarbaseDBDurableObject',
+ ])
+ })
+
+ it('exposes documented plugin constructors from the plugin export', () => {
+ expect(pluginApi.StudioPlugin).toBe(StudioPlugin)
+ expect(pluginApi.WebSocketPlugin).toBe(WebSocketPlugin)
+ expect(pluginApi.SqlMacrosPlugin).toBe(SqlMacrosPlugin)
+ expect(pluginApi.StripeSubscriptionPlugin).toBe(
+ StripeSubscriptionPlugin
+ )
+ expect(pluginApi.ChangeDataCapturePlugin).toBe(ChangeDataCapturePlugin)
+ expect(pluginApi.QueryLogPlugin).toBe(QueryLogPlugin)
+ expect(pluginApi.ResendPlugin).toBe(ResendPlugin)
+ expect(pluginApi.ClerkPlugin).toBe(ClerkPlugin)
+ expect(Object.keys(pluginApi).sort()).toEqual([
+ 'ChangeDataCapturePlugin',
+ 'ClerkPlugin',
+ 'QueryLogPlugin',
+ 'ResendPlugin',
+ 'SqlMacrosPlugin',
+ 'StripeSubscriptionPlugin',
+ 'StudioPlugin',
+ 'WebSocketPlugin',
+ ])
+ })
+})
From 52c842401e4ca4af10214e5de2d75a9a02dce1fa Mon Sep 17 00:00:00 2001
From: taherd <183945978+taherdhanera@users.noreply.github.com>
Date: Thu, 14 May 2026 14:54:42 +0530
Subject: [PATCH 5/5] test: cover JSON import validation paths
---
src/import/json.test.ts | 139 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 139 insertions(+)
diff --git a/src/import/json.test.ts b/src/import/json.test.ts
index 04b4ed1..053dcf6 100644
--- a/src/import/json.test.ts
+++ b/src/import/json.test.ts
@@ -83,6 +83,38 @@ describe('JSON Import Module', () => {
expect(jsonResponse.error).toContain('Invalid JSON format')
})
+ it.each([
+ ['missing data', {}],
+ ['null data', { data: null }],
+ ['object data', { data: { id: 1, name: 'Alice' } }],
+ ])(
+ 'should return 400 without inserts for application/json with %s',
+ async (_caseName, payload) => {
+ const request = new Request('http://localhost', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(payload),
+ })
+
+ const response = await importTableFromJsonRoute(
+ 'users',
+ request,
+ mockDataSource,
+ mockConfig
+ )
+
+ expect(response.status).toBe(400)
+ expect(executeOperation).not.toHaveBeenCalled()
+ const jsonResponse = (await response.json()) as {
+ error?: string
+ result?: any
+ }
+ expect(jsonResponse.error).toBe(
+ 'Invalid JSON format. Expected an object with "data" array and optional "columnMapping".'
+ )
+ }
+ )
+
it('should return 400 if no file is uploaded in multipart form-data', async () => {
const formData = new FormData()
@@ -106,6 +138,36 @@ describe('JSON Import Module', () => {
expect(jsonResponse.error).toBe('No file uploaded')
})
+ it('should return 400 if uploaded JSON file is invalid', async () => {
+ const formData = new FormData()
+ formData.set(
+ 'file',
+ new File(['not json'], 'users.json', {
+ type: 'application/json',
+ })
+ )
+
+ const request = new Request('http://localhost', {
+ method: 'POST',
+ body: formData,
+ })
+
+ const response = await importTableFromJsonRoute(
+ 'users',
+ request,
+ mockDataSource,
+ mockConfig
+ )
+
+ expect(response.status).toBe(400)
+ expect(executeOperation).not.toHaveBeenCalled()
+ const jsonResponse = (await response.json()) as {
+ error?: string
+ result?: any
+ }
+ expect(jsonResponse.error).toBe('Invalid file upload')
+ })
+
it('should successfully insert valid JSON data into the table', async () => {
vi.mocked(executeOperation).mockResolvedValue([])
@@ -136,6 +198,83 @@ describe('JSON Import Module', () => {
)
})
+ it('should apply column mapping when inserting JSON records', async () => {
+ vi.mocked(executeOperation).mockResolvedValue([])
+
+ const request = new Request('http://localhost', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ data: [{ fullName: 'Alice', emailAddress: 'alice@test.dev' }],
+ columnMapping: {
+ fullName: 'name',
+ emailAddress: 'email',
+ },
+ }),
+ })
+
+ const response = await importTableFromJsonRoute(
+ 'users',
+ request,
+ mockDataSource,
+ mockConfig
+ )
+
+ expect(response.status).toBe(200)
+ expect(executeOperation).toHaveBeenCalledWith(
+ [
+ {
+ sql: 'INSERT INTO users (name, email) VALUES (?, ?)',
+ params: ['Alice', 'alice@test.dev'],
+ },
+ ],
+ mockDataSource,
+ mockConfig
+ )
+ })
+
+ it('should insert valid JSON data from multipart file upload', async () => {
+ vi.mocked(executeOperation).mockResolvedValue([])
+
+ const formData = new FormData()
+ formData.set(
+ 'file',
+ new File(
+ [
+ JSON.stringify({
+ data: [{ id: 1, name: 'Alice' }],
+ }),
+ ],
+ 'users.json',
+ { type: 'application/json' }
+ )
+ )
+
+ const request = new Request('http://localhost', {
+ method: 'POST',
+ body: formData,
+ })
+
+ const response = await importTableFromJsonRoute(
+ 'users',
+ request,
+ mockDataSource,
+ mockConfig
+ )
+
+ expect(response.status).toBe(200)
+ expect(executeOperation).toHaveBeenCalledWith(
+ [
+ {
+ sql: 'INSERT INTO users (id, name) VALUES (?, ?)',
+ params: [1, 'Alice'],
+ },
+ ],
+ mockDataSource,
+ mockConfig
+ )
+ })
+
it('should return partial success if some inserts fail', async () => {
vi.mocked(executeOperation)
.mockResolvedValueOnce([])