chore(): Fix database test utils and utils (#6383)

**What**
Fix the test utils database to trully run the migrations, the migration path is deprecated and not used anymore as umzung infer the path under the hood. It also fix the schema so that it is possible to specify different schema if needed.

The index helper can now create named constraints for uniqueness. 

extracted [from](https://github.com/medusajs/medusa/pull/6381)
This commit is contained in:
Adrien de Peretti
2024-02-12 18:07:15 +00:00
committed by GitHub
parent 1593e0b192
commit e85463b2a7
5 changed files with 90 additions and 32 deletions
+6
View File
@@ -0,0 +1,6 @@
---
"medusa-test-utils": patch
"@medusajs/utils": patch
---
chore(): Fix database test utils and utils
@@ -23,7 +23,7 @@ export class Migration20240124154000 extends Migration {
'create index if not exists "IDX_customer_address_customer_id" on "customer_address" ("customer_id");' 'create index if not exists "IDX_customer_address_customer_id" on "customer_address" ("customer_id");'
) )
this.addSql( this.addSql(
'create unique index "IDX_customer_address_unqiue_customer_billing" on "customer_address" ("customer_id") where "is_default_billing" = true;' 'create unique index "IDX_customer_address_unique_customer_billing" on "customer_address" ("customer_id") where "is_default_billing" = true;'
) )
this.addSql( this.addSql(
'create unique index "IDX_customer_address_unique_customer_shipping" on "customer_address" ("customer_id") where "is_default_shipping" = true;' 'create unique index "IDX_customer_address_unique_customer_shipping" on "customer_address" ("customer_id") where "is_default_shipping" = true;'
+51 -23
View File
@@ -1,6 +1,6 @@
import { TSMigrationGenerator } from "@mikro-orm/migrations"
import { MikroORM, Options, SqlEntityManager } from "@mikro-orm/postgresql" import { MikroORM, Options, SqlEntityManager } from "@mikro-orm/postgresql"
import * as process from "process" import * as process from "process"
import { Migrator } from "@mikro-orm/migrations"
export function getDatabaseURL(): string { export function getDatabaseURL(): string {
const DB_HOST = process.env.DB_HOST ?? "localhost" const DB_HOST = process.env.DB_HOST ?? "localhost"
@@ -15,7 +15,8 @@ export function getDatabaseURL(): string {
export function getMikroOrmConfig( export function getMikroOrmConfig(
mikroOrmEntities: any[], mikroOrmEntities: any[],
pathToMigrations: string pathToMigrations: string, // deprecated, auto inferred
schema?: string
): Options { ): Options {
const DB_URL = getDatabaseURL() const DB_URL = getDatabaseURL()
@@ -23,23 +24,17 @@ export function getMikroOrmConfig(
type: "postgresql", type: "postgresql",
clientUrl: DB_URL, clientUrl: DB_URL,
entities: Object.values(mikroOrmEntities), entities: Object.values(mikroOrmEntities),
schema: process.env.MEDUSA_DB_SCHEMA, schema: schema ?? process.env.MEDUSA_DB_SCHEMA,
debug: false, debug: false,
migrations: { extensions: [Migrator],
path: pathToMigrations,
pathTs: pathToMigrations,
glob: "!(*.d).{js,ts}",
silent: true,
dropTables: true,
transactional: true,
allOrNothing: true,
safe: false,
generator: TSMigrationGenerator,
},
} }
} }
export interface TestDatabase { export interface TestDatabase {
mikroOrmEntities: any[]
pathToMigrations: any // deprecated, auto inferred
schema?: string
orm: MikroORM | null orm: MikroORM | null
manager: SqlEntityManager | null manager: SqlEntityManager | null
@@ -52,9 +47,14 @@ export interface TestDatabase {
export function getMikroOrmWrapper( export function getMikroOrmWrapper(
mikroOrmEntities: any[], mikroOrmEntities: any[],
pathToMigrations: string pathToMigrations: string, // deprecated, auto inferred
schema?: string
): TestDatabase { ): TestDatabase {
return { return {
mikroOrmEntities,
pathToMigrations, // deprecated, auto inferred
schema: schema ?? process.env.MEDUSA_DB_SCHEMA,
orm: null, orm: null,
manager: null, manager: null,
@@ -83,18 +83,36 @@ export function getMikroOrmWrapper(
}, },
async setupDatabase() { async setupDatabase() {
const OrmConfig = getMikroOrmConfig(mikroOrmEntities, pathToMigrations) const OrmConfig = getMikroOrmConfig(
this.mikroOrmEntities,
this.pathToMigrations,
this.schema
)
// Initializing the ORM // Initializing the ORM
this.orm = await MikroORM.init(OrmConfig) this.orm = await MikroORM.init(OrmConfig)
if (this.orm === null) { this.manager = this.orm.em
throw new Error("ORM not configured")
try {
await this.orm.getSchemaGenerator().ensureDatabase()
} catch (err) {}
await this.manager?.execute(
`CREATE SCHEMA IF NOT EXISTS "${this.schema ?? "public"}";`
)
const pendingMigrations = await this.orm
.getMigrator()
.getPendingMigrations()
if (pendingMigrations && pendingMigrations.length > 0) {
await this.orm
.getMigrator()
.up({ migrations: pendingMigrations.map((m) => m.name!) })
} else {
await this.orm.schema.refreshDatabase() // ensure db exists and is fresh
} }
this.manager = await this.orm.em
await this.orm.schema.refreshDatabase() // ensure db exists and is fresh
}, },
async clearDatabase() { async clearDatabase() {
@@ -102,7 +120,17 @@ export function getMikroOrmWrapper(
throw new Error("ORM not configured") throw new Error("ORM not configured")
} }
await this.orm.close() await this.manager?.execute(
`DROP SCHEMA IF EXISTS "${this.schema ?? "public"}" CASCADE;`
)
await this.manager?.execute(
`CREATE SCHEMA IF NOT EXISTS "${this.schema ?? "public"}";`
)
try {
await this.orm.close()
} catch {}
this.orm = null this.orm = null
this.manager = null this.manager = null
@@ -10,7 +10,7 @@ describe("createPsqlIndexStatementHelper", function () {
const indexStatement = createPsqlIndexStatementHelper(options) const indexStatement = createPsqlIndexStatementHelper(options)
expect(indexStatement).toEqual( expect(indexStatement).toEqual(
`CREATE INDEX IF NOT EXISTS ${options.name} ON ${options.tableName} (${options.columns})` `CREATE INDEX IF NOT EXISTS "${options.name}" ON "${options.tableName}" (${options.columns})`
) )
}) })
@@ -23,9 +23,9 @@ describe("createPsqlIndexStatementHelper", function () {
const indexStatement = createPsqlIndexStatementHelper(options) const indexStatement = createPsqlIndexStatementHelper(options)
expect(indexStatement).toEqual( expect(indexStatement).toEqual(
`CREATE INDEX IF NOT EXISTS ${options.name} ON ${ `CREATE INDEX IF NOT EXISTS "${options.name}" ON "${
options.tableName options.tableName
} (${options.columns.join(", ")})` }" (${options.columns.join(", ")})`
) )
}) })
@@ -39,9 +39,9 @@ describe("createPsqlIndexStatementHelper", function () {
const indexStatement = createPsqlIndexStatementHelper(options) const indexStatement = createPsqlIndexStatementHelper(options)
expect(indexStatement).toEqual( expect(indexStatement).toEqual(
`CREATE INDEX IF NOT EXISTS ${options.name} ON ${ `CREATE INDEX IF NOT EXISTS "${options.name}" ON "${
options.tableName options.tableName
} (${options.columns.join(", ")}) WHERE ${options.where}` }" (${options.columns.join(", ")}) WHERE ${options.where}`
) )
}) })
@@ -56,9 +56,26 @@ describe("createPsqlIndexStatementHelper", function () {
const indexStatement = createPsqlIndexStatementHelper(options) const indexStatement = createPsqlIndexStatementHelper(options)
expect(indexStatement).toEqual( expect(indexStatement).toEqual(
`CREATE INDEX IF NOT EXISTS ${options.name} ON ${ `CREATE INDEX IF NOT EXISTS "${options.name}" ON "${
options.tableName options.tableName
} USING GIN (${options.columns.join(", ")}) WHERE ${options.where}` }" USING GIN (${options.columns.join(", ")}) WHERE ${options.where}`
)
})
it("should generate unique constraint", function () {
const options = {
name: "index_name",
tableName: "table_name",
columns: ["column_name_1", "column_name_2"],
unique: true,
where: "column_name_1 IS NOT NULL",
}
const indexStatement = createPsqlIndexStatementHelper(options)
expect(indexStatement).toEqual(
`ALTER TABLE IF EXISTS "${options.tableName}" ADD CONSTRAINT "${
options.name
}" UNIQUE (${options.columns.join(", ")}) WHERE ${options.where}`
) )
}) })
}) })
@@ -5,6 +5,7 @@
* @param columns The columns to index * @param columns The columns to index
* @param type The type of index (e.g GIN, GIST, BTREE, etc) * @param type The type of index (e.g GIN, GIST, BTREE, etc)
* @param where The where clause * @param where The where clause
* @param unique If the index should be a unique index
* *
* @example * @example
* createPsqlIndexStatementHelper({ * createPsqlIndexStatementHelper({
@@ -32,16 +33,22 @@ export function createPsqlIndexStatementHelper({
columns, columns,
type, type,
where, where,
unique,
}: { }: {
name: string name: string
tableName: string tableName: string
columns: string | string[] columns: string | string[]
type?: string type?: string
where?: string where?: string
unique?: boolean
}) { }) {
columns = Array.isArray(columns) ? columns.join(", ") : columns columns = Array.isArray(columns) ? columns.join(", ") : columns
const typeStr = type ? ` USING ${type}` : "" const typeStr = type ? ` USING ${type}` : ""
const optionsStr = where ? ` WHERE ${where}` : "" const optionsStr = where ? ` WHERE ${where}` : ""
return `CREATE INDEX IF NOT EXISTS ${name} ON ${tableName}${typeStr} (${columns})${optionsStr}` if (!unique) {
return `CREATE INDEX IF NOT EXISTS "${name}" ON "${tableName}"${typeStr} (${columns})${optionsStr}`
} else {
return `ALTER TABLE IF EXISTS "${tableName}" ADD CONSTRAINT "${name}" UNIQUE (${columns})${optionsStr}`
}
} }