@elasticpath/component-test-framework 1.0.0
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/README.md +147 -0
- package/lib/api.d.ts +28 -0
- package/lib/api.interfaces.d.ts +42 -0
- package/lib/api.interfaces.js +3 -0
- package/lib/api.interfaces.js.map +1 -0
- package/lib/api.js +191 -0
- package/lib/api.js.map +1 -0
- package/lib/elasticsearch.d.ts +6 -0
- package/lib/elasticsearch.js +21 -0
- package/lib/elasticsearch.js.map +1 -0
- package/lib/index.d.ts +7 -0
- package/lib/index.js +14 -0
- package/lib/index.js.map +1 -0
- package/lib/logger.d.ts +2 -0
- package/lib/logger.js +16 -0
- package/lib/logger.js.map +1 -0
- package/lib/mongodb.d.ts +25 -0
- package/lib/mongodb.js +64 -0
- package/lib/mongodb.js.map +1 -0
- package/lib/payload.d.ts +7 -0
- package/lib/payload.js +24 -0
- package/lib/payload.js.map +1 -0
- package/lib/resource.d.ts +15 -0
- package/lib/resource.js +47 -0
- package/lib/resource.js.map +1 -0
- package/lib/resource_store.d.ts +19 -0
- package/lib/resource_store.js +81 -0
- package/lib/resource_store.js.map +1 -0
- package/lib/utils.d.ts +3 -0
- package/lib/utils.js +66 -0
- package/lib/utils.js.map +1 -0
- package/package.json +70 -0
package/README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
## Elasticpath Component Test Framework
|
|
2
|
+
|
|
3
|
+
### Installation
|
|
4
|
+
|
|
5
|
+
*With Yarn*
|
|
6
|
+
```shell
|
|
7
|
+
yarn add --dev @moltin/component-test-framework
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
*With NPM*
|
|
11
|
+
```shell
|
|
12
|
+
npm install --save-dev @moltin/component-test-framework
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Usage
|
|
16
|
+
|
|
17
|
+
The framework exposes a few classes:
|
|
18
|
+
|
|
19
|
+
#### Api
|
|
20
|
+
This is the class responsible for communicating with your API. You can use the methods directly, however, it's usually a better idea to have it as a binding.
|
|
21
|
+
|
|
22
|
+
*Example*
|
|
23
|
+
```javascript
|
|
24
|
+
import { binding, then } from 'cucumber-tsflow'
|
|
25
|
+
import { Api } from 'component-test-framework'
|
|
26
|
+
|
|
27
|
+
@binding([ Api ])
|
|
28
|
+
export default class MyStepDefinitions {
|
|
29
|
+
constructor(protected api: Api) {
|
|
30
|
+
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@then(...)
|
|
34
|
+
public async myStep(): void {
|
|
35
|
+
await this.api.get('/products')
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
...
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Payloads
|
|
42
|
+
Because everything that comes from the Gherkin language is a string, it's impossible to specify literals such as `null`.
|
|
43
|
+
The framework has a `Payload` class to handle such cases. Whenever you want to send a payload to the API, you can use
|
|
44
|
+
```javascript
|
|
45
|
+
const payload = new Payload(table.hashes()[0])
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
#### Type conversions
|
|
49
|
+
The framework is clever when it comes to type conversions. Consider the following Gherkin table
|
|
50
|
+
```
|
|
51
|
+
| null | 123 | foo | "" | [{"foo": "bar"}] |
|
|
52
|
+
```
|
|
53
|
+
When sent to the framework, they are all strings
|
|
54
|
+
```javascript
|
|
55
|
+
[ "null", "123", "foo", "\"\"", "[{\"foo\": \"bar\"}]"]
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The `new Payload` method does some conversion for us. Here's a mapping of the conversion:
|
|
59
|
+
```
|
|
60
|
+
{
|
|
61
|
+
"null": null,
|
|
62
|
+
"123": "123",
|
|
63
|
+
"foo": "foo",
|
|
64
|
+
"\"\"": "",
|
|
65
|
+
"[{"foo": "bar"}]": [{"foo": "bar"}],
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
You may have noticed the number remains a string. The framework *could* convert that, however there are certain cases
|
|
70
|
+
where you need to keep it as a string (a product upc_ean can be specified like a number but is a string).
|
|
71
|
+
Therefore, the framework introduces a special symbol to force an integer. Given the following gherkin table, the framework will parse the first value as
|
|
72
|
+
an integer and leave the second as a string
|
|
73
|
+
```
|
|
74
|
+
| <i>123 | 456 |
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
### ResourceStore
|
|
79
|
+
When working with the API in your component tests, it's often benificial to reference the last created resource
|
|
80
|
+
|
|
81
|
+
*Example*
|
|
82
|
+
```
|
|
83
|
+
Given An admin creates a product
|
|
84
|
+
When They get the created product
|
|
85
|
+
```
|
|
86
|
+
For this, we can use the ResourceStore. When ever you use the API module, it stores the resource that was created, or fetched in the resource store.
|
|
87
|
+
Knowing that, we can create our step definition to easily fetch the last created resource
|
|
88
|
+
|
|
89
|
+
*Example*
|
|
90
|
+
```javascript
|
|
91
|
+
import { ResourceStore } from 'component-test-framework'
|
|
92
|
+
...
|
|
93
|
+
const resource: Resource = ResourceStore.LastCreated('file')
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
We can also get all of the resources under one type
|
|
97
|
+
|
|
98
|
+
*Example*
|
|
99
|
+
```javascript
|
|
100
|
+
import { ResourceStore } from 'component-test-framework'
|
|
101
|
+
...
|
|
102
|
+
const resource = ResourceStore.FetchByType('file')
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
And find a resource
|
|
106
|
+
|
|
107
|
+
*Example*
|
|
108
|
+
```javascript
|
|
109
|
+
import { ResourceStore } from 'component-test-framework'
|
|
110
|
+
...
|
|
111
|
+
const resource = ResourceStore.Find('file', 'id', 'abc-123')
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Each method on the `ResourceStore` returns a `Resource`
|
|
115
|
+
|
|
116
|
+
### Resource
|
|
117
|
+
This is a representation of a resource.
|
|
118
|
+
|
|
119
|
+
```javascript
|
|
120
|
+
const resource = new Resource(data)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
These are usually only created by the ResourceStore. However, there are a few public methods
|
|
124
|
+
|
|
125
|
+
#### asPayload()
|
|
126
|
+
|
|
127
|
+
Useful if you want to build an update payload for your `PUT` request. If no argument is supplied, then the
|
|
128
|
+
resource is returned as a payload, which removes attributes not allowed in payloads (relationships) and nullifies
|
|
129
|
+
values which are string "null"
|
|
130
|
+
|
|
131
|
+
If an argument is supplied, this function will merge the data from that with the current data
|
|
132
|
+
|
|
133
|
+
*Example*
|
|
134
|
+
```javascript
|
|
135
|
+
const resource = ResourceStore.LastCreated('hierarchy')
|
|
136
|
+
const payload = resource.asPayload(table.hashes()[0])
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Publishing
|
|
140
|
+
|
|
141
|
+
Publishing is handled via the GitLab pipeline. On an MR branch, the pipeline checks to see if the version in `package.json` is already
|
|
142
|
+
a published version, and fails if so, letting you know that the version needs to be updated.
|
|
143
|
+
|
|
144
|
+
Actual publishing happens on a merge to main.
|
|
145
|
+
|
|
146
|
+
In the event that a rollback is needed, the rollback MR will fail because the version in `package.json` will exist on NPM. To resolve this,
|
|
147
|
+
you will need to bump the version in `package.json`.
|
package/lib/api.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
import * as FormData from 'form-data';
|
|
3
|
+
import { ApiPayload, ApiResponse, ApiArrayResponse, Error, V2Response, V3Response } from './api.interfaces';
|
|
4
|
+
declare class Api {
|
|
5
|
+
axiosInstance: AxiosInstance;
|
|
6
|
+
private axiosResponseObject;
|
|
7
|
+
private requestPath;
|
|
8
|
+
private requestMethod;
|
|
9
|
+
private readonly defaultHeaders;
|
|
10
|
+
private headers;
|
|
11
|
+
constructor();
|
|
12
|
+
private isError;
|
|
13
|
+
isV3Response(data: V2Response | V3Response): data is V3Response;
|
|
14
|
+
IsV2Response(data: V2Response | V3Response): data is V2Response;
|
|
15
|
+
get errors(): Array<Error> | Array<any>;
|
|
16
|
+
get axiosResponse(): ApiResponse | ApiArrayResponse;
|
|
17
|
+
get(endpoint: string, abortOnError?: boolean): Promise<void>;
|
|
18
|
+
post(endpoint: string, payload: ApiPayload, abortOnError?: boolean): Promise<void>;
|
|
19
|
+
form(endpoint: string, form: FormData, abortOnError?: boolean): Promise<void>;
|
|
20
|
+
put(endpoint: string, payload: ApiPayload, abortOnError?: boolean): Promise<void>;
|
|
21
|
+
delete(endpoint: string, payload?: ApiPayload, abortOnError?: boolean): Promise<void>;
|
|
22
|
+
setHeaders(newHeaders: object, reset?: boolean, preserveValueType?: boolean): void;
|
|
23
|
+
deleteHeader(key: string): void;
|
|
24
|
+
private fail;
|
|
25
|
+
private beautifyError;
|
|
26
|
+
private isEmpty;
|
|
27
|
+
}
|
|
28
|
+
export default Api;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface Error {
|
|
2
|
+
status: string;
|
|
3
|
+
title: string;
|
|
4
|
+
detail: string;
|
|
5
|
+
}
|
|
6
|
+
export interface V2Response {
|
|
7
|
+
id: string;
|
|
8
|
+
type: string;
|
|
9
|
+
[key: string]: any;
|
|
10
|
+
errors?: Array<any>;
|
|
11
|
+
}
|
|
12
|
+
export interface V3Response {
|
|
13
|
+
id: string;
|
|
14
|
+
type: string;
|
|
15
|
+
attributes: {
|
|
16
|
+
[key: string]: any;
|
|
17
|
+
};
|
|
18
|
+
relationships?: any;
|
|
19
|
+
errors?: Array<Error>;
|
|
20
|
+
}
|
|
21
|
+
export interface ApiResponse {
|
|
22
|
+
status: number;
|
|
23
|
+
data: V2Response | V3Response;
|
|
24
|
+
}
|
|
25
|
+
interface V2Payload {
|
|
26
|
+
[key: string]: any;
|
|
27
|
+
}
|
|
28
|
+
interface V3Payload {
|
|
29
|
+
id?: string;
|
|
30
|
+
type?: string;
|
|
31
|
+
attributes: {
|
|
32
|
+
[key: string]: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export interface ApiArrayResponse {
|
|
36
|
+
status: number;
|
|
37
|
+
data: Array<V2Response> | Array<V3Response>;
|
|
38
|
+
}
|
|
39
|
+
export interface ApiPayload {
|
|
40
|
+
data: V2Payload | V3Payload;
|
|
41
|
+
}
|
|
42
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.interfaces.js","sourceRoot":"","sources":["../src/api.interfaces.ts"],"names":[],"mappings":"","sourcesContent":["export interface Error {\n status: string\n title: string\n detail: string\n}\n\nexport interface V2Response {\n id: string\n type: string\n [key: string]: any\n errors?: Array<any> // V2 has inconsistant error responses\n}\n\nexport interface V3Response {\n id: string\n type: string\n attributes: {\n [key: string]: any\n }\n relationships?: any\n errors?: Array<Error>\n}\n\nexport interface ApiResponse {\n status: number\n data: V2Response | V3Response\n}\n\ninterface V2Payload {\n [key: string]: any\n}\n\ninterface V3Payload {\n id?: string\n type?: string\n attributes: {\n [key: string]: string\n }\n}\n\nexport interface ApiArrayResponse {\n status: number\n data: Array<V2Response> | Array<V3Response>\n}\n\nexport interface ApiPayload {\n data: V2Payload | V3Payload\n}\n"]}
|
package/lib/api.js
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const axios_1 = require("axios");
|
|
13
|
+
const AxiosLogger = require("axios-logger");
|
|
14
|
+
const chai_1 = require("chai");
|
|
15
|
+
const resource_store_1 = require("./resource_store");
|
|
16
|
+
const Logger = require("./logger");
|
|
17
|
+
const utils_1 = require("./utils");
|
|
18
|
+
class Api {
|
|
19
|
+
constructor() {
|
|
20
|
+
const { CUCUMBER_BASE_URL, CUCUMBER_LOGGING_LEVEL } = process.env;
|
|
21
|
+
this.defaultHeaders = {
|
|
22
|
+
'content-type': 'application/json',
|
|
23
|
+
};
|
|
24
|
+
this.headers = this.defaultHeaders;
|
|
25
|
+
this.axiosInstance = axios_1.default.create({
|
|
26
|
+
baseURL: CUCUMBER_BASE_URL,
|
|
27
|
+
timeout: 4000,
|
|
28
|
+
timeoutErrorMessage: `[Fail] Api request timed out. Is the service running on ${CUCUMBER_BASE_URL}`,
|
|
29
|
+
});
|
|
30
|
+
this.axiosInstance.interceptors.request.use((config) => {
|
|
31
|
+
// eslint-disable-next-line no-param-reassign
|
|
32
|
+
config.headers.accept = 'application/json';
|
|
33
|
+
return config;
|
|
34
|
+
});
|
|
35
|
+
if (CUCUMBER_LOGGING_LEVEL === 'debug') {
|
|
36
|
+
this.axiosInstance.interceptors.request.use(AxiosLogger.requestLogger);
|
|
37
|
+
this.axiosInstance.interceptors.response.use(AxiosLogger.responseLogger);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
isError(response) {
|
|
41
|
+
return this.axiosResponseObject.isAxiosError !== undefined;
|
|
42
|
+
}
|
|
43
|
+
isV3Response(data) {
|
|
44
|
+
if (this.isError(this.axiosResponseObject)) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return data.attributes !== undefined;
|
|
48
|
+
}
|
|
49
|
+
IsV2Response(data) {
|
|
50
|
+
return !this.isV3Response(data);
|
|
51
|
+
}
|
|
52
|
+
get errors() {
|
|
53
|
+
// Response data is never an array if there's errors
|
|
54
|
+
if (Array.isArray(this.axiosResponse.data)) {
|
|
55
|
+
Logger.error('Attempted to access errors on an array response');
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return this.axiosResponse.data.errors;
|
|
59
|
+
}
|
|
60
|
+
get axiosResponse() {
|
|
61
|
+
var _a, _b;
|
|
62
|
+
if (this.isError(this.axiosResponseObject)) {
|
|
63
|
+
let status;
|
|
64
|
+
// Status exists in a different place depending on an API request failure or
|
|
65
|
+
// a general AxiosError
|
|
66
|
+
if (Object.prototype.hasOwnProperty.call(this.axiosResponseObject, 'code')) {
|
|
67
|
+
status = this.axiosResponseObject.code;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
status = this.axiosResponseObject.response.status;
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
status: parseInt(status, 10),
|
|
74
|
+
data: (_b = (_a = this.axiosResponseObject) === null || _a === void 0 ? void 0 : _a.response) === null || _b === void 0 ? void 0 : _b.data,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return Object.assign({ status: this.axiosResponseObject.status }, this.axiosResponseObject.data);
|
|
78
|
+
}
|
|
79
|
+
get(endpoint, abortOnError = true) {
|
|
80
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
81
|
+
this.requestPath = endpoint;
|
|
82
|
+
this.requestMethod = 'GET';
|
|
83
|
+
this.axiosResponseObject = yield this.axiosInstance
|
|
84
|
+
.get(endpoint, { headers: this.headers })
|
|
85
|
+
.catch((err) => this.fail(err, abortOnError));
|
|
86
|
+
if (!this.isError(this.axiosResponseObject) && !this.isEmpty(this.axiosResponseObject)) {
|
|
87
|
+
resource_store_1.default.Store(this.axiosResponseObject.data);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
post(endpoint, payload, abortOnError = true) {
|
|
92
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
93
|
+
this.requestPath = endpoint;
|
|
94
|
+
this.requestMethod = 'POST';
|
|
95
|
+
this.axiosResponseObject = yield this.axiosInstance
|
|
96
|
+
.post(endpoint, payload, { headers: this.headers })
|
|
97
|
+
.catch((err) => this.fail(err, abortOnError));
|
|
98
|
+
if (!this.isError(this.axiosResponseObject)) {
|
|
99
|
+
resource_store_1.default.Store(this.axiosResponseObject.data);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
form(endpoint, form, abortOnError = true) {
|
|
104
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
105
|
+
this.requestPath = endpoint;
|
|
106
|
+
this.requestMethod = 'POST';
|
|
107
|
+
const headers = Object.assign(Object.assign({}, this.headers), form.getHeaders());
|
|
108
|
+
this.axiosResponseObject = yield this.axiosInstance
|
|
109
|
+
.post(endpoint, form, { headers })
|
|
110
|
+
.catch((err) => this.fail(err, abortOnError));
|
|
111
|
+
if (!this.isError(this.axiosResponseObject)) {
|
|
112
|
+
resource_store_1.default.Store(this.axiosResponseObject.data);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
put(endpoint, payload, abortOnError = true) {
|
|
117
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
118
|
+
this.requestPath = endpoint;
|
|
119
|
+
this.requestMethod = 'PUT';
|
|
120
|
+
this.axiosResponseObject = yield this.axiosInstance
|
|
121
|
+
.put(endpoint, payload, { headers: this.headers })
|
|
122
|
+
.catch((err) => this.fail(err, abortOnError));
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
delete(endpoint, payload, abortOnError = true) {
|
|
126
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
127
|
+
this.requestPath = endpoint;
|
|
128
|
+
this.requestMethod = 'DELETE';
|
|
129
|
+
// For some reason, axios delete requests specify the payload and headers in the same object
|
|
130
|
+
const config = Object.assign(Object.assign({}, payload), { headers: this.headers });
|
|
131
|
+
this.axiosResponseObject = yield this.axiosInstance
|
|
132
|
+
.delete(endpoint, config)
|
|
133
|
+
.catch((err) => this.fail(err, abortOnError));
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
// setHeaders will merge the new headers with the current ones, overwriting if
|
|
137
|
+
// the same key exists. The value will use nullOrValue to properly map strings to literals ('null' => null)
|
|
138
|
+
setHeaders(newHeaders, reset = false, preserveValueType = false) {
|
|
139
|
+
if (reset) {
|
|
140
|
+
this.headers = {};
|
|
141
|
+
}
|
|
142
|
+
Object.entries(newHeaders).forEach((h) => {
|
|
143
|
+
let value = h[1];
|
|
144
|
+
if (!preserveValueType) {
|
|
145
|
+
value = (0, utils_1.nullOrValue)(value);
|
|
146
|
+
}
|
|
147
|
+
return Object.assign(this.headers, {
|
|
148
|
+
[h[0]]: value,
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
deleteHeader(key) {
|
|
153
|
+
delete this.headers[key];
|
|
154
|
+
}
|
|
155
|
+
fail(error, abortOnError) {
|
|
156
|
+
if (abortOnError) {
|
|
157
|
+
this.beautifyError(error);
|
|
158
|
+
chai_1.expect.fail(error.message);
|
|
159
|
+
}
|
|
160
|
+
return error;
|
|
161
|
+
}
|
|
162
|
+
beautifyError(error) {
|
|
163
|
+
var _a, _b, _c, _d;
|
|
164
|
+
if (error.response) {
|
|
165
|
+
Logger.error(`Failed requesting ${this.requestMethod.toUpperCase()} ${process.env.CUCUMBER_BASE_URL}${this.requestPath}`);
|
|
166
|
+
if (((_b = (_a = error.response) === null || _a === void 0 ? void 0 : _a.data) === null || _b === void 0 ? void 0 : _b.errors) !== undefined) {
|
|
167
|
+
Logger.error((_d = (_c = error.response) === null || _c === void 0 ? void 0 : _c.data) === null || _d === void 0 ? void 0 : _d.errors);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
Logger.error('[FATAL ERROR]', error, '\n');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
// eslint-disable-next-line class-methods-use-this
|
|
175
|
+
isEmpty(response) {
|
|
176
|
+
if (!response.data) {
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
if (Array.isArray(response.data.data)) {
|
|
180
|
+
if (response.data.data.length === 0) {
|
|
181
|
+
return true;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
else if (Object.keys(response.data.data).length === 0) {
|
|
185
|
+
return true;
|
|
186
|
+
}
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
exports.default = Api;
|
|
191
|
+
//# sourceMappingURL=api.js.map
|
package/lib/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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","sourcesContent":["import Axios, { AxiosInstance, AxiosError, AxiosResponse, AxiosRequestConfig } from 'axios'\nimport * as AxiosLogger from 'axios-logger'\nimport * as FormData from 'form-data'\nimport { expect } from 'chai'\n\nimport { ApiPayload, ApiResponse, ApiArrayResponse, Error, V2Response, V3Response } from './api.interfaces'\nimport ResourceStore from './resource_store'\nimport * as Logger from './logger'\nimport { nullOrValue } from './utils'\n\nclass Api {\n public axiosInstance: AxiosInstance\n\n private axiosResponseObject: AxiosResponse | AxiosError\n\n private requestPath: string\n\n private requestMethod: string\n\n // We can't add this to the interceptors because we sometimes\n // need to overwrite this\n private readonly defaultHeaders: object\n\n private headers: object\n\n public constructor() {\n const { CUCUMBER_BASE_URL, CUCUMBER_LOGGING_LEVEL } = process.env\n\n this.defaultHeaders = {\n 'content-type': 'application/json',\n }\n this.headers = this.defaultHeaders\n\n this.axiosInstance = Axios.create({\n baseURL: CUCUMBER_BASE_URL,\n timeout: 4000,\n timeoutErrorMessage: `[Fail] Api request timed out. Is the service running on ${CUCUMBER_BASE_URL}`,\n })\n\n this.axiosInstance.interceptors.request.use((config: AxiosRequestConfig) => {\n // eslint-disable-next-line no-param-reassign\n config.headers.accept = 'application/json'\n return config\n })\n\n if (CUCUMBER_LOGGING_LEVEL === 'debug') {\n this.axiosInstance.interceptors.request.use(AxiosLogger.requestLogger)\n this.axiosInstance.interceptors.response.use(AxiosLogger.responseLogger)\n }\n }\n\n private isError(response): response is AxiosError {\n return (<AxiosError>this.axiosResponseObject).isAxiosError !== undefined\n }\n\n public isV3Response(data: V2Response | V3Response): data is V3Response {\n if (this.isError(this.axiosResponseObject)) {\n return false\n }\n\n return <V3Response>data.attributes !== undefined\n }\n\n public IsV2Response(data: V2Response | V3Response): data is V2Response {\n return !this.isV3Response(data)\n }\n\n public get errors(): Array<Error> | Array<any> {\n // Response data is never an array if there's errors\n if (Array.isArray(this.axiosResponse.data)) {\n Logger.error('Attempted to access errors on an array response')\n return null\n }\n\n return this.axiosResponse.data.errors\n }\n\n public get axiosResponse(): ApiResponse | ApiArrayResponse {\n if (this.isError(this.axiosResponseObject)) {\n let status\n\n // Status exists in a different place depending on an API request failure or\n // a general AxiosError\n if (Object.prototype.hasOwnProperty.call(this.axiosResponseObject, 'code')) {\n status = this.axiosResponseObject.code\n } else {\n status = this.axiosResponseObject.response.status\n }\n\n return {\n status: parseInt(status, 10),\n data: this.axiosResponseObject?.response?.data,\n } as ApiResponse\n }\n\n return {\n status: this.axiosResponseObject.status,\n // add everything else from the response\n ...this.axiosResponseObject.data,\n }\n }\n\n public async get(endpoint: string, abortOnError: boolean = true): Promise<void> {\n this.requestPath = endpoint\n this.requestMethod = 'GET'\n\n this.axiosResponseObject = await this.axiosInstance\n .get(endpoint, { headers: this.headers })\n .catch((err) => this.fail(err, abortOnError))\n\n if (!this.isError(this.axiosResponseObject) && !this.isEmpty(this.axiosResponseObject)) {\n ResourceStore.Store(this.axiosResponseObject.data)\n }\n }\n\n public async post(endpoint: string, payload: ApiPayload, abortOnError: boolean = true): Promise<void> {\n this.requestPath = endpoint\n this.requestMethod = 'POST'\n\n this.axiosResponseObject = await this.axiosInstance\n .post(endpoint, payload, { headers: this.headers })\n .catch((err) => this.fail(err, abortOnError))\n\n if (!this.isError(this.axiosResponseObject)) {\n ResourceStore.Store(this.axiosResponseObject.data)\n }\n }\n\n public async form(endpoint: string, form: FormData, abortOnError: boolean = true): Promise<void> {\n this.requestPath = endpoint\n this.requestMethod = 'POST'\n const headers = { ...this.headers, ...form.getHeaders() }\n\n this.axiosResponseObject = await this.axiosInstance\n .post(endpoint, form, { headers })\n .catch((err) => this.fail(err, abortOnError))\n\n if (!this.isError(this.axiosResponseObject)) {\n ResourceStore.Store(this.axiosResponseObject.data)\n }\n }\n\n public async put(endpoint: string, payload: ApiPayload, abortOnError: boolean = true): Promise<void> {\n this.requestPath = endpoint\n this.requestMethod = 'PUT'\n\n this.axiosResponseObject = await this.axiosInstance\n .put(endpoint, payload, { headers: this.headers })\n .catch((err) => this.fail(err, abortOnError))\n }\n\n public async delete(endpoint: string, payload?: ApiPayload, abortOnError: boolean = true): Promise<void> {\n this.requestPath = endpoint\n this.requestMethod = 'DELETE'\n // For some reason, axios delete requests specify the payload and headers in the same object\n const config = {\n ...payload,\n ...{ headers: this.headers },\n }\n\n this.axiosResponseObject = await this.axiosInstance\n .delete(endpoint, config)\n .catch((err) => this.fail(err, abortOnError))\n }\n\n // setHeaders will merge the new headers with the current ones, overwriting if\n // the same key exists. The value will use nullOrValue to properly map strings to literals ('null' => null)\n public setHeaders(newHeaders: object, reset: boolean = false, preserveValueType: boolean = false): void {\n if (reset) {\n this.headers = {}\n }\n\n Object.entries(newHeaders).forEach((h) => {\n let value = h[1]\n if (!preserveValueType) {\n value = nullOrValue(value)\n }\n return Object.assign(this.headers, {\n [h[0]]: value,\n })\n })\n }\n\n public deleteHeader(key: string) {\n delete this.headers[key]\n }\n\n private fail(error: AxiosError, abortOnError: boolean): AxiosError {\n if (abortOnError) {\n this.beautifyError(error)\n expect.fail(error.message)\n }\n\n return error\n }\n\n private beautifyError(error: any): void {\n if (error.response) {\n Logger.error(\n `Failed requesting ${this.requestMethod.toUpperCase()} ${process.env.CUCUMBER_BASE_URL}${this.requestPath}`,\n )\n\n if (error.response?.data?.errors !== undefined) {\n Logger.error(error.response?.data?.errors)\n }\n } else {\n Logger.error('[FATAL ERROR]', error, '\\n')\n }\n }\n\n // eslint-disable-next-line class-methods-use-this\n private isEmpty(response: AxiosResponse): boolean {\n if (!response.data) {\n return true\n }\n\n if (Array.isArray(response.data.data)) {\n if (response.data.data.length === 0) {\n return true\n }\n } else if (Object.keys(response.data.data).length === 0) {\n return true\n }\n\n return false\n }\n}\n\nexport default Api\n"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const elasticsearch_1 = require("@elastic/elasticsearch");
|
|
4
|
+
const Logger = require("./logger");
|
|
5
|
+
class Elasticsearch {
|
|
6
|
+
constructor() {
|
|
7
|
+
if (!process.env.ELS_URL) {
|
|
8
|
+
Logger.error('No Elasticsearch URL specified');
|
|
9
|
+
Logger.error('Please update the .env file to provide an ELS_URL');
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
this.elsClient = new elasticsearch_1.Client({
|
|
13
|
+
node: process.env.ELS_URL,
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
get client() {
|
|
17
|
+
return this.elsClient;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.default = Elasticsearch;
|
|
21
|
+
//# sourceMappingURL=elasticsearch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elasticsearch.js","sourceRoot":"","sources":["../src/elasticsearch.ts"],"names":[],"mappings":";;AAAA,0DAA+C;AAC/C,mCAAkC;AAElC,MAAqB,aAAa;IAGhC;QACE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE;YACxB,MAAM,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAA;YAC9C,MAAM,CAAC,KAAK,CAAC,mDAAmD,CAAC,CAAA;YACjE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;SAChB;QACD,IAAI,CAAC,SAAS,GAAG,IAAI,sBAAM,CAAC;YAC1B,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,OAAO;SAC1B,CAAC,CAAA;IACJ,CAAC;IAED,IAAW,MAAM;QACf,OAAO,IAAI,CAAC,SAAS,CAAA;IACvB,CAAC;CACF;AAjBD,gCAiBC","sourcesContent":["import { Client } from '@elastic/elasticsearch'\nimport * as Logger from './logger'\n\nexport default class Elasticsearch {\n private readonly elsClient: Client\n\n public constructor() {\n if (!process.env.ELS_URL) {\n Logger.error('No Elasticsearch URL specified')\n Logger.error('Please update the .env file to provide an ELS_URL')\n process.exit(1)\n }\n this.elsClient = new Client({\n node: process.env.ELS_URL,\n })\n }\n\n public get client() {\n return this.elsClient\n }\n}\n"]}
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import Api from './api';
|
|
2
|
+
import MongoDB from './mongodb';
|
|
3
|
+
import Payload from './payload';
|
|
4
|
+
import ResourceStore from './resource_store';
|
|
5
|
+
import { Resource } from './resource';
|
|
6
|
+
import { V2Response, V3Response } from './api.interfaces';
|
|
7
|
+
export { Api, MongoDB, Payload, Resource, ResourceStore, V2Response, V3Response };
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ResourceStore = exports.Resource = exports.Payload = exports.MongoDB = exports.Api = void 0;
|
|
4
|
+
const api_1 = require("./api");
|
|
5
|
+
exports.Api = api_1.default;
|
|
6
|
+
const mongodb_1 = require("./mongodb");
|
|
7
|
+
exports.MongoDB = mongodb_1.default;
|
|
8
|
+
const payload_1 = require("./payload");
|
|
9
|
+
exports.Payload = payload_1.default;
|
|
10
|
+
const resource_store_1 = require("./resource_store");
|
|
11
|
+
exports.ResourceStore = resource_store_1.default;
|
|
12
|
+
const resource_1 = require("./resource");
|
|
13
|
+
Object.defineProperty(exports, "Resource", { enumerable: true, get: function () { return resource_1.Resource; } });
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,+BAAuB;AAOd,cAPF,aAAG,CAOE;AANZ,uCAA+B;AAMjB,kBANP,iBAAO,CAMO;AALrB,uCAA+B;AAKR,kBALhB,iBAAO,CAKgB;AAJ9B,qDAA4C;AAIF,wBAJnC,wBAAa,CAImC;AAHvD,yCAAqC;AAGL,yFAHvB,mBAAQ,OAGuB","sourcesContent":["import Api from './api'\nimport MongoDB from './mongodb'\nimport Payload from './payload'\nimport ResourceStore from './resource_store'\nimport { Resource } from './resource'\nimport { V2Response, V3Response } from './api.interfaces'\n\nexport { Api, MongoDB, Payload, Resource, ResourceStore, V2Response, V3Response }\n"]}
|
package/lib/logger.d.ts
ADDED
package/lib/logger.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/* eslint-disable no-console */
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.error = exports.debug = void 0;
|
|
5
|
+
const debug = (...stuff) => {
|
|
6
|
+
if (process.env.LOG_LEVEL !== 'debug') {
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
console.log(stuff);
|
|
10
|
+
};
|
|
11
|
+
exports.debug = debug;
|
|
12
|
+
const error = (...stuff) => {
|
|
13
|
+
console.error(...stuff);
|
|
14
|
+
};
|
|
15
|
+
exports.error = error;
|
|
16
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":";AAAA,+BAA+B;;;AAExB,MAAM,KAAK,GAAG,CAAC,GAAG,KAAU,EAAQ,EAAE;IAC3C,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,OAAO,EAAE;QACrC,OAAM;KACP;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAA;AACpB,CAAC,CAAA;AANY,QAAA,KAAK,SAMjB;AAEM,MAAM,KAAK,GAAG,CAAC,GAAG,KAAU,EAAQ,EAAE;IAC3C,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,CAAA;AACzB,CAAC,CAAA;AAFY,QAAA,KAAK,SAEjB","sourcesContent":["/* eslint-disable no-console */\n\nexport const debug = (...stuff: any): void => {\n if (process.env.LOG_LEVEL !== 'debug') {\n return\n }\n\n console.log(stuff)\n}\n\nexport const error = (...stuff: any): void => {\n console.error(...stuff)\n}\n"]}
|
package/lib/mongodb.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Collection } from 'mongodb';
|
|
2
|
+
export default class MongoDB {
|
|
3
|
+
private client;
|
|
4
|
+
/**
|
|
5
|
+
* Sets up the MongoDB Client
|
|
6
|
+
*/
|
|
7
|
+
constructor();
|
|
8
|
+
/**
|
|
9
|
+
* Connects to the Mongo Database.
|
|
10
|
+
*/
|
|
11
|
+
connect(): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Returns all MongoDB Collections.
|
|
14
|
+
*/
|
|
15
|
+
getAllCollections(): Promise<Collection<any>[]>;
|
|
16
|
+
/**
|
|
17
|
+
* Returns a specific Collection.
|
|
18
|
+
*/
|
|
19
|
+
collection(name: string): Collection;
|
|
20
|
+
/**
|
|
21
|
+
* Closes the MongoDB connection.
|
|
22
|
+
* @return Promise<void>
|
|
23
|
+
*/
|
|
24
|
+
close(): Promise<void>;
|
|
25
|
+
}
|
package/lib/mongodb.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const mongodb_1 = require("mongodb");
|
|
13
|
+
const Logger = require("./logger");
|
|
14
|
+
class MongoDB {
|
|
15
|
+
/**
|
|
16
|
+
* Sets up the MongoDB Client
|
|
17
|
+
*/
|
|
18
|
+
constructor() {
|
|
19
|
+
if (!process.env.MONGO_DSN) {
|
|
20
|
+
Logger.error('No Mongo DSN specified');
|
|
21
|
+
Logger.error('Please update the .env file to provide a MONGO_DSN');
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
this.client = new mongodb_1.MongoClient(process.env.MONGO_DSN, {
|
|
25
|
+
serverSelectionTimeoutMS: 4000,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Connects to the Mongo Database.
|
|
30
|
+
*/
|
|
31
|
+
connect() {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
yield this.client.connect().catch((e) => {
|
|
34
|
+
Logger.error('Could not connect to MongoDB:', e);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Returns all MongoDB Collections.
|
|
41
|
+
*/
|
|
42
|
+
getAllCollections() {
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
+
return this.client.db(process.env.MONGO_DB).collections();
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Returns a specific Collection.
|
|
49
|
+
*/
|
|
50
|
+
collection(name) {
|
|
51
|
+
return this.client.db(process.env.MONGO_DB).collection(name);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Closes the MongoDB connection.
|
|
55
|
+
* @return Promise<void>
|
|
56
|
+
*/
|
|
57
|
+
close() {
|
|
58
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
yield this.client.close();
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
exports.default = MongoDB;
|
|
64
|
+
//# sourceMappingURL=mongodb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mongodb.js","sourceRoot":"","sources":["../src/mongodb.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,qCAAqC;AAErC,mCAAkC;AAElC,MAAqB,OAAO;IAG1B;;OAEG;IACH;QACE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE;YAC1B,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;YACtC,MAAM,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAA;YAClE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;SAChB;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,qBAAW,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE;YACnD,wBAAwB,EAAE,IAAI;SAC/B,CAAC,CAAA;IACJ,CAAC;IAED;;OAEG;IACU,OAAO;;YAClB,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;gBACtC,MAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE,CAAC,CAAC,CAAA;gBAChD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;YACjB,CAAC,CAAC,CAAA;QACJ,CAAC;KAAA;IAED;;OAEG;IACU,iBAAiB;;YAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAA;QAC3D,CAAC;KAAA;IAED;;OAEG;IACI,UAAU,CAAC,IAAY;QAC5B,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;IAC9D,CAAC;IAED;;;OAGG;IACU,KAAK;;YAChB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QAC3B,CAAC;KAAA;CACF;AAjDD,0BAiDC","sourcesContent":["import { MongoClient } from 'mongodb'\nimport type { Collection } from 'mongodb'\nimport * as Logger from './logger'\n\nexport default class MongoDB {\n private client: MongoClient\n\n /**\n * Sets up the MongoDB Client\n */\n public constructor() {\n if (!process.env.MONGO_DSN) {\n Logger.error('No Mongo DSN specified')\n Logger.error('Please update the .env file to provide a MONGO_DSN')\n process.exit(1)\n }\n\n this.client = new MongoClient(process.env.MONGO_DSN, {\n serverSelectionTimeoutMS: 4000,\n })\n }\n\n /**\n * Connects to the Mongo Database.\n */\n public async connect(): Promise<void> {\n await this.client.connect().catch((e) => {\n Logger.error('Could not connect to MongoDB:', e)\n process.exit(1)\n })\n }\n\n /**\n * Returns all MongoDB Collections.\n */\n public async getAllCollections(): Promise<Collection<any>[]> {\n return this.client.db(process.env.MONGO_DB).collections()\n }\n\n /**\n * Returns a specific Collection.\n */\n public collection(name: string): Collection {\n return this.client.db(process.env.MONGO_DB).collection(name)\n }\n\n /**\n * Closes the MongoDB connection.\n * @return Promise<void>\n */\n public async close(): Promise<void> {\n await this.client.close()\n }\n}\n"]}
|
package/lib/payload.d.ts
ADDED
package/lib/payload.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_1 = require("./utils");
|
|
4
|
+
// Returns data formatted as a payload, converting string "null" to literal null
|
|
5
|
+
class Payload {
|
|
6
|
+
constructor(type, data) {
|
|
7
|
+
const clone = data;
|
|
8
|
+
if (Object.prototype.hasOwnProperty.call(data, 'attributes')) {
|
|
9
|
+
Object.keys(data.attributes).forEach((key) => {
|
|
10
|
+
clone.attributes[key] = (0, utils_1.nullOrValue)(data.attributes[key]);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
else {
|
|
14
|
+
Object.keys(data).forEach((key) => {
|
|
15
|
+
clone[key] = (0, utils_1.nullOrValue)(data[key]);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
clone.type = type;
|
|
19
|
+
// eslint-disable-next-line no-constructor-return
|
|
20
|
+
return clone;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.default = Payload;
|
|
24
|
+
//# sourceMappingURL=payload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"payload.js","sourceRoot":"","sources":["../src/payload.ts"],"names":[],"mappings":";;AAAA,mCAAqC;AAMrC,gFAAgF;AAChF,MAAM,OAAO;IACX,YAAY,IAAY,EAAE,IAAc;QACtC,MAAM,KAAK,GAAG,IAAI,CAAA;QAElB,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE;YAC5D,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;gBAC3C,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,IAAA,mBAAW,EAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAA;YAC3D,CAAC,CAAC,CAAA;SACH;aAAM;YACL,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;gBAChC,KAAK,CAAC,GAAG,CAAC,GAAG,IAAA,mBAAW,EAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;YACrC,CAAC,CAAC,CAAA;SACH;QAED,KAAK,CAAC,IAAI,GAAG,IAAI,CAAA;QAEjB,iDAAiD;QACjD,OAAO,KAAK,CAAA;IACd,CAAC;CACF;AAED,kBAAe,OAAO,CAAA","sourcesContent":["import { nullOrValue } from './utils'\n\ninterface KeyValue {\n [key: string]: any\n}\n\n// Returns data formatted as a payload, converting string \"null\" to literal null\nclass Payload {\n constructor(type: string, data: KeyValue) {\n const clone = data\n\n if (Object.prototype.hasOwnProperty.call(data, 'attributes')) {\n Object.keys(data.attributes).forEach((key) => {\n clone.attributes[key] = nullOrValue(data.attributes[key])\n })\n } else {\n Object.keys(data).forEach((key) => {\n clone[key] = nullOrValue(data[key])\n })\n }\n\n clone.type = type\n\n // eslint-disable-next-line no-constructor-return\n return clone\n }\n}\n\nexport default Payload\n"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface Attributes {
|
|
2
|
+
[key: string]: any;
|
|
3
|
+
}
|
|
4
|
+
export interface ResourceData {
|
|
5
|
+
id: string;
|
|
6
|
+
type: string;
|
|
7
|
+
attributes?: Attributes;
|
|
8
|
+
[key: string]: any;
|
|
9
|
+
}
|
|
10
|
+
export declare class Resource {
|
|
11
|
+
data: ResourceData;
|
|
12
|
+
constructor(type: string, attributes: any);
|
|
13
|
+
asPayload(updateAttributes?: Attributes): ResourceData;
|
|
14
|
+
}
|
|
15
|
+
export {};
|
package/lib/resource.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Resource = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
class Resource {
|
|
6
|
+
constructor(type, attributes) {
|
|
7
|
+
this.data = Object.assign({ type }, attributes);
|
|
8
|
+
// eslint-disable-next-line no-constructor-return
|
|
9
|
+
return this;
|
|
10
|
+
}
|
|
11
|
+
// Returns the resource as a payload, removing all attributes that cannot appear
|
|
12
|
+
// in a payload, as well as converting values from string "null" to literal null
|
|
13
|
+
asPayload(updateAttributes) {
|
|
14
|
+
var _a, _b;
|
|
15
|
+
(_a = this.data) === null || _a === void 0 ? true : delete _a.meta;
|
|
16
|
+
(_b = this.data) === null || _b === void 0 ? true : delete _b.relationships;
|
|
17
|
+
if (!updateAttributes) {
|
|
18
|
+
return this.data;
|
|
19
|
+
}
|
|
20
|
+
const clonedUpdate = updateAttributes;
|
|
21
|
+
// Loop through all update attributes and nullify the key
|
|
22
|
+
// if its value is string "null"
|
|
23
|
+
Object.keys(updateAttributes).forEach((key) => {
|
|
24
|
+
clonedUpdate[key] = (0, utils_1.nullOrValue)(updateAttributes[key]);
|
|
25
|
+
});
|
|
26
|
+
const clone = this.data;
|
|
27
|
+
// For those test cases where you want to remove or change these
|
|
28
|
+
// attributes to assert an error
|
|
29
|
+
if (Object.prototype.hasOwnProperty.call(clonedUpdate, 'id')) {
|
|
30
|
+
this.data.id = clonedUpdate.id;
|
|
31
|
+
delete clonedUpdate.id; // so we don't put it in the attributes
|
|
32
|
+
}
|
|
33
|
+
if (Object.prototype.hasOwnProperty.call(clonedUpdate, 'type')) {
|
|
34
|
+
this.data.type = updateAttributes.type;
|
|
35
|
+
delete clonedUpdate.type; // so we don't put it in the attributes
|
|
36
|
+
}
|
|
37
|
+
if (Object.prototype.hasOwnProperty.call(this.data, 'attributes')) {
|
|
38
|
+
this.data.attributes = Object.assign(clone.attributes, clonedUpdate);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
this.data = Object.assign(clone, clonedUpdate);
|
|
42
|
+
}
|
|
43
|
+
return this.data;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.Resource = Resource;
|
|
47
|
+
//# sourceMappingURL=resource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource.js","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":";;;AAAA,mCAAqC;AAcrC,MAAa,QAAQ;IAGnB,YAAY,IAAY,EAAE,UAAe;QACvC,IAAI,CAAC,IAAI,mBACP,IAAI,IACD,UAAU,CACd,CAAA;QACD,iDAAiD;QACjD,OAAO,IAAI,CAAA;IACb,CAAC;IAED,gFAAgF;IAChF,gFAAgF;IACzE,SAAS,CAAC,gBAA6B;;QACrC,MAAA,IAAI,CAAC,IAAI,+CAAE,IAAI,CAAA;QACf,MAAA,IAAI,CAAC,IAAI,+CAAE,aAAa,CAAA;QAE/B,IAAI,CAAC,gBAAgB,EAAE;YACrB,OAAO,IAAI,CAAC,IAAI,CAAA;SACjB;QAED,MAAM,YAAY,GAAG,gBAAgB,CAAA;QAErC,yDAAyD;QACzD,gCAAgC;QAChC,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;YAC5C,YAAY,CAAC,GAAG,CAAC,GAAG,IAAA,mBAAW,EAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAA;QACxD,CAAC,CAAC,CAAA;QAEF,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAA;QAEvB,gEAAgE;QAChE,gCAAgC;QAChC,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,EAAE;YAC5D,IAAI,CAAC,IAAI,CAAC,EAAE,GAAG,YAAY,CAAC,EAAE,CAAA;YAC9B,OAAO,YAAY,CAAC,EAAE,CAAA,CAAC,uCAAuC;SAC/D;QAED,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE;YAC9D,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAA;YACtC,OAAO,YAAY,CAAC,IAAI,CAAA,CAAC,uCAAuC;SACjE;QAED,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE;YACjE,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;SACrE;aAAM;YACL,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,CAAA;SAC/C;QAED,OAAO,IAAI,CAAC,IAAI,CAAA;IAClB,CAAC;CACF;AApDD,4BAoDC","sourcesContent":["import { nullOrValue } from './utils'\n\ninterface Attributes {\n [key: string]: any\n}\n\nexport interface ResourceData {\n id: string\n type: string\n attributes?: Attributes\n // Allow for V2 resources\n [key: string]: any\n}\n\nexport class Resource {\n public data: ResourceData\n\n constructor(type: string, attributes: any) {\n this.data = {\n type,\n ...attributes,\n }\n // eslint-disable-next-line no-constructor-return\n return this\n }\n\n // Returns the resource as a payload, removing all attributes that cannot appear\n // in a payload, as well as converting values from string \"null\" to literal null\n public asPayload(updateAttributes?: Attributes) {\n delete this.data?.meta\n delete this.data?.relationships\n\n if (!updateAttributes) {\n return this.data\n }\n\n const clonedUpdate = updateAttributes\n\n // Loop through all update attributes and nullify the key\n // if its value is string \"null\"\n Object.keys(updateAttributes).forEach((key) => {\n clonedUpdate[key] = nullOrValue(updateAttributes[key])\n })\n\n const clone = this.data\n\n // For those test cases where you want to remove or change these\n // attributes to assert an error\n if (Object.prototype.hasOwnProperty.call(clonedUpdate, 'id')) {\n this.data.id = clonedUpdate.id\n delete clonedUpdate.id // so we don't put it in the attributes\n }\n\n if (Object.prototype.hasOwnProperty.call(clonedUpdate, 'type')) {\n this.data.type = updateAttributes.type\n delete clonedUpdate.type // so we don't put it in the attributes\n }\n\n if (Object.prototype.hasOwnProperty.call(this.data, 'attributes')) {\n this.data.attributes = Object.assign(clone.attributes, clonedUpdate)\n } else {\n this.data = Object.assign(clone, clonedUpdate)\n }\n\n return this.data\n }\n}\n"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ApiResponse, ApiArrayResponse } from './api.interfaces';
|
|
2
|
+
import { ResourceData, Resource } from './resource';
|
|
3
|
+
export default class ResourceStore {
|
|
4
|
+
private static resources;
|
|
5
|
+
static FetchByType(type: string): ResourceData;
|
|
6
|
+
/**
|
|
7
|
+
* Finds the resource by looking for the key and value
|
|
8
|
+
* @param type {string} the type of resource
|
|
9
|
+
* @param key {string} a JSON path string. Eg: attributes.name
|
|
10
|
+
* @param value {any} the value to look for
|
|
11
|
+
* @return {Resource | undefined}
|
|
12
|
+
*/
|
|
13
|
+
static Find(type: string, key: string, value: any): Resource;
|
|
14
|
+
static LastCreated(type: string): ResourceData;
|
|
15
|
+
private static isArrayResponse;
|
|
16
|
+
static Store(responses: ApiResponse | ApiArrayResponse): void;
|
|
17
|
+
static Clear(): void;
|
|
18
|
+
private static getResourceType;
|
|
19
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const chai_1 = require("chai");
|
|
4
|
+
const resource_1 = require("./resource");
|
|
5
|
+
class ResourceStore {
|
|
6
|
+
static FetchByType(type) {
|
|
7
|
+
return this.resources[type];
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Finds the resource by looking for the key and value
|
|
11
|
+
* @param type {string} the type of resource
|
|
12
|
+
* @param key {string} a JSON path string. Eg: attributes.name
|
|
13
|
+
* @param value {any} the value to look for
|
|
14
|
+
* @return {Resource | undefined}
|
|
15
|
+
*/
|
|
16
|
+
static Find(type, key, value) {
|
|
17
|
+
const resources = this.resources[type] || [];
|
|
18
|
+
return resources.find((resource) => {
|
|
19
|
+
let target = resource;
|
|
20
|
+
if (key.indexOf('.') > -1) {
|
|
21
|
+
target = key.split('.').reduce((original, i) => original === null || original === void 0 ? void 0 : original[i], target);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
target = resource[key];
|
|
25
|
+
}
|
|
26
|
+
return target === value;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/*
|
|
30
|
+
Returns the last created resource
|
|
31
|
+
@param type string The type of the resource, eg: product
|
|
32
|
+
@return The Resource
|
|
33
|
+
*/
|
|
34
|
+
static LastCreated(type) {
|
|
35
|
+
const resources = this.resources[type] || [];
|
|
36
|
+
return resources[resources.length - 1];
|
|
37
|
+
}
|
|
38
|
+
static isArrayResponse(responses) {
|
|
39
|
+
var _a;
|
|
40
|
+
return ((_a = responses === null || responses === void 0 ? void 0 : responses.data) === null || _a === void 0 ? void 0 : _a.length) !== undefined;
|
|
41
|
+
}
|
|
42
|
+
static Store(responses) {
|
|
43
|
+
const type = this.getResourceType(responses);
|
|
44
|
+
if (!Object.prototype.hasOwnProperty.call(this.resources, type)) {
|
|
45
|
+
this.resources[type] = [];
|
|
46
|
+
}
|
|
47
|
+
if (this.isArrayResponse(responses)) {
|
|
48
|
+
;
|
|
49
|
+
responses.data.forEach((data) => {
|
|
50
|
+
const resource = new resource_1.Resource(type, data);
|
|
51
|
+
this.resources[type].push(resource.data);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
const resource = new resource_1.Resource(type, responses.data);
|
|
56
|
+
this.resources[type].push(resource.data);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
static Clear() {
|
|
60
|
+
this.resources = [];
|
|
61
|
+
}
|
|
62
|
+
// Gets the type of the resource, taking in to account an array API response, where it will
|
|
63
|
+
// infer the type from the first object
|
|
64
|
+
static getResourceType(responses) {
|
|
65
|
+
var _a;
|
|
66
|
+
if (this.isArrayResponse(responses)) {
|
|
67
|
+
if (responses.data[0] === undefined) {
|
|
68
|
+
chai_1.expect.fail('Could not find any resources in the response');
|
|
69
|
+
}
|
|
70
|
+
return (_a = responses.data[0]) === null || _a === void 0 ? void 0 : _a.type;
|
|
71
|
+
}
|
|
72
|
+
if (responses.data === undefined) {
|
|
73
|
+
chai_1.expect.fail('Could not a resource in the response');
|
|
74
|
+
}
|
|
75
|
+
return responses.data.type;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Contains a list of resources (singular keys for the resource type eg: flow/product)
|
|
79
|
+
ResourceStore.resources = [];
|
|
80
|
+
exports.default = ResourceStore;
|
|
81
|
+
//# sourceMappingURL=resource_store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource_store.js","sourceRoot":"","sources":["../src/resource_store.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect } from 'chai'\n\nimport { ApiResponse, ApiArrayResponse, V3Response, V2Response } from './api.interfaces'\nimport { ResourceData, Resource } from './resource'\n\nexport default class ResourceStore {\n // Contains a list of resources (singular keys for the resource type eg: flow/product)\n private static resources: Array<ResourceData> = []\n\n public static FetchByType(type: string): ResourceData {\n return this.resources[type]\n }\n\n /**\n * Finds the resource by looking for the key and value\n * @param type {string} the type of resource\n * @param key {string} a JSON path string. Eg: attributes.name\n * @param value {any} the value to look for\n * @return {Resource | undefined}\n */\n public static Find(type: string, key: string, value: any): Resource {\n const resources = this.resources[type] || []\n\n return resources.find((resource) => {\n let target = resource\n if (key.indexOf('.') > -1) {\n target = key.split('.').reduce((original, i) => original?.[i], target)\n } else {\n target = resource[key]\n }\n\n return target === value\n })\n }\n\n /*\n Returns the last created resource\n @param type string The type of the resource, eg: product\n @return The Resource\n */\n public static LastCreated(type: string): ResourceData {\n const resources = this.resources[type] || []\n return resources[resources.length - 1]\n }\n\n private static isArrayResponse(responses: ApiResponse | ApiArrayResponse): boolean {\n return (responses as ApiArrayResponse)?.data?.length !== undefined\n }\n\n public static Store(responses: ApiResponse | ApiArrayResponse): void {\n const type = this.getResourceType(responses)\n\n if (!Object.prototype.hasOwnProperty.call(this.resources, type)) {\n this.resources[type] = []\n }\n\n if (this.isArrayResponse(responses)) {\n ;(responses.data as Array<V3Response | V2Response>).forEach((data) => {\n const resource = new Resource(type, data)\n this.resources[type].push(resource.data)\n })\n } else {\n const resource = new Resource(type, responses.data)\n this.resources[type].push(resource.data)\n }\n }\n\n public static Clear(): void {\n this.resources = []\n }\n\n // Gets the type of the resource, taking in to account an array API response, where it will\n // infer the type from the first object\n private static getResourceType(responses: ApiResponse | ApiArrayResponse): string {\n if (this.isArrayResponse(responses)) {\n if (responses.data[0] === undefined) {\n expect.fail('Could not find any resources in the response')\n }\n return responses.data[0]?.type\n }\n\n if (responses.data === undefined) {\n expect.fail('Could not a resource in the response')\n }\n return (responses as ApiResponse).data.type\n }\n}\n"]}
|
package/lib/utils.d.ts
ADDED
package/lib/utils.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Capitalize = exports.Pluralize = exports.nullOrValue = void 0;
|
|
4
|
+
const Logger = require("./logger");
|
|
5
|
+
/*
|
|
6
|
+
Values from the component tests are always strings. Some times we
|
|
7
|
+
want to actually nullify a value. This makes sure any string 'null' is
|
|
8
|
+
parsed as literal null as well as some other type conversions
|
|
9
|
+
*/
|
|
10
|
+
const nullOrValue = (value) => {
|
|
11
|
+
if (value === true || value === false) {
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
if (value === 'null') {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
if (value === '""') {
|
|
18
|
+
return '';
|
|
19
|
+
}
|
|
20
|
+
if (value === undefined) {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
if (value === 'true') {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
if (value === 'false') {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
let returnValue = value;
|
|
30
|
+
if (typeof value === 'string') {
|
|
31
|
+
// We can't just parseInt the string if it's numeric like "123" because
|
|
32
|
+
// a product upc_ean can be numeric but the api expects it as a string still
|
|
33
|
+
if (value.match('<i>') !== null) {
|
|
34
|
+
return parseInt(value.replace('<i>', ''), 10);
|
|
35
|
+
}
|
|
36
|
+
if (value.match('<f>') !== null) {
|
|
37
|
+
return parseFloat(value.replace('<f>', ''));
|
|
38
|
+
}
|
|
39
|
+
if (value.match(/^\[|{/)) {
|
|
40
|
+
try {
|
|
41
|
+
returnValue = JSON.parse(value);
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
Logger.error('Failed to parse JSON value', value);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return returnValue;
|
|
49
|
+
};
|
|
50
|
+
exports.nullOrValue = nullOrValue;
|
|
51
|
+
const Pluralize = (word) => {
|
|
52
|
+
const oddities = {
|
|
53
|
+
hierarchy: 'hierarchies',
|
|
54
|
+
};
|
|
55
|
+
if (Object.prototype.hasOwnProperty.call(oddities, word)) {
|
|
56
|
+
return oddities[word];
|
|
57
|
+
}
|
|
58
|
+
return `${word}s`;
|
|
59
|
+
};
|
|
60
|
+
exports.Pluralize = Pluralize;
|
|
61
|
+
const Capitalize = (word) => word
|
|
62
|
+
.split(/[_-]/)
|
|
63
|
+
.map((w) => `${w.charAt(0).toUpperCase()}${w.slice(1)}`)
|
|
64
|
+
.join('');
|
|
65
|
+
exports.Capitalize = Capitalize;
|
|
66
|
+
//# sourceMappingURL=utils.js.map
|
package/lib/utils.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;AAAA,mCAAkC;AAElC;;;;GAIG;AACI,MAAM,WAAW,GAAG,CAAC,KAAU,EAAO,EAAE;IAC7C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,KAAK,EAAE;QACrC,OAAO,KAAK,CAAA;KACb;IAED,IAAI,KAAK,KAAK,MAAM,EAAE;QACpB,OAAO,IAAI,CAAA;KACZ;IAED,IAAI,KAAK,KAAK,IAAI,EAAE;QAClB,OAAO,EAAE,CAAA;KACV;IAED,IAAI,KAAK,KAAK,SAAS,EAAE;QACvB,OAAO,SAAS,CAAA;KACjB;IAED,IAAI,KAAK,KAAK,MAAM,EAAE;QACpB,OAAO,IAAI,CAAA;KACZ;IAED,IAAI,KAAK,KAAK,OAAO,EAAE;QACrB,OAAO,KAAK,CAAA;KACb;IAED,IAAI,WAAW,GAAG,KAAK,CAAA;IAEvB,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;QAC7B,uEAAuE;QACvE,4EAA4E;QAC5E,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE;YAC/B,OAAO,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;SAC9C;QACD,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE;YAC/B,OAAO,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAA;SAC5C;QAED,IAAI,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;YACxB,IAAI;gBACF,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;aAChC;YAAC,OAAO,CAAC,EAAE;gBACV,MAAM,CAAC,KAAK,CAAC,4BAA4B,EAAE,KAAK,CAAC,CAAA;aAClD;SACF;KACF;IAED,OAAO,WAAW,CAAA;AACpB,CAAC,CAAA;AA/CY,QAAA,WAAW,eA+CvB;AAEM,MAAM,SAAS,GAAG,CAAC,IAAY,EAAU,EAAE;IAChD,MAAM,QAAQ,GAAG;QACf,SAAS,EAAE,aAAa;KACzB,CAAA;IAED,IAAI,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE;QACxD,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAA;KACtB;IAED,OAAO,GAAG,IAAI,GAAG,CAAA;AACnB,CAAC,CAAA;AAVY,QAAA,SAAS,aAUrB;AAEM,MAAM,UAAU,GAAG,CAAC,IAAY,EAAU,EAAE,CACjD,IAAI;KACD,KAAK,CAAC,MAAM,CAAC;KACb,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;KACvD,IAAI,CAAC,EAAE,CAAC,CAAA;AAJA,QAAA,UAAU,cAIV","sourcesContent":["import * as Logger from './logger'\n\n/*\n Values from the component tests are always strings. Some times we\n want to actually nullify a value. This makes sure any string 'null' is\n parsed as literal null as well as some other type conversions\n */\nexport const nullOrValue = (value: any): any => {\n if (value === true || value === false) {\n return value\n }\n\n if (value === 'null') {\n return null\n }\n\n if (value === '\"\"') {\n return ''\n }\n\n if (value === undefined) {\n return undefined\n }\n\n if (value === 'true') {\n return true\n }\n\n if (value === 'false') {\n return false\n }\n\n let returnValue = value\n\n if (typeof value === 'string') {\n // We can't just parseInt the string if it's numeric like \"123\" because\n // a product upc_ean can be numeric but the api expects it as a string still\n if (value.match('<i>') !== null) {\n return parseInt(value.replace('<i>', ''), 10)\n }\n if (value.match('<f>') !== null) {\n return parseFloat(value.replace('<f>', ''))\n }\n\n if (value.match(/^\\[|{/)) {\n try {\n returnValue = JSON.parse(value)\n } catch (e) {\n Logger.error('Failed to parse JSON value', value)\n }\n }\n }\n\n return returnValue\n}\n\nexport const Pluralize = (word: string): string => {\n const oddities = {\n hierarchy: 'hierarchies',\n }\n\n if (Object.prototype.hasOwnProperty.call(oddities, word)) {\n return oddities[word]\n }\n\n return `${word}s`\n}\n\nexport const Capitalize = (word: string): string =>\n word\n .split(/[_-]/)\n .map((w) => `${w.charAt(0).toUpperCase()}${w.slice(1)}`)\n .join('')\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@elasticpath/component-test-framework",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A framework for component tests written using ts-flow",
|
|
5
|
+
"main": "./lib/index.js",
|
|
6
|
+
"directories": {
|
|
7
|
+
"lib": "./lib"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"/lib"
|
|
11
|
+
],
|
|
12
|
+
"engines": {
|
|
13
|
+
"npm": "Please use Yarn",
|
|
14
|
+
"yarn": "^1.22.19",
|
|
15
|
+
"node": "^16.15.0"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"test": "./node_modules/.bin/mocha tests/*.ts",
|
|
19
|
+
"lint": "./node_modules/.bin/eslint src/**/*.ts --max-warnings 0",
|
|
20
|
+
"format": "./node_modules/.bin/prettier --check src/**/*.ts",
|
|
21
|
+
"format-fix": "./node_modules/.bin/prettier --write src/**/*.ts",
|
|
22
|
+
"build": "./node_modules/.bin/tsc --build ."
|
|
23
|
+
},
|
|
24
|
+
"repository": {
|
|
25
|
+
"type": "git",
|
|
26
|
+
"url": "git@gitlab.elasticpath.com:commerce-cloud/ncl-projects/nebula/component-test-framework.git"
|
|
27
|
+
},
|
|
28
|
+
"keywords": [],
|
|
29
|
+
"author": "carl.markham@elasticpath.com",
|
|
30
|
+
"license": "ISC",
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@cucumber/cucumber": "^9.3.0",
|
|
33
|
+
"@elastic/elasticsearch": "^7.12.0",
|
|
34
|
+
"@faker-js/faker": "^8.0.2",
|
|
35
|
+
"axios": "^0.21.1",
|
|
36
|
+
"axios-logger": "^2.6.2",
|
|
37
|
+
"chai": "^4.3.7",
|
|
38
|
+
"cucumber-tsflow": "^4.0.6",
|
|
39
|
+
"dotenv": "^16.3.1",
|
|
40
|
+
"eslint": "^8.45.0",
|
|
41
|
+
"form-data": "^4.0.0",
|
|
42
|
+
"mongodb": "^5.7.0",
|
|
43
|
+
"sinon": "^15.2.0",
|
|
44
|
+
"ts-node": "^10.9.1",
|
|
45
|
+
"typescript": "^5.1.6",
|
|
46
|
+
"uuid": "^9.0.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/chai": "^4.3.5",
|
|
50
|
+
"@types/elasticsearch": "^5.0.40",
|
|
51
|
+
"@types/mocha": "^10.0.1",
|
|
52
|
+
"@types/node": "^16.18.38",
|
|
53
|
+
"@types/sinon": "^10.0.15",
|
|
54
|
+
"@types/uuid": "^9.0.2",
|
|
55
|
+
"@typescript-eslint/eslint-plugin": "^6.1.0",
|
|
56
|
+
"@typescript-eslint/parser": "^6.1.0",
|
|
57
|
+
"eslint": "^8.45.0",
|
|
58
|
+
"eslint-config-airbnb-base": "^15.0.0",
|
|
59
|
+
"eslint-config-prettier": "8.8.0",
|
|
60
|
+
"eslint-plugin-import": "^2.27.5",
|
|
61
|
+
"eslint-plugin-prettier": "5.0.0",
|
|
62
|
+
"mocha": "^10.2.0",
|
|
63
|
+
"prettier": "^3.0.0"
|
|
64
|
+
},
|
|
65
|
+
"mocha": {
|
|
66
|
+
"require": [
|
|
67
|
+
"ts-node/register"
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
}
|