@mojaloop/ml-testing-toolkit-shared-lib 12.0.2 → 13.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/.ncurc.yaml +6 -0
- package/.nvmrc +1 -0
- package/CHANGELOG.md +16 -0
- package/CODEOWNERS +30 -0
- package/README.md +41 -0
- package/audit-ci.jsonc +10 -0
- package/jest.config.js +4 -4
- package/package.json +51 -28
- package/src/lib/openApiMockGenerator.js +36 -3
- package/src/lib/testcase-folder/folder-parser.js +113 -70
- package/.circleci/config.yml +0 -301
- package/audit-resolve.json +0 -22
- package/test/samples/api_spec_async.yaml +0 -2157
- package/test/samples/api_spec_sync.yaml +0 -529
- package/test/samples/api_spec_sync_empty.yaml +0 -7
- package/test/unit/index.test.js +0 -44
- package/test/unit/lib/openApiMockGenerator.test.js +0 -136
- package/test/unit/lib/testcase-folder/folder-parser.test.js +0 -451
- package/test/unit/lib/traceHeaderUtils.test.js +0 -91
package/.ncurc.yaml
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
## Add a TODO comment indicating the reason for each rejected dependency upgrade added to this list, and what should be done to resolve it (i.e. handle it through a story, etc).
|
|
2
|
+
reject: [
|
|
3
|
+
# Downgraded to 5.5.3 - Reason: removal of functional code in faker.js - https://github.com/advisories/GHSA-5w9c-rv96-fr7g
|
|
4
|
+
"faker"
|
|
5
|
+
|
|
6
|
+
]
|
package/.nvmrc
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
16.15.0
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
|
+
|
|
5
|
+
## [13.0.0](https://github.com/mojaloop/ml-testing-toolkit-shared-lib/compare/v12.2.0...v13.0.0) (2022-07-21)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### ⚠ BREAKING CHANGES
|
|
9
|
+
|
|
10
|
+
* Major version bump for node v16 LTS support, re-structuring of project directories to align to core Mojaloop repositories.
|
|
11
|
+
|
|
12
|
+
Major version bump since this is a big upgrade.
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* node upgrade ([#10](https://github.com/mojaloop/ml-testing-toolkit-shared-lib/issues/10)) ([e287fb5](https://github.com/mojaloop/ml-testing-toolkit-shared-lib/commit/e287fb517671689036d63f56cb27f0af1da64451))
|
package/CODEOWNERS
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Each line is a file pattern followed by one or more owners.
|
|
2
|
+
## These owners will be the default owners for everything in
|
|
3
|
+
## the repo. Unless a later match takes precedence,
|
|
4
|
+
## @global-owner1 and @global-owner2 will be requested for
|
|
5
|
+
## review when someone opens a pull request.
|
|
6
|
+
#* @global-owner1 @global-owner2
|
|
7
|
+
* @vijayg10 @mdebarros @elnyry-sam-k
|
|
8
|
+
## Order is important; the last matching pattern takes the most
|
|
9
|
+
## precedence. When someone opens a pull request that only
|
|
10
|
+
## modifies JS files, only @js-owner and not the global
|
|
11
|
+
## owner(s) will be requested for a review.
|
|
12
|
+
# *.js @js-owner
|
|
13
|
+
## You can also use email addresses if you prefer. They'll be
|
|
14
|
+
## used to look up users just like we do for commit author
|
|
15
|
+
## emails.
|
|
16
|
+
#*.go docs@example.com
|
|
17
|
+
# In this example, @doctocat owns any files in the build/logs
|
|
18
|
+
# directory at the root of the repository and any of its
|
|
19
|
+
# subdirectories.
|
|
20
|
+
# /build/logs/ @doctocat
|
|
21
|
+
## The `docs/*` pattern will match files like
|
|
22
|
+
## `docs/getting-started.md` but not further nested files like
|
|
23
|
+
## `docs/build-app/troubleshooting.md`.
|
|
24
|
+
# docs/* docs@example.com
|
|
25
|
+
## In this example, @octocat owns any file in an apps directory
|
|
26
|
+
## anywhere in your repository.
|
|
27
|
+
#apps/ @octocat
|
|
28
|
+
## In this example, @doctocat owns any file in the `/docs`
|
|
29
|
+
## directory in the root of your repository.
|
|
30
|
+
#/docs/ @doctocat
|
package/README.md
CHANGED
|
@@ -1 +1,42 @@
|
|
|
1
1
|
# ml-testing-toolkit-shared-lib
|
|
2
|
+
Library for shared code between Mojaloop testing-toolkit backend and frontend
|
|
3
|
+
|
|
4
|
+
## Auditing Dependencies
|
|
5
|
+
|
|
6
|
+
We use `npm-audit-resolver` along with `npm audit` to check dependencies for node vulnerabilities, and keep track of resolved dependencies with an `audit-resolve.json` file.
|
|
7
|
+
|
|
8
|
+
To start a new resolution process, run:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm run audit:resolve
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
You can then check to see if the CI will pass based on the current dependencies with:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm run audit:check
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
And commit the changed `audit-resolve.json` to ensure that CircleCI will build correctly.
|
|
21
|
+
|
|
22
|
+
## Container Scans
|
|
23
|
+
|
|
24
|
+
As part of our CI/CD process, we use anchore-cli to scan our built docker container for vulnerabilities upon release.
|
|
25
|
+
|
|
26
|
+
If you find your release builds are failing, refer to the [container scanning](https://github.com/mojaloop/ci-config#container-scanning) in our shared Mojaloop CI config repo. There is a good chance you simply need to update the `mojaloop-policy-generator.js` file and re-run the circleci workflow.
|
|
27
|
+
|
|
28
|
+
For more information on anchore and anchore-cli, refer to:
|
|
29
|
+
- [Anchore CLI](https://github.com/anchore/anchore-cli)
|
|
30
|
+
- [Circle Orb Registry](https://circleci.com/orbs/registry/orb/anchore/anchore-engine)
|
|
31
|
+
|
|
32
|
+
## Automated Releases
|
|
33
|
+
|
|
34
|
+
As part of our CI/CD process, we use a combination of CircleCI, standard-version
|
|
35
|
+
npm package and github-release CircleCI orb to automatically trigger our releases
|
|
36
|
+
and image builds. This process essentially mimics a manual tag and release.
|
|
37
|
+
|
|
38
|
+
On a merge to master, CircleCI is configured to use the mojaloopci github account
|
|
39
|
+
to push the latest generated CHANGELOG and package version number.
|
|
40
|
+
|
|
41
|
+
Once those changes are pushed, CircleCI will pull the updated master, tag and
|
|
42
|
+
push a release triggering another subsequent build that also publishes a docker image.
|
package/audit-ci.jsonc
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://github.com/IBM/audit-ci/raw/main/docs/schema.json",
|
|
3
|
+
// audit-ci supports reading JSON, JSONC, and JSON5 config files.
|
|
4
|
+
// Only use one of ["low": true, "moderate": true, "high": true, "critical": true]
|
|
5
|
+
"moderate": true,
|
|
6
|
+
"allowlist": [
|
|
7
|
+
// Unable to downgrade due to breaking change: glob-parent before 6.0.1 vulnerable to Regular Expression Denial of Service (ReDoS) - https://github.com/advisories/GHSA-cj88-88mr-972w
|
|
8
|
+
"GHSA-cj88-88mr-972w"
|
|
9
|
+
]
|
|
10
|
+
}
|
package/jest.config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,14 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mojaloop/ml-testing-toolkit-shared-lib",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "13.0.0",
|
|
4
4
|
"description": "Shared library for ml-testing-toolkit re-usable functions",
|
|
5
5
|
"main": "src/index.js",
|
|
6
|
+
"contributors": [
|
|
7
|
+
"Vijaya Kumar <vijaya.guthi@modusbox.com>",
|
|
8
|
+
"Miguel de Barros <miguel.debarros@modusbox.com>"
|
|
9
|
+
],
|
|
10
|
+
"engines": {
|
|
11
|
+
"node": "=16.x"
|
|
12
|
+
},
|
|
13
|
+
"license": "Apache-2.0",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/mojaloop/ml-testing-toolkit-shared-lib.git"
|
|
17
|
+
},
|
|
18
|
+
"author": "Vijaya Kumar Guthi, ModusBox Inc.",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/mojaloop/ml-testing-toolkit-shared-lib/issues"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/mojaloop/ml-testing-toolkit-shared-lib#readme",
|
|
6
23
|
"pre-commit": [
|
|
7
|
-
"
|
|
24
|
+
"lint",
|
|
25
|
+
"dep:check"
|
|
8
26
|
],
|
|
9
27
|
"scripts": {
|
|
10
28
|
"start": "node src/index.js",
|
|
11
29
|
"standard": "standard",
|
|
30
|
+
"standard:fix": "standard --fix",
|
|
31
|
+
"lint": "npm run standard",
|
|
32
|
+
"lint:fix": "npm run standard:fix",
|
|
12
33
|
"test": "npm run test:unit",
|
|
13
34
|
"test:unit": "jest --testMatch '**/test/unit/**/*.test.js'",
|
|
14
35
|
"test:int": "jest --reporters=default --reporters=jest-junit --testMatch '**/test/integration/**/*.test.js'",
|
|
@@ -17,40 +38,42 @@
|
|
|
17
38
|
"test:junit": "jest --reporters=default --reporters=jest-junit --testMatch '**/test/unit/**/*.test.js'",
|
|
18
39
|
"test:integration": "./test/integration-runner.sh ",
|
|
19
40
|
"cover": "npx nyc --all report --reporter=lcov npm run test",
|
|
20
|
-
"
|
|
21
|
-
"audit:resolve": "SHELL=sh resolve-audit",
|
|
22
|
-
"audit:check": "SHELL=sh check-audit",
|
|
41
|
+
"audit:check": "npx audit-ci --config ./audit-ci.jsonc",
|
|
23
42
|
"dep:check": "npx ncu -e 2",
|
|
24
|
-
"dep:update": "npx ncu -u"
|
|
43
|
+
"dep:update": "npx ncu -u",
|
|
44
|
+
"release": "npx standard-version --no-verify --releaseCommitMessageFormat 'chore(release): {{currentTag}} [skip ci]'",
|
|
45
|
+
"snapshot": "npx standard-version --no-verify --skip.changelog --prerelease snapshot --releaseCommitMessageFormat 'chore(snapshot): {{currentTag}}'"
|
|
25
46
|
},
|
|
26
|
-
"repository": {
|
|
27
|
-
"type": "git",
|
|
28
|
-
"url": "git+https://github.com/mojaloop/ml-testing-toolkit-shared-lib.git"
|
|
29
|
-
},
|
|
30
|
-
"author": "Vijaya Kumar Guthi, ModusBox Inc.",
|
|
31
|
-
"contributors": [
|
|
32
|
-
"Vijaya Kumar <vijaya.guthi@modusbox.com>"
|
|
33
|
-
],
|
|
34
|
-
"license": "Apache-2.0",
|
|
35
|
-
"bugs": {
|
|
36
|
-
"url": "https://github.com/mojaloop/ml-testing-toolkit-shared-lib/issues"
|
|
37
|
-
},
|
|
38
|
-
"homepage": "https://github.com/mojaloop/ml-testing-toolkit-shared-lib#readme",
|
|
39
47
|
"dependencies": {
|
|
40
|
-
"ajv": "
|
|
41
|
-
"faker": "5.
|
|
42
|
-
"json-schema-faker": "0.5.0-rcv.
|
|
43
|
-
"json-schema-ref-parser": "9.0.
|
|
44
|
-
"lodash": "4.17.
|
|
48
|
+
"ajv": "8.11.0",
|
|
49
|
+
"faker": "5.5.3",
|
|
50
|
+
"json-schema-faker": "0.5.0-rcv.44",
|
|
51
|
+
"json-schema-ref-parser": "9.0.9",
|
|
52
|
+
"lodash": "4.17.21",
|
|
45
53
|
"node-dir": "0.1.17"
|
|
46
54
|
},
|
|
47
55
|
"devDependencies": {
|
|
48
|
-
"
|
|
49
|
-
"
|
|
50
|
-
"jest": "
|
|
51
|
-
"jest-junit": "
|
|
56
|
+
"@types/jest": "28.1.6",
|
|
57
|
+
"audit-ci": "^6.3.0",
|
|
58
|
+
"jest": "28.1.3",
|
|
59
|
+
"jest-junit": "14.0.0",
|
|
60
|
+
"npm-check-updates": "15.3.4",
|
|
61
|
+
"pre-commit": "^1.2.2",
|
|
62
|
+
"replace": "^1.2.1",
|
|
63
|
+
"standard": "^17.0.0",
|
|
64
|
+
"standard-version": "^9.5.0"
|
|
65
|
+
},
|
|
66
|
+
"standard-version": {
|
|
67
|
+
"scripts": {
|
|
68
|
+
"postchangelog": "replace '\\[mojaloop/#(\\d+)\\]\\(https://github.com/mojaloop/(.*)/issues/(\\d+)\\)' '[mojaloop/#$1](https://github.com/mojaloop/project/issues/$1)' CHANGELOG.md"
|
|
69
|
+
}
|
|
52
70
|
},
|
|
53
71
|
"publishConfig": {
|
|
54
72
|
"registry": "https://registry.npmjs.org/"
|
|
73
|
+
},
|
|
74
|
+
"standard": {
|
|
75
|
+
"env": [
|
|
76
|
+
"jest"
|
|
77
|
+
]
|
|
55
78
|
}
|
|
56
79
|
}
|
|
@@ -29,6 +29,7 @@ const _ = require('lodash')
|
|
|
29
29
|
const faker = require('faker')
|
|
30
30
|
const jsf = require('json-schema-faker')
|
|
31
31
|
const $RefParser = require('json-schema-ref-parser')
|
|
32
|
+
const Ajv = require('ajv')
|
|
32
33
|
|
|
33
34
|
jsf.format('byte', () => Buffer.alloc(faker.lorem.sentence(12)).toString('base64'))
|
|
34
35
|
|
|
@@ -39,8 +40,11 @@ jsf.option({
|
|
|
39
40
|
})
|
|
40
41
|
jsf.extend('faker', () => require('faker'))
|
|
41
42
|
|
|
42
|
-
const ajv =
|
|
43
|
-
|
|
43
|
+
const ajv = new Ajv({
|
|
44
|
+
strict: false,
|
|
45
|
+
formats: {
|
|
46
|
+
reserved: true
|
|
47
|
+
}
|
|
44
48
|
})
|
|
45
49
|
|
|
46
50
|
async function loadYamlFile (fn) {
|
|
@@ -208,7 +212,7 @@ const generateMockQueryParams = async (method, name, data, jsfRefs) => {
|
|
|
208
212
|
const queryParams = {}
|
|
209
213
|
data.parameters.forEach(param => {
|
|
210
214
|
if (param.in === 'query') {
|
|
211
|
-
queryParams[param.name] = (param.schema) ? { ...
|
|
215
|
+
queryParams[param.name] = (param.schema) ? { ...param.schema } : {}
|
|
212
216
|
}
|
|
213
217
|
})
|
|
214
218
|
jsfRefs.forEach(ref => {
|
|
@@ -226,6 +230,28 @@ const generateMockQueryParams = async (method, name, data, jsfRefs) => {
|
|
|
226
230
|
return fakedResponse
|
|
227
231
|
}
|
|
228
232
|
|
|
233
|
+
const generateMockPathParams = async (method, name, data, jsfRefs) => {
|
|
234
|
+
const pathParams = {}
|
|
235
|
+
data.parameters.forEach(param => {
|
|
236
|
+
if (param.in === 'path') {
|
|
237
|
+
pathParams[param.name] = (param.schema) ? { ...param.schema } : {}
|
|
238
|
+
}
|
|
239
|
+
})
|
|
240
|
+
jsfRefs.forEach(ref => {
|
|
241
|
+
if (pathParams[ref.id]) {
|
|
242
|
+
pathParams[ref.id] = { $ref: ref.id }
|
|
243
|
+
}
|
|
244
|
+
})
|
|
245
|
+
|
|
246
|
+
if (Object.keys(pathParams).length === 0) {
|
|
247
|
+
return {}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const fakedResponse = await jsf.resolve(pathParams, jsfRefs)
|
|
251
|
+
|
|
252
|
+
return fakedResponse
|
|
253
|
+
}
|
|
254
|
+
|
|
229
255
|
class OpenApiRequestGenerator {
|
|
230
256
|
constructor () {
|
|
231
257
|
this.schema = {}
|
|
@@ -256,6 +282,13 @@ class OpenApiRequestGenerator {
|
|
|
256
282
|
return generateMockQueryParams(httpMethod, id, operation, jsfRefs)
|
|
257
283
|
}
|
|
258
284
|
|
|
285
|
+
async generateRequestPathParams (path, httpMethod, jsfRefs = []) {
|
|
286
|
+
const pathValue = this.schema.paths[path]
|
|
287
|
+
const operation = pathValue[httpMethod]
|
|
288
|
+
const id = operation.operationId || operation.summary
|
|
289
|
+
return generateMockPathParams(httpMethod, id, operation, jsfRefs)
|
|
290
|
+
}
|
|
291
|
+
|
|
259
292
|
async generateResponseBody (path, httpMethod, jsfRefs = []) {
|
|
260
293
|
const pathValue = this.schema.paths[path]
|
|
261
294
|
const operation = pathValue[httpMethod]
|
|
@@ -28,71 +28,75 @@ const MASTERFILE_NAME = 'master.json'
|
|
|
28
28
|
|
|
29
29
|
const convertToFolderNestedArray = (folderRawData) => {
|
|
30
30
|
// Form the object tree based from the array of paths
|
|
31
|
-
|
|
31
|
+
const fileTree = {}
|
|
32
32
|
const mergePathsIntoFileTree = (fileItem) => {
|
|
33
|
-
|
|
33
|
+
return (prevDir, currDir, i, filePath) => {
|
|
34
34
|
if (i === filePath.length - 1) {
|
|
35
|
-
|
|
35
|
+
prevDir[currDir] = { type: 'file', content: fileItem.content }
|
|
36
36
|
}
|
|
37
|
-
if (!
|
|
38
|
-
|
|
37
|
+
if (!Object.prototype.hasOwnProperty.call(prevDir, currDir)) {
|
|
38
|
+
prevDir[currDir] = {}
|
|
39
39
|
}
|
|
40
|
-
return prevDir[currDir]
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
function parseFileItem(fileItem) {
|
|
44
|
-
var fileLocation = fileItem.path.split('/');
|
|
45
|
-
// If file is in root directory, eg 'index.js'
|
|
46
|
-
if (fileLocation.length === 1) {
|
|
47
|
-
return (fileTree[fileLocation[0]] = { type: 'file', content: fileItem.content });
|
|
40
|
+
return prevDir[currDir]
|
|
41
|
+
}
|
|
48
42
|
}
|
|
49
|
-
|
|
43
|
+
function parseFileItem (fileItem) {
|
|
44
|
+
const fileLocation = fileItem.path.split('/')
|
|
45
|
+
// If file is in root directory, eg 'index.js'
|
|
46
|
+
if (fileLocation.length === 1) {
|
|
47
|
+
return (fileTree[fileLocation[0]] = { type: 'file', content: fileItem.content })
|
|
48
|
+
}
|
|
49
|
+
fileLocation.reduce(mergePathsIntoFileTree(fileItem), fileTree)
|
|
50
50
|
}
|
|
51
|
-
folderRawData.forEach(parseFileItem)
|
|
52
|
-
|
|
51
|
+
folderRawData.forEach(parseFileItem)
|
|
53
52
|
|
|
54
53
|
// Form the array from the object fileTree
|
|
55
54
|
const processFileOrFolder = (inputItem, inputArray, prefix = '') => {
|
|
56
55
|
const actionFileOrFolder = (fileOrFolderItem, extraInfo = null) => {
|
|
57
|
-
|
|
58
|
-
if(inputItem[fileOrFolderItem].type === 'file') {
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
if (inputItem[fileOrFolderItem]) {
|
|
57
|
+
if (inputItem[fileOrFolderItem].type === 'file') {
|
|
58
|
+
extraInfo = extraInfo || { type: 'file' }
|
|
59
|
+
inputArray.push({ key: (prefix ? (prefix + '/') : '') + fileOrFolderItem, title: fileOrFolderItem, isLeaf: true, extraInfo, content: inputItem[fileOrFolderItem].content })
|
|
61
60
|
} else {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
61
|
+
const children = []
|
|
62
|
+
processFileOrFolder(inputItem[fileOrFolderItem], children, (prefix ? (prefix + '/') : '') + fileOrFolderItem)
|
|
63
|
+
extraInfo = extraInfo || { type: 'folder' }
|
|
64
|
+
inputArray.push({ key: (prefix ? (prefix + '/') : '') + fileOrFolderItem, title: fileOrFolderItem, extraInfo, children })
|
|
67
65
|
}
|
|
66
|
+
}
|
|
68
67
|
}
|
|
69
68
|
const actionFileRef = (name, refPath) => {
|
|
70
|
-
|
|
69
|
+
const extraInfo = {
|
|
71
70
|
type: 'fileRef',
|
|
72
71
|
path: refPath
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
}
|
|
73
|
+
inputArray.push({ key: (prefix ? (prefix + '/') : '') + name, title: name, extraInfo, isLeaf: true })
|
|
75
74
|
}
|
|
76
75
|
// If master.json file exists in inputItem
|
|
77
|
-
if (
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
actionFileRef(orderItem.name, orderItem.path)
|
|
76
|
+
if (Object.prototype.hasOwnProperty.call(inputItem, MASTERFILE_NAME)) {
|
|
77
|
+
inputItem[MASTERFILE_NAME].content.order.forEach(orderItem => {
|
|
78
|
+
if (orderItem.type === 'file' || orderItem.type === 'folder') {
|
|
79
|
+
const extraInfo = {
|
|
80
|
+
type: orderItem.type
|
|
83
81
|
}
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
for (const fileOrFolderItem in inputItem) {
|
|
87
|
-
if (fileOrFolderItem !== MASTERFILE_NAME && inputItem[MASTERFILE_NAME].content.order.find(item => (item.name === fileOrFolderItem)) === undefined) {
|
|
88
|
-
actionFileOrFolder(fileOrFolderItem)
|
|
82
|
+
if (orderItem.labels) {
|
|
83
|
+
extraInfo.labels = orderItem.labels
|
|
89
84
|
}
|
|
85
|
+
actionFileOrFolder(orderItem.name, extraInfo)
|
|
86
|
+
} else if (orderItem.type === 'fileRef') {
|
|
87
|
+
actionFileRef(orderItem.name, orderItem.path)
|
|
90
88
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
})
|
|
90
|
+
// Add missing files in MASTERFILE
|
|
91
|
+
for (const fileOrFolderItem in inputItem) {
|
|
92
|
+
if (fileOrFolderItem !== MASTERFILE_NAME && inputItem[MASTERFILE_NAME].content.order.find(item => (item.name === fileOrFolderItem)) === undefined) {
|
|
94
93
|
actionFileOrFolder(fileOrFolderItem)
|
|
95
94
|
}
|
|
95
|
+
}
|
|
96
|
+
} else {
|
|
97
|
+
for (const fileOrFolderItem in inputItem) {
|
|
98
|
+
actionFileOrFolder(fileOrFolderItem)
|
|
99
|
+
}
|
|
96
100
|
}
|
|
97
101
|
}
|
|
98
102
|
const treeDataArray = []
|
|
@@ -108,7 +112,7 @@ const findNodeFromAbsolutePath = (path, folderData) => {
|
|
|
108
112
|
// Get the content of the corresponding node based on the absolute path from this.state.folderData
|
|
109
113
|
const pathArray = path.split('/')
|
|
110
114
|
let children = folderData
|
|
111
|
-
for (let i=0; i<pathArray.length - 1; i++) {
|
|
115
|
+
for (let i = 0; i < pathArray.length - 1; i++) {
|
|
112
116
|
// Check if the key exists in the children
|
|
113
117
|
const findNode = children.find(item => (item.title === pathArray[i]))
|
|
114
118
|
if (findNode) {
|
|
@@ -133,15 +137,15 @@ const getAbsolutePathOfRelativeFileRef = (refNode) => {
|
|
|
133
137
|
const basePathArray = refNode.key.split('/')
|
|
134
138
|
const refPathArray = refNode.extraInfo.path.split('/')
|
|
135
139
|
let absolutePath = ''
|
|
136
|
-
if (refPathArray[0]
|
|
140
|
+
if (refPathArray[0] === '') { // If the path is already absolute path
|
|
137
141
|
absolutePath = refPathArray.slice(1).join('/') // Just remove the starting slash
|
|
138
|
-
} else if (refPathArray[0]
|
|
142
|
+
} else if (refPathArray[0] === '.') {
|
|
139
143
|
absolutePath = basePathArray.slice(0, -1).join('/') + '/' + refPathArray.slice(1).join('/')
|
|
140
|
-
} else if (refPathArray[0]
|
|
144
|
+
} else if (refPathArray[0] === '..') {
|
|
141
145
|
// Count the double dots
|
|
142
146
|
let doubleDotCount
|
|
143
|
-
for (doubleDotCount=0; doubleDotCount<refPathArray.length; doubleDotCount++) {
|
|
144
|
-
if (refPathArray[doubleDotCount]
|
|
147
|
+
for (doubleDotCount = 0; doubleDotCount < refPathArray.length; doubleDotCount++) {
|
|
148
|
+
if (refPathArray[doubleDotCount] !== '..') {
|
|
145
149
|
break
|
|
146
150
|
}
|
|
147
151
|
}
|
|
@@ -149,19 +153,30 @@ const getAbsolutePathOfRelativeFileRef = (refNode) => {
|
|
|
149
153
|
if ((basePathArray.length - 1) < doubleDotCount) {
|
|
150
154
|
return null
|
|
151
155
|
}
|
|
152
|
-
const newBasePath = basePathArray.slice(0, -1-doubleDotCount).join('/')
|
|
153
|
-
absolutePath = (newBasePath? (newBasePath + '/') : '') + refPathArray.slice(doubleDotCount).join('/')
|
|
154
|
-
|
|
156
|
+
const newBasePath = basePathArray.slice(0, -1 - doubleDotCount).join('/')
|
|
157
|
+
absolutePath = (newBasePath ? (newBasePath + '/') : '') + refPathArray.slice(doubleDotCount).join('/')
|
|
155
158
|
} else {
|
|
156
159
|
absolutePath = basePathArray.slice(0, -1).join('/') + '/' + refPathArray.join('/')
|
|
157
160
|
}
|
|
158
161
|
|
|
159
162
|
return absolutePath
|
|
160
|
-
}
|
|
163
|
+
}
|
|
161
164
|
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
+
const getLabels = (currentLabels, newLabels = []) => {
|
|
166
|
+
// eslint-disable-next-line no-unneeded-ternary
|
|
167
|
+
currentLabels = currentLabels ? currentLabels : []
|
|
168
|
+
const labels = (currentLabels && currentLabels.length > 0) ? [...currentLabels] : []
|
|
169
|
+
newLabels.forEach(label => {
|
|
170
|
+
if (!currentLabels.includes(label)) {
|
|
171
|
+
labels.push(label)
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
return labels
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const addChildrenToTestCases = (folderData, nodeChildren, testCases, selectedFiles, selectedLabels, labels) => {
|
|
178
|
+
let newTestCases = testCases
|
|
179
|
+
for (let i = 0; i < nodeChildren.length; i++) {
|
|
165
180
|
if (nodeChildren[i].isLeaf) {
|
|
166
181
|
if (selectedFiles && !selectedFiles.includes(nodeChildren[i].key)) {
|
|
167
182
|
continue
|
|
@@ -177,10 +192,10 @@ const addChildrenToTestCases = (folderData, nodeChildren, testCases, selectedFil
|
|
|
177
192
|
}
|
|
178
193
|
}
|
|
179
194
|
} else {
|
|
180
|
-
templateContent = nodeChildren[i].content
|
|
195
|
+
templateContent = nodeChildren[i].content
|
|
181
196
|
}
|
|
182
197
|
try {
|
|
183
|
-
templateContent.test_cases = templateContent.test_cases
|
|
198
|
+
// templateContent.test_cases = templateContent.test_cases
|
|
184
199
|
// templateContent.test_cases = templateContent.test_cases.map((testCase, index) => {
|
|
185
200
|
// const { id, ...remainingProps } = testCase
|
|
186
201
|
// return {
|
|
@@ -188,37 +203,65 @@ const addChildrenToTestCases = (folderData, nodeChildren, testCases, selectedFil
|
|
|
188
203
|
// ...remainingProps
|
|
189
204
|
// }
|
|
190
205
|
// })
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
206
|
+
templateContent.test_cases = templateContent.test_cases.map((testCase) => {
|
|
207
|
+
testCase.fileInfo = {
|
|
208
|
+
path: nodeChildren[i].key
|
|
209
|
+
}
|
|
210
|
+
if ((labels && labels.length > 0) || (nodeChildren[i].extraInfo.labels && nodeChildren[i].extraInfo.labels.length > 0)) {
|
|
211
|
+
testCase.fileInfo.labels = getLabels(labels, nodeChildren[i].extraInfo.labels)
|
|
212
|
+
}
|
|
213
|
+
if (selectedLabels && selectedLabels.length > 0) {
|
|
214
|
+
let isSelected = false
|
|
215
|
+
if (testCase.fileInfo.labels && testCase.fileInfo.labels.length > 0) {
|
|
216
|
+
for (let j = 0; j < testCase.fileInfo.labels.length; j++) {
|
|
217
|
+
const l = testCase.fileInfo.labels[j]
|
|
218
|
+
if (selectedLabels.includes(l)) {
|
|
219
|
+
isSelected = true
|
|
220
|
+
break
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
if (!isSelected) {
|
|
225
|
+
return null
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
return testCase
|
|
229
|
+
})
|
|
230
|
+
if (selectedLabels && selectedLabels.length > 0) {
|
|
231
|
+
templateContent.test_cases = templateContent.test_cases.filter((testcase) => testcase != null)
|
|
232
|
+
}
|
|
233
|
+
if (templateContent.test_cases && templateContent.test_cases.length > 0) {
|
|
234
|
+
newTestCases = newTestCases.concat(templateContent.test_cases)
|
|
235
|
+
}
|
|
236
|
+
} catch (err) {
|
|
194
237
|
console.log(err.message)
|
|
195
|
-
break
|
|
238
|
+
break
|
|
196
239
|
}
|
|
197
240
|
} else {
|
|
198
241
|
if (nodeChildren[i].children) {
|
|
199
242
|
// console.log('The node has children', nodeChildren[i].children, newTestCases)
|
|
200
|
-
newTestCases = addChildrenToTestCases(folderData, nodeChildren[i].children, newTestCases, selectedFiles,
|
|
243
|
+
newTestCases = addChildrenToTestCases(folderData, nodeChildren[i].children, newTestCases, selectedFiles, selectedLabels, getLabels(labels, nodeChildren[i].extraInfo.labels))
|
|
201
244
|
}
|
|
202
245
|
}
|
|
203
246
|
}
|
|
204
247
|
return newTestCases
|
|
205
248
|
}
|
|
206
249
|
|
|
207
|
-
const getTestCases = (folderData, selectedFiles = null) => {
|
|
208
|
-
|
|
209
|
-
testCases = addChildrenToTestCases(folderData, folderData, testCases, selectedFiles,
|
|
250
|
+
const getTestCases = (folderData, selectedFiles = null, selectedLabels = null) => {
|
|
251
|
+
let testCases = []
|
|
252
|
+
testCases = addChildrenToTestCases(folderData, folderData, testCases, selectedFiles, selectedLabels, null)
|
|
210
253
|
return testCases
|
|
211
254
|
}
|
|
212
255
|
|
|
213
256
|
const sequenceTestCases = (testCases) => {
|
|
214
|
-
for (let i=0; i < testCases.length; i++) {
|
|
257
|
+
for (let i = 0; i < testCases.length; i++) {
|
|
215
258
|
testCases[i].id = i + 1
|
|
216
259
|
}
|
|
217
260
|
}
|
|
218
261
|
|
|
219
262
|
module.exports = {
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
263
|
+
getTestCases,
|
|
264
|
+
getFolderData,
|
|
265
|
+
sequenceTestCases,
|
|
266
|
+
findNodeFromAbsolutePath
|
|
224
267
|
}
|