test-server.ts 3.2 KB

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