test-server.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. import { INestApplication } from '@nestjs/common';
  2. import { NestFactory } from '@nestjs/core';
  3. import * as fs from 'fs';
  4. import * as path from 'path';
  5. import { ConnectionOptions } from 'typeorm';
  6. import { SqljsConnectionOptions } from 'typeorm/driver/sqljs/SqljsConnectionOptions';
  7. import { populate, PopulateOptions } from '../mock-data/populate';
  8. import { preBootstrapConfig } from '../src/bootstrap';
  9. import { Mutable } from '../src/common/types/common-types';
  10. import { VendureConfig } from '../src/config/vendure-config';
  11. import { testConfig } from './config/test-config';
  12. import { setTestEnvironment } from './test-utils';
  13. // tslint:disable:no-console
  14. /**
  15. * A server against which the e2e tests should be run.
  16. */
  17. export class TestServer {
  18. app: INestApplication;
  19. /**
  20. * Bootstraps an instance of Vendure server and populates the database according to the options
  21. * passed in. Should be called immediately after creating the client in the `beforeAll` function.
  22. *
  23. * The populated data is saved into an .sqlite file for each test file. On subsequent runs, this file
  24. * is loaded so that the populate step can be skipped, which speeds up the tests significantly.
  25. */
  26. async init(options: PopulateOptions, customConfig: Partial<VendureConfig> = {}): Promise<void> {
  27. setTestEnvironment();
  28. const testingConfig = { ...testConfig, ...customConfig };
  29. if (options.logging) {
  30. (testingConfig.dbConnectionOptions as Mutable<ConnectionOptions>).logging = true;
  31. }
  32. const dbFilePath = this.getDbFilePath();
  33. (testingConfig.dbConnectionOptions as Mutable<SqljsConnectionOptions>).location = dbFilePath;
  34. if (!fs.existsSync(dbFilePath)) {
  35. console.log(`Test data not found. Populating database and saving to "${dbFilePath}"`);
  36. await this.populateInitialData(testingConfig, options);
  37. }
  38. console.log(`Loading test data from "${dbFilePath}"`);
  39. this.app = await this.bootstrapForTesting(testingConfig);
  40. }
  41. /**
  42. * Destroy the Vendure instance. Should be called in the `afterAll` function.
  43. */
  44. async destroy() {
  45. await this.app.close();
  46. }
  47. private getDbFilePath() {
  48. const dbDataDir = '__data__';
  49. // tslint:disable-next-line:no-non-null-assertion
  50. const testFilePath = module!.parent!.filename;
  51. const dbFileName = path.basename(testFilePath) + '.sqlite';
  52. const dbFilePath = path.join(path.dirname(testFilePath), dbDataDir, dbFileName);
  53. return dbFilePath;
  54. }
  55. /**
  56. * Populates an .sqlite database file based on the PopulateOptions.
  57. */
  58. private async populateInitialData(testingConfig: VendureConfig, options: PopulateOptions): Promise<void> {
  59. (testingConfig.dbConnectionOptions as Mutable<SqljsConnectionOptions>).autoSave = true;
  60. const app = await populate(testingConfig, this.bootstrapForTesting, {
  61. logging: false,
  62. ...options,
  63. });
  64. await app.close();
  65. (testingConfig.dbConnectionOptions as Mutable<SqljsConnectionOptions>).autoSave = false;
  66. }
  67. /**
  68. * Bootstraps an instance of the Vendure server for testing against.
  69. */
  70. private async bootstrapForTesting(userConfig: Partial<VendureConfig>): Promise<INestApplication> {
  71. const config = await preBootstrapConfig(userConfig);
  72. const appModule = await import('../src/app.module');
  73. const app = await NestFactory.create(appModule.AppModule, { cors: config.cors, logger: false });
  74. await app.listen(config.port);
  75. return app;
  76. }
  77. }