@loopback/example-references-many 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +5 -0
- package/.eslintrc.js +8 -0
- package/.prettierignore +2 -0
- package/.prettierrc +7 -0
- package/.vscode/settings.json +20 -0
- package/.vscode/tasks.json +29 -0
- package/CHANGELOG.md +25 -0
- package/Dockerfile +28 -0
- package/LICENSE +25 -0
- package/README.md +49 -0
- package/data/db.json +18 -0
- package/dist/__tests__/acceptance/account.acceptance.d.ts +1 -0
- package/dist/__tests__/acceptance/account.acceptance.js +111 -0
- package/dist/__tests__/acceptance/account.acceptance.js.map +1 -0
- package/dist/__tests__/acceptance/customer.acceptance.d.ts +1 -0
- package/dist/__tests__/acceptance/customer.acceptance.js +163 -0
- package/dist/__tests__/acceptance/customer.acceptance.js.map +1 -0
- package/dist/__tests__/acceptance/home-page.acceptance.d.ts +1 -0
- package/dist/__tests__/acceptance/home-page.acceptance.js +31 -0
- package/dist/__tests__/acceptance/home-page.acceptance.js.map +1 -0
- package/dist/__tests__/acceptance/test-helper.d.ts +7 -0
- package/dist/__tests__/acceptance/test-helper.js +20 -0
- package/dist/__tests__/acceptance/test-helper.js.map +1 -0
- package/dist/__tests__/helpers.d.ts +26 -0
- package/dist/__tests__/helpers.js +101 -0
- package/dist/__tests__/helpers.js.map +1 -0
- package/dist/__tests__/integration/customer.repository.integration.d.ts +1 -0
- package/dist/__tests__/integration/customer.repository.integration.js +61 -0
- package/dist/__tests__/integration/customer.repository.integration.js.map +1 -0
- package/dist/__tests__/unit/controllers/account.controller.unit.d.ts +1 -0
- package/dist/__tests__/unit/controllers/account.controller.unit.js +106 -0
- package/dist/__tests__/unit/controllers/account.controller.unit.js.map +1 -0
- package/dist/__tests__/unit/controllers/customer.controller.unit.d.ts +1 -0
- package/dist/__tests__/unit/controllers/customer.controller.unit.js +108 -0
- package/dist/__tests__/unit/controllers/customer.controller.unit.js.map +1 -0
- package/dist/application.d.ts +272 -0
- package/dist/application.js +41 -0
- package/dist/application.js.map +1 -0
- package/dist/controllers/account.controller.d.ts +15 -0
- package/dist/controllers/account.controller.js +192 -0
- package/dist/controllers/account.controller.js.map +1 -0
- package/dist/controllers/customer.controller.d.ts +15 -0
- package/dist/controllers/customer.controller.js +192 -0
- package/dist/controllers/customer.controller.js.map +1 -0
- package/dist/controllers/index.d.ts +2 -0
- package/dist/controllers/index.js +10 -0
- package/dist/controllers/index.js.map +1 -0
- package/dist/datasources/db.datasource.d.ts +12 -0
- package/dist/datasources/db.datasource.js +34 -0
- package/dist/datasources/db.datasource.js.map +1 -0
- package/dist/datasources/index.d.ts +1 -0
- package/dist/datasources/index.js +9 -0
- package/dist/datasources/index.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +44 -0
- package/dist/index.js.map +1 -0
- package/dist/migrate.d.ts +1 -0
- package/dist/migrate.js +25 -0
- package/dist/migrate.js.map +1 -0
- package/dist/models/account.model.d.ts +9 -0
- package/dist/models/account.model.js +35 -0
- package/dist/models/account.model.js.map +1 -0
- package/dist/models/customer.model.d.ts +13 -0
- package/dist/models/customer.model.js +45 -0
- package/dist/models/customer.model.js.map +1 -0
- package/dist/models/index.d.ts +2 -0
- package/dist/models/index.js +10 -0
- package/dist/models/index.js.map +1 -0
- package/dist/openapi-spec.d.ts +1 -0
- package/dist/openapi-spec.js +28 -0
- package/dist/openapi-spec.js.map +1 -0
- package/dist/repositories/account.repository.d.ts +6 -0
- package/dist/repositories/account.repository.js +23 -0
- package/dist/repositories/account.repository.js.map +1 -0
- package/dist/repositories/customer.repository.d.ts +11 -0
- package/dist/repositories/customer.repository.js +29 -0
- package/dist/repositories/customer.repository.js.map +1 -0
- package/dist/repositories/index.d.ts +2 -0
- package/dist/repositories/index.js +10 -0
- package/dist/repositories/index.js.map +1 -0
- package/dist/sequence.d.ts +3 -0
- package/dist/sequence.js +12 -0
- package/dist/sequence.js.map +1 -0
- package/package.json +78 -0
- package/public/index.html +72 -0
- package/src/__tests__/acceptance/account.acceptance.ts +139 -0
- package/src/__tests__/acceptance/customer.acceptance.ts +198 -0
- package/src/__tests__/acceptance/home-page.acceptance.ts +36 -0
- package/src/__tests__/acceptance/test-helper.ts +29 -0
- package/src/__tests__/helpers.ts +119 -0
- package/src/__tests__/integration/customer.repository.integration.ts +80 -0
- package/src/__tests__/unit/controllers/account.controller.unit.ts +127 -0
- package/src/__tests__/unit/controllers/customer.controller.unit.ts +136 -0
- package/src/application.ts +49 -0
- package/src/controllers/account.controller.ts +177 -0
- package/src/controllers/customer.controller.ts +177 -0
- package/src/controllers/index.ts +7 -0
- package/src/datasources/db.datasource.ts +34 -0
- package/src/datasources/index.ts +6 -0
- package/src/index.ts +42 -0
- package/src/migrate.ts +25 -0
- package/src/models/account.model.ts +31 -0
- package/src/models/customer.model.ts +40 -0
- package/src/models/index.ts +7 -0
- package/src/openapi-spec.ts +28 -0
- package/src/repositories/account.repository.ts +19 -0
- package/src/repositories/customer.repository.ts +42 -0
- package/src/repositories/index.ts +7 -0
- package/src/sequence.ts +8 -0
- package/tsconfig.json +39 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright IBM Corp. and LoopBack contributors 2022. All Rights Reserved.
|
|
3
|
+
// Node module: @loopback/example-references-many
|
|
4
|
+
// This file is licensed under the MIT License.
|
|
5
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
const tslib_1 = require("tslib");
|
|
8
|
+
tslib_1.__exportStar(require("./account.repository"), exports);
|
|
9
|
+
tslib_1.__exportStar(require("./customer.repository"), exports);
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/repositories/index.ts"],"names":[],"mappings":";AAAA,2EAA2E;AAC3E,iDAAiD;AACjD,+CAA+C;AAC/C,gEAAgE;;;AAEhE,+DAAqC;AACrC,gEAAsC"}
|
package/dist/sequence.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Copyright IBM Corp. and LoopBack contributors 2022. All Rights Reserved.
|
|
3
|
+
// Node module: @loopback/example-references-many
|
|
4
|
+
// This file is licensed under the MIT License.
|
|
5
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.MySequence = void 0;
|
|
8
|
+
const rest_1 = require("@loopback/rest");
|
|
9
|
+
class MySequence extends rest_1.MiddlewareSequence {
|
|
10
|
+
}
|
|
11
|
+
exports.MySequence = MySequence;
|
|
12
|
+
//# sourceMappingURL=sequence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sequence.js","sourceRoot":"","sources":["../src/sequence.ts"],"names":[],"mappings":";AAAA,2EAA2E;AAC3E,iDAAiD;AACjD,+CAA+C;AAC/C,gEAAgE;;;AAEhE,yCAAkD;AAElD,MAAa,UAAW,SAAQ,yBAAkB;CAAG;AAArD,gCAAqD"}
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@loopback/example-references-many",
|
|
3
|
+
"description": "Example of the references many relation in LoopBack 4.",
|
|
4
|
+
"version": "6.0.1",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"loopback",
|
|
7
|
+
"LoopBack",
|
|
8
|
+
"example",
|
|
9
|
+
"tutorial",
|
|
10
|
+
"relations",
|
|
11
|
+
"CRUD",
|
|
12
|
+
"models",
|
|
13
|
+
"referenceMany",
|
|
14
|
+
"HasMany"
|
|
15
|
+
],
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"main": "dist/index.js",
|
|
18
|
+
"types": "dist/index.d.ts",
|
|
19
|
+
"author": "IBM Corp. and LoopBack contributors",
|
|
20
|
+
"copyright.owner": "IBM Corp. and LoopBack contributors",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/loopbackio/loopback-next.git",
|
|
24
|
+
"directory": "examples/references-many"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": "14 || 16 || 17 || 18"
|
|
28
|
+
},
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "lb-tsc",
|
|
31
|
+
"build:watch": "lb-tsc --watch",
|
|
32
|
+
"clean": "lb-clean *example-references-many*.tgz dist *.tsbuildinfo package",
|
|
33
|
+
"lint": "npm run prettier:check && npm run eslint",
|
|
34
|
+
"lint:fix": "npm run eslint:fix && npm run prettier:fix",
|
|
35
|
+
"prettier:cli": "lb-prettier \"**/*.ts\"",
|
|
36
|
+
"prettier:check": "npm run prettier:cli -- -l",
|
|
37
|
+
"prettier:fix": "npm run prettier:cli -- --write",
|
|
38
|
+
"eslint": "lb-eslint --report-unused-disable-directives .",
|
|
39
|
+
"eslint:fix": "npm run eslint -- --fix",
|
|
40
|
+
"pretest": "npm run rebuild",
|
|
41
|
+
"test": "lb-mocha \"dist/__tests__/**/*.js\"",
|
|
42
|
+
"test:dev": "lb-mocha --allow-console-logs dist/__tests__/**/*.js && npm run posttest",
|
|
43
|
+
"verify": "npm pack && tar xf loopback-references-many*.tgz && tree package && npm run clean",
|
|
44
|
+
"premigrate": "npm run build ",
|
|
45
|
+
"migrate": "node ./dist/migrate",
|
|
46
|
+
"preopenapi-spec": "npm run build",
|
|
47
|
+
"openapi-spec": "node ./dist/openapi-spec",
|
|
48
|
+
"rebuild": "npm run clean && npm run build",
|
|
49
|
+
"prestart": "npm run rebuild",
|
|
50
|
+
"start": "node ."
|
|
51
|
+
},
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@loopback/boot": "^5.0.1",
|
|
57
|
+
"@loopback/core": "^4.0.1",
|
|
58
|
+
"@loopback/repository": "^5.0.1",
|
|
59
|
+
"@loopback/rest": "^12.0.1",
|
|
60
|
+
"@loopback/rest-explorer": "^5.0.1",
|
|
61
|
+
"@loopback/service-proxy": "^5.0.1",
|
|
62
|
+
"loopback-connector-rest": "^4.0.1",
|
|
63
|
+
"tslib": "^2.4.0"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@loopback/build": "^9.0.1",
|
|
67
|
+
"@loopback/eslint-config": "^13.0.1",
|
|
68
|
+
"@loopback/http-caching-proxy": "^4.0.1",
|
|
69
|
+
"@loopback/repository": "^5.0.1",
|
|
70
|
+
"@loopback/testlab": "^5.0.1",
|
|
71
|
+
"@types/lodash": "^4.14.182",
|
|
72
|
+
"@types/node": "^14.18.21",
|
|
73
|
+
"eslint": "^8.17.0",
|
|
74
|
+
"lodash": "^4.17.21",
|
|
75
|
+
"typescript": "~4.7.3"
|
|
76
|
+
},
|
|
77
|
+
"gitHead": "ccf7863d0639de966d6c6129b4aa94ba1dce2c33"
|
|
78
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<title>myapp</title>
|
|
6
|
+
|
|
7
|
+
<meta charset="utf-8">
|
|
8
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
9
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
10
|
+
<link rel="shortcut icon" type="image/x-icon" href="https://loopback.io/favicon.ico">
|
|
11
|
+
|
|
12
|
+
<style>
|
|
13
|
+
h3 {
|
|
14
|
+
margin-left: 25px;
|
|
15
|
+
text-align: center;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
a, a:visited {
|
|
19
|
+
color: #3f5dff;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
h3 a {
|
|
23
|
+
margin-left: 10px;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
a:hover, a:focus, a:active {
|
|
27
|
+
color: #001956;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.power {
|
|
31
|
+
position: absolute;
|
|
32
|
+
bottom: 25px;
|
|
33
|
+
left: 50%;
|
|
34
|
+
transform: translateX(-50%);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.info {
|
|
38
|
+
position: absolute;
|
|
39
|
+
top: 50%;
|
|
40
|
+
left: 50%;
|
|
41
|
+
transform: translate(-50%, -50%)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.info h1 {
|
|
45
|
+
text-align: center;
|
|
46
|
+
margin-bottom: 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.info p {
|
|
50
|
+
text-align: center;
|
|
51
|
+
margin-bottom: 3em;
|
|
52
|
+
margin-top: 1em;
|
|
53
|
+
}
|
|
54
|
+
</style>
|
|
55
|
+
</head>
|
|
56
|
+
|
|
57
|
+
<body>
|
|
58
|
+
<div class="info">
|
|
59
|
+
<h1>@loopback/example-references-many</h1>
|
|
60
|
+
|
|
61
|
+
<h3>OpenAPI spec: <a href="/openapi.json">/openapi.json</a></h3>
|
|
62
|
+
<h3>API Explorer: <a href="/explorer">/explorer</a></h3>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
<footer class="power">
|
|
66
|
+
<a href="https://loopback.io" target="_blank">
|
|
67
|
+
<img src="https://loopback.io/images/branding/powered-by-loopback/blue/powered-by-loopback-sm.png" />
|
|
68
|
+
</a>
|
|
69
|
+
</footer>
|
|
70
|
+
</body>
|
|
71
|
+
|
|
72
|
+
</html>
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// Copyright IBM Corp. and LoopBack contributors 2019,2020. All Rights Reserved.
|
|
2
|
+
// Node module: @loopback/example-references-many
|
|
3
|
+
// This file is licensed under the MIT License.
|
|
4
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
5
|
+
|
|
6
|
+
import {EntityNotFoundError} from '@loopback/repository';
|
|
7
|
+
import {Client, createRestAppClient, expect, toJSON} from '@loopback/testlab';
|
|
8
|
+
import {ReferencesManyApplication} from '../../application';
|
|
9
|
+
import {Account} from '../../models/';
|
|
10
|
+
import {AccountRepository} from '../../repositories/';
|
|
11
|
+
import {
|
|
12
|
+
givenAccount,
|
|
13
|
+
givenAccountInstance,
|
|
14
|
+
givenAccountRepositories,
|
|
15
|
+
givenRunningApplicationWithCustomConfiguration,
|
|
16
|
+
} from '../helpers';
|
|
17
|
+
|
|
18
|
+
describe('ReferencesManyApplication', () => {
|
|
19
|
+
let app: ReferencesManyApplication;
|
|
20
|
+
let client: Client;
|
|
21
|
+
let accountRepo: AccountRepository;
|
|
22
|
+
|
|
23
|
+
before(async () => {
|
|
24
|
+
app = await givenRunningApplicationWithCustomConfiguration();
|
|
25
|
+
});
|
|
26
|
+
after(() => app.stop());
|
|
27
|
+
|
|
28
|
+
before(async () => {
|
|
29
|
+
({accountRepo} = await givenAccountRepositories(app));
|
|
30
|
+
});
|
|
31
|
+
before(() => {
|
|
32
|
+
client = createRestAppClient(app);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
beforeEach(async () => {
|
|
36
|
+
await accountRepo.deleteAll();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('creates an account', async function () {
|
|
40
|
+
const account = givenAccount();
|
|
41
|
+
const response = await client.post('/accounts').send(account).expect(200);
|
|
42
|
+
expect(response.body).to.containDeep(account);
|
|
43
|
+
const result = await accountRepo.findById(response.body.id);
|
|
44
|
+
expect(result).to.containDeep(account);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('gets a count of accounts', async function () {
|
|
48
|
+
await givenAccountInstance(accountRepo, {balance: 22});
|
|
49
|
+
await givenAccountInstance(accountRepo, {balance: 33});
|
|
50
|
+
await client.get('/accounts/count').expect(200, {count: 2});
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
context('when dealing with a single persisted account', () => {
|
|
54
|
+
let persistedAccount: Account;
|
|
55
|
+
|
|
56
|
+
beforeEach(async () => {
|
|
57
|
+
persistedAccount = await givenAccountInstance(accountRepo);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('gets an account by ID', () => {
|
|
61
|
+
return client
|
|
62
|
+
.get(`/accounts/${persistedAccount.id}`)
|
|
63
|
+
.send()
|
|
64
|
+
.expect(200, toJSON(persistedAccount));
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('returns 404 when getting an account that does not exist', () => {
|
|
68
|
+
return client.get('/accounts/99999').expect(404);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('replaces the account by ID', async () => {
|
|
72
|
+
const updatedAccount = givenAccount({
|
|
73
|
+
balance: 44,
|
|
74
|
+
});
|
|
75
|
+
await client
|
|
76
|
+
.put(`/accounts/${persistedAccount.id}`)
|
|
77
|
+
.send(updatedAccount)
|
|
78
|
+
.expect(204);
|
|
79
|
+
const result = await accountRepo.findById(persistedAccount.id);
|
|
80
|
+
expect(result).to.containEql(updatedAccount);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('returns 404 when replacing an account that does not exist', () => {
|
|
84
|
+
return client.put('/accounts/99999').send(givenAccount()).expect(404);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('updates the account by ID ', async () => {
|
|
88
|
+
const updatedAccount = givenAccount({
|
|
89
|
+
balance: 55,
|
|
90
|
+
});
|
|
91
|
+
await client
|
|
92
|
+
.patch(`/accounts/${persistedAccount.id}`)
|
|
93
|
+
.send(updatedAccount)
|
|
94
|
+
.expect(204);
|
|
95
|
+
const result = await accountRepo.findById(persistedAccount.id);
|
|
96
|
+
expect(result).to.containEql(updatedAccount);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('returns 404 when updating an account that does not exist', () => {
|
|
100
|
+
return client.patch('/account/99999').send(givenAccount()).expect(404);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it('deletes the account', async () => {
|
|
104
|
+
await client.del(`/accounts/${persistedAccount.id}`).send().expect(204);
|
|
105
|
+
await expect(
|
|
106
|
+
accountRepo.findById(persistedAccount.id),
|
|
107
|
+
).to.be.rejectedWith(EntityNotFoundError);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('returns 404 when deleting an account that does not exist', async () => {
|
|
111
|
+
await client.del(`/accounts/99999`).expect(404);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
it('queries accounts with a filter', async () => {
|
|
116
|
+
await givenAccountInstance(accountRepo, {balance: 77});
|
|
117
|
+
|
|
118
|
+
const emptyAccount = await givenAccountInstance(accountRepo, {balance: 0});
|
|
119
|
+
|
|
120
|
+
await client
|
|
121
|
+
.get('/accounts')
|
|
122
|
+
.query({filter: {where: {balance: 0}}})
|
|
123
|
+
.expect(200, [toJSON(emptyAccount)]);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('updates accounts using a filter', async () => {
|
|
127
|
+
await givenAccountInstance(accountRepo, {
|
|
128
|
+
balance: 1,
|
|
129
|
+
});
|
|
130
|
+
await givenAccountInstance(accountRepo, {
|
|
131
|
+
balance: 2,
|
|
132
|
+
});
|
|
133
|
+
await client
|
|
134
|
+
.patch('/accounts')
|
|
135
|
+
.query({where: {balance: 2}})
|
|
136
|
+
.send({balance: 3})
|
|
137
|
+
.expect(200, {count: 1});
|
|
138
|
+
});
|
|
139
|
+
});
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
// Copyright IBM Corp. and LoopBack contributors 2019,2020. All Rights Reserved.
|
|
2
|
+
// Node module: @loopback/example-references-many
|
|
3
|
+
// This file is licensed under the MIT License.
|
|
4
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
5
|
+
|
|
6
|
+
import {EntityNotFoundError} from '@loopback/repository';
|
|
7
|
+
import {Client, createRestAppClient, expect, toJSON} from '@loopback/testlab';
|
|
8
|
+
import {ReferencesManyApplication} from '../../application';
|
|
9
|
+
import {Customer} from '../../models/';
|
|
10
|
+
import {AccountRepository, CustomerRepository} from '../../repositories/';
|
|
11
|
+
import {
|
|
12
|
+
givenAccountInstance,
|
|
13
|
+
givenCustomer,
|
|
14
|
+
givenCustomerInstance,
|
|
15
|
+
givenCustomerRepositories,
|
|
16
|
+
givenRunningApplicationWithCustomConfiguration,
|
|
17
|
+
} from '../helpers';
|
|
18
|
+
|
|
19
|
+
describe('ReferencesManyApplication', () => {
|
|
20
|
+
let app: ReferencesManyApplication;
|
|
21
|
+
let client: Client;
|
|
22
|
+
let customerRepo: CustomerRepository;
|
|
23
|
+
let accountRepo: AccountRepository;
|
|
24
|
+
|
|
25
|
+
before(async () => {
|
|
26
|
+
app = await givenRunningApplicationWithCustomConfiguration();
|
|
27
|
+
});
|
|
28
|
+
after(() => app.stop());
|
|
29
|
+
|
|
30
|
+
before(async () => {
|
|
31
|
+
({customerRepo, accountRepo} = await givenCustomerRepositories(app));
|
|
32
|
+
});
|
|
33
|
+
before(() => {
|
|
34
|
+
client = createRestAppClient(app);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
beforeEach(async () => {
|
|
38
|
+
await customerRepo.deleteAll();
|
|
39
|
+
await accountRepo.deleteAll();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it('creates a customer', async function () {
|
|
43
|
+
const customer = givenCustomer();
|
|
44
|
+
const response = await client.post('/customers').send(customer).expect(200);
|
|
45
|
+
expect(response.body).to.containDeep(customer);
|
|
46
|
+
const result = await customerRepo.findById(response.body.id);
|
|
47
|
+
expect(result).to.containDeep(customer);
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('gets a count of customers', async function () {
|
|
51
|
+
await givenCustomerInstance(customerRepo, {
|
|
52
|
+
firstName: 'Andrew',
|
|
53
|
+
lastName: 'Jackson',
|
|
54
|
+
});
|
|
55
|
+
await givenCustomerInstance(customerRepo, {
|
|
56
|
+
firstName: 'James',
|
|
57
|
+
lastName: 'Gunn',
|
|
58
|
+
});
|
|
59
|
+
await client.get('/customers/count').expect(200, {count: 2});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
context('when dealing with a single persisted customer', () => {
|
|
63
|
+
let persistedCustomer: Customer;
|
|
64
|
+
|
|
65
|
+
beforeEach(async () => {
|
|
66
|
+
persistedCustomer = await givenCustomerInstance(customerRepo);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it('gets a customer by ID', () => {
|
|
70
|
+
return client
|
|
71
|
+
.get(`/customers/${persistedCustomer.id}`)
|
|
72
|
+
.send()
|
|
73
|
+
.expect(200, toJSON(persistedCustomer));
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('returns 404 when getting a customer that does not exist', () => {
|
|
77
|
+
return client.get('/customers/99999').expect(404);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('replaces the customer by ID', async () => {
|
|
81
|
+
const updatedCustomer = givenCustomer({
|
|
82
|
+
firstName: 'Andrew',
|
|
83
|
+
lastName: 'Jackson',
|
|
84
|
+
});
|
|
85
|
+
await client
|
|
86
|
+
.put(`/customers/${persistedCustomer.id}`)
|
|
87
|
+
.send(updatedCustomer)
|
|
88
|
+
.expect(204);
|
|
89
|
+
const result = await customerRepo.findById(persistedCustomer.id);
|
|
90
|
+
expect(result).to.containEql(updatedCustomer);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it('returns 404 when replacing a customer that does not exist', () => {
|
|
94
|
+
return client.put('/customers/99999').send(givenCustomer()).expect(404);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('updates the customer by ID ', async () => {
|
|
98
|
+
const updatedCustomer = givenCustomer({
|
|
99
|
+
firstName: 'Tommy',
|
|
100
|
+
lastName: 'Jeans',
|
|
101
|
+
});
|
|
102
|
+
await client
|
|
103
|
+
.patch(`/customers/${persistedCustomer.id}`)
|
|
104
|
+
.send(updatedCustomer)
|
|
105
|
+
.expect(204);
|
|
106
|
+
const result = await customerRepo.findById(persistedCustomer.id);
|
|
107
|
+
expect(result).to.containEql(updatedCustomer);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('returns 404 when updating a customer that does not exist', () => {
|
|
111
|
+
return client.patch('/customer/99999').send(givenCustomer()).expect(404);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
it('deletes the customer', async () => {
|
|
115
|
+
await client.del(`/customers/${persistedCustomer.id}`).send().expect(204);
|
|
116
|
+
await expect(
|
|
117
|
+
customerRepo.findById(persistedCustomer.id),
|
|
118
|
+
).to.be.rejectedWith(EntityNotFoundError);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('returns 404 when deleting a customer that does not exist', async () => {
|
|
122
|
+
await client.del(`/customers/99999`).expect(404);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it('queries customers with a filter', async () => {
|
|
127
|
+
await givenCustomerInstance(customerRepo, {
|
|
128
|
+
firstName: 'Andrew',
|
|
129
|
+
lastName: 'Jackson',
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const unnamedCustomer = await givenCustomerInstance(customerRepo, {
|
|
133
|
+
firstName: '',
|
|
134
|
+
lastName: '',
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
await client
|
|
138
|
+
.get('/customers')
|
|
139
|
+
.query({filter: {where: {firstName: ''}}})
|
|
140
|
+
.expect(200, [toJSON(unnamedCustomer)]);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('updates customers using a filter', async () => {
|
|
144
|
+
await givenCustomerInstance(customerRepo, {
|
|
145
|
+
firstName: 'Andrew',
|
|
146
|
+
lastName: 'Jackson',
|
|
147
|
+
});
|
|
148
|
+
await givenCustomerInstance(customerRepo, {
|
|
149
|
+
firstName: 'James',
|
|
150
|
+
lastName: 'Gunn',
|
|
151
|
+
});
|
|
152
|
+
await client
|
|
153
|
+
.patch('/customers')
|
|
154
|
+
.query({where: {firstName: 'Andrew'}})
|
|
155
|
+
.send({firstName: 'Tommy'})
|
|
156
|
+
.expect(200, {count: 1});
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
it('includes Accounts in query result', async () => {
|
|
160
|
+
const firstAccount = await givenAccountInstance(accountRepo, {balance: 10});
|
|
161
|
+
const secondAccount = await givenAccountInstance(accountRepo, {
|
|
162
|
+
balance: 20,
|
|
163
|
+
});
|
|
164
|
+
const customer = await givenCustomerInstance(customerRepo);
|
|
165
|
+
const customerWithAccounts = await givenCustomerInstance(customerRepo, {
|
|
166
|
+
accountIds: [firstAccount.id, secondAccount.id],
|
|
167
|
+
});
|
|
168
|
+
const filter = JSON.stringify({include: ['accounts']});
|
|
169
|
+
|
|
170
|
+
const response = await client.get('/customers').query({filter: filter});
|
|
171
|
+
|
|
172
|
+
expect(response.body).to.have.length(2);
|
|
173
|
+
expect(response.body[0]).to.deepEqual({
|
|
174
|
+
...toJSON(customer),
|
|
175
|
+
accounts: [],
|
|
176
|
+
});
|
|
177
|
+
expect(response.body[1]).to.deepEqual({
|
|
178
|
+
...toJSON(customerWithAccounts),
|
|
179
|
+
accounts: [toJSON(firstAccount), toJSON(secondAccount)],
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('not includes a not existed Account in query result', async () => {
|
|
184
|
+
const notExistedId = 1;
|
|
185
|
+
const customer = await givenCustomerInstance(customerRepo, {
|
|
186
|
+
accountIds: [notExistedId],
|
|
187
|
+
});
|
|
188
|
+
const filter = JSON.stringify({include: ['accounts']});
|
|
189
|
+
|
|
190
|
+
const response = await client.get('/customers').query({filter: filter});
|
|
191
|
+
|
|
192
|
+
expect(response.body).to.have.length(1);
|
|
193
|
+
expect(response.body[0]).to.deepEqual({
|
|
194
|
+
...toJSON(customer),
|
|
195
|
+
accounts: [],
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Copyright IBM Corp. and LoopBack contributors 2019,2020. All Rights Reserved.
|
|
2
|
+
// Node module: @loopback/example-references-many
|
|
3
|
+
// This file is licensed under the MIT License.
|
|
4
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
5
|
+
|
|
6
|
+
import {Client} from '@loopback/testlab';
|
|
7
|
+
import {ReferencesManyApplication} from '../..';
|
|
8
|
+
import {setupApplication} from './test-helper';
|
|
9
|
+
|
|
10
|
+
describe('HomePage', () => {
|
|
11
|
+
let app: ReferencesManyApplication;
|
|
12
|
+
let client: Client;
|
|
13
|
+
|
|
14
|
+
before('setupApplication', async () => {
|
|
15
|
+
({app, client} = await setupApplication());
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
after(async () => {
|
|
19
|
+
await app.stop();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('exposes a default home page', async () => {
|
|
23
|
+
await client
|
|
24
|
+
.get('/')
|
|
25
|
+
.expect(200)
|
|
26
|
+
.expect('Content-Type', /text\/html/);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('exposes self-hosted explorer', async () => {
|
|
30
|
+
await client
|
|
31
|
+
.get('/explorer/')
|
|
32
|
+
.expect(200)
|
|
33
|
+
.expect('Content-Type', /text\/html/)
|
|
34
|
+
.expect(/<title>LoopBack API Explorer/);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Copyright IBM Corp. and LoopBack contributors 2019,2020. All Rights Reserved.
|
|
2
|
+
// Node module: @loopback/example-references-many
|
|
3
|
+
// This file is licensed under the MIT License.
|
|
4
|
+
// License text available at https://opensource.org/licenses/MIT
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
Client,
|
|
8
|
+
createRestAppClient,
|
|
9
|
+
givenHttpServerConfig,
|
|
10
|
+
} from '@loopback/testlab';
|
|
11
|
+
import {ReferencesManyApplication} from '../..';
|
|
12
|
+
|
|
13
|
+
export async function setupApplication(): Promise<AppWithClient> {
|
|
14
|
+
const app = new ReferencesManyApplication({
|
|
15
|
+
rest: givenHttpServerConfig(),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
await app.boot();
|
|
19
|
+
await app.start();
|
|
20
|
+
|
|
21
|
+
const client = createRestAppClient(app);
|
|
22
|
+
|
|
23
|
+
return {app, client};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface AppWithClient {
|
|
27
|
+
app: ReferencesManyApplication;
|
|
28
|
+
client: Client;
|
|
29
|
+
}
|