sqlserver.test.ts•13.4 kB
import path from 'path'
import { DbPull } from '../../commands/DbPull'
import { setupMSSQL, tearDownMSSQL } from '../../utils/setupMSSQL'
import { SetupParams } from '../../utils/setupPostgres'
import { describeMatrix, sqlServerOnly } from '../__helpers__/conditionalTests'
import { createDefaultTestContext } from '../__helpers__/context'
const isMacOrWindowsCI = Boolean(process.env.CI) && ['darwin', 'win32'].includes(process.platform)
if (isMacOrWindowsCI) {
jest.setTimeout(60_000)
}
const ctx = createDefaultTestContext()
// We want to remove unique IDs to have stable snapshots
// Example:
// `PK__User__3213E83E450CDF1F` will be changed to `PK__User__RANDOM_ID_SANITIZED`
function sanitizeSQLServerIdName(schema: string) {
const schemaRows = schema.split('\n')
const regexp = new RegExp(/map: "PK__(.*)__(.*)"/)
const schemaRowsSanitized = schemaRows.map((row) => {
const match = regexp.exec(row)
if (match) {
row = row.replace(match[2], 'RANDOM_ID_SANITIZED')
}
return row
})
return schemaRowsSanitized.join('\n')
}
describeMatrix(sqlServerOnly, 'SQL Server', () => {
if (!process.env.TEST_SKIP_MSSQL && !process.env.TEST_MSSQL_URI) {
throw new Error('You must set a value for process.env.TEST_MSSQL_URI. See TESTING.md')
}
if (!process.env.TEST_SKIP_MSSQL && !process.env.TEST_MSSQL_JDBC_URI_MIGRATE) {
throw new Error('You must set a value for process.env.TEST_MSSQL_JDBC_URI_MIGRATE. See TESTING.md')
}
const databaseName = 'tests-migrate-db-pull-sqlserver'
const setupParams: SetupParams = {
connectionString: process.env.TEST_MSSQL_URI!,
// Note: at this location there is a setup.sql file
// which will be executed a SQL file so the database is not empty
dirname: path.join(__dirname, '..', '..', '__tests__', 'fixtures', 'introspection', 'sqlserver'),
}
beforeAll(async () => {
await tearDownMSSQL(setupParams, databaseName).catch((e) => {
console.error(e)
})
})
beforeEach(async () => {
await setupMSSQL(setupParams, databaseName).catch((e) => {
console.error(e)
})
// Update env var because it's the one that is used in the schemas tested
process.env.TEST_MSSQL_JDBC_URI_MIGRATE = process.env.TEST_MSSQL_JDBC_URI_MIGRATE?.replace(
'tests-migrate',
databaseName,
)
process.env.TEST_MSSQL_SHADOWDB_JDBC_URI_MIGRATE = process.env.TEST_MSSQL_SHADOWDB_JDBC_URI_MIGRATE?.replace(
'tests-migrate-shadowdb',
`${databaseName}-shadowdb`,
)
})
afterEach(async () => {
await tearDownMSSQL(setupParams, databaseName).catch((e) => {
console.error(e)
})
})
test('basic introspection', async () => {
ctx.fixture('introspection/sqlserver')
const introspect = new DbPull()
const result = introspect.parse(['--print'], await ctx.config())
await expect(result).resolves.toMatchInlineSnapshot(`""`)
expect(ctx.normalizedCapturedStdout()).toMatchInlineSnapshot(`
"datasource db {
provider = "sqlserver"
url = env("TEST_MSSQL_JDBC_URI_MIGRATE")
}
model jobs {
job_id Int @id(map: "PK__jobs__CustomNameToAvoidRandomNumber") @default(autoincrement())
customer_id Int?
description String? @db.VarChar(200)
created_at DateTime?
}
"
`)
expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(`""`)
})
test('basic introspection --url', async () => {
const introspect = new DbPull()
const result = introspect.parse(['--print', '--url', process.env.TEST_MSSQL_JDBC_URI_MIGRATE!], await ctx.config())
await expect(result).resolves.toMatchInlineSnapshot(`""`)
expect(ctx.normalizedCapturedStdout()).toMatchInlineSnapshot(`
"datasource db {
provider = "sqlserver"
url = "sqlserver://localhost:1433;database=tests-migrate-db-pull-sqlserver;user=SA;password=Pr1sm4_Pr1sm4;trustServerCertificate=true;"
}
model jobs {
job_id Int @id(map: "PK__jobs__CustomNameToAvoidRandomNumber") @default(autoincrement())
customer_id Int?
description String? @db.VarChar(200)
created_at DateTime?
}
"
`)
expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(`""`)
})
})
describeMatrix(sqlServerOnly, 'sqlserver-multischema', () => {
if (process.env.CI) {
// to avoid timeouts on macOS
jest.setTimeout(80_000)
} else {
jest.setTimeout(20_000)
}
if (!process.env.TEST_SKIP_MSSQL && !process.env.TEST_MSSQL_URI) {
throw new Error('You must set a value for process.env.TEST_MSSQL_URI. See TESTING.md')
}
// Note that this needs to be exactly the same as the one in the setup.sql file
const databaseName = 'tests-migrate-db-pull-sqlserver-multischema'
const setupParams: SetupParams = {
connectionString: process.env.TEST_MSSQL_URI!,
// Note: at this location there is a setup.sql file
// which will be executed a SQL file so the database is not empty
dirname: path.join(__dirname, '..', '..', '__tests__', 'fixtures', 'introspection', 'sqlserver-multischema'),
}
beforeAll(async () => {
await tearDownMSSQL(setupParams, databaseName).catch((e) => {
console.error(e)
})
})
beforeEach(async () => {
await setupMSSQL(setupParams, databaseName).catch((e) => {
console.error(e)
})
// Update env var because it's the one that is used in the schemas tested
process.env.TEST_MSSQL_JDBC_URI_MIGRATE = process.env.TEST_MSSQL_JDBC_URI_MIGRATE?.replace(
'tests-migrate',
databaseName,
)
})
afterEach(async () => {
await tearDownMSSQL(setupParams, databaseName).catch((e) => {
console.error(e)
})
})
test('without datasource property `schemas` it should error with P4001, empty database', async () => {
ctx.fixture('introspection/sqlserver-multischema')
const introspect = new DbPull()
const result = introspect.parse(['--print', '--schema', 'without-schemas-in-datasource.prisma'], await ctx.config())
await expect(result).rejects.toThrow(`P4001`)
expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(`""`)
})
test('datasource property `schemas=[]` should error with P1012, array can not be empty', async () => {
ctx.fixture('introspection/sqlserver-multischema')
const introspect = new DbPull()
const result = introspect.parse(
['--print', '--schema', 'with-schemas-in-datasource-0-value.prisma'],
await ctx.config(),
)
await expect(result).rejects.toMatchInlineSnapshot(`
"Prisma schema validation - (get-config wasm)
Error code: P1012
error: If provided, the schemas array can not be empty.
--> with-schemas-in-datasource-0-value.prisma:4
|
3 | url = env("TEST_MSSQL_JDBC_URI_MIGRATE")
4 | schemas = []
|
Validation Error Count: 1
[Context: getConfig]
Prisma CLI Version : 0.0.0"
`)
expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(`""`)
})
// TODO unskip in a following PR
// We need to find out why this test can fail and pass in CI...
// It was blocking the release pipeline
// Examples
// https://github.com/prisma/prisma/actions/runs/4013789656/jobs/6893546711 (most recent)
// https://buildkite.com/prisma/test-prisma-typescript/builds/18825#01855966-3d90-4362-b130-502021a1047b
test.skip('datasource property `schemas=["base", "transactional"]` should succeed', async () => {
ctx.fixture('introspection/sqlserver-multischema')
const introspect = new DbPull()
const result = introspect.parse(
['--print', '--schema', 'with-schemas-in-datasource-2-values.prisma'],
await ctx.config(),
)
await expect(result).resolves.toMatchInlineSnapshot(``)
expect(sanitizeSQLServerIdName(ctx.normalizedCapturedStdout())).toMatchInlineSnapshot('')
expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(`
// *** WARNING ***
//
// The following models were ignored as they do not have a valid unique identifier or id. This is currently not supported by Prisma Client:
// - transactional_some_table
//
// These items were renamed due to their names being duplicates in the Prisma schema:
// - type: model, name: base_some_table
// - type: model, name: transactional_some_table
//
`)
})
test('datasource property `schemas=["base"]` should succeed', async () => {
ctx.fixture('introspection/sqlserver-multischema')
const introspect = new DbPull()
const result = introspect.parse(
['--print', '--schema', 'with-schemas-in-datasource-1-value.prisma'],
await ctx.config(),
)
await expect(result).resolves.toMatchInlineSnapshot(`""`)
expect(sanitizeSQLServerIdName(ctx.normalizedCapturedStdout())).toMatchInlineSnapshot(`
"generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlserver"
url = env("TEST_MSSQL_JDBC_URI_MIGRATE")
schemas = ["base"]
}
model some_table {
id String @id(map: "PK__some_tab__RANDOM_ID_SANITIZED") @db.NVarChar(1)
email String @db.NVarChar(1)
@@schema("base")
}
model SomeUser {
id String @id(clustered: false, map: "PK__SomeUser__RANDOM_ID_SANITIZED") @db.NVarChar(1)
email String @db.NVarChar(1)
@@schema("base")
}
"
`)
expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(`""`)
})
test('datasource property `schemas=["does-not-exist"]` should error with P4001, empty database', async () => {
ctx.fixture('introspection/sqlserver-multischema')
const introspect = new DbPull()
const result = introspect.parse(
['--print', '--schema', 'with-schemas-in-datasource-1-non-existing-value.prisma'],
await ctx.config(),
)
await expect(result).rejects.toThrow(`P4001`)
expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(`""`)
})
test('datasource property `schemas=["does-not-exist", "base"]` should succeed', async () => {
ctx.fixture('introspection/sqlserver-multischema')
const introspect = new DbPull()
const result = introspect.parse(
['--print', '--schema', 'with-schemas-in-datasource-1-existing-1-non-existing-value.prisma'],
await ctx.config(),
)
await expect(result).resolves.toMatchInlineSnapshot(`""`)
expect(sanitizeSQLServerIdName(ctx.normalizedCapturedStdout())).toMatchInlineSnapshot(`
"generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlserver"
url = env("TEST_MSSQL_JDBC_URI_MIGRATE")
schemas = ["base", "does-not-exist"]
}
model some_table {
id String @id(map: "PK__some_tab__RANDOM_ID_SANITIZED") @db.NVarChar(1)
email String @db.NVarChar(1)
@@schema("base")
}
model SomeUser {
id String @id(clustered: false, map: "PK__SomeUser__RANDOM_ID_SANITIZED") @db.NVarChar(1)
email String @db.NVarChar(1)
@@schema("base")
}
"
`)
expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(`""`)
})
test('--url with `?schema=does-not-exist` should error with with P4001, empty database', async () => {
const introspect = new DbPull()
const connectionString = `${process.env.TEST_MSSQL_JDBC_URI_MIGRATE}schema=does-not-exist`
const result = introspect.parse(['--print', '--url', connectionString], await ctx.config())
await expect(result).rejects.toThrow(`P4001`)
expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(`""`)
})
test('--url with `?schema=base` should succeed', async () => {
const introspect = new DbPull()
const connectionString = `${process.env.TEST_MSSQL_JDBC_URI_MIGRATE}schema=base`
const result = introspect.parse(['--print', '--url', connectionString], await ctx.config())
await expect(result).resolves.toMatchInlineSnapshot(`""`)
expect(sanitizeSQLServerIdName(ctx.normalizedCapturedStdout())).toMatchInlineSnapshot(`
"datasource db {
provider = "sqlserver"
url = "sqlserver://localhost:1433;database=tests-migrate-db-pull-sqlserver-multischema;user=SA;password=Pr1sm4_Pr1sm4;trustServerCertificate=true;schema=base"
}
model some_table {
id String @id(map: "PK__some_tab__RANDOM_ID_SANITIZED") @db.NVarChar(1)
email String @db.NVarChar(1)
}
model SomeUser {
id String @id(clustered: false, map: "PK__SomeUser__RANDOM_ID_SANITIZED") @db.NVarChar(1)
email String @db.NVarChar(1)
}
"
`)
expect(ctx.mocked['console.error'].mock.calls.join('\n')).toMatchInlineSnapshot(`""`)
})
})