Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: add acceptance-level tests for repository.execute() #6046

Merged
merged 3 commits into from
Aug 11, 2020
Merged
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
1 change: 1 addition & 0 deletions acceptance/repository-mongodb/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@loopback/eslint-config": "^9.0.0",
"@loopback/repository": "^2.11.0",
"@loopback/repository-tests": "^0.12.11",
"@loopback/testlab": "^3.2.2",
"@types/node": "^10.17.28",
"loopback-connector-mongodb": "^5.3.0",
"tslib": "^2.0.1"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright IBM Corp. 2019. All Rights Reserved.
// Node module: @loopback/test-repository-mongodb
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {
DefaultTransactionalRepository,
Entity,
juggler,
model,
property,
} from '@loopback/repository';
import {expect, toJSON} from '@loopback/testlab';
import {MONGODB_CONFIG} from './mongodb.datasource';

describe('MongoDB repository.execute()', () => {
it('executes a custom MongoDB query', async () => {
const db = new juggler.DataSource(MONGODB_CONFIG);

@model()
class Product extends Entity {
@property({id: true, generated: true})
id: string;

@property({required: true})
name: string;

@property()
owner: string;
}

const repo = new DefaultTransactionalRepository<Product, string, {}>(
Product,
db,
);
await db.automigrate(Product.modelName);
await repo.create({name: 'Pen', owner: 'bajtos'});
await repo.create({name: 'Car', owner: 'admin'});
await repo.create({name: 'Chair', owner: 'admin'});

// MongoDB's aggregate() command returns an AggregationCursor instance
const cursor = await repo.execute('Product', 'aggregate', [
{
$group: {
_id: '$owner',
count: {$sum: 1},
},
},
{
$sort: {
_id: 1,
},
},
]);
// Fetch all items from the cursor at once
const result = await cursor.toArray();

expect(toJSON(result)).to.deepEqual([
{_id: 'admin', count: 2},
{_id: 'bajtos', count: 1},
]);
});
});
3 changes: 3 additions & 0 deletions acceptance/repository-mongodb/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
},
{
"path": "../../packages/repository/tsconfig.json"
},
{
"path": "../../packages/testlab/tsconfig.json"
}
]
}
1 change: 1 addition & 0 deletions acceptance/repository-mysql/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@loopback/eslint-config": "^9.0.0",
"@loopback/repository": "^2.11.0",
"@loopback/repository-tests": "^0.12.11",
"@loopback/testlab": "^3.2.2",
"@types/node": "^10.17.28",
"loopback-connector-mysql": "^5.4.4",
"tslib": "^2.0.1"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright IBM Corp. 2019. All Rights Reserved.
// Node module: @loopback/test-repository-mysql
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {
DefaultTransactionalRepository,
Entity,
juggler,
model,
property,
} from '@loopback/repository';
import {expect, toJSON} from '@loopback/testlab';
import {MYSQL_CONFIG} from './mysql.datasource';

describe('MySQL repository.execute()', () => {
it('executes a parameterized native SQL query', async () => {
const db = new juggler.DataSource(MYSQL_CONFIG);

@model()
class Product extends Entity {
@property({id: true, generated: true})
id: number;

@property({required: true})
name: string;
}

const repo = new DefaultTransactionalRepository<Product, number, {}>(
Product,
db,
);
await db.automigrate(Product.modelName);
const pen = await repo.create({name: 'Pen'});
await repo.create({name: 'Car'});

const result = await repo.execute('SELECT * FROM Product WHERE name = ?', [
'Pen',
]);

expect(toJSON(result)).to.deepEqual([toJSON(pen)]);
});
});
3 changes: 3 additions & 0 deletions acceptance/repository-mysql/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
},
{
"path": "../../packages/repository/tsconfig.json"
},
{
"path": "../../packages/testlab/tsconfig.json"
}
]
}
1 change: 1 addition & 0 deletions acceptance/repository-postgresql/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"@loopback/eslint-config": "^9.0.0",
"@loopback/repository": "^2.11.0",
"@loopback/repository-tests": "^0.12.11",
"@loopback/testlab": "^3.2.2",
"@types/node": "^10.17.28",
"loopback-connector-postgresql": "^5.0.2",
"tslib": "^2.0.1"
Expand Down
1 change: 1 addition & 0 deletions acceptance/repository-postgresql/setup.sh
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
source ./node_modules/loopback-connector-postgresql/setup.sh
export POSTGRESQL_DATABASE=repository_tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright IBM Corp. 2019. All Rights Reserved.
// Node module: @loopback/test-repository-postgresql
// This file is licensed under the MIT License.
// License text available at https://opensource.org/licenses/MIT

