| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208 |
- import { describe, expect, it } from 'vitest'
- import { formatTableRowsToSQL, getTablePoliciesUrl } from './TableEntity.utils'
- import type { SupaTable } from '@/components/grid/types'
- import { ENTITY_TYPE } from '@/data/entity-types/entity-type-constants'
- describe('TableEntity.utils: formatTableRowsToSQL', () => {
- it('should format rows into a single SQL INSERT statement', () => {
- const table: SupaTable = {
- id: 1,
- type: ENTITY_TYPE.TABLE,
- columns: [
- { name: 'id', dataType: 'bigint', format: 'int8', position: 0 },
- { name: 'name', dataType: 'text', format: 'text', position: 1 },
- ],
- name: 'people',
- schema: 'public',
- comment: undefined,
- estimateRowCount: 1,
- }
- const rows = [
- { id: 1, name: 'Person 1' },
- { id: 2, name: 'Person 2' },
- { id: 3, name: 'Person 3' },
- ]
- const result = formatTableRowsToSQL(table, rows)
- const expected = `INSERT INTO "public"."people" ("id", "name") VALUES (1, 'Person 1'), (2, 'Person 2'), (3, 'Person 3');`
- expect(result).toBe(expected)
- })
- it('should not stringify null values', () => {
- const table: SupaTable = {
- id: 1,
- type: ENTITY_TYPE.TABLE,
- columns: [
- { name: 'id', dataType: 'bigint', format: 'int8', position: 0 },
- { name: 'name', dataType: 'text', format: 'text', position: 1 },
- ],
- name: 'people',
- schema: 'public',
- comment: undefined,
- estimateRowCount: 1,
- }
- const rows = [
- { id: 1, name: 'Person 1' },
- { id: 2, name: null },
- { id: 3, name: 'Person 3' },
- ]
- const result = formatTableRowsToSQL(table, rows)
- const expected = `INSERT INTO "public"."people" ("id", "name") VALUES (1, 'Person 1'), (2, null), (3, 'Person 3');`
- expect(result).toBe(expected)
- })
- it('should handle PG JSON and array columns', () => {
- const table: SupaTable = {
- id: 1,
- type: ENTITY_TYPE.TABLE,
- columns: [
- { name: 'id', dataType: 'bigint', format: 'int8', position: 0 },
- { name: 'name', dataType: 'text', format: 'text', position: 1 },
- { name: 'tags', dataType: 'ARRAY', format: '_text', position: 2 },
- { name: 'metadata', dataType: 'jsonb', format: 'jsonb', position: 3 },
- ],
- name: 'demo',
- schema: 'public',
- comment: undefined,
- estimateRowCount: 1,
- }
- const rows = [
- {
- idx: 1,
- id: 2,
- name: 'Person 1',
- tags: ['tag-a', 'tag-c'],
- metadata: '{"version": 1}',
- },
- {
- idx: 2,
- id: 3,
- name: 'ONeil',
- tags: ['tag-a'],
- metadata: `{"version": 1, "name": "O'Neil"}`,
- },
- ]
- const result = formatTableRowsToSQL(table, rows)
- const expected = `INSERT INTO "public"."demo" ("id", "name", "tags", "metadata") VALUES (2, 'Person 1', ARRAY['tag-a','tag-c'], '{"version": 1}'), (3, 'ONeil', ARRAY['tag-a'], '{"version": 1, "name": "O''Neil"}');`
- expect(result).toBe(expected)
- })
- it('should emit valid Postgres literals for booleans, numbers and text arrays', () => {
- const table: SupaTable = {
- id: 1,
- type: ENTITY_TYPE.TABLE,
- columns: [
- { name: 'id', dataType: 'text', format: 'text', position: 0 },
- { name: 'public', dataType: 'bool', format: 'bool', position: 1 },
- { name: 'avif_autodetection', dataType: 'bool', format: 'bool', position: 2 },
- { name: 'file_size_limit', dataType: 'int8', format: 'int8', position: 3 },
- { name: 'allowed_mime_types', dataType: 'ARRAY', format: '_text', position: 4 },
- ],
- name: 'buckets',
- schema: 'storage',
- comment: undefined,
- estimateRowCount: 1,
- }
- const rows = [
- {
- id: 'emails',
- public: true,
- avif_autodetection: false,
- file_size_limit: 10485760,
- allowed_mime_types: ['image/*', "image/o'neil"],
- },
- ]
- const result = formatTableRowsToSQL(table, rows)
- const expected = `INSERT INTO "storage"."buckets" ("id", "public", "avif_autodetection", "file_size_limit", "allowed_mime_types") VALUES ('emails', true, false, 10485760, ARRAY['image/*','image/o''neil']);`
- expect(result).toBe(expected)
- })
- it('should escape fallback string formats outside text and varchar', () => {
- const table: SupaTable = {
- id: 1,
- type: ENTITY_TYPE.TABLE,
- columns: [{ name: 'email', dataType: 'USER-DEFINED', format: 'citext', position: 0 }],
- name: 'users',
- schema: 'public',
- comment: undefined,
- estimateRowCount: 1,
- }
- const rows = [{ email: "o'neil@example.com" }]
- const result = formatTableRowsToSQL(table, rows)
- const expected = `INSERT INTO "public"."users" ("email") VALUES ('o''neil@example.com');`
- expect(result).toBe(expected)
- })
- it('should return an empty string for empty rows', () => {
- const table: SupaTable = {
- id: 1,
- type: ENTITY_TYPE.TABLE,
- columns: [
- { name: 'id', dataType: 'bigint', format: 'int8', position: 0 },
- { name: 'name', dataType: 'text', format: 'text', position: 1 },
- ],
- name: 'people',
- schema: 'public',
- comment: undefined,
- estimateRowCount: 1,
- }
- const result = formatTableRowsToSQL(table, [])
- expect(result).toBe('')
- })
- it('should remove the idx property', () => {
- const table: SupaTable = {
- id: 1,
- type: ENTITY_TYPE.TABLE,
- columns: [
- { name: 'id', dataType: 'bigint', format: 'int8', position: 0 },
- { name: 'name', dataType: 'text', format: 'text', position: 1 },
- ],
- name: 'people',
- schema: 'public',
- comment: undefined,
- estimateRowCount: 1,
- }
- const rows = [
- { idx: 0, id: 1, name: 'Person 1' },
- { idx: 1, id: 2, name: 'Person 2' },
- ]
- const result = formatTableRowsToSQL(table, rows)
- const expected = `INSERT INTO "public"."people" ("id", "name") VALUES (1, 'Person 1'), (2, 'Person 2');`
- expect(result).toBe(expected)
- })
- })
- describe('TableEntity.utils: getTablePoliciesUrl', () => {
- it('builds the policies url for plain schema and name values', () => {
- expect(getTablePoliciesUrl('abc', 'public', 'users')).toBe(
- '/project/abc/auth/policies?search=users&schema=public'
- )
- })
- it('preserves special characters in the table name', () => {
- const url = getTablePoliciesUrl('abc', 'public', 'user_data&secret=1')
- const parsed = new URL(url, 'http://example.com')
- expect(parsed.searchParams.get('search')).toBe('user_data&secret=1')
- expect(parsed.searchParams.get('schema')).toBe('public')
- })
- it('preserves special characters in the schema', () => {
- const url = getTablePoliciesUrl('abc', 'my schema+x', 'users')
- const parsed = new URL(url, 'http://example.com')
- expect(parsed.searchParams.get('schema')).toBe('my schema+x')
- expect(parsed.searchParams.get('search')).toBe('users')
- })
- it('encodes both the table name and schema together', () => {
- const url = getTablePoliciesUrl('abc', 'a&b=c', 'd e+f')
- const parsed = new URL(url, 'http://example.com')
- expect(parsed.searchParams.get('search')).toBe('d e+f')
- expect(parsed.searchParams.get('schema')).toBe('a&b=c')
- })
- })
|