Skip to content

Commit

Permalink
feat(testing): Add support for e2e tests backed by MySQL/MariaDB
Browse files Browse the repository at this point in the history
Relates to #207
  • Loading branch information
michaelbromley committed Jan 24, 2020
1 parent e44d372 commit dbc591f
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 20 deletions.
2 changes: 2 additions & 0 deletions packages/testing/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@
"sql.js": "^1.0.0"
},
"devDependencies": {
"@types/mysql": "^2.15.8",
"@vendure/core": "^0.7.0",
"mysql": "^2.17.1",
"rimraf": "^3.0.0",
"typescript": "^3.6.4"
}
Expand Down
3 changes: 0 additions & 3 deletions packages/testing/src/data-population/clear-all-tables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,6 @@ export async function clearAllTables(config: VendureConfig, logging = true) {
config = await preBootstrapConfig(config);
const entityIdStrategy = config.entityIdStrategy;
const connection = await createConnection({ ...config.dbConnectionOptions });
if (logging) {
console.log('Clearing all tables...');
}
try {
await connection.synchronize(true);
} catch (err) {
Expand Down
2 changes: 0 additions & 2 deletions packages/testing/src/data-population/populate-for-testing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import fs from 'fs-extra';

import { TestServerOptions } from '../types';

import { clearAllTables } from './clear-all-tables';
import { populateCustomers } from './populate-customers';

// tslint:disable:no-floating-promises
Expand All @@ -23,7 +22,6 @@ export async function populateForTesting(
const originalRequireVerification = config.authOptions.requireVerification;
config.authOptions.requireVerification = false;

await clearAllTables(config, logging);
const [app, worker] = await bootstrapFn(config);

await populateInitialData(app, options.initialData, logging);
Expand Down
103 changes: 89 additions & 14 deletions packages/testing/src/test-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import { NestFactory } from '@nestjs/core';
import { DefaultLogger, Logger, VendureConfig } from '@vendure/core';
import { preBootstrapConfig } from '@vendure/core/dist/bootstrap';
import fs from 'fs';
import { Connection } from 'mysql';
import path from 'path';
import { MysqlConnectionOptions } from 'typeorm/driver/mysql/MysqlConnectionOptions';
import { SqljsConnectionOptions } from 'typeorm/driver/sqljs/SqljsConnectionOptions';

import { populateForTesting } from './data-population/populate-for-testing';
Expand Down Expand Up @@ -31,16 +33,19 @@ export class TestServer {
* is loaded so that the populate step can be skipped, which speeds up the tests significantly.
*/
async init(options: TestServerOptions): Promise<void> {
const dbFilePath = this.getDbFilePath(options.dataDir);
(this.vendureConfig.dbConnectionOptions as Mutable<SqljsConnectionOptions>).location = dbFilePath;
if (!fs.existsSync(dbFilePath)) {
if (options.logging) {
console.log(`Test data not found. Populating database and caching...`);
}
await this.populateInitialData(this.vendureConfig, options);
}
if (options.logging) {
console.log(`Loading test data from "${dbFilePath}"`);
const { type } = this.vendureConfig.dbConnectionOptions;
switch (type) {
case 'sqljs':
await this.initSqljs(options);
break;
case 'mysql':
await this.initMysql(
this.vendureConfig.dbConnectionOptions as MysqlConnectionOptions,
options,
);
break;
default:
throw new Error(`The TestServer does not support the database type "${type}"`);
}
const [app, worker] = await this.bootstrapForTesting(this.vendureConfig);
if (app) {
Expand Down Expand Up @@ -68,15 +73,79 @@ export class TestServer {
}
}

private async initSqljs(options: TestServerOptions) {
const dbFilePath = this.getDbFilePath(options.dataDir);
(this.vendureConfig.dbConnectionOptions as Mutable<SqljsConnectionOptions>).location = dbFilePath;
if (!fs.existsSync(dbFilePath)) {
if (options.logging) {
console.log(`Test data not found. Populating database and caching...`);
}
await this.populateInitialData(this.vendureConfig, options);
}
if (options.logging) {
console.log(`Loading test data from "${dbFilePath}"`);
}
}

private async initMysql(connectionOptions: MysqlConnectionOptions, options: TestServerOptions) {
const filename = this.getCallerFilename(2);
const conn = await this.getMysqlConnection(connectionOptions);
const dbName = 'e2e_' + path.basename(filename).replace(/[^a-z0-9_]/gi, '_');
(connectionOptions as any).database = dbName;
(connectionOptions as any).synchronize = true;
await new Promise((resolve, reject) => {
conn.query(`DROP DATABASE IF EXISTS ${dbName}`, err => {
if (err) {
console.log(err);
reject(err);
return;
}
resolve();
});
});
await new Promise((resolve, reject) => {
conn.query(`CREATE DATABASE IF NOT EXISTS ${dbName}`, err => {
if (err) {
console.log(err);
reject(err);
return;
}
resolve();
});
});
await this.populateInitialData(this.vendureConfig, options);
conn.destroy();
}

private async getMysqlConnection(connectionOptions: MysqlConnectionOptions): Promise<Connection> {
const { createConnection } = await import('mysql');
const conn = createConnection({
host: connectionOptions.host,
port: connectionOptions.port,
user: connectionOptions.username,
password: connectionOptions.password,
});
await new Promise((resolve, reject) => {
conn.connect(err => {
if (err) {
reject(err);
return;
}
resolve();
});
});
return conn;
}

private getDbFilePath(dataDir: string) {
// tslint:disable-next-line:no-non-null-assertion
const testFilePath = this.getCallerFilename(2);
const testFilePath = this.getCallerFilename(3);
const dbFileName = path.basename(testFilePath) + '.sqlite';
const dbFilePath = path.join(dataDir, dbFileName);
return dbFilePath;
}

private getCallerFilename(depth: number) {
private getCallerFilename(depth: number): string {
let pst: ErrorConstructor['prepareStackTrace'];
let stack: any;
let file: any;
Expand Down Expand Up @@ -106,7 +175,11 @@ export class TestServer {
testingConfig: Required<VendureConfig>,
options: TestServerOptions,
): Promise<void> {
(testingConfig.dbConnectionOptions as Mutable<SqljsConnectionOptions>).autoSave = true;
const isSqljs = testingConfig.dbConnectionOptions.type === 'sqljs';
if (isSqljs) {
(testingConfig.dbConnectionOptions as Mutable<SqljsConnectionOptions>).autoSave = true;
(testingConfig.dbConnectionOptions as Mutable<SqljsConnectionOptions>).synchronize = true;
}

const [app, worker] = await populateForTesting(testingConfig, this.bootstrapForTesting, {
logging: false,
Expand All @@ -117,7 +190,9 @@ export class TestServer {
}
await app.close();

(testingConfig.dbConnectionOptions as Mutable<SqljsConnectionOptions>).autoSave = false;
if (isSqljs) {
(testingConfig.dbConnectionOptions as Mutable<SqljsConnectionOptions>).autoSave = false;
}
}

/**
Expand Down
9 changes: 8 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2295,6 +2295,13 @@
resolved "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz#31b7ca6407128a3d2bbc27fe2d21b345397f6197"
integrity sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==

"@types/mysql@^2.15.8":
version "2.15.8"
resolved "https://registry.npmjs.org/@types/mysql/-/mysql-2.15.8.tgz#305172ee6ec530acd16a713f680dbfb4399960a8"
integrity sha512-l0TUdg6KDEaLO75/yjdjksobJDRWv8iZlpRfv/WW1lQZCQDKdTDnKCkeH10oapzP/JTuKiTy6Cvq/sm/0GgcUw==
dependencies:
"@types/node" "*"

"@types/nanoid@^2.1.0":
version "2.1.0"
resolved "https://registry.npmjs.org/@types/nanoid/-/nanoid-2.1.0.tgz#41edfda78986e9127d0dc14de982de766f994020"
Expand Down Expand Up @@ -10904,7 +10911,7 @@ [email protected], mute-stream@~0.0.4:
resolved "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==

mysql@^2.16.0:
mysql@^2.16.0, mysql@^2.17.1:
version "2.17.1"
resolved "https://registry.npmjs.org/mysql/-/mysql-2.17.1.tgz#62bba4a039a9b2f73638cd1652ce50fc6f682899"
integrity sha512-7vMqHQ673SAk5C8fOzTG2LpPcf3bNt0oL3sFpxPEEFp1mdlDcrLK0On7z8ZYKaaHrHwNcQ/MTUz7/oobZ2OyyA==
Expand Down

0 comments on commit dbc591f

Please sign in to comment.