chore: Move factories and helpers to a better place (#4551)

* chore: Move factories and helpers to a better place

* align factory product variant

* fix factory cart

* add simple store fac

* fix tests

* fix tests

* fix

* fix cart seeder
This commit is contained in:
Adrien de Peretti
2023-07-20 13:16:04 +02:00
committed by GitHub
parent 26e2f81c24
commit 4d326fbbdf
197 changed files with 1073 additions and 4332 deletions
+26
View File
@@ -0,0 +1,26 @@
const path = require("path")
const express = require("express")
const getPort = require("get-port")
module.exports = {
bootstrapApp: async ({ cwd } = {}) => {
const app = express()
const loaders = require("@medusajs/medusa/dist/loaders").default
const { container, dbConnection } = await loaders({
directory: path.resolve(cwd || process.cwd()),
expressApp: app,
isTest: false,
})
const PORT = await getPort()
return {
container,
db: dbConnection,
app,
port: PORT,
}
},
}
@@ -0,0 +1,48 @@
const path = require("path")
const { spawn } = require("child_process")
const { setPort } = require("./use-api")
module.exports = ({ cwd, redisUrl, uploadDir, verbose, env }) => {
const serverPath = path.join(__dirname, "test-server.js")
// in order to prevent conflicts in redis, use a different db for each worker
// same fix as for databases (works with up to 15)
// redis dbs are 0-indexed and jest worker ids are indexed from 1
const workerId = parseInt(process.env.JEST_WORKER_ID || "1")
const redisUrlWithDatabase = `${redisUrl}/${workerId - 1}`
verbose = verbose ?? false
return new Promise((resolve, reject) => {
const medusaProcess = spawn("node", [path.resolve(serverPath)], {
cwd,
env: {
...process.env,
NODE_ENV: "development",
JWT_SECRET: "test",
COOKIE_SECRET: "test",
REDIS_URL: redisUrl ? redisUrlWithDatabase : undefined, // If provided, will use a real instance, otherwise a fake instance
UPLOAD_DIR: uploadDir, // If provided, will be used for the fake local file service
...env,
},
stdio: verbose
? ["inherit", "inherit", "inherit", "ipc"]
: ["ignore", "ignore", "ignore", "ipc"],
})
medusaProcess.on("error", (err) => {
console.log(err)
process.exit()
})
medusaProcess.on("uncaughtException", (err) => {
console.log(err)
medusaProcess.kill()
})
medusaProcess.on("message", (port) => {
setPort(port)
resolve(medusaProcess)
})
})
}
@@ -0,0 +1,38 @@
const setupServer = require("./setup-server")
const { initDb } = require("./use-db")
const startServerWithEnvironment = async ({
cwd,
redisUrl,
uploadDir,
verbose,
env,
}) => {
if (env) {
Object.entries(env).forEach(([key, value]) => {
process.env[key] = value
})
}
const dbConnection = await initDb({
cwd,
})
if (env) {
Object.entries(env).forEach(([key]) => {
delete process.env[key]
})
}
const medusaProcess = await setupServer({
cwd,
verbose,
redisUrl,
uploadDir,
env,
})
return [medusaProcess, dbConnection]
}
export default startServerWithEnvironment
@@ -0,0 +1,11 @@
const { bootstrapApp } = require("./bootstrap-app")
const setup = async () => {
const { app, port } = await bootstrapApp()
app.listen(port, (err) => {
process.send(port)
})
}
setup()
@@ -0,0 +1,21 @@
const axios = require("axios").default
const ServerTestUtil = {
port_: null,
client_: null,
setPort: function (port) {
this.client_ = axios.create({ baseURL: `http://localhost:${port}` })
},
}
const instance = ServerTestUtil
module.exports = {
setPort: function (port) {
instance.setPort(port)
},
useApi: function () {
return instance.client_
},
}
@@ -0,0 +1,136 @@
const path = require("path")
const { getConfigFile } = require("medusa-core-utils")
const { dropDatabase } = require("pg-god")
const { DataSource } = require("typeorm")
const dbFactory = require("./use-template-db")
const DB_HOST = process.env.DB_HOST
const DB_USERNAME = process.env.DB_USERNAME
const DB_PASSWORD = process.env.DB_PASSWORD
const DB_NAME = process.env.DB_TEMP_NAME
const DB_URL = `postgres://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}/${DB_NAME}`
const pgGodCredentials = {
user: DB_USERNAME,
password: DB_PASSWORD,
host: DB_HOST,
}
const keepTables = [
"store",
"staged_job",
"shipping_profile",
"fulfillment_provider",
"payment_provider",
"country",
"currency",
]
const DbTestUtil = {
db_: null,
setDb: function (dataSource) {
this.db_ = dataSource
},
clear: async function () {
this.db_.synchronize(true)
},
teardown: async function ({ forceDelete } = {}) {
forceDelete = forceDelete || []
const entities = this.db_.entityMetadatas
const manager = this.db_.manager
await manager.query(`SET session_replication_role = 'replica';`)
for (const entity of entities) {
if (
keepTables.includes(entity.tableName) &&
!forceDelete.includes(entity.tableName)
) {
continue
}
await manager.query(`DELETE
FROM "${entity.tableName}";`)
}
await manager.query(`SET session_replication_role = 'origin';`)
},
shutdown: async function () {
await this.db_.destroy()
return await dropDatabase({ DB_NAME }, pgGodCredentials)
},
}
const instance = DbTestUtil
module.exports = {
initDb: async function ({ cwd, database_extra }) {
const { configModule } = getConfigFile(cwd, `medusa-config`)
const { featureFlags } = configModule
const featureFlagsLoader =
require("@medusajs/medusa/dist/loaders/feature-flags").default
const featureFlagsRouter = featureFlagsLoader({ featureFlags })
const modelsLoader = require("@medusajs/medusa/dist/loaders/models").default
const entities = modelsLoader({}, { register: false })
await dbFactory.createFromTemplate(DB_NAME)
// get migrations with enabled featureflags
const migrationDir = path.resolve(
path.join(
__dirname,
`../../`,
`node_modules`,
`@medusajs`,
`medusa`,
`dist`,
`migrations`,
`*.js`
)
)
const {
getEnabledMigrations,
getModuleSharedResources,
} = require("@medusajs/medusa/dist/commands/utils/get-migrations")
const { migrations: moduleMigrations, models: moduleModels } =
getModuleSharedResources(configModule, featureFlagsRouter)
const enabledMigrations = getEnabledMigrations([migrationDir], (flag) =>
featureFlagsRouter.isFeatureEnabled(flag)
)
const enabledEntities = entities.filter(
(e) => typeof e.isFeatureEnabled === "undefined" || e.isFeatureEnabled()
)
const dbDataSource = new DataSource({
type: "postgres",
url: DB_URL,
entities: enabledEntities.concat(moduleModels),
migrations: enabledMigrations.concat(moduleMigrations),
extra: database_extra ?? {},
name: "integration-tests",
})
await dbDataSource.initialize()
await dbDataSource.runMigrations()
instance.setDb(dbDataSource)
return dbDataSource
},
useDb: function () {
return instance
},
}
@@ -0,0 +1,41 @@
const ServerTestUtil = {
server_: null,
app_: null,
setApp: function (app) {
this.app_ = app
},
start: async function () {
this.server_ = await new Promise((resolve, reject) => {
const s = this.app_.listen(PORT, (err) => {
if (err) {
reject(err)
}
})
resolve(s)
})
},
kill: function () {
return new Promise((resolve, _) => {
if (this.server_) {
this.server_.close(() => resolve())
}
resolve()
})
},
}
const instance = ServerTestUtil
module.exports = {
setApp: function (app) {
instance.setApp(app)
return instance
},
useServer: function () {
return instance
},
}
@@ -0,0 +1,120 @@
const path = require("path")
require("dotenv").config({ path: path.join(__dirname, "../.env.test") })
const { getConfigFile } = require("medusa-core-utils")
const { createDatabase, dropDatabase } = require("pg-god")
const { DataSource } = require("typeorm")
const DB_HOST = process.env.DB_HOST
const DB_USERNAME = process.env.DB_USERNAME
const DB_PASSWORD = process.env.DB_PASSWORD
const DB_URL = `postgres://${DB_USERNAME}:${DB_PASSWORD}@${DB_HOST}`
let masterDataSource
const pgGodCredentials = {
user: DB_USERNAME,
password: DB_PASSWORD,
host: DB_HOST,
}
class DatabaseFactory {
constructor() {
this.dataSource_ = null
this.masterDataSourceName = "master"
this.templateDbName = "medusa-integration-template"
}
async createTemplateDb_({ cwd }) {
const { configModule } = getConfigFile(cwd, `medusa-config`)
const dataSource = await this.getMasterDataSource()
const migrationDir = path.resolve(
path.join(
__dirname,
`../../`,
`node_modules`,
`@medusajs`,
`medusa`,
`dist`,
`migrations`,
`*.js`
)
)
const {
getEnabledMigrations,
getModuleSharedResources,
} = require("@medusajs/medusa/dist/commands/utils/get-migrations")
// filter migrations to only include those that don't have feature flags
const enabledMigrations = getEnabledMigrations(
[migrationDir],
(flag) => false
)
const { migrations: moduleMigrations } =
getModuleSharedResources(configModule)
await dropDatabase(
{
databaseName: this.templateDbName,
errorIfNonExist: false,
},
pgGodCredentials
)
await createDatabase(
{ databaseName: this.templateDbName },
pgGodCredentials
)
const templateDbDataSource = new DataSource({
type: "postgres",
name: "templateDataSource",
url: `${DB_URL}/${this.templateDbName}`,
migrations: enabledMigrations.concat(moduleMigrations),
})
await templateDbDataSource.initialize()
await templateDbDataSource.runMigrations()
await templateDbDataSource.destroy()
return dataSource
}
async getMasterDataSource() {
masterDataSource = masterDataSource || (await this.createMasterDataSource())
return masterDataSource
}
async createMasterDataSource() {
const dataSource = new DataSource({
type: "postgres",
name: this.masterDataSourceName,
url: `${DB_URL}`,
})
await dataSource.initialize()
return dataSource
}
async createFromTemplate(dbName) {
const dataSource = await this.getMasterDataSource()
await dataSource.query(`DROP DATABASE IF EXISTS "${dbName}";`)
await dataSource.query(
`CREATE DATABASE "${dbName}" TEMPLATE "${this.templateDbName}";`
)
}
async destroy() {
const dataSource = await this.getMasterDataSource()
await dataSource.query(`DROP DATABASE IF EXISTS "${this.templateDbName}";`)
await dataSource.destroy()
}
}
module.exports = new DatabaseFactory()