Skip to content

Commit

Permalink
Tests now all appear to be passing
Browse files Browse the repository at this point in the history
I have maintained the file-sequential execution style (which I will next
attempt to take away.) tests currently run through in ~99 seconds or so.
This is much longer than it needs to be, and so this is where the vitest
optimizations can really have an opportunity to shine.
  • Loading branch information
CocoisBuggy committed Dec 11, 2024
1 parent e64abd5 commit d2a9503
Show file tree
Hide file tree
Showing 18 changed files with 97 additions and 172 deletions.
35 changes: 0 additions & 35 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,40 +76,5 @@
],
"console": "integratedTerminal"
},
{
"name": "Debug Jest Tests",
"type": "node",
"request": "launch",
"env": {
"NODE_OPTIONS": "--experimental-vm-modules"
},
"runtimeArgs": [
"--inspect-brk",
"${workspaceRoot}/node_modules/.bin/jest",
"--runInBand",
"history"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
},
{
"type": "node",
"name": "vscode-jest-tests.v2",
"request": "launch",
"env": {
"NODE_OPTIONS": "--experimental-vm-modules"
},
"args": [
"${workspaceRoot}/node_modules/.bin/jest",
"--runInBand",
"--watchAll=false",
"--testNamePattern",
"${jest.testNamePattern}",
"--runTestsByPath",
"${jest.testFile}"
],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}
]
}
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
"@types/underscore": "^1.11.4",
"cross-env": "^7.0.3",
"husky": "^8.0.1",
"jest-extended": "^4.0.2",
"mongodb-memory-server": "^10.1.2",
"nock": "^13.3.0",
"supertest": "^6.3.3",
Expand Down Expand Up @@ -71,7 +70,7 @@
"scripts": {
"lint": "yarn ts-standard",
"fix": "yarn ts-standard --fix",
"test": "cross-env NODE_OPTIONS=\"--experimental-vm-modules\" jest --runInBand",
"test": "vitest run --no-file-parallelism",
"build": "tsc -p tsconfig.json",
"build-release": "tsc -p tsconfig.release.json",
"clean": "tsc -b --clean && rm -rf build/*",
Expand Down
3 changes: 0 additions & 3 deletions src/__tests__/areas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ApolloServer } from '@apollo/server'
import muuid from 'uuid-mongodb'
import { jest } from '@jest/globals'
import MutableAreaDataSource from '../model/MutableAreaDataSource.js'
import MutableOrganizationDataSource from '../model/MutableOrganizationDataSource.js'
import { AreaType } from '../db/AreaTypes.js'
Expand All @@ -10,8 +9,6 @@ import { muuidToString } from '../utils/helpers.js'
import { InMemoryDB } from '../utils/inMemoryDB.js'
import express from 'express'

jest.setTimeout(60000)

