Skip to content

Commit

Permalink
Set up integration tests
Browse files Browse the repository at this point in the history
  • Loading branch information
clayne11 committed Nov 11, 2018
1 parent 6dfc274 commit 9a11386
Show file tree
Hide file tree
Showing 17 changed files with 456 additions and 19 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ WEBPACK_PROXY_SERVER_PORT=3000
PORT=3001
WEBPACK_CLIENT_PORT=4402
WEBPACK_SERVER_PORT=4403
ROOT_URL=http://localhost:3000
42 changes: 42 additions & 0 deletions jest.integration.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"displayName": "ts-express-react-starter-kit - integration",
"setupFiles": [
"raf/polyfill",
"core-js/modules/es7.symbol.async-iterator",
"core-js/modules/es7.symbol.async-iterator"
],
"setupTestFrameworkScriptFile": "./src/__tests__/integrationTestSetup.ts",
"transform": {
"\\.(gql|graphql)$": "jest-transform-graphql",
"\\.(ts|tsx)$": "ts-jest",
".*": "<rootDir>/babel-jest.js"
},
"watchPathIgnorePatterns": ["/lib/*", "/node_modules/*"],
"moduleNameMapper": {
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|html|yml)$": "<rootDir>/src/__mocks__/fileMock.js",
"\\.(scss|css)$": "identity-obj-proxy",
"^client/(.*)": "<rootDir>/src/client/$1",
"^__tests__/(.*)": "<rootDir>/src/__tests__/$1",
"^server/(.*)": "<rootDir>/src/server/$1",
"^universal/(.*)": "<rootDir>/src/universal/$1"
},
"testRegex": "src/?.*/__tests__/.*\\.integ\\.spec\\.(ts|tsx|js|jsx)$",
"moduleFileExtensions": ["ts", "tsx", "js", "jsx", "json"],
"globals": {
"__DEV__": true,
"__SERVER__": false,
"__PROD__": false,
"__HMR__": false,
"ts-jest": {
"tsConfig": "./tsconfig.test.json",
"diagnostics": false
}
},
"globalSetup": "./src/__tests__/integration-global-setup.js",
"globalTeardown": "./src/__tests__/integration-global-teardown.js",
"testEnvironment": "./src/__tests__/integration-environment.js",
"snapshotSerializers": ["enzyme-to-json/serializer"],
"testURL": "http://localhost",
"preset": "ts-jest/presets/js-with-babel",
"testMatch": null
}
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
"generate-schema-and-types": "yarn generate-schema && yarn generate-types",
"lint:ts": "tslint -p tsconfig.json -c ./tslint.json './src/**/*.{ts,tsx}'",
"lint:es": "yarn build:test && eslint --ext .js ./test-build-interim",
"lint:graphql": "eslint -c .eslintrc.graphql.js --ext .graphql --ext .gql ./src",
"lint:graphql": "eslint -c .eslintrc.graphql.js --ext .graphql --ext .gql ./src/code/client",
"lint": "yarn lint:ts && yarn lint:graphql && yarn lint:es",
"test": "node ${UNIT_DEBUG:+--inspect} --max_old_space_size=4096 node_modules/.bin/jest --config ./jest.unit.config.json",
"test:unit": "cross-env NODE_PATH=$NODE_PATH:src node ${UNIT_DEBUG:+--inspect} --max_old_space_size=4096 node_modules/.bin/jest --config ./jest.unit.config.json",
"test:integration": "cross-env NODE_PATH=$NODE_PATH:src node ${INTEG_DEBUG:+--inspect} --max_old_space_size=4096 node_modules/.bin/jest --config ./jest.integration.config.json --forceExit",
"start:client": "cross-env NODE_ENV=development babel-node ./webpack/server.js",
"start:server": "cross-env NODE_ENV=development NODE_PATH=$NODE_PATH:./src babel-node ./webpack/server/webpackServer.js",
"start": "nf -j Procfile.dev start"
Expand Down Expand Up @@ -92,6 +93,7 @@
"jest-environment-node": "^23.4.0",
"jest-transform-graphql": "^2.1.0",
"mkdirp": "^0.5.1",
"mongodb-memory-server": "^2.7.0",
"prettier": "^1.14.3",
"progress-bar-webpack-plugin": "^1.11.0",
"raf": "^3.4.1",
Expand Down Expand Up @@ -138,6 +140,7 @@
"moment": "^2.22.2",
"mongodb": "^3.1.8",
"mongoose": "^5.3.11",
"passport": "^0.4.0",
"qs": "^6.5.2",
"react": "^16.6.0",
"react-apollo": "^2.2.4",
Expand Down
40 changes: 40 additions & 0 deletions src/__tests__/integration-environment.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
const range = require('lodash/range')
const random = require('lodash/random')
const sample = require('lodash/sample')
const NodeEnvironment = require('jest-environment-node')

const LOWERCASE_LETTERS = 'abcdefghijklmnopqrstuvwxyz'

const choice = arrayOrString => sample([...arrayOrString])

const randomString = (charsCount, alphabet = LOWERCASE_LETTERS) =>
range(charsCount)
.map(_ => choice(alphabet))
.join('')

const id = (charsCount = 17) => randomString(charsCount, LOWERCASE_LETTERS)

class IntegrationEnvironment extends NodeEnvironment {
constructor(config) {
super(config)
}

async setup() {
const COLLECTION_PREFIX = `${id()}_`
this.global.COLLECTION_PREFIX = COLLECTION_PREFIX
this.global.PORT = random(3010, 9000)
this.global.ROOT_URL = `http://localhost:${this.global.PORT}`

await super.setup()
}

async teardown() {
await super.teardown()
}

runScript(script) {
return super.runScript(script)
}
}

