From 3b969686d39d2da818532073a9cb6ab3c0f828f5 Mon Sep 17 00:00:00 2001 From: FunamaYukina Date: Mon, 27 Jan 2025 20:56:10 +0900 Subject: [PATCH] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Add=20createParserTestCase?= =?UTF-8?q?s=20function=20and=20update=20parser=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .changeset/nice-starfishes-collect.md | 6 + .../src/parser/__tests__/testcase.ts | 69 +++---- .../src/parser/prisma/index.test.ts | 179 ++++++------------ .../db-structure/src/parser/prisma/parser.ts | 2 +- .../src/parser/schemarb/index.test.ts | 9 +- .../src/parser/sql/postgresql/index.test.ts | 37 +++- 6 files changed, 128 insertions(+), 174 deletions(-) create mode 100644 .changeset/nice-starfishes-collect.md diff --git a/.changeset/nice-starfishes-collect.md b/.changeset/nice-starfishes-collect.md new file mode 100644 index 000000000..b3175163d --- /dev/null +++ b/.changeset/nice-starfishes-collect.md @@ -0,0 +1,6 @@ +--- +"@liam-hq/db-structure": patch +"@liam-hq/cli": patch +--- + +♻️ Add createParserTestCases function and update parser tests diff --git a/frontend/packages/db-structure/src/parser/__tests__/testcase.ts b/frontend/packages/db-structure/src/parser/__tests__/testcase.ts index 74336a18f..d636be6f5 100644 --- a/frontend/packages/db-structure/src/parser/__tests__/testcase.ts +++ b/frontend/packages/db-structure/src/parser/__tests__/testcase.ts @@ -1,35 +1,13 @@ import { type Table, aColumn, - aDBStructure, - aTable, + type aDBStructure, anIndex, } from '../../schema/index.js' -const userTable = (override?: Partial) => - aDBStructure({ - tables: { - users: aTable({ - name: 'users', - columns: { - id: aColumn({ - name: 'id', - type: 'bigserial', - notNull: true, - primary: true, - unique: true, - }), - ...override?.columns, - }, - indices: { - ...override?.indices, - }, - comment: override?.comment ?? null, - }), - }, - }) - -export const parserTestCases = { +export const createParserTestCases = ( + userTable: (override?: Partial
) => ReturnType, +) => ({ 'table comment': userTable({ comment: 'store our users.', }), @@ -96,20 +74,21 @@ export const parserTestCases = { }), }, }), - 'index (unique: false)': userTable({ - columns: { - email: aColumn({ - name: 'email', - }), - }, - indices: { - index_users_on_id_and_email: anIndex({ - name: 'index_users_on_id_and_email', - unique: false, - columns: ['id', 'email'], - }), - }, - }), + 'index (unique: false)': (indexName: string) => + userTable({ + columns: { + email: aColumn({ + name: 'email', + }), + }, + indices: { + [indexName]: anIndex({ + name: indexName, + unique: false, + columns: ['id', 'email'], + }), + }, + }), 'index (unique: true)': userTable({ columns: { email: aColumn({ @@ -136,9 +115,9 @@ export const parserTestCases = { deleteConstraint: 'NO_ACTION', }, }), - 'foreign key (one-to-one)': { - users_id_to_posts_user_id: { - name: 'users_id_to_posts_user_id', + 'foreign key (one-to-one)': (name: string) => ({ + [name]: { + name, primaryTableName: 'users', primaryColumnName: 'id', foreignTableName: 'posts', @@ -147,7 +126,7 @@ export const parserTestCases = { updateConstraint: 'NO_ACTION', deleteConstraint: 'NO_ACTION', }, - }, + }), 'foreign key with action': { fk_posts_user_id: { name: 'fk_posts_user_id', @@ -160,4 +139,4 @@ export const parserTestCases = { deleteConstraint: 'CASCADE', }, }, -} +}) diff --git a/frontend/packages/db-structure/src/parser/prisma/index.test.ts b/frontend/packages/db-structure/src/parser/prisma/index.test.ts index 8198e5ba1..93f419b5a 100644 --- a/frontend/packages/db-structure/src/parser/prisma/index.test.ts +++ b/frontend/packages/db-structure/src/parser/prisma/index.test.ts @@ -1,6 +1,7 @@ import { describe, expect, it } from 'vitest' import type { Table } from '../../schema/index.js' import { aColumn, aDBStructure, aTable, anIndex } from '../../schema/index.js' +import { createParserTestCases } from '../__tests__/index.js' import { processor as _processor } from './index.js' describe(_processor, () => { @@ -12,11 +13,11 @@ describe(_processor, () => { columns: { id: aColumn({ name: 'id', - type: 'serial', + type: 'bigserial', default: 'autoincrement()', notNull: true, primary: true, - unique: false, + unique: true, }), ...override?.columns, }, @@ -46,11 +47,13 @@ describe(_processor, () => { const processor = async (schema: string) => _processor(`${prismaSchemaHeader}\n\n${schema}`) + const parserTestCases = createParserTestCases(userTable) + describe('should parse prisma schema correctly', () => { it('not null', async () => { const { value } = await processor(` model users { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) name String } `) @@ -71,50 +74,29 @@ describe(_processor, () => { it('nullable', async () => { const { value } = await processor(` model users { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) description String? } `) - const expected = userTable({ - columns: { - description: aColumn({ - name: 'description', - type: 'text', - notNull: false, - }), - }, - }) - - expect(value).toEqual(expected) + expect(value).toEqual(parserTestCases.nullable) }) it('default value as string', async () => { const { value } = await processor(` model users { - id Int @id @default(autoincrement()) - description String @default("user's description") + id BigInt @id @default(autoincrement()) + description String? @default("user's description") } `) - const expected = userTable({ - columns: { - description: aColumn({ - name: 'description', - type: 'text', - default: "user's description", - notNull: true, - }), - }, - }) - - expect(value).toEqual(expected) + expect(value).toEqual(parserTestCases['default value as string']) }) it('default value as integer', async () => { const { value } = await processor(` model users { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) age Int @default(30) } `) @@ -136,7 +118,7 @@ describe(_processor, () => { it('default value as boolean', async () => { const { value } = await processor(` model users { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) active Boolean @default(true) } `) @@ -158,84 +140,54 @@ describe(_processor, () => { it('column comment', async () => { const { value } = await processor(` model users { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) /// this is description description String? } `) - const expected = userTable({ - columns: { - description: aColumn({ - name: 'description', - type: 'text', - comment: 'this is description', - }), - }, - }) - - expect(value).toEqual(expected) + expect(value).toEqual(parserTestCases['column comment']) }) it('table comment', async () => { const { value } = await processor(` /// store our users. model users { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) } `) - const expected = userTable({ - comment: 'store our users.', - }) - - expect(value).toEqual(expected) + expect(value).toEqual(parserTestCases['table comment']) }) it('index (unique: false)', async () => { + const indexName = 'users_id_email_idx' const { value } = await processor(` model users { - id Int @id @default(autoincrement()) - email String + id BigInt @id @default(autoincrement()) + email String? @db.VarChar @@index([id, email]) } `) - - const expected = userTable({ - columns: { - email: aColumn({ - name: 'email', - type: 'text', - notNull: true, - }), - }, - indices: { - users_id_email_idx: anIndex({ - name: 'users_id_email_idx', - unique: false, - columns: ['id', 'email'], - }), - }, - }) - - expect(value).toEqual(expected) + expect(value).toEqual(parserTestCases['index (unique: false)'](indexName)) }) it('index (unique: true)', async () => { const { value } = await processor(` model users { - id Int @id @default(autoincrement()) - email String - @@unique([id, email]) + id BigInt @id @default(autoincrement()) + mention String? @unique + @@unique([id, mention]) } `) const expected = userTable({ columns: { - email: aColumn({ - name: 'email', + mention: aColumn({ + name: 'mention', type: 'text', - notNull: true, + notNull: false, + unique: true, }), }, indices: { @@ -244,10 +196,15 @@ describe(_processor, () => { unique: true, columns: ['id'], }), - users_id_email_key: anIndex({ - name: 'users_id_email_key', + users_id_mention_key: anIndex({ + name: 'users_id_mention_key', + unique: true, + columns: ['id', 'mention'], + }), + users_mention_key: anIndex({ + name: 'users_mention_key', unique: true, - columns: ['id', 'email'], + columns: ['mention'], }), }, }) @@ -256,63 +213,43 @@ describe(_processor, () => { }) it('relationship (one-to-many)', async () => { + const keyName = 'postsTousers' const { value } = await processor(` model users { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) posts posts[] } model posts { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) user users @relation(fields: [user_id], references: [id]) - user_id Int + user_id BigInt } `) - const expected = { - postsTousers: { - name: 'postsTousers', - primaryTableName: 'users', - primaryColumnName: 'id', - foreignTableName: 'posts', - foreignColumnName: 'user_id', - cardinality: 'ONE_TO_MANY', - updateConstraint: 'NO_ACTION', - deleteConstraint: 'NO_ACTION', - }, - } - - expect(value.relationships).toEqual(expected) + expect(value.relationships).toEqual( + parserTestCases['foreign key (one-to-many)'](keyName), + ) }) it('relationship (one-to-one)', async () => { + const keyName = 'postsTousers' const { value } = await processor(` model users { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) post posts? } model posts { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) user users @relation(fields: [user_id], references: [id]) - user_id Int @unique + user_id BigInt @unique } `) - const expected = { - postsTousers: { - name: 'postsTousers', - primaryTableName: 'users', - primaryColumnName: 'id', - foreignTableName: 'posts', - foreignColumnName: 'user_id', - cardinality: 'ONE_TO_ONE', - updateConstraint: 'NO_ACTION', - deleteConstraint: 'NO_ACTION', - }, - } - - expect(value.relationships).toEqual(expected) + expect(value.relationships).toEqual( + parserTestCases['foreign key (one-to-one)'](keyName), + ) }) describe('foreign key constraints (on delete)', () => { @@ -329,14 +266,14 @@ describe(_processor, () => { async (prismaAction: string, expectedAction: string) => { const { value } = await processor(` model users { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) posts posts[] } model posts { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) user users @relation(fields: [user_id], references: [id], onDelete: ${prismaAction}) - user_id Int + user_id BigInt } `) @@ -361,14 +298,14 @@ describe(_processor, () => { it('columns do not include model type', async () => { const { value } = await processor(` model users { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) posts posts[] } model posts { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) user users @relation(fields: [user_id], references: [id]) - user_id Int + user_id BigInt } `) @@ -396,7 +333,7 @@ describe(_processor, () => { it('unique', async () => { const { value } = await processor(` model users { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) email String @unique } `) @@ -425,7 +362,7 @@ describe(_processor, () => { it('not unique', async () => { const { value } = await processor(` model users { - id Int @id @default(autoincrement()) + id BigInt @id @default(autoincrement()) email String } `) diff --git a/frontend/packages/db-structure/src/parser/prisma/parser.ts b/frontend/packages/db-structure/src/parser/prisma/parser.ts index 69136ba77..dddf17577 100644 --- a/frontend/packages/db-structure/src/parser/prisma/parser.ts +++ b/frontend/packages/db-structure/src/parser/prisma/parser.ts @@ -34,7 +34,7 @@ async function parsePrismaSchema(schemaString: string): Promise { ), default: defaultValue, notNull: field.isRequired, - unique: field.isUnique, + unique: field.isId || field.isUnique, primary: field.isId, comment: field.documentation ?? null, check: null, diff --git a/frontend/packages/db-structure/src/parser/schemarb/index.test.ts b/frontend/packages/db-structure/src/parser/schemarb/index.test.ts index 9f3465f63..2b555a5d6 100644 --- a/frontend/packages/db-structure/src/parser/schemarb/index.test.ts +++ b/frontend/packages/db-structure/src/parser/schemarb/index.test.ts @@ -3,7 +3,7 @@ import type { Table } from '../../schema/index.js' import { aColumn, aDBStructure, aTable } from '../../schema/index.js' import { UnsupportedTokenError, processor } from './index.js' -import { parserTestCases } from '../__tests__/index.js' +import { createParserTestCases } from '../__tests__/index.js' describe(processor, () => { const userTable = (override?: Partial
) => @@ -28,6 +28,7 @@ describe(processor, () => { }), }, }) + const parserTestCases = createParserTestCases(userTable) describe('should parse create_table correctly', () => { it('table comment', async () => { @@ -188,6 +189,7 @@ describe(processor, () => { }) it('index (unique: false)', async () => { + const indexName = 'index_users_on_id_and_email' const { value } = await processor(/* Ruby */ ` create_table "users" do |t| t.string "email" @@ -195,7 +197,7 @@ describe(processor, () => { end `) - expect(value).toEqual(parserTestCases['index (unique: false)']) + expect(value).toEqual(parserTestCases['index (unique: false)'](indexName)) }) it('index (unique: true)', async () => { @@ -244,6 +246,7 @@ describe(processor, () => { }) it('foreign key (one-to-one)', async () => { + const keyName = 'users_id_to_posts_user_id' const { value } = await processor(/* Ruby */ ` create_table "posts" do |t| t.bigint "user_id", unique: true @@ -253,7 +256,7 @@ describe(processor, () => { `) expect(value.relationships).toEqual( - parserTestCases['foreign key (one-to-one)'], + parserTestCases['foreign key (one-to-one)'](keyName), ) }) diff --git a/frontend/packages/db-structure/src/parser/sql/postgresql/index.test.ts b/frontend/packages/db-structure/src/parser/sql/postgresql/index.test.ts index 4e06836b5..b92785e95 100644 --- a/frontend/packages/db-structure/src/parser/sql/postgresql/index.test.ts +++ b/frontend/packages/db-structure/src/parser/sql/postgresql/index.test.ts @@ -1,9 +1,35 @@ import { describe, expect, it } from 'vitest' -import { parserTestCases } from '../../__tests__/index.js' +import type { Table } from '../../../schema/index.js' +import { aColumn, aDBStructure, aTable } from '../../../schema/index.js' +import { createParserTestCases } from '../../__tests__/index.js' import { UnexpectedTokenWarningError } from '../../errors.js' import { processor } from './index.js' describe(processor, () => { + const userTable = (override?: Partial
) => + aDBStructure({ + tables: { + users: aTable({ + name: 'users', + columns: { + id: aColumn({ + name: 'id', + type: 'bigserial', + notNull: true, + primary: true, + unique: true, + }), + ...override?.columns, + }, + indices: { + ...override?.indices, + }, + comment: override?.comment ?? null, + }), + }, + }) + const parserTestCases = createParserTestCases(userTable) + describe('should parse CREATE TABLE statement correctly', () => { it('table comment', async () => { const { value } = await processor(/* sql */ ` @@ -95,6 +121,7 @@ describe(processor, () => { }) it('index (unique: false)', async () => { + const indexName = 'index_users_on_id_and_email' const { value } = await processor(/* sql */ ` CREATE TABLE users ( id BIGSERIAL PRIMARY KEY, @@ -104,7 +131,7 @@ describe(processor, () => { CREATE INDEX index_users_on_id_and_email ON public.users USING btree (id, email); `) - expect(value).toEqual(parserTestCases['index (unique: false)']) + expect(value).toEqual(parserTestCases['index (unique: false)'](indexName)) }) it('index (unique: true)', async () => { @@ -152,6 +179,7 @@ describe(processor, () => { }) it('foreign key (one-to-one)', async () => { + const keyName = 'users_id_to_posts_user_id' const { value } = await processor(/* sql */ ` CREATE TABLE posts ( id BIGSERIAL PRIMARY KEY, @@ -160,7 +188,7 @@ describe(processor, () => { `) expect(value.relationships).toEqual( - parserTestCases['foreign key (one-to-one)'], + parserTestCases['foreign key (one-to-one)'](keyName), ) }) }) @@ -179,6 +207,7 @@ describe(processor, () => { }) it('foreign key (one-to-one)', async () => { + const keyName = 'users_id_to_posts_user_id' const { value } = await processor(/* sql */ ` CREATE TABLE posts ( id SERIAL PRIMARY KEY, @@ -190,7 +219,7 @@ describe(processor, () => { `) expect(value.relationships).toEqual( - parserTestCases['foreign key (one-to-one)'], + parserTestCases['foreign key (one-to-one)'](keyName), ) })