datagrok-tools 6.3.3 → 6.4.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/CHANGELOG.md +12 -0
- package/bin/commands/publish.js +2 -4
- package/bin/utils/test-utils.js +13 -28
- package/eslint.config.mjs +42 -0
- package/package.json +38 -36
- package/.eslintrc.json +0 -43
- package/bin/__tests__/build.test.js +0 -116
- package/bin/__tests__/jira-wiki-converter.test.js +0 -101
- package/bin/__tests__/node-dapi.connections.test.js +0 -120
- package/bin/__tests__/node-dapi.groups.test.js +0 -467
- package/bin/__tests__/node-dapi.integration.test.js +0 -406
- package/bin/__tests__/node-dapi.shares.test.js +0 -107
- package/bin/__tests__/node-dapi.users.test.js +0 -86
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Datagrok-tools changelog
|
|
2
2
|
|
|
3
|
+
## 6.4.1 (2026-06-18)
|
|
4
|
+
|
|
5
|
+
* Fixed `grok` failing with `Cannot find module './commands/build'` — the `.npmignore` `build.js` rule was unanchored and excluded the compiled `bin/commands/build.js` from the published package; anchored it to `/build.js`.
|
|
6
|
+
* Pinned `ignore-walk` to ^6.0.5 so the package still supports Node 18 (9.x requires Node 22+).
|
|
7
|
+
|
|
8
|
+
## 6.4.0 (2026-06-18)
|
|
9
|
+
|
|
10
|
+
* Dependencies: sanitized and updated all dependencies; `npm install` is now warning-free and `npm audit` reports 0 vulnerabilities (was 24).
|
|
11
|
+
* Dependencies: migrated linting to ESLint 9 flat config (`eslint.config.mjs` + `typescript-eslint` + `@stylistic`), dropping the archived `eslint-config-google`.
|
|
12
|
+
* Dependencies: upgraded Puppeteer to v24 and migrated to its native `page.screencast()` for `--record`, removing `puppeteer-screen-recorder` and the deprecated `fluent-ffmpeg`.
|
|
13
|
+
* Dependencies: replaced `archiver-promise` with `archiver` directly, and replaced `@babel/cli` with a small `@babel/core` build script (`build.js`) to drop deprecated transitive packages (glob@7, inflight).
|
|
14
|
+
|
|
3
15
|
## 6.3.3 (2026-06-16)
|
|
4
16
|
|
|
5
17
|
* Fixed Celery Docker image generation — the image wasn't built locally on publish.
|
package/bin/commands/publish.js
CHANGED
|
@@ -6,7 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.processPackage = processPackage;
|
|
8
8
|
exports.publish = publish;
|
|
9
|
-
var
|
|
9
|
+
var _archiver = _interopRequireDefault(require("archiver"));
|
|
10
10
|
var _crypto = _interopRequireDefault(require("crypto"));
|
|
11
11
|
var _fs = _interopRequireDefault(require("fs"));
|
|
12
12
|
var _nodeFetch = _interopRequireDefault(require("node-fetch"));
|
|
@@ -22,8 +22,6 @@ var _pythonCeleryGen = require("../utils/python-celery-gen");
|
|
|
22
22
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
23
23
|
// @ts-ignore
|
|
24
24
|
|
|
25
|
-
// @ts-ignore
|
|
26
|
-
|
|
27
25
|
const {
|
|
28
26
|
exec,
|
|
29
27
|
execSync
|
|
@@ -426,7 +424,7 @@ async function processPackage(debug, rebuild, host, devKey, packageName, dropDb,
|
|
|
426
424
|
if (color.isVerbose()) console.error(error);
|
|
427
425
|
return 1;
|
|
428
426
|
}
|
|
429
|
-
const zip = (0,
|
|
427
|
+
const zip = (0, _archiver.default)('zip', {
|
|
430
428
|
store: false
|
|
431
429
|
});
|
|
432
430
|
const chunks = [];
|
package/bin/utils/test-utils.js
CHANGED
|
@@ -21,7 +21,6 @@ exports.loadPackages = loadPackages;
|
|
|
21
21
|
exports.loadTestsList = loadTestsList;
|
|
22
22
|
exports.mergeBrowsersResults = mergeBrowsersResults;
|
|
23
23
|
exports.printBrowsersResult = printBrowsersResult;
|
|
24
|
-
exports.recorderConfig = void 0;
|
|
25
24
|
exports.runBrowser = runBrowser;
|
|
26
25
|
exports.runWithTimeout = runWithTimeout;
|
|
27
26
|
exports.saveCsvResults = saveCsvResults;
|
|
@@ -32,7 +31,6 @@ var _path = _interopRequireDefault(require("path"));
|
|
|
32
31
|
var _jsYaml = _interopRequireDefault(require("js-yaml"));
|
|
33
32
|
var _utils = _interopRequireWildcard(require("../utils/utils"));
|
|
34
33
|
var utils = _utils;
|
|
35
|
-
var _puppeteerScreenRecorder = require("puppeteer-screen-recorder");
|
|
36
34
|
var _puppeteer = _interopRequireDefault(require("puppeteer"));
|
|
37
35
|
var color = _interopRequireWildcard(require("../utils/color-utils"));
|
|
38
36
|
var _papaparse = _interopRequireDefault(require("papaparse"));
|
|
@@ -43,8 +41,8 @@ const confPath = _path.default.join(grokDir, 'config.yaml');
|
|
|
43
41
|
const testCollectionTimeout = 600000;
|
|
44
42
|
const defaultLaunchParameters = exports.defaultLaunchParameters = {
|
|
45
43
|
args: ['--disable-dev-shm-usage', '--disable-features=site-per-process', '--window-size=1920,1080', '--js-flags=--expose-gc'],
|
|
46
|
-
|
|
47
|
-
headless:
|
|
44
|
+
acceptInsecureCerts: true,
|
|
45
|
+
headless: true,
|
|
48
46
|
protocolTimeout: 0
|
|
49
47
|
};
|
|
50
48
|
async function getToken(url, key) {
|
|
@@ -150,9 +148,10 @@ async function getBrowserPage(puppeteer, params = defaultLaunchParameters, urlPa
|
|
|
150
148
|
});
|
|
151
149
|
page.setDefaultNavigationTimeout(0);
|
|
152
150
|
await page.goto(`${url}/oauth/`);
|
|
153
|
-
await page.setCookie({
|
|
151
|
+
await page.browser().setCookie({
|
|
154
152
|
name: 'auth',
|
|
155
|
-
value: token
|
|
153
|
+
value: token,
|
|
154
|
+
domain: new URL(url).hostname
|
|
156
155
|
});
|
|
157
156
|
await page.evaluate(token => {
|
|
158
157
|
window.localStorage.setItem('auth', token);
|
|
@@ -201,23 +200,6 @@ function exitWithCode(code) {
|
|
|
201
200
|
console.log(`Exiting with code ${code}`);
|
|
202
201
|
process.exit(code);
|
|
203
202
|
}
|
|
204
|
-
const recorderConfig = exports.recorderConfig = {
|
|
205
|
-
followNewTab: true,
|
|
206
|
-
fps: 25,
|
|
207
|
-
ffmpeg_Path: null,
|
|
208
|
-
videoFrame: {
|
|
209
|
-
width: 1280,
|
|
210
|
-
height: 630
|
|
211
|
-
},
|
|
212
|
-
videoCrf: 18,
|
|
213
|
-
videoCodec: 'libx264',
|
|
214
|
-
videoPreset: 'ultrafast',
|
|
215
|
-
videoBitrate: 1000,
|
|
216
|
-
autopad: {
|
|
217
|
-
color: 'black'
|
|
218
|
-
}
|
|
219
|
-
// aspectRatio: '16:9',
|
|
220
|
-
};
|
|
221
203
|
async function loadPackage(packageDir, dirName, hostString, skipPublish, skipBuild, linkPackage, release) {
|
|
222
204
|
if (skipPublish != true) {
|
|
223
205
|
process.stdout.write(`Building and publishing ${dirName}...`);
|
|
@@ -274,8 +256,9 @@ async function loadTestsList(packages, core = false, record = false) {
|
|
|
274
256
|
const suffix = process.env.BACKUP_SIZE && process.env.WORKER_ID && process.env.TOTAL_WORKERS ? `_${process.env.BACKUP_SIZE}_${process.env.WORKER_ID}_${process.env.TOTAL_WORKERS}` : '';
|
|
275
257
|
const logsDir = `./load-test-console-output${suffix}.log`;
|
|
276
258
|
const recordDir = `./load-test-record${suffix}.mp4`;
|
|
277
|
-
recorder =
|
|
278
|
-
|
|
259
|
+
recorder = await page.screencast({
|
|
260
|
+
path: recordDir
|
|
261
|
+
});
|
|
279
262
|
await page.exposeFunction('addLogsToFile', addLogsToFile);
|
|
280
263
|
_fs.default.writeFileSync(logsDir, ``);
|
|
281
264
|
page.on('console', msg => {
|
|
@@ -648,13 +631,15 @@ async function runBrowser(testExecutionData, browserOptions, browsersId, testInv
|
|
|
648
631
|
page = out.page;
|
|
649
632
|
webUrl = await getWebUrlFromPage(page);
|
|
650
633
|
}
|
|
651
|
-
|
|
634
|
+
let recorder = null;
|
|
652
635
|
const currentBrowserNum = browsersId;
|
|
653
636
|
const logsDir = `./test-console-output-${currentBrowserNum}.log`;
|
|
654
637
|
const recordDir = `./test-record-${currentBrowserNum}.mp4`;
|
|
655
638
|
if (browserOptions.record && !existingBrowserSession) {
|
|
656
639
|
// Only set up recording on initial browser creation, not on retry
|
|
657
|
-
await
|
|
640
|
+
recorder = await page.screencast({
|
|
641
|
+
path: recordDir
|
|
642
|
+
});
|
|
658
643
|
await page.exposeFunction('addLogsToFile', addLogsToFile);
|
|
659
644
|
_fs.default.writeFileSync(logsDir, ``);
|
|
660
645
|
page.on('console', msg => {
|
|
@@ -866,7 +851,7 @@ async function runBrowser(testExecutionData, browserOptions, browsersId, testInv
|
|
|
866
851
|
|
|
867
852
|
// Print the final category summary
|
|
868
853
|
printFinalCategorySummary();
|
|
869
|
-
if (browserOptions.record && !existingBrowserSession) await recorder
|
|
854
|
+
if (browserOptions.record && !existingBrowserSession) await recorder?.stop();
|
|
870
855
|
if (modernOutput) {
|
|
871
856
|
testingResults.verbosePassed = '';
|
|
872
857
|
testingResults.verboseSkipped = '';
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import js from '@eslint/js';
|
|
2
|
+
import tseslint from 'typescript-eslint';
|
|
3
|
+
import stylistic from '@stylistic/eslint-plugin';
|
|
4
|
+
import globals from 'globals';
|
|
5
|
+
|
|
6
|
+
// Flat config (ESLint 9). Replaces the legacy .eslintrc.json + eslint-config-google.
|
|
7
|
+
// Stylistic rules that used to live in ESLint core now come from @stylistic.
|
|
8
|
+
export default tseslint.config(
|
|
9
|
+
{
|
|
10
|
+
ignores: [
|
|
11
|
+
'bin/**/*.js',
|
|
12
|
+
'bin/**/*.js.map',
|
|
13
|
+
'node_modules/**',
|
|
14
|
+
'package-template/**',
|
|
15
|
+
'entity-template/**',
|
|
16
|
+
'script-template/**',
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
js.configs.recommended,
|
|
20
|
+
...tseslint.configs.recommended,
|
|
21
|
+
{
|
|
22
|
+
files: ['bin/**/*.ts'],
|
|
23
|
+
plugins: {'@stylistic': stylistic},
|
|
24
|
+
languageOptions: {
|
|
25
|
+
ecmaVersion: 2022,
|
|
26
|
+
sourceType: 'module',
|
|
27
|
+
globals: {...globals.browser, ...globals.node},
|
|
28
|
+
},
|
|
29
|
+
rules: {
|
|
30
|
+
'@stylistic/no-trailing-spaces': 'off',
|
|
31
|
+
'@stylistic/indent': ['error', 2],
|
|
32
|
+
'@stylistic/max-len': ['error', 140],
|
|
33
|
+
'@stylistic/padded-blocks': 'off',
|
|
34
|
+
'@stylistic/spaced-comment': 'off',
|
|
35
|
+
'@stylistic/linebreak-style': 'off',
|
|
36
|
+
'guard-for-in': 'off',
|
|
37
|
+
'curly': ['error', 'multi-or-nest'],
|
|
38
|
+
'@stylistic/brace-style': ['error', '1tbs', {allowSingleLine: true}],
|
|
39
|
+
'@stylistic/block-spacing': ['error', 'always'],
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
);
|
package/package.json
CHANGED
|
@@ -1,39 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "datagrok-tools",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.4.1",
|
|
4
4
|
"description": "Utility to upload and publish packages to Datagrok",
|
|
5
5
|
"homepage": "https://github.com/datagrok-ai/public/tree/master/tools#readme",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@babel/parser": "^7.
|
|
8
|
-
"@babel/runtime": "^7.
|
|
9
|
-
"@babel/traverse": "^7.
|
|
10
|
-
"@typescript-eslint/typescript-estree": "^8.
|
|
11
|
-
"@typescript-eslint/visitor-keys": "^8.
|
|
7
|
+
"@babel/parser": "^7.29.7",
|
|
8
|
+
"@babel/runtime": "^7.29.7",
|
|
9
|
+
"@babel/traverse": "^7.29.7",
|
|
10
|
+
"@typescript-eslint/typescript-estree": "^8.61.1",
|
|
11
|
+
"@typescript-eslint/visitor-keys": "^8.61.1",
|
|
12
12
|
"adm-zip": "^0.5.17",
|
|
13
|
-
"archiver": "^
|
|
14
|
-
"
|
|
15
|
-
"datagrok-api": "^1.26.0",
|
|
13
|
+
"archiver": "^7.0.1",
|
|
14
|
+
"datagrok-api": "^1.27.6",
|
|
16
15
|
"estraverse": "^5.3.0",
|
|
17
16
|
"glob": "^13.0.6",
|
|
18
|
-
"ignore-walk": "^
|
|
19
|
-
"inquirer": "^
|
|
20
|
-
"js-yaml": "^4.
|
|
17
|
+
"ignore-walk": "^6.0.5",
|
|
18
|
+
"inquirer": "^8.2.7",
|
|
19
|
+
"js-yaml": "^4.2.0",
|
|
21
20
|
"minimist": "^1.2.8",
|
|
22
21
|
"node-fetch": "^2.7.0",
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"puppeteer": "22.10.0",
|
|
27
|
-
"puppeteer-screen-recorder": "3.0.3",
|
|
28
|
-
"ts-morph": "^27.0.2"
|
|
22
|
+
"papaparse": "^5.5.3",
|
|
23
|
+
"puppeteer": "^24.15.0",
|
|
24
|
+
"ts-morph": "^28.0.0"
|
|
29
25
|
},
|
|
30
26
|
"scripts": {
|
|
31
27
|
"link": "npm link",
|
|
32
|
-
"prepublishOnly": "
|
|
33
|
-
"babel": "
|
|
34
|
-
"build": "
|
|
28
|
+
"prepublishOnly": "node build.js",
|
|
29
|
+
"babel": "node build.js",
|
|
30
|
+
"build": "node build.js",
|
|
35
31
|
"update:ivp-parser": "esbuild plugins/ivp-parser.entry.mjs --bundle --format=cjs --platform=node --alias:diff-grok=../libraries/compute-utils/node_modules/diff-grok --outfile=plugins/ivp-parser.bundle.cjs",
|
|
36
|
-
"debug-source-map": "
|
|
32
|
+
"debug-source-map": "node build.js --source-maps",
|
|
37
33
|
"test": "vitest run --project unit",
|
|
38
34
|
"test:watch": "vitest --project unit",
|
|
39
35
|
"test:integration": "vitest run --project integration",
|
|
@@ -64,27 +60,33 @@
|
|
|
64
60
|
]
|
|
65
61
|
},
|
|
66
62
|
"devDependencies": {
|
|
67
|
-
"@babel/
|
|
68
|
-
"@babel/
|
|
69
|
-
"@babel/plugin-
|
|
70
|
-
"
|
|
71
|
-
"@babel/
|
|
72
|
-
"@
|
|
73
|
-
"@
|
|
74
|
-
"@datagrok-misc/eslint-plugin-config": "^1.0.0",
|
|
63
|
+
"@babel/core": "^7.29.7",
|
|
64
|
+
"@babel/plugin-proposal-decorators": "^7.29.0",
|
|
65
|
+
"@babel/plugin-transform-runtime": "^7.29.0",
|
|
66
|
+
"@babel/preset-env": "^7.29.7",
|
|
67
|
+
"@babel/preset-typescript": "^7.29.0",
|
|
68
|
+
"@eslint/js": "^9.39.0",
|
|
69
|
+
"@stylistic/eslint-plugin": "^5.10.0",
|
|
75
70
|
"@types/adm-zip": "^0.5.8",
|
|
71
|
+
"@types/archiver": "^6.0.3",
|
|
76
72
|
"@types/ignore-walk": "^4.0.3",
|
|
77
73
|
"@types/inquirer": "^8.2.10",
|
|
78
74
|
"@types/js-yaml": "^4.0.9",
|
|
79
|
-
"@types/node": "^
|
|
75
|
+
"@types/node": "^22.0.0",
|
|
80
76
|
"@types/papaparse": "^5.3.15",
|
|
81
|
-
"
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"eslint-config-google": "^0.14.0",
|
|
77
|
+
"esbuild": "^0.28.1",
|
|
78
|
+
"eslint": "^9.39.0",
|
|
79
|
+
"globals": "^17.6.0",
|
|
85
80
|
"typescript": "^5.3.3",
|
|
86
|
-
"
|
|
81
|
+
"typescript-eslint": "^8.61.1",
|
|
82
|
+
"vitest": "^3.2.6",
|
|
87
83
|
"webpack": "^5.89.0",
|
|
88
84
|
"webpack-cli": "^5.1.4"
|
|
85
|
+
},
|
|
86
|
+
"overrides": {
|
|
87
|
+
"esbuild": "^0.28.1",
|
|
88
|
+
"archiver-utils": {
|
|
89
|
+
"glob": "$glob"
|
|
90
|
+
}
|
|
89
91
|
}
|
|
90
92
|
}
|
package/.eslintrc.json
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"env": {
|
|
3
|
-
"browser": true,
|
|
4
|
-
"es2022": true
|
|
5
|
-
},
|
|
6
|
-
"extends": [
|
|
7
|
-
"google"
|
|
8
|
-
],
|
|
9
|
-
"parser": "@typescript-eslint/parser",
|
|
10
|
-
"parserOptions": {
|
|
11
|
-
"ecmaVersion": 12,
|
|
12
|
-
"sourceType": "module"
|
|
13
|
-
},
|
|
14
|
-
"plugins": ["@typescript-eslint"],
|
|
15
|
-
"rules": {
|
|
16
|
-
"no-trailing-spaces": "off",
|
|
17
|
-
"indent": [
|
|
18
|
-
"error",
|
|
19
|
-
2
|
|
20
|
-
],
|
|
21
|
-
"max-len": [
|
|
22
|
-
"error",
|
|
23
|
-
140
|
|
24
|
-
],
|
|
25
|
-
"padded-blocks": "off",
|
|
26
|
-
"require-jsdoc": "off",
|
|
27
|
-
"spaced-comment": "off",
|
|
28
|
-
"linebreak-style": "off",
|
|
29
|
-
"guard-for-in": "off",
|
|
30
|
-
"curly": [
|
|
31
|
-
"error",
|
|
32
|
-
"multi-or-nest"
|
|
33
|
-
],
|
|
34
|
-
"brace-style": [
|
|
35
|
-
"error",
|
|
36
|
-
"1tbs",
|
|
37
|
-
{
|
|
38
|
-
"allowSingleLine": true
|
|
39
|
-
}
|
|
40
|
-
],
|
|
41
|
-
"block-spacing": 2
|
|
42
|
-
}
|
|
43
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var _vitest = require("vitest");
|
|
4
|
-
var _build = require("../commands/build");
|
|
5
|
-
(0, _vitest.describe)('getNestedValue', () => {
|
|
6
|
-
(0, _vitest.it)('returns value for a simple key', () => {
|
|
7
|
-
(0, _vitest.expect)((0, _build.getNestedValue)({
|
|
8
|
-
name: 'Chem'
|
|
9
|
-
}, 'name')).toBe('Chem');
|
|
10
|
-
});
|
|
11
|
-
(0, _vitest.it)('returns value for a nested path', () => {
|
|
12
|
-
(0, _vitest.expect)((0, _build.getNestedValue)({
|
|
13
|
-
a: {
|
|
14
|
-
b: {
|
|
15
|
-
c: 42
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
}, 'a.b.c')).toBe(42);
|
|
19
|
-
});
|
|
20
|
-
(0, _vitest.it)('returns undefined for a missing key', () => {
|
|
21
|
-
(0, _vitest.expect)((0, _build.getNestedValue)({
|
|
22
|
-
name: 'Chem'
|
|
23
|
-
}, 'version')).toBeUndefined();
|
|
24
|
-
});
|
|
25
|
-
(0, _vitest.it)('returns undefined when a mid-path segment is null', () => {
|
|
26
|
-
(0, _vitest.expect)((0, _build.getNestedValue)({
|
|
27
|
-
a: null
|
|
28
|
-
}, 'a.b')).toBeUndefined();
|
|
29
|
-
});
|
|
30
|
-
(0, _vitest.it)('returns undefined when a mid-path segment is missing', () => {
|
|
31
|
-
(0, _vitest.expect)((0, _build.getNestedValue)({
|
|
32
|
-
a: {}
|
|
33
|
-
}, 'a.b.c')).toBeUndefined();
|
|
34
|
-
});
|
|
35
|
-
(0, _vitest.it)('returns undefined for an empty path (splits to empty string key)', () => {
|
|
36
|
-
(0, _vitest.expect)((0, _build.getNestedValue)({
|
|
37
|
-
x: 1
|
|
38
|
-
}, '')).toBeUndefined();
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
const pkg = overrides => ({
|
|
42
|
-
dir: '/tmp/pkg',
|
|
43
|
-
name: overrides.name ?? 'test-pkg',
|
|
44
|
-
friendlyName: overrides.friendlyName ?? overrides.name ?? 'Test Pkg',
|
|
45
|
-
version: overrides.version ?? '1.0.0',
|
|
46
|
-
packageJson: overrides
|
|
47
|
-
});
|
|
48
|
-
(0, _vitest.describe)('applyFilter', () => {
|
|
49
|
-
const packages = [pkg({
|
|
50
|
-
name: 'Chem',
|
|
51
|
-
version: '1.5.0',
|
|
52
|
-
category: 'Cheminformatics'
|
|
53
|
-
}), pkg({
|
|
54
|
-
name: 'Bio',
|
|
55
|
-
version: '2.0.0',
|
|
56
|
-
category: 'Bioinformatics'
|
|
57
|
-
}), pkg({
|
|
58
|
-
name: 'PowerGrid',
|
|
59
|
-
version: '1.5.0',
|
|
60
|
-
category: 'Viewers'
|
|
61
|
-
})];
|
|
62
|
-
(0, _vitest.it)('returns all packages when filter matches all', () => {
|
|
63
|
-
(0, _vitest.expect)((0, _build.applyFilter)(packages, 'name:.')).toHaveLength(3);
|
|
64
|
-
});
|
|
65
|
-
(0, _vitest.it)('filters by exact name match', () => {
|
|
66
|
-
const result = (0, _build.applyFilter)(packages, 'name:^Chem$');
|
|
67
|
-
(0, _vitest.expect)(result).toHaveLength(1);
|
|
68
|
-
(0, _vitest.expect)(result[0].name).toBe('Chem');
|
|
69
|
-
});
|
|
70
|
-
(0, _vitest.it)('filters by partial name (regex substring)', () => {
|
|
71
|
-
const result = (0, _build.applyFilter)(packages, 'name:Bio');
|
|
72
|
-
(0, _vitest.expect)(result).toHaveLength(1);
|
|
73
|
-
(0, _vitest.expect)(result[0].name).toBe('Bio');
|
|
74
|
-
});
|
|
75
|
-
(0, _vitest.it)('returns empty array when nothing matches', () => {
|
|
76
|
-
(0, _vitest.expect)((0, _build.applyFilter)(packages, 'name:NOMATCH')).toHaveLength(0);
|
|
77
|
-
});
|
|
78
|
-
(0, _vitest.it)('filters by version', () => {
|
|
79
|
-
const result = (0, _build.applyFilter)(packages, 'version:^1\\.5');
|
|
80
|
-
(0, _vitest.expect)(result).toHaveLength(2);
|
|
81
|
-
(0, _vitest.expect)(result.map(p => p.name)).toEqual(_vitest.expect.arrayContaining(['Chem', 'PowerGrid']));
|
|
82
|
-
});
|
|
83
|
-
(0, _vitest.it)('applies && conjunction (both conditions must match)', () => {
|
|
84
|
-
const result = (0, _build.applyFilter)(packages, 'name:Chem && version:1\\.5');
|
|
85
|
-
(0, _vitest.expect)(result).toHaveLength(1);
|
|
86
|
-
(0, _vitest.expect)(result[0].name).toBe('Chem');
|
|
87
|
-
});
|
|
88
|
-
(0, _vitest.it)('returns empty when one part of && conjunction fails', () => {
|
|
89
|
-
(0, _vitest.expect)((0, _build.applyFilter)(packages, 'name:Chem && version:^2')).toHaveLength(0);
|
|
90
|
-
});
|
|
91
|
-
(0, _vitest.it)('filters by nested field', () => {
|
|
92
|
-
const withNested = [pkg({
|
|
93
|
-
name: 'A',
|
|
94
|
-
datagrok: {
|
|
95
|
-
apiVersion: '1.0'
|
|
96
|
-
}
|
|
97
|
-
}), pkg({
|
|
98
|
-
name: 'B',
|
|
99
|
-
datagrok: {
|
|
100
|
-
apiVersion: '2.0'
|
|
101
|
-
}
|
|
102
|
-
})];
|
|
103
|
-
const result = (0, _build.applyFilter)(withNested, 'datagrok.apiVersion:^1');
|
|
104
|
-
(0, _vitest.expect)(result).toHaveLength(1);
|
|
105
|
-
(0, _vitest.expect)(result[0].name).toBe('A');
|
|
106
|
-
});
|
|
107
|
-
(0, _vitest.it)('returns empty when field does not exist', () => {
|
|
108
|
-
(0, _vitest.expect)((0, _build.applyFilter)(packages, 'nonexistent:anything')).toHaveLength(0);
|
|
109
|
-
});
|
|
110
|
-
(0, _vitest.it)('treats filter with no colon as field name with match-all pattern', () => {
|
|
111
|
-
// No colon → field = whole string, pattern = /./ (matches any value)
|
|
112
|
-
// The function returns packages where the field exists and is non-empty
|
|
113
|
-
const result = (0, _build.applyFilter)(packages, 'name');
|
|
114
|
-
(0, _vitest.expect)(result).toHaveLength(3);
|
|
115
|
-
});
|
|
116
|
-
});
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
var _vitest = require("vitest");
|
|
4
|
-
var _report = require("../commands/report");
|
|
5
|
-
(0, _vitest.describe)('markdownToJiraWiki — basic rules', () => {
|
|
6
|
-
(0, _vitest.it)('converts H1', () => {
|
|
7
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('# Title')).toBe('h1. Title');
|
|
8
|
-
});
|
|
9
|
-
(0, _vitest.it)('converts H2 / H3 / H6', () => {
|
|
10
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('## Sub')).toBe('h2. Sub');
|
|
11
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('### Sub-sub')).toBe('h3. Sub-sub');
|
|
12
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('###### Deep')).toBe('h6. Deep');
|
|
13
|
-
});
|
|
14
|
-
(0, _vitest.it)('converts bold', () => {
|
|
15
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('hello **world** foo')).toBe('hello *world* foo');
|
|
16
|
-
});
|
|
17
|
-
(0, _vitest.it)('converts italic with single asterisks', () => {
|
|
18
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('hello *world* foo')).toBe('hello _world_ foo');
|
|
19
|
-
});
|
|
20
|
-
(0, _vitest.it)('converts strikethrough', () => {
|
|
21
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('~~gone~~')).toBe('-gone-');
|
|
22
|
-
});
|
|
23
|
-
(0, _vitest.it)('converts links', () => {
|
|
24
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('see [docs](https://x.example/y)')).toBe('see [docs|https://x.example/y]');
|
|
25
|
-
});
|
|
26
|
-
(0, _vitest.it)('converts blockquote', () => {
|
|
27
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('> quoted line')).toBe('bq. quoted line');
|
|
28
|
-
});
|
|
29
|
-
(0, _vitest.it)('converts unordered list', () => {
|
|
30
|
-
const md = '- one\n- two\n- three';
|
|
31
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)(md)).toBe('* one\n* two\n* three');
|
|
32
|
-
});
|
|
33
|
-
(0, _vitest.it)('converts one level of nested unordered list', () => {
|
|
34
|
-
const md = '- top\n - sub\n- back';
|
|
35
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)(md)).toBe('* top\n** sub\n* back');
|
|
36
|
-
});
|
|
37
|
-
(0, _vitest.it)('converts ordered list', () => {
|
|
38
|
-
const md = '1. one\n2. two\n3. three';
|
|
39
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)(md)).toBe('# one\n# two\n# three');
|
|
40
|
-
});
|
|
41
|
-
(0, _vitest.it)('converts inline code', () => {
|
|
42
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('use `foo()` here')).toBe('use {{foo()}} here');
|
|
43
|
-
});
|
|
44
|
-
(0, _vitest.it)('converts plain code fence to noformat', () => {
|
|
45
|
-
const md = '```\nraw code\nmore\n```';
|
|
46
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)(md)).toBe('{noformat}\nraw code\nmore\n{noformat}');
|
|
47
|
-
});
|
|
48
|
-
(0, _vitest.it)('converts code fence with language tag to {code:lang}', () => {
|
|
49
|
-
const md = '```js\nconst x = 1;\n```';
|
|
50
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)(md)).toBe('{code:js}\nconst x = 1;\n{code}');
|
|
51
|
-
});
|
|
52
|
-
(0, _vitest.it)('converts HTML entities / & / < / >', () => {
|
|
53
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('a b')).toBe('a b');
|
|
54
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('a&b')).toBe('a&b');
|
|
55
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('a<b>c')).toBe('a<b>c');
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
(0, _vitest.describe)('markdownToJiraWiki — content-protection inside code fences', () => {
|
|
59
|
-
(0, _vitest.it)('does not transform `{{plates}}` inside a fenced block (run-#4 false-positive case)', () => {
|
|
60
|
-
const md = ['Before', '```', 'context: {{plates}} should stay literal', '# not a heading', '- not a list', '```', 'After'].join('\n');
|
|
61
|
-
const out = (0, _report.markdownToJiraWiki)(md);
|
|
62
|
-
(0, _vitest.expect)(out).toContain('{noformat}\ncontext: {{plates}} should stay literal');
|
|
63
|
-
(0, _vitest.expect)(out).toContain('# not a heading');
|
|
64
|
-
(0, _vitest.expect)(out).toContain('- not a list');
|
|
65
|
-
(0, _vitest.expect)(out).not.toContain('h1.');
|
|
66
|
-
});
|
|
67
|
-
(0, _vitest.it)('does not transform headings/links/lists inside an inline code span', () => {
|
|
68
|
-
const md = 'use `# not a heading` and `[ref](u)` here';
|
|
69
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)(md)).toBe('use {{# not a heading}} and {{[ref](u)}} here');
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
(0, _vitest.describe)('markdownToJiraWiki — edge cases', () => {
|
|
73
|
-
(0, _vitest.it)('handles bold containing italic: **bold *inside* bold**', () => {
|
|
74
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('**bold *inside* bold**')).toBe('*bold _inside_ bold*');
|
|
75
|
-
});
|
|
76
|
-
(0, _vitest.it)('preserves bold and italic on the same line', () => {
|
|
77
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('**a** and *b*')).toBe('*a* and _b_');
|
|
78
|
-
});
|
|
79
|
-
(0, _vitest.it)('handles a heading whose text contains backticks', () => {
|
|
80
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('## use `foo()` for x')).toBe('h2. use {{foo()}} for x');
|
|
81
|
-
});
|
|
82
|
-
(0, _vitest.it)('passes plain text through unchanged', () => {
|
|
83
|
-
const plain = 'Just a normal sentence with no markdown.';
|
|
84
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)(plain)).toBe(plain);
|
|
85
|
-
});
|
|
86
|
-
(0, _vitest.it)('returns empty string unchanged', () => {
|
|
87
|
-
(0, _vitest.expect)((0, _report.markdownToJiraWiki)('')).toBe('');
|
|
88
|
-
});
|
|
89
|
-
(0, _vitest.it)('handles a multi-block document end-to-end', () => {
|
|
90
|
-
const md = ['# Handoff', '', 'Some **bold** intro and a [link](https://x.example).', '', '## Findings', '', '- first', '- second', '', '> note: this matters', '', '```js', 'const x = 1;', '```', '', 'Done here.'].join('\n');
|
|
91
|
-
const out = (0, _report.markdownToJiraWiki)(md);
|
|
92
|
-
(0, _vitest.expect)(out).toContain('h1. Handoff');
|
|
93
|
-
(0, _vitest.expect)(out).toContain('h2. Findings');
|
|
94
|
-
(0, _vitest.expect)(out).toContain('Some *bold* intro and a [link|https://x.example].');
|
|
95
|
-
(0, _vitest.expect)(out).toContain('* first\n* second');
|
|
96
|
-
(0, _vitest.expect)(out).toContain('bq. note: this matters');
|
|
97
|
-
(0, _vitest.expect)(out).toContain('{code:js}\nconst x = 1;\n{code}');
|
|
98
|
-
(0, _vitest.expect)(out).toContain('Done here.');
|
|
99
|
-
(0, _vitest.expect)(out).not.toContain(' ');
|
|
100
|
-
});
|
|
101
|
-
});
|