Skip to content

Commit

Permalink
Setup core vitest (#43)
Browse files Browse the repository at this point in the history
  • Loading branch information
csansoon authored Jul 18, 2024
1 parent 393a84f commit dfddce0
Show file tree
Hide file tree
Showing 13 changed files with 405 additions and 14 deletions.
8 changes: 7 additions & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"db:studio": "drizzle-kit studio --port 3002",
"lint": "eslint src",
"tc": "tsc --noEmit",
"test": "pnpm run db:migrate:test && vitest run --pool=forks",
"test:watch": "vitest",
"prettier": "prettier --write src/**/*.ts"
},
Expand All @@ -29,12 +30,17 @@
"zod": "^3.23.8"
},
"devDependencies": {
"@faker-js/faker": "^8.4.1",
"@latitude-data/eslint-config": "workspace:*",
"@latitude-data/typescript-config": "workspace:*",
"@types/bcrypt": "^5.0.2",
"@types/lodash-es": "^4.17.12",
"@types/node": "^20.14.10",
"drizzle-kit": "^0.22.8",
"eslint-plugin-drizzle": "^0.2.3"
"eslint-plugin-drizzle": "^0.2.3",
"pg-transactional-tests": "^1.0.9",
"supertest": "^7.0.0",
"vite-tsconfig-paths": "^4.3.2",
"vitest": "^2.0.3"
}
}
20 changes: 20 additions & 0 deletions packages/core/src/tests/factories/commits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Project } from '$core/schema'
import createCommitFn from '$core/services/commits/create'

import { createProject, ICreateProject } from './projects'

export type ICreateDraft = {
project?: Project | ICreateProject
}
export async function createDraft(commitData: Partial<ICreateDraft> = {}) {
let project = commitData.project ?? {}
if (!('id' in project)) {
const { project: newProject } = await createProject(project)
project = newProject
}

const result = await createCommitFn({ projectId: (project as Project).id })
const commit = result.unwrap()

return { commit }
}
4 changes: 4 additions & 0 deletions packages/core/src/tests/factories/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export * from './users'
export * from './workspaces'
export * from './projects'
export * from './commits'
57 changes: 57 additions & 0 deletions packages/core/src/tests/factories/projects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { faker } from '@faker-js/faker'
import { database as db } from '$core/client'
import { getUser } from '$core/data-access'
import { Result, Transaction } from '$core/lib'
import { Project, projects, Workspace, type SafeUser } from '$core/schema'

import { createWorkspace, type ICreateWorkspace } from './workspaces'

// TODO: Replace with actual service
const createProjectFn = ({
name,
workspaceId,
}: {
name: string
workspaceId: number
}) => {
return Transaction.call<Project>(async (tx) => {
const insertedProjects = await tx
.insert(projects)
.values({ name, workspaceId })
.returning()

const newProject = insertedProjects[0]!

return Result.ok(newProject)
}, db)
}

export type ICreateProject = {
name?: string
workspace?: Workspace | ICreateWorkspace
}
export async function createProject(projectData: Partial<ICreateProject> = {}) {
let workspaceData = projectData.workspace ?? {}
let user: SafeUser
let workspace: Workspace

if ('id' in workspaceData) {
user = (await getUser(workspaceData.creatorId!)) as SafeUser
workspace = workspaceData as Workspace
} else {
const newWorkspace = await createWorkspace(workspaceData)
workspace = newWorkspace.workspace
user = newWorkspace.userData
}

const randomName = faker.commerce.department()
const { name } = projectData

const result = await createProjectFn({
name: name ?? randomName,
workspaceId: workspace.id,
})
const project = result.unwrap()

return { project, user, workspace }
}
22 changes: 22 additions & 0 deletions packages/core/src/tests/factories/users.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { faker } from '@faker-js/faker'
import { createUser as createUserFn } from '$core/services/users/createUser'