import {
DefaultTransactionalRepository,
Entity,
juggler,
model,
property,
} from '@loopback/repository';
import {expect, toJSON} from '@loopback/testlab';
import {POSTGRESQL_CONFIG} from './postgresql.datasource';

describe('PostgreSQL repository.execute()', () => {
// FIXME(bajtos) This test passes when executed in isolation, but fails
// on connection timeout when executed after repository-test suite.
it.skip('executes a parameterized native SQL query', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm interesting. It is indicative of some sort of bug somewhere (maybe a shared global state somehere?). I think we should resolve this.

Copy link
Member Author

Choose a reason for hiding this comment

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

Sure, I agree this needs to be fixed. See #6046 (comment)

I am proposing to skip the failing test for now and investigate the problem more either as part of #3342 or in a follow-up issue.

My primary motivation in this pull request is to ensure MongoDB commands can be executed. I don't want to keep this pull request open for too long, to avoid merge conflicts.

I am going to investigate the failing test as part of #3342, I added a sub-task to the TODO list.

const db = new juggler.DataSource(POSTGRESQL_CONFIG);

@model()
class Product extends Entity {
@property({id: true, generated: true})
id: number;

@property({required: true})
name: string;
}

const repo = new DefaultTransactionalRepository<Product, number, {}>(
Product,
db,
);
await db.automigrate(Product.modelName);
const pen = await repo.create({name: 'Pen'});
await repo.create({name: 'Car'});

const result = await repo.execute('SELECT * FROM Product WHERE name = $1', [
'Pen',
]);

expect(toJSON(result)).to.deepEqual([toJSON(pen)]);
});
});
3 changes: 3 additions & 0 deletions acceptance/repository-postgresql/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
},
{
"path": "../../packages/repository/tsconfig.json"
},
{
"path": "../../packages/testlab/tsconfig.json"
}
]
}
7 changes: 7 additions & 0 deletions packages/repository-tests/src/crud-test-suite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,16 @@ export function crudRepositoryTestSuite(
);
before(
withCrudCtx(function setupGlobalDataSource(ctx: CrudTestContext) {
debug('Initializing the shared datasource instance.');
ctx.dataSource = new juggler.DataSource(ctx.dataSourceOptions);
}),
);
after(
withCrudCtx(function destroyGlobalDataSource(ctx: CrudTestContext) {
debug('Disconnecting the shared datasource instance.');
return ctx.dataSource.disconnect();
}),
);

let testFiles = [];

Expand Down
11 changes: 10 additions & 1 deletion packages/repository-tests/src/crud/transactions.suite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export function transactionSuite(
>;
let tx: Transaction | undefined;
let ds: juggler.DataSource;
let ds2: juggler.DataSource;

before(
withCrudCtx(async function setupRepository(ctx: CrudTestContext) {
ds = ctx.dataSource;
Expand All @@ -85,6 +87,13 @@ export function transactionSuite(
}
});

afterEach(async () => {
if (ds2) {
ds2.disconnect();
(ds2 as unknown) = undefined;
}
});

it('retrieves model instance once transaction is committed', async () => {
tx = await repo.beginTransaction(IsolationLevel.READ_COMMITTED);
const created = await repo.create(
Expand Down Expand Up @@ -149,7 +158,7 @@ export function transactionSuite(
const ds2Options = Object.assign({}, dataSourceOptions);
ds2Options.name = 'anotherDataSource';
ds2Options.database = ds2Options.database + '_new';
const ds2 = new juggler.DataSource(ds2Options);
ds2 = new juggler.DataSource(ds2Options);
const anotherRepo = new repositoryClass(Product, ds2);
await ds2.automigrate(Product.name);

Expand Down