module.exports = IntegrationEnvironment
21 changes: 21 additions & 0 deletions src/__tests__/integration-global-setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const MongodbMemoryServer = require('mongodb-memory-server')

module.exports = async () => {
global.__TEARDOWN__ = []

const MONGO_DB_NAME = 'jest'
const mongod = new MongodbMemoryServer.default({
instance: {
dbName: MONGO_DB_NAME,
},
binary: {
version: '4.0.4',
},
})

global.__TEARDOWN__.push(async () => {
console.log('Teardown mongod')
await mongod.stop()
})
process.env.MONGODB_URI = await mongod.getConnectionString()
}
3 changes: 3 additions & 0 deletions src/__tests__/integration-global-teardown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = async function() {
await Promise.all(global.__TEARDOWN__.map(fn => fn))
}
24 changes: 24 additions & 0 deletions src/__tests__/integrationTestSetup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import {createApolloServer} from 'code/server/apollo/createApolloServer'
import {runHttpServer} from 'code/server/bootstrap/runHttpServer'
import {setupExternalResources} from 'code/server/bootstrap/setupExternalResources'
import {runStartup, runTeardown} from 'code/server/utils/startup'

/* tslint:disable:no-console */
/* globals PORT */

jest.setTimeout(10000)

beforeAll(async () => {
await setupExternalResources()
await runStartup()
await createApolloServer()
await runHttpServer()
})

afterAll(async () => {
try {
await runTeardown()
} catch (err) {
console.log('err', err)
}
})
3 changes: 2 additions & 1 deletion src/code/client/apollo/createApolloClient.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {DefaultOptions} from 'apollo-client/ApolloClient'
import {getRootUrl} from 'code/server/utils/getUrl'
import graphqlSchema from 'code/universal/graphql-schema.json'
import {createGenericApolloClient} from './createGenericApolloClient'

Expand All @@ -11,7 +12,7 @@ export default ({
initialState: {[x: string]: any}
defaultOptions?: DefaultOptions
}) => {
const uri = 'http://localhost:3000/graphql'
const uri = `${getRootUrl()}/graphql`
const useSubscriptions = true

return createGenericApolloClient({
Expand Down
11 changes: 11 additions & 0 deletions src/code/server/apollo/foo/model/__tests__/fooSchema.integ.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {FooModel} from 'code/server/apollo/foo/model/fooSchema'

describe('fooSchema', () => {
it('should create a foo', async () => {
const title = 'My title'
const foo = await FooModel.create({
title,
})
expect(foo.title).toBe(title)
})
})
12 changes: 10 additions & 2 deletions src/code/server/apollo/foo/model/fooSchema.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import mongoose from 'mongoose'
import {prefixCollection} from 'code/server/utils/prefixCollection'
import mongoose, {Document} from 'mongoose'

export const fooSchema = new mongoose.Schema({
title: {type: String, required: true},
})

export const FooModel = mongoose.model('Foo', fooSchema)
interface FooDocument extends Document {
title: string
}

export const FooModel = mongoose.model<FooDocument>(
prefixCollection('Foo'),
fooSchema
)
3 changes: 2 additions & 1 deletion src/code/server/bootstrap/runHttpServer.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import {getPort} from 'code/server/utils/getPort'
import {httpServer} from '../app'
import {teardown} from '../utils/startup'

/* globals PORT */

const runHttpServer = () =>
new Promise((resolve, reject) => {
const port = typeof PORT !== 'undefined' ? PORT : process.env.PORT
const port = getPort()

if (!port) {
throw new Error(
Expand Down
10 changes: 10 additions & 0 deletions src/code/server/bootstrap/setupExternalResources.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import mongoose from 'mongoose'

export const setupExternalResources = async () => {
await mongoose.connect(
process.env.MONGODB_URI!,
{
useNewUrlParser: true,
}
)
}
11 changes: 4 additions & 7 deletions src/code/server/bootstrap/startup.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,14 @@
import {setupExternalResources} from 'code/server/bootstrap/setupExternalResources'
import {runStartup} from 'code/server/utils/startup'
import {createApolloServer} from '../apollo/createApolloServer'
import {startupSubject} from '../utils/startupSubject'
import {runHttpServer} from './runHttpServer'
import mongoose from 'mongoose'

export const startup = async () => {
await mongoose.connect(
process.env.MONGODB_URI!,
{
useNewUrlParser: true,
}
)
await setupExternalResources()
await createApolloServer()
await runHttpServer()
await runStartup()

require('code/server/webpack')

Expand Down
4 changes: 4 additions & 0 deletions src/code/server/utils/getPort.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* globals PORT */

export const getPort = () =>
typeof PORT !== 'undefined' ? PORT : process.env.PORT
4 changes: 4 additions & 0 deletions src/code/server/utils/getUrl.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/* globals ROOT_URL */

export const getRootUrl = () =>
typeof ROOT_URL !== 'undefined' ? ROOT_URL : process.env.ROOT_URL
11 changes: 11 additions & 0 deletions src/code/server/utils/prefixCollection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* global COLLECTION_PREFIX */

export const getCollectionPrefix = () => {
if (process.env.COLLECTION_PREFIX) {
return process.env.COLLECTION_PREFIX
}

return typeof COLLECTION_PREFIX !== 'undefined' ? COLLECTION_PREFIX : ''
}

export const prefixCollection = collection => getCollectionPrefix() + collection
Loading

0 comments on commit 9a11386

Please sign in to comment.