function makeRandomUserData() {
return {
name: faker.person.firstName(),
email: faker.internet.email(),
password: faker.internet.password(),
}
}
export type ICreateUser = {
name?: string
email?: string
password?: string
}
export async function createUser(userData: Partial<ICreateUser> = {}) {
const randomUserData = makeRandomUserData()
const data = { ...randomUserData, ...userData }

const result = await createUserFn(data)
return result.unwrap()
}
28 changes: 28 additions & 0 deletions packages/core/src/tests/factories/workspaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { faker } from '@faker-js/faker'
import { type SafeUser } from '$core/schema'
import { createWorkspace as createWorkspaceFn } from '$core/services/workspaces/create'

import { createUser, type ICreateUser } from './users'

export type ICreateWorkspace = {
name?: string
creator?: SafeUser | ICreateUser
}
export async function createWorkspace(
workspaceData: Partial<ICreateWorkspace> = {},
) {
let userData = workspaceData.creator ?? {}
if (!('id' in userData)) {
userData = await createUser(userData)
}

const randomName = faker.company.name()
const { name } = workspaceData
const result = await createWorkspaceFn({
name: name ?? randomName,
creatorId: userData.id,
})
const workspace = result.unwrap()

return { workspace, userData }
}
12 changes: 12 additions & 0 deletions packages/core/src/tests/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// vitest-env.d.ts
import { beforeEach } from 'vitest'

import * as factories from './factories'
import useTestDatabase from './useTestDatabase'

// This do rollback stragegy for each test. Faster than truncate.
useTestDatabase()

beforeEach((ctx) => {
ctx.factories = factories
})
8 changes: 8 additions & 0 deletions packages/core/src/tests/tmp.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { describe, expect, it } from 'vitest'

// TODO: Remove when adding an actual test suite
describe('placeholder', () => {
it('works', () => {
expect(true).toBe(true)
})
})
22 changes: 22 additions & 0 deletions packages/core/src/tests/useTestDatabase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {
close,
patchPgForTransactions,
rollbackTransaction,
startTransaction,
unpatchPgForTransactions,
} from 'pg-transactional-tests'
import { afterAll, afterEach, beforeAll, beforeEach } from 'vitest'

export default function useTestDatabase() {
beforeAll(async () => {
patchPgForTransactions()
await startTransaction()
})
beforeEach(startTransaction)
afterEach(rollbackTransaction)
afterAll(async () => {
await rollbackTransaction()
unpatchPgForTransactions()
await close()
})
}
9 changes: 9 additions & 0 deletions packages/core/src/tests/vitest.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import 'vitest'

import * as factories from './factories'

declare module 'vitest' {
export interface TestContext {
factories: typeof factories
}
}
19 changes: 19 additions & 0 deletions packages/core/vitest.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/// <reference types="vitest" />
import { fileURLToPath } from 'url'
import { dirname } from 'path'
import { defineConfig } from 'vitest/config'
import tsconfigPaths from 'vite-tsconfig-paths'

const filename = fileURLToPath(import.meta.url)
const root = dirname(filename)

export default defineConfig({
plugins: [tsconfigPaths({ root })],
test: {
globals: true,
testTimeout: 5000,
environment: 'node',
setupFiles: ['./src/tests/setup.ts'],
include: ['./src/**/*.test.ts'],
},
})
2 changes: 1 addition & 1 deletion packages/env/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const env = process.env.NODE_ENV || 'development'
if (env !== 'production') {
dotenv.populate(process.env as DotenvPopulateInput, {
NODE_ENV: env,
DATABASE_URL: `postgres://latitude:secret@localhost:5432/latitude_development`,
DATABASE_URL: `postgres://latitude:secret@localhost:5432/latitude_${env}`,
ELASTIC_URL: 'https://elastic:9200',
ELASTIC_USERNAME: 'latitude',
ELASTIC_PASSWORD: 'secret',
Expand Down
Loading

0 comments on commit dfddce0

Please sign in to comment.