describe('areas API', () => {
let server: ApolloServer
let user: muuid.MUUID
Expand Down
69 changes: 28 additions & 41 deletions src/__tests__/fixtures/gql.fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,64 +10,56 @@ import { applyMiddleware } from 'graphql-middleware'
import { localDevBypassAuthContext } from '../../auth/local-dev/middleware'
import localDevBypassAuthPermissions from '../../auth/local-dev/permissions'
import { graphqlSchema } from '../../graphql/resolvers'
import BulkImportDataSource from '../../model/BulkImportDataSource'
import ChangeLogDataSource from '../../model/ChangeLogDataSource'
import MutableMediaDataSource from '../../model/MutableMediaDataSource'
import TickDataSource from '../../model/TickDataSource'
import UserDataSource from '../../model/UserDataSource'
import cors from 'cors'
import MutableOrganizationDataSource from '../../model/MutableOrganizationDataSource'
import { muuidToString } from '../../utils/helpers'
import muuid, { MUUID } from 'uuid-mongodb'
import { AreaType } from '../../db/AreaTypes'



interface ServerTestFixtures {
ctx: {
server: ApolloServer<BaseContext>
app: Application
},
query: (opts: QueryAPIProps) => Promise<request.Response>,
user: MUUID,
userUuid: string,

usa: AreaType,
ca: AreaType,
wa: AreaType,
or: AreaType
}
query: (opts: QueryAPIProps) => Promise<request.Response>
user: MUUID
userUuid: string
}


export const serverTest = dbTest.extend<ServerTestFixtures>({
ctx: async ({ task, db, climbs, areas }, use) => {
ctx: async ({
task, climbs, areas, bulkImport,
organizations,
ticks,
history,
media,
users
}, use) => {
const schema = applyMiddleware(
graphqlSchema,
(localDevBypassAuthPermissions).generate(graphqlSchema)
)
const dataSources = ({
climbs,
areas,
bulkImport: BulkImportDataSource.getInstance(),
organizations: MutableOrganizationDataSource.getInstance(),
ticks: TickDataSource.getInstance(),
history: ChangeLogDataSource.getInstance(),
media: MutableMediaDataSource.getInstance(),
users: UserDataSource.getInstance()
bulkImport,
organizations,
ticks,
history,
media,
users
})

const app = express()

const server = new ApolloServer({
schema,
introspection: false,
plugins: []
})
// server must be started before applying middleware
await server.start()

const context = localDevBypassAuthContext

app.use('/',
bodyParser.json({ limit: '10mb' }),
cors<cors.CorsRequest>(),
Expand All @@ -77,14 +69,14 @@ export const serverTest = dbTest.extend<ServerTestFixtures>({
})
)


await use({
app, server
})

await server.stop()
},

query: async ({ctx}, use) => {
query: async ({ ctx }, use) => {
await use(
async ({
query,
Expand All @@ -103,26 +95,21 @@ export const serverTest = dbTest.extend<ServerTestFixtures>({
'https://tacos.openbeta.io/uuid': userUuid
}
})

const queryObj = { query, operationName, variables }
let req = request(ctx.app)
.post(endpoint)
.send(queryObj)

if (userUuid != null) {
req = req.set('Authorization', 'Bearer placeholder-jwt-see-SpyOn')
}

return await req
}
)
},

user: async ({ task }, use) => await use(muuid.mode('relaxed').from(task.id)),
userUuid: async ({ user }, use) => await use(muuidToString(user)),

usa: async ({ areas }, use) => await use(await areas.addCountry('usa')),
ca: async ({ user, usa, areas }, use) => await use(await areas.addArea(user, 'CA', usa.metadata.area_id)),
wa: async ({ user, usa, areas }, use) => await use(await areas.addArea(user, 'WA', usa.metadata.area_id)),
or: async ({ user, usa, areas }, use) => await use(await areas.addArea(user, 'OR', usa.metadata.area_id))
userUuid: async ({ user }, use) => await use(muuidToString(user))
})
77 changes: 29 additions & 48 deletions src/__tests__/fixtures/mongo.fixtures.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { MongoMemoryReplSet } from 'mongodb-memory-server'
import { ChangeStream, MongoClient } from 'mongodb'
import mongoose, { Model, Mongoose } from 'mongoose'
import mongoose from 'mongoose'
import { checkVar, defaultPostConnect } from '../../db'
import { testStreamListener } from '../../db/edit/streamListener'
import { Mock } from 'vitest'
import { ClimbSchema } from '../../db/ClimbSchema'
import { AreaSchema } from '../../db/AreaSchema'
import { ClimbType } from '../../db/ClimbTypes'
import { AreaType } from '../../db/AreaTypes'
import MutableAreaDataSource from '../../model/MutableAreaDataSource'
import MutableClimbDataSource from '../../model/MutableClimbDataSource'
import { MediaObject } from '../../db/MediaObjectTypes'
import { MediaObjectSchema } from '../../db/MediaObjectSchema'
import BulkImportDataSource from '../../model/BulkImportDataSource'
import ChangeLogDataSource from '../../model/ChangeLogDataSource'
import MutableMediaDataSource from '../../model/MutableMediaDataSource'
import MutableOrganizationDataSource from '../../model/MutableOrganizationDataSource'
import TickDataSource from '../../model/TickDataSource'
import UserDataSource from '../../model/UserDataSource'

/**
* In-memory Mongo replset used for testing.
Expand All @@ -21,12 +21,18 @@ import { MediaObjectSchema } from '../../db/MediaObjectSchema'
let mongod: MongoMemoryReplSet
const onChange: Mock = vi.fn()
let stream: ChangeStream
let uri: string

beforeAll(async () => {
mongod = await MongoMemoryReplSet.create({
// Stream listener listens on DB denoted by 'MONGO_DBNAME' env var.
replSet: { count: 1, storageEngine: 'wiredTiger', dbName: checkVar('MONGO_DBNAME') }
})

uri = await mongod.getUri(checkVar('MONGO_DBNAME'))
await mongoose.connect(uri, { autoIndex: false })
mongoose.set('debug', false) // Set to 'true' to enable verbose mode

stream = await defaultPostConnect(async () => await testStreamListener(onChange))
})

Expand All @@ -39,35 +45,27 @@ afterAll(async () => {

interface DbTestContext {
uri: string
db: Mongoose
client: MongoClient
insertDirectly: (collection: string, documents: any[]) => Promise<void>
climbModel: Model<ClimbType>
areaModel: Model<AreaType>
mediaModel: Model<MediaObject>

areas: MutableAreaDataSource
climbs: MutableClimbDataSource
bulkImport: BulkImportDataSource
organizations: MutableOrganizationDataSource
ticks: TickDataSource
history: ChangeLogDataSource
media: MutableMediaDataSource
users: UserDataSource
}

export const dbTest = test.extend<DbTestContext>({
uri: async ({ task }, use) => await use(await mongod.getUri(task.id)),
client: async ({ task, uri }, use) => {
uri: async ({ }, use) => await use(uri),
client: async ({ uri }, use) => {
const client = new MongoClient(uri)
await use(client)
await client.close()
},
db: async ({ task, uri, client }, use) => {
const mongooseInstance = await mongoose.connect(uri, {
autoIndex: false // Create indices using defaultPostConnect instead.
})

mongoose.set('debug', false) // Set to 'true' to enable verbose mode
await use(mongooseInstance)

// Clear the collections this instance created
await client.db(task.id).dropDatabase()
},
insertDirectly: async ({ task, uri }, use) => {
/**
* Bypass Mongoose to insert data directly into Mongo.
Expand All @@ -92,29 +90,12 @@ export const dbTest = test.extend<DbTestContext>({
await use(insertDirectly)
},

climbModel: async ({ task, db }, use) => {
const climbModel = db.model('climbs', ClimbSchema)
await climbModel.createIndexes()
await use(climbModel)
},

areaModel: async ({ db }, use) => {
const model = db.model('areas', AreaSchema)
await model.createIndexes()
await use(model)
},

mediaModel: async ({ db }, use) => {
const model = db.model('media_objects', MediaObjectSchema)
await model.createIndexes()
await use(model)
},

areas: async ({ climbModel, areaModel, mediaModel, client }, use) => {
await use(new MutableAreaDataSource({ climbModel, areaModel, mediaModel, modelOrCollection: client.db().collection('areas') }))
},

climbs: async ({ climbModel, areaModel, client }, use) => {
await use(new MutableClimbDataSource({ climbModel, areaModel, modelOrCollection: client.db().collection('climbs') }))
}
areas: async ({ }, use) => await use(MutableAreaDataSource.getInstance()),
climbs: async ({ }, use) => await use(MutableClimbDataSource.getInstance()),
bulkImport: async ({ }, use) => await use(BulkImportDataSource.getInstance()),
organizations: async ({ }, use) => await use(MutableOrganizationDataSource.getInstance()),
ticks: async ({ }, use) => await use(TickDataSource.getInstance()),
history: async ({ }, use) => await use(ChangeLogDataSource.getInstance()),
media: async ({ }, use) => await use(MutableMediaDataSource.getInstance()),
users: async ({ }, use) => await use(UserDataSource.getInstance())
})
3 changes: 0 additions & 3 deletions src/__tests__/history.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ApolloServer } from '@apollo/server'
import muuid from 'uuid-mongodb'
import { jest } from '@jest/globals'
import MutableAreaDataSource from '../model/MutableAreaDataSource.js'
import MutableOrganizationDataSource from '../model/MutableOrganizationDataSource.js'
import MutableClimbDataSource from '../model/MutableClimbDataSource.js'
Expand All @@ -11,8 +10,6 @@ import { queryAPI, setUpServer } from '../utils/testUtils.js'
import { InMemoryDB } from '../utils/inMemoryDB.js'
import express from 'express'

jest.setTimeout(60000)

describe('history API', () => {
let server: ApolloServer
let user: muuid.MUUID
Expand Down
3 changes: 0 additions & 3 deletions src/__tests__/ticks.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ApolloServer } from '@apollo/server'
import muuid from 'uuid-mongodb'
import { jest } from '@jest/globals'
import { queryAPI, setUpServer } from '../utils/testUtils.js'
import { muuidToString } from '../utils/helpers.js'
import { TickInput } from '../db/TickTypes.js'
Expand All @@ -10,8 +9,6 @@ import { UpdateProfileGQLInput } from '../db/UserTypes.js'
import { InMemoryDB } from '../utils/inMemoryDB.js'
import express from 'express'

jest.setTimeout(110000)

describe('ticks API', () => {
let server: ApolloServer
let user: muuid.MUUID
Expand Down
9 changes: 7 additions & 2 deletions src/db/export/json/async-file.processor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,13 @@ describe('file processor', () => {
})
}

function withFailedWriteOn (failingData: { name: string }) {
function withFailedWriteOn (failingData: { name: string }): Writer {
return async (data, path) => {
console.log(data, failingData)
if (data === JSON.stringify(failingData)) {
return await Promise.reject('error')
}

return await writer(data, path)
}
}
Expand All @@ -42,7 +44,10 @@ describe('file processor', () => {
it('should continue batch processing on error', async () => {
const processor = createProcessor(withFailedWriteOn(testData[0]))

await expect(processor(testData, 0)).rejects.toContain('Failed to write 1/2 files')
// First, check that our failed writer fires as expected
await expect(() => withFailedWriteOn(testData[0])(JSON.stringify(testData[0]), 'path')).rejects.toContain('error')
// now in the context of a strem, we should expect 1 out of two possible files to fail
await expect(async () => await processor(testData, 0)).rejects.toThrow('Failed to write 1/2 files')

assertWriterCalledFor(testData[1])
})
Expand Down
Loading

0 comments on commit d2a9503

Please sign in to comment.