Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ import {BooterApp} from '../fixtures/application';
describe('application metadata booter acceptance tests', () => {
let app: BooterApp;
const sandbox = new TestSandbox(resolve(__dirname, '../../.sandbox'));

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(getApp);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ describe('component application booter acceptance tests', () => {
let app: BooterApp;
const sandbox = new TestSandbox(resolve(__dirname, '../../.sandbox'));

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(getApp);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ describe('controller booter acceptance tests', () => {
let app: BooterApp;
const sandbox = new TestSandbox(resolve(__dirname, '../../.sandbox'));

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(getApp);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ describe('CRUD rest builder acceptance tests', () => {
let app: BooterApp;
const sandbox = new TestSandbox(resolve(__dirname, '../../.sandbox'));

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(givenAppWithDataSource);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ describe('model API booter acceptance tests', () => {
let app: BooterApp;
const sandbox = new TestSandbox(resolve(__dirname, '../../.sandbox'));

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(givenAppWithDataSource);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ describe('controller booter integration tests', () => {

let app: BooterApp;

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(getApp);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ describe('datasource booter integration tests', () => {

let app: BooterApp;

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(getApp);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ describe('interceptor script booter integration tests', () => {

let app: BooterApp;

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(buildAppWithInterceptors);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ describe('lifecycle script booter integration tests', () => {

let app: BooterApp;

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(getApp);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ describe('repository booter integration tests', () => {

let app: BooterApp;

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(getApp);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ describe('repository booter integration tests', () => {

let app: BooterApp;

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(getApp);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ describe('service booter integration tests', () => {

let app: BooterApp;

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(getApp);

Expand Down
2 changes: 2 additions & 0 deletions packages/boot/src/__tests__/unit/booters/booter-utils.unit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import {discoverFiles, isClass, loadClassesFromFiles} from '../../..';
describe('booter-utils unit tests', () => {
const sandbox = new TestSandbox(resolve(__dirname, '../../../.sandbox'));

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());

describe('discoverFiles()', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ describe('controller booter unit tests', () => {

let app: Application;

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(getApp);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ describe('datasource booter unit tests', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let stub: sinon.SinonStub<[any?, ...any[]], void>;

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(getApp);
beforeEach(createStub);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ describe('repository booter unit tests', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let stub: sinon.SinonStub<[any?, ...any[]], void>;

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(getApp);
beforeEach(createStub);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ describe('service booter unit tests', () => {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let stub: sinon.SinonStub<[any?, ...any[]], void>;

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());
beforeEach(getApp);
beforeEach(createStub);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const sandbox = new TestSandbox(path.resolve(__dirname, '../.sandbox'));
describe('cloneExampleFromGitHub (SLOW)', /** @this {Mocha.Suite} */ function () {
this.timeout(20000);

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());

it('extracts project files', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ describe('controller-generator extending BaseGenerator', baseTests);
describe('generator-loopback4:controller', tests);

describe('lb4 controller', () => {
after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());

it('does not run without package.json', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ describe('datasource-generator extending BaseGenerator', baseTests);
describe('generator-loopback4:datasource', tests);

describe('lb4 datasource integration', () => {
after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());

it('does not run without package.json', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ describe('lb4 import-lb3-models', function () {
return loadLb3App(COFFEE_SHOP_EXAMPLE);
}

after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());

it('imports CoffeeShop model from lb3-example app', async () => {
Expand Down
72 changes: 39 additions & 33 deletions packages/cli/test/integration/generators/model.integration.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ describe('model-generator extending BaseGenerator', baseTests);
describe('generator-loopback4:model', tests);

describe('lb4 model integration', () => {
after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());

it('does not run without package.json', () => {
Expand Down Expand Up @@ -261,52 +263,56 @@ describe('lb4 model integration', () => {
basicModelFileChecks(expectedModelFile, expectedIndexFile);
});
});
});

describe('model generator using --config option', () => {
it('create models with valid json', async () => {
await testUtils
.executeGenerator(generator)
.inDir(sandbox.path, () => testUtils.givenLBProject(sandbox.path))
.withArguments(['--config', '{"name":"test", "base":"Entity"}', '--yes']);

basicModelFileChecks(expectedModelFile, expectedIndexFile);
});

it('does not run if pass invalid json', () => {
return expect(
testUtils
describe('model generator using --config option', () => {
it('create models with valid json', async () => {
await testUtils
.executeGenerator(generator)
.inDir(sandbox.path, () => testUtils.givenLBProject(sandbox.path))
.withArguments([
'--config',
'{"name":"test", "base":"InvalidBaseModel"}',
'{"name":"test", "base":"Entity"}',
'--yes',
]),
).to.be.rejectedWith(/Model was not found in/);
});
]);

describe('model generator using --config option with model settings', () => {
it('creates a model with valid settings', async () => {
await testUtils
.executeGenerator(generator)
.inDir(sandbox.path, () => testUtils.givenLBProject(sandbox.path))
.withArguments([
'--config',
'{"name":"test", "base":"Entity", \
basicModelFileChecks(expectedModelFile, expectedIndexFile);
});

it('does not run if pass invalid json', () => {
return expect(
testUtils
.executeGenerator(generator)
.inDir(sandbox.path, () => testUtils.givenLBProject(sandbox.path))
.withArguments([
'--config',
'{"name":"test", "base":"InvalidBaseModel"}',
'--yes',
]),
).to.be.rejectedWith(/Model was not found in/);
});

describe('model generator using --config option with model settings', () => {
it('creates a model with valid settings', async () => {
await testUtils
.executeGenerator(generator)
.inDir(sandbox.path, () => testUtils.givenLBProject(sandbox.path))
.withArguments([
'--config',
'{"name":"test", "base":"Entity", \
"modelSettings": {"annotations": \
[{"destinationClass": "class1","argument": 0}],\
"foreignKeys": {"fk_destination": {"name": "fk_destination"}}},\
"allowAdditionalProperties":true}',
'--yes',
]);
'--yes',
]);

basicModelFileChecks(expectedModelFile, expectedIndexFile);
basicModelFileChecks(expectedModelFile, expectedIndexFile);

assert.fileContent(
expectedModelFile,
/@model\({\n {2}settings: {\n {4}annotations: \[{destinationClass: 'class1', argument: 0}],\n {4}foreignKeys: {fk_destination: {name: 'fk_destination'}},\n {4}strict: false\n {2}}\n}\)/,
);
assert.fileContent(
expectedModelFile,
/@model\({\n {2}settings: {\n {4}annotations: \[{destinationClass: 'class1', argument: 0}],\n {4}foreignKeys: {fk_destination: {name: 'fk_destination'}},\n {4}strict: false\n {2}}\n}\)/,
);
});
});
});
});
2 changes: 2 additions & 0 deletions packages/cli/test/unit/update-index.unit.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const sandbox = new TestSandbox(path.resolve(__dirname, '.sandbox'));
const expectedFile = path.join(sandbox.path, 'index.ts');

describe('update-index unit tests', () => {
after('delete sandbox', () => sandbox.delete());

beforeEach('reset sandbox', () => sandbox.reset());

it('creates index.ts when not present', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,16 @@ describe('TestSandbox integration tests', () => {
expect(await pathExists(path)).to.be.False();
});

it('keeps the test sandbox with KEEP_TEST_SANDBOX env var', async () => {
process.env.KEEP_TEST_SANDBOX = '1';
try {
await sandbox.delete();
expect(await pathExists(path)).to.be.true();
} finally {
delete process.env.KEEP_TEST_SANDBOX;
}
});

describe('after deleting sandbox', () => {
const ERR = 'TestSandbox instance was deleted. Create a new instance.';

Expand Down Expand Up @@ -172,6 +182,6 @@ describe('TestSandbox integration tests', () => {

async function deleteSandbox() {
if (!(await pathExists(path))) return;
await remove(sandbox.path);
await remove(path);
}
});
7 changes: 5 additions & 2 deletions packages/testlab/src/test-sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,13 @@ export class TestSandbox {
}

/**
* Deletes the TestSandbox.
* Deletes the TestSandbox. If `KEEP_TEST_SANDBOX` env variable is set, we
* leave the sandbox directory as-is on the file system.
*/
async delete(): Promise<void> {
await remove(this.path);
if (!process.env.KEEP_TEST_SANDBOX) {
await remove(this.path);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am little bit reluctant to implement env-based behavior inside delete, I think it could be surprising. Can we implement a new method please and find a descriptive name that will make it more clear what is happening or where it should be used?

Since our motivation is to run this code in after/afterEach hooks, maybe cleanupAfterTests could be a better name?

after('delete sandbox', () => sandbox.cleanupAfterTests());

When I was trying to troubleshoot test failures, I found there were many left-over subdirectories under .sandbox. This prevented me from knowing which directory I should look into.

I would like to investigate a way how to let the sandbox cleanup routine detect when a test failed and print a helpful message (something along the lines "sandbox for test XYZ is in directory ABC"). This is probably out of scope of this PR, but if we introduce a new method like cleanupAfterTests, then it will be easier to enhance the behavior in the future.

Do we want to honor this env var in @loopback/testlab for both reset and delete?

I think we should apply ENV-specific behavior in delete only. reset is meant to be called before the tests, I think the test would fail when the sanbox was not cleared because of ENV config.

delete this._path;
}

Expand Down