@datagrok/peptides 1.5.1 → 1.7.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/.eslintrc.json +2 -0
- package/dist/package-test.js +5127 -60267
- package/dist/package.js +4838 -60056
- package/dist/vendors-node_modules_datagrok-libraries_ml_src_workers_dimensionality-reducer_js.js +354 -265
- package/files/tests/aligned_5k.d42 +0 -0
- package/package.json +15 -22
- package/src/model.ts +373 -236
- package/src/package-test.ts +1 -0
- package/src/package.ts +23 -50
- package/src/styles.css +7 -0
- package/src/tests/core.ts +54 -13
- package/src/tests/peptide-space-test.ts +5 -53
- package/src/tests/viewers.ts +17 -0
- package/src/utils/cell-renderer.ts +28 -29
- package/src/utils/constants.ts +11 -1
- package/src/utils/misc.ts +16 -4
- package/src/utils/peptide-similarity-space.ts +1 -1
- package/src/utils/types.ts +2 -0
- package/src/viewers/logo-summary.ts +239 -74
- package/src/viewers/sar-viewer.ts +63 -49
- package/src/widgets/distribution.ts +74 -29
- package/src/widgets/manual-alignment.ts +2 -2
- package/src/widgets/mutation-cliffs.ts +6 -2
- package/src/widgets/peptides.ts +17 -10
- package/jest.config.js +0 -33
- package/src/__jest__/remote.test.ts +0 -76
- package/src/__jest__/test-node.ts +0 -97
- package/test-Peptides-4775b69ad08a-1bc1a2b4.html +0 -277
|
@@ -7,6 +7,8 @@ import $ from 'cash-dom';
|
|
|
7
7
|
import * as C from '../utils/constants';
|
|
8
8
|
import {getStats, MaskInfo, Stats} from '../utils/statistics';
|
|
9
9
|
import {PeptidesModel} from '../model';
|
|
10
|
+
import {wrapDistroAndStatsDefault} from '../utils/misc';
|
|
11
|
+
import wu from 'wu';
|
|
10
12
|
|
|
11
13
|
const allConst = 'All';
|
|
12
14
|
const otherConst = 'Other';
|
|
@@ -17,13 +19,9 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
17
19
|
const selectionObject = model.mutationCliffsSelection;
|
|
18
20
|
const clustersColName = model.settings.clustersColumnName;
|
|
19
21
|
let clustersProcessedObject: string[] = [];
|
|
20
|
-
if (clustersColName)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
clustersProcessedObject = new Array(clustersRawObject.length);
|
|
24
|
-
for (let i = 0; i < clustersRawObject.length; ++i)
|
|
25
|
-
clustersProcessedObject[i] = clustersColCategories[clustersRawObject[i]];
|
|
26
|
-
}
|
|
22
|
+
if (clustersColName)
|
|
23
|
+
clustersProcessedObject = model.logoSummarySelection;
|
|
24
|
+
|
|
27
25
|
const positions = Object.keys(selectionObject);
|
|
28
26
|
const positionsLen = positions.length;
|
|
29
27
|
let aarStr = allConst;
|
|
@@ -43,18 +41,28 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
43
41
|
continue;
|
|
44
42
|
|
|
45
43
|
for (const aar of aarList) {
|
|
44
|
+
const indexes: number[] = [];
|
|
46
45
|
aarStr = `${position} : ${aar}`;
|
|
47
|
-
const splitCol = DG.Column.bool(C.COLUMNS_NAMES.SPLIT_COL, rowCount).init((i) =>
|
|
48
|
-
|
|
46
|
+
const splitCol = DG.Column.bool(C.COLUMNS_NAMES.SPLIT_COL, rowCount).init((i) => {
|
|
47
|
+
const flag = posCol.get(i) == aar;
|
|
48
|
+
if (flag)
|
|
49
|
+
indexes.push(i);
|
|
50
|
+
});
|
|
49
51
|
const distributionTable = DG.DataFrame.fromColumns([activityScaledCol, splitCol]);
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
52
|
+
|
|
53
|
+
const colResults: {[colName: string]: number} = {};
|
|
54
|
+
for (const [col, agg] of Object.entries(model.settings.columns || {})) {
|
|
55
|
+
const currentCol = table.getCol(col);
|
|
56
|
+
const currentColData = currentCol.getRawData();
|
|
57
|
+
const tempCol = DG.Column.float('', indexes.length);
|
|
58
|
+
tempCol.init((i) => currentColData[indexes[i]]);
|
|
59
|
+
colResults[`${agg}(${col})`] = tempCol.stats[agg as keyof DG.Stats] as number;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const stats = model.monomerPositionStats[position][aar];
|
|
63
|
+
const das = getDistributionAndStats(distributionTable, stats, aarStr, otherStr, true);
|
|
64
|
+
const resultMap: {[key: string]: any} = {...das.tableMap, ...colResults};
|
|
65
|
+
const distributionRoot = wrapDistroAndStatsDefault(das.labels, das.histRoot, resultMap);
|
|
58
66
|
$(distributionRoot).addClass('d4-flex-col');
|
|
59
67
|
|
|
60
68
|
res.push(distributionRoot);
|
|
@@ -81,7 +89,20 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
81
89
|
const stats = getStats(activityScaledData, maskInfo);
|
|
82
90
|
const splitCol = DG.Column.fromBitSet(C.COLUMNS_NAMES.SPLIT_COL, mask);
|
|
83
91
|
const distributionTable = DG.DataFrame.fromColumns([activityScaledCol, splitCol]);
|
|
84
|
-
|
|
92
|
+
|
|
93
|
+
const indexes = mask.getSelectedIndexes();
|
|
94
|
+
const colResults: {[colName: string]: number} = {};
|
|
95
|
+
for (const [col, agg] of Object.entries(model.settings.columns || {})) {
|
|
96
|
+
const currentCol = table.getCol(col);
|
|
97
|
+
const currentColData = currentCol.getRawData();
|
|
98
|
+
const tempCol = DG.Column.float('', indexes.length);
|
|
99
|
+
tempCol.init((i) => currentColData[indexes[i]]);
|
|
100
|
+
colResults[`${agg}(${col})`] = tempCol.stats[agg as keyof DG.Stats] as number;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const das = getDistributionAndStats(distributionTable, stats, aarStr, otherStr, true);
|
|
104
|
+
const resultMap: {[key: string]: any} = {...das.tableMap, ...colResults};
|
|
105
|
+
const distributionRoot = wrapDistroAndStatsDefault(das.labels, das.histRoot, resultMap);
|
|
85
106
|
$(distributionRoot).addClass('d4-flex-col');
|
|
86
107
|
|
|
87
108
|
res.push(distributionRoot);
|
|
@@ -124,7 +145,20 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
124
145
|
const stats = getStats(activityScaledData, maskInfo);
|
|
125
146
|
const splitCol = DG.Column.fromBitSet(C.COLUMNS_NAMES.SPLIT_COL, mask);
|
|
126
147
|
const distributionTable = DG.DataFrame.fromColumns([activityScaledCol, splitCol]);
|
|
127
|
-
|
|
148
|
+
|
|
149
|
+
const indexes = mask.getSelectedIndexes();
|
|
150
|
+
const colResults: {[colName: string]: number} = {};
|
|
151
|
+
for (const [col, agg] of Object.entries(model.settings.columns || {})) {
|
|
152
|
+
const currentCol = table.getCol(col);
|
|
153
|
+
const currentColData = currentCol.getRawData();
|
|
154
|
+
const tempCol = DG.Column.float('', indexes.length);
|
|
155
|
+
tempCol.init((i) => currentColData[indexes[i]]);
|
|
156
|
+
colResults[`${agg}(${col})`] = tempCol.stats[agg as keyof DG.Stats] as number;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const das = getDistributionAndStats(distributionTable, stats, aarStr, otherStr, true);
|
|
160
|
+
const resultMap: {[key: string]: any} = {...das.tableMap, ...colResults};
|
|
161
|
+
const distributionRoot = wrapDistroAndStatsDefault(das.labels, das.histRoot, resultMap);
|
|
128
162
|
$(distributionRoot).addClass('d4-flex-col');
|
|
129
163
|
|
|
130
164
|
res.push(distributionRoot);
|
|
@@ -151,13 +185,27 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
151
185
|
}
|
|
152
186
|
|
|
153
187
|
const distributionTable = DG.DataFrame.fromColumns([activityScaledCol, splitCol]);
|
|
188
|
+
// distributionTable.filter.copyFrom(table.filter);
|
|
189
|
+
|
|
190
|
+
const indexes = model.getCompoundBitest().getSelectedIndexes();
|
|
191
|
+
const colResults: {[colName: string]: number} = {};
|
|
192
|
+
for (const [col, agg] of Object.entries(model.settings.columns || {})) {
|
|
193
|
+
const currentCol = table.getCol(col);
|
|
194
|
+
const currentColData = currentCol.getRawData();
|
|
195
|
+
const tempCol = DG.Column.float('', indexes.length);
|
|
196
|
+
tempCol.init((i) => currentColData[indexes[i]]);
|
|
197
|
+
colResults[`${agg}(${col})`] = tempCol.stats[agg as keyof DG.Stats] as number;
|
|
198
|
+
}
|
|
199
|
+
|
|
154
200
|
const maskInfo: MaskInfo = {
|
|
155
201
|
mask: table.selection.getBuffer(),
|
|
156
202
|
trueCount: table.selection.trueCount,
|
|
157
203
|
falseCount: table.selection.falseCount,
|
|
158
204
|
};
|
|
159
205
|
const stats = getStats(activityScaledCol.getRawData(), maskInfo);
|
|
160
|
-
const
|
|
206
|
+
const das = getDistributionAndStats(distributionTable, stats, aarStr, otherStr);
|
|
207
|
+
const resultMap: {[key: string]: any} = {...das.tableMap, ...colResults};
|
|
208
|
+
const distributionRoot = wrapDistroAndStatsDefault(das.labels, das.histRoot, resultMap);
|
|
161
209
|
$(distributionRoot).addClass('d4-flex-col');
|
|
162
210
|
|
|
163
211
|
res.push(distributionRoot);
|
|
@@ -194,9 +242,10 @@ export function getDistributionWidget(table: DG.DataFrame, model: PeptidesModel)
|
|
|
194
242
|
return new DG.Widget(ui.divV([controlsHost, distributionHost]));
|
|
195
243
|
}
|
|
196
244
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
245
|
+
type DistroAndStats = {labels: HTMLDivElement, histRoot: HTMLElement, tableMap: StringDictionary};
|
|
246
|
+
|
|
247
|
+
export function getDistributionAndStats(table: DG.DataFrame, stats: Stats, thisLabel: string, otherLabel: string = '',
|
|
248
|
+
isTooltip: boolean = false, splitColName?: string): DistroAndStats {
|
|
200
249
|
const labels = ui.divV([
|
|
201
250
|
ui.label(thisLabel, {style: {color: DG.Color.toHtml(otherLabel == '' ? DG.Color.blue : DG.Color.orange)}}),
|
|
202
251
|
ui.label(otherLabel, {style: {color: DG.Color.toHtml(DG.Color.blue)}})]);
|
|
@@ -204,7 +253,7 @@ export function getDistributionAndStats(
|
|
|
204
253
|
const histRoot = table.plot.histogram({
|
|
205
254
|
filteringEnabled: false,
|
|
206
255
|
valueColumnName: C.COLUMNS_NAMES.ACTIVITY_SCALED,
|
|
207
|
-
splitColumnName: C.COLUMNS_NAMES.SPLIT_COL,
|
|
256
|
+
splitColumnName: splitColName ?? C.COLUMNS_NAMES.SPLIT_COL,
|
|
208
257
|
legendVisibility: 'Never',
|
|
209
258
|
showXAxis: true,
|
|
210
259
|
showColumnSelector: false,
|
|
@@ -222,9 +271,5 @@ export function getDistributionAndStats(
|
|
|
222
271
|
'Mean difference': stats.meanDifference.toFixed(2),
|
|
223
272
|
};
|
|
224
273
|
|
|
225
|
-
|
|
226
|
-
result.style.minWidth = '200px';
|
|
227
|
-
if (isTooltip)
|
|
228
|
-
histRoot.style.maxHeight = '150px';
|
|
229
|
-
return result;
|
|
274
|
+
return {labels: labels, histRoot: histRoot, tableMap: tableMap};
|
|
230
275
|
}
|
|
@@ -5,7 +5,7 @@ import * as DG from 'datagrok-api/dg';
|
|
|
5
5
|
import $ from 'cash-dom';
|
|
6
6
|
import '../styles.css';
|
|
7
7
|
import {PeptidesModel} from '../model';
|
|
8
|
-
import {splitAlignedSequences} from '@datagrok-libraries/bio';
|
|
8
|
+
import {splitAlignedSequences} from '@datagrok-libraries/bio/src/utils/splitter';
|
|
9
9
|
|
|
10
10
|
/** Manual sequence alignment widget.
|
|
11
11
|
*
|
|
@@ -31,7 +31,7 @@ export function manualAlignmentWidget(alignedSequenceCol: DG.Column<string>, cur
|
|
|
31
31
|
grok.shell.o = temp;
|
|
32
32
|
|
|
33
33
|
const peptidesController = PeptidesModel.getInstance(currentDf);
|
|
34
|
-
peptidesController.
|
|
34
|
+
peptidesController.updateGrid();
|
|
35
35
|
});
|
|
36
36
|
|
|
37
37
|
const resetBtn = ui.button(
|
|
@@ -6,6 +6,7 @@ import {PeptidesModel} from '../model';
|
|
|
6
6
|
import {getSeparator} from '../utils/misc';
|
|
7
7
|
|
|
8
8
|
export function mutationCliffsWidget(table: DG.DataFrame, model: PeptidesModel): DG.Widget {
|
|
9
|
+
const currentFilter = table.filter.getSelectedIndexes();
|
|
9
10
|
const substInfo = model.substitutionsInfo;
|
|
10
11
|
const currentCell = model.mutationCliffsSelection;
|
|
11
12
|
const positions = Object.keys(currentCell);
|
|
@@ -28,12 +29,15 @@ export function mutationCliffsWidget(table: DG.DataFrame, model: PeptidesModel):
|
|
|
28
29
|
|
|
29
30
|
const posCol = table.getCol(pos);
|
|
30
31
|
for (const [referenceIdx, indexArray] of substitutionsMap.entries()) {
|
|
31
|
-
|
|
32
|
+
if (!currentFilter.includes(referenceIdx))
|
|
33
|
+
continue;
|
|
34
|
+
|
|
35
|
+
const forbiddentIndexes = seenIndexes.get(referenceIdx) ?? [];
|
|
32
36
|
const baseSequence = alignedSeqCol.get(referenceIdx);
|
|
33
37
|
const baseActivity = activityScaledCol.get(referenceIdx);
|
|
34
38
|
|
|
35
39
|
for (const subIdx of indexArray) {
|
|
36
|
-
if (forbiddentIndexes.includes(subIdx))
|
|
40
|
+
if (forbiddentIndexes.includes(subIdx) || !currentFilter.includes(subIdx))
|
|
37
41
|
continue;
|
|
38
42
|
|
|
39
43
|
if (!seenIndexes.has(subIdx))
|
package/src/widgets/peptides.ts
CHANGED
|
@@ -2,13 +2,15 @@ import * as grok from 'datagrok-api/grok';
|
|
|
2
2
|
import * as ui from 'datagrok-api/ui';
|
|
3
3
|
import * as DG from 'datagrok-api/dg';
|
|
4
4
|
|
|
5
|
+
import * as uuid from 'uuid';
|
|
6
|
+
|
|
5
7
|
import '../styles.css';
|
|
6
8
|
import * as C from '../utils/constants';
|
|
7
9
|
import * as type from '../utils/types';
|
|
8
10
|
import {PeptidesModel} from '../model';
|
|
9
11
|
import $ from 'cash-dom';
|
|
10
12
|
import {scaleActivity} from '../utils/misc';
|
|
11
|
-
import
|
|
13
|
+
import {ALIGNMENT, NOTATION, TAGS as bioTAGS} from '@datagrok-libraries/bio/src/utils/macromolecule';
|
|
12
14
|
|
|
13
15
|
/** Peptide analysis widget.
|
|
14
16
|
*
|
|
@@ -16,7 +18,7 @@ import * as bio from '@datagrok-libraries/bio';
|
|
|
16
18
|
* @param {DG.Column} col Aligned sequence column
|
|
17
19
|
* @return {Promise<DG.Widget>} Widget containing peptide analysis */
|
|
18
20
|
export function analyzePeptidesUI(df: DG.DataFrame, col?: DG.Column<string>):
|
|
19
|
-
{host: HTMLElement, callback: () => Promise<boolean>} {
|
|
21
|
+
{ host: HTMLElement, callback: () => Promise<boolean> } {
|
|
20
22
|
const logoHost = ui.div();
|
|
21
23
|
// logoHost.style.alignContent = 'center';
|
|
22
24
|
let seqColInput: DG.InputBase | null = null;
|
|
@@ -38,8 +40,8 @@ export function analyzePeptidesUI(df: DG.DataFrame, col?: DG.Column<string>):
|
|
|
38
40
|
return viewer.root;
|
|
39
41
|
}));
|
|
40
42
|
});
|
|
41
|
-
} else if (!(col.getTag(
|
|
42
|
-
|
|
43
|
+
} else if (!(col.getTag(bioTAGS.aligned) == ALIGNMENT.SEQ_MSA) &&
|
|
44
|
+
col.getTag(DG.TAGS.UNITS) !== NOTATION.HELM) {
|
|
43
45
|
return {
|
|
44
46
|
host: ui.label('Peptides analysis only works with aligned sequences'),
|
|
45
47
|
callback: async (): Promise<boolean> => false,
|
|
@@ -65,7 +67,8 @@ export function analyzePeptidesUI(df: DG.DataFrame, col?: DG.Column<string>):
|
|
|
65
67
|
let scaledCol: DG.Column<number>;
|
|
66
68
|
|
|
67
69
|
const defaultActivityColumn: DG.Column<number> | null =
|
|
68
|
-
df.col('activity') || df.col('IC50') || DG.Utils.firstOrNull(df.columns.numerical);
|
|
70
|
+
df.col('activity') || df.col('IC50') || DG.Utils.firstOrNull(df.columns.numerical);
|
|
71
|
+
;
|
|
69
72
|
const histogramHost = ui.div([], {id: 'pep-hist-host'});
|
|
70
73
|
|
|
71
74
|
const activityScalingMethod = ui.choiceInput(
|
|
@@ -94,6 +97,7 @@ export function analyzePeptidesUI(df: DG.DataFrame, col?: DG.Column<string>):
|
|
|
94
97
|
};
|
|
95
98
|
const activityColumnChoice = ui.columnInput('Activity', df, defaultActivityColumn, activityScalingMethodState);
|
|
96
99
|
const clustersColumnChoice = ui.columnInput('Clusters', df, null);
|
|
100
|
+
clustersColumnChoice.nullable = true;
|
|
97
101
|
activityColumnChoice.fireChanged();
|
|
98
102
|
activityScalingMethod.fireChanged();
|
|
99
103
|
|
|
@@ -118,12 +122,14 @@ export function analyzePeptidesUI(df: DG.DataFrame, col?: DG.Column<string>):
|
|
|
118
122
|
return false;
|
|
119
123
|
};
|
|
120
124
|
|
|
125
|
+
let bottomHeight = 'auto';
|
|
121
126
|
const inputElements: HTMLElement[] = [ui.inputs(inputsList)];
|
|
122
127
|
$(inputElements[0]).find('label').css('width', 'unset');
|
|
123
128
|
if (typeof col !== 'undefined') {
|
|
124
129
|
const startBtn = ui.button('Launch SAR', startAnalysisCallback);
|
|
125
130
|
startBtn.style.alignSelf = 'center';
|
|
126
131
|
inputElements.push(startBtn);
|
|
132
|
+
bottomHeight = '215px';
|
|
127
133
|
}
|
|
128
134
|
|
|
129
135
|
$(logoHost).empty().append(ui.wait(async () => {
|
|
@@ -137,7 +143,7 @@ export function analyzePeptidesUI(df: DG.DataFrame, col?: DG.Column<string>):
|
|
|
137
143
|
ui.splitH([
|
|
138
144
|
ui.splitV(inputElements),
|
|
139
145
|
histogramHost,
|
|
140
|
-
], {style: {height:
|
|
146
|
+
], {style: {height: bottomHeight}}),
|
|
141
147
|
]);
|
|
142
148
|
mainHost.style.maxWidth = '400px';
|
|
143
149
|
return {host: mainHost, callback: startAnalysisCallback};
|
|
@@ -164,22 +170,23 @@ export async function startAnalysis(activityColumn: DG.Column<number>, peptidesC
|
|
|
164
170
|
};
|
|
165
171
|
if (clustersColumn) {
|
|
166
172
|
const clusterCol = newDf.getCol(clustersColumn.name);
|
|
167
|
-
|
|
173
|
+
if (clusterCol.type != DG.COLUMN_TYPE.STRING)
|
|
174
|
+
newDfCols.replace(clusterCol, clusterCol.convertTo(DG.COLUMN_TYPE.STRING));
|
|
168
175
|
settings.clustersColumnName = clustersColumn.name;
|
|
169
176
|
}
|
|
170
177
|
newDf.setTag(C.TAGS.SETTINGS, JSON.stringify(settings));
|
|
171
178
|
|
|
172
179
|
let monomerType = 'HELM_AA';
|
|
173
|
-
if (peptidesCol.getTag(DG.TAGS.UNITS) ==
|
|
180
|
+
if (peptidesCol.getTag(DG.TAGS.UNITS) == NOTATION.HELM) {
|
|
174
181
|
const sampleSeq = peptidesCol.get(0)!;
|
|
175
182
|
monomerType = sampleSeq.startsWith('PEPTIDE') ? 'HELM_AA' : 'HELM_BASE';
|
|
176
183
|
} else {
|
|
177
184
|
const alphabet = peptidesCol.tags[C.TAGS.ALPHABET];
|
|
178
185
|
monomerType = alphabet == 'DNA' || alphabet == 'RNA' ? 'HELM_BASE' : 'HELM_AA';
|
|
179
186
|
}
|
|
180
|
-
|
|
187
|
+
const dfUuid = uuid.v4();
|
|
188
|
+
newDf.setTag(C.TAGS.UUID, dfUuid);
|
|
181
189
|
newDf.setTag('monomerType', monomerType);
|
|
182
|
-
newDf.setTag('newAnalysis', '1');
|
|
183
190
|
model = PeptidesModel.getInstance(newDf);
|
|
184
191
|
await model.addViewers();
|
|
185
192
|
} else
|
package/jest.config.js
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
"roots": [
|
|
3
|
-
"<rootDir>/src"
|
|
4
|
-
],
|
|
5
|
-
"testMatch": [
|
|
6
|
-
"**/__jest__/**/*.test.+(ts|tsx)"
|
|
7
|
-
],
|
|
8
|
-
moduleFileExtensions: [
|
|
9
|
-
'ts',
|
|
10
|
-
'js',
|
|
11
|
-
],
|
|
12
|
-
"transform": {
|
|
13
|
-
"^.+\\.(ts|tsx)$": "ts-jest"
|
|
14
|
-
},
|
|
15
|
-
transformIgnorePatterns: ['^.+\\.js$'],
|
|
16
|
-
globals: {
|
|
17
|
-
'ts-jest': {
|
|
18
|
-
'tsconfig': {
|
|
19
|
-
"target": "es6",
|
|
20
|
-
"module": "es2020",
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
reporters: [
|
|
25
|
-
"default",
|
|
26
|
-
[
|
|
27
|
-
"./node_modules/jest-html-reporter",
|
|
28
|
-
{
|
|
29
|
-
"includeConsoleLog": true
|
|
30
|
-
}
|
|
31
|
-
]
|
|
32
|
-
]
|
|
33
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @jest-environment jsdom
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import * as utils from './test-node';
|
|
6
|
-
import puppeteer from 'puppeteer';
|
|
7
|
-
|
|
8
|
-
const P_START_TIMEOUT: number = 3600000;
|
|
9
|
-
let browser: puppeteer.Browser;
|
|
10
|
-
let page: puppeteer.Page;
|
|
11
|
-
|
|
12
|
-
beforeAll(async () => {
|
|
13
|
-
const out = await utils.getBrowserPage(puppeteer);
|
|
14
|
-
browser = out.browser;
|
|
15
|
-
page = out.page;
|
|
16
|
-
}, P_START_TIMEOUT);
|
|
17
|
-
|
|
18
|
-
afterAll(async () => {
|
|
19
|
-
await browser?.close();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
expect.extend({
|
|
23
|
-
checkOutput(received, expected, context) {
|
|
24
|
-
if (received === expected) {
|
|
25
|
-
return {
|
|
26
|
-
message: () => context,
|
|
27
|
-
pass: true,
|
|
28
|
-
};
|
|
29
|
-
} else {
|
|
30
|
-
return {
|
|
31
|
-
message: () => context,
|
|
32
|
-
pass: false,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('TEST', async () => {
|
|
39
|
-
const targetPackage:string = process.env.TARGET_PACKAGE ?? 'Peptides';
|
|
40
|
-
console.log(`Testing ${targetPackage} package`);
|
|
41
|
-
|
|
42
|
-
const r = await page.evaluate((targetPackage):Promise<object> => {
|
|
43
|
-
return new Promise<object>((resolve, reject) => {
|
|
44
|
-
(<any>window).grok.functions.eval(targetPackage + ':test()').then((df: any) => {
|
|
45
|
-
const cStatus = df.columns.byName('success');
|
|
46
|
-
const cSkipped = df.columns.byName('skipped');
|
|
47
|
-
const cMessage = df.columns.byName('result');
|
|
48
|
-
const cCat = df.columns.byName('category');
|
|
49
|
-
const cName = df.columns.byName('name');
|
|
50
|
-
const cTime = df.columns.byName('ms');
|
|
51
|
-
let failed = false;
|
|
52
|
-
let skipReport = '';
|
|
53
|
-
let passReport = '';
|
|
54
|
-
let failReport = '';
|
|
55
|
-
for (let i = 0; i < df.rowCount; i++) {
|
|
56
|
-
if (cStatus.get(i)) {
|
|
57
|
-
if (cSkipped.get(i))
|
|
58
|
-
skipReport += `Test result : Skipped : ${cTime.get(i)} : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
59
|
-
else
|
|
60
|
-
passReport += `Test result : Success : ${cTime.get(i)} : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
61
|
-
} else {
|
|
62
|
-
failed = true;
|
|
63
|
-
failReport += `Test result : Failed : ${cTime.get(i)} : ${targetPackage}.${cCat.get(i)}.${cName.get(i)} : ${cMessage.get(i)}\n`;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
resolve({failReport, skipReport, passReport, failed});
|
|
67
|
-
}).catch((e: any) => reject(e));
|
|
68
|
-
});
|
|
69
|
-
}, targetPackage);
|
|
70
|
-
// @ts-ignore
|
|
71
|
-
console.log(r.passReport);
|
|
72
|
-
// @ts-ignore
|
|
73
|
-
console.log(r.skipReport);
|
|
74
|
-
// @ts-ignore
|
|
75
|
-
expect(r.failed).checkOutput(false, r.failReport);
|
|
76
|
-
}, 7200000);
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
import * as path from 'path';
|
|
2
|
-
import * as os from 'os';
|
|
3
|
-
import * as fs from 'fs';
|
|
4
|
-
// @ts-ignore
|
|
5
|
-
import * as yaml from 'js-yaml';
|
|
6
|
-
const fetch = require('node-fetch');
|
|
7
|
-
|
|
8
|
-
export async function getToken(url: string, key: string) {
|
|
9
|
-
const response = await fetch(`${url}/users/login/dev/${key}`, {method: 'POST'});
|
|
10
|
-
const json = await response.json();
|
|
11
|
-
if (json.isSuccess == true)
|
|
12
|
-
return json.token;
|
|
13
|
-
else
|
|
14
|
-
throw 'Unable to login to server. Check your dev key';
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export async function getWebUrl(url: string, token: string) {
|
|
18
|
-
const response = await fetch(`${url}/admin/plugins/admin/settings`, {headers: {Authorization: token}});
|
|
19
|
-
const json = await response.json();
|
|
20
|
-
return json.settings.webRoot;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const grokDir = path.join(os.homedir(), '.grok');
|
|
24
|
-
const confPath = path.join(grokDir, 'config.yaml');
|
|
25
|
-
|
|
26
|
-
function mapURL(conf: Config): Indexable {
|
|
27
|
-
const urls: Indexable = {};
|
|
28
|
-
for (const server in conf.servers)
|
|
29
|
-
urls[conf['servers'][server]['url']] = conf['servers'][server];
|
|
30
|
-
|
|
31
|
-
return urls;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function getDevKey(hostKey: string): {url: string, key: string} {
|
|
35
|
-
const config = yaml.load(fs.readFileSync(confPath, 'utf8')) as any;
|
|
36
|
-
let host = hostKey == '' ? config.default : hostKey;
|
|
37
|
-
host = host.trim();
|
|
38
|
-
const urls = mapURL(config);
|
|
39
|
-
let key = '';
|
|
40
|
-
let url = '';
|
|
41
|
-
try {
|
|
42
|
-
let url = new URL(host).href;
|
|
43
|
-
if (url.endsWith('/')) url = url.slice(0, -1);
|
|
44
|
-
if (url in urls) key = config['servers'][urls[url]]['key'];
|
|
45
|
-
} catch (error) {
|
|
46
|
-
if (config['servers'][host] == null)
|
|
47
|
-
throw `Unknown server alias. Please add it to ${confPath}`;
|
|
48
|
-
url = config['servers'][host]['url'];
|
|
49
|
-
key = config['servers'][host]['key'];
|
|
50
|
-
}
|
|
51
|
-
return {url, key};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export async function getBrowserPage(puppeteer: any): Promise<{browser: any, page: any}> {
|
|
55
|
-
let url:string = process.env.HOST ?? '';
|
|
56
|
-
const cfg = getDevKey(url);
|
|
57
|
-
url = cfg.url;
|
|
58
|
-
|
|
59
|
-
const key = cfg.key;
|
|
60
|
-
const token = await getToken(url, key);
|
|
61
|
-
url = await getWebUrl(url, token);
|
|
62
|
-
console.log(`Using web root: ${url}`);
|
|
63
|
-
|
|
64
|
-
const browser = await puppeteer.launch({
|
|
65
|
-
args: ['--disable-dev-shm-usage', '--disable-features=site-per-process'],
|
|
66
|
-
ignoreHTTPSErrors: true,
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
const page = await browser.newPage();
|
|
70
|
-
await page.setDefaultNavigationTimeout(0);
|
|
71
|
-
await page.goto(`${url}/oauth/`);
|
|
72
|
-
await page.setCookie({name: 'auth', value: token});
|
|
73
|
-
await page.evaluate((token: any) => {
|
|
74
|
-
window.localStorage.setItem('auth', token);
|
|
75
|
-
}, token);
|
|
76
|
-
await page.goto(url);
|
|
77
|
-
try {
|
|
78
|
-
// await page.waitForSelector('.grok-preloader', {timeout: 1800000});
|
|
79
|
-
await page.waitForFunction(() => document.querySelector('.grok-preloader') == null, {timeout: 3600000});
|
|
80
|
-
} catch (error) {
|
|
81
|
-
throw error;
|
|
82
|
-
}
|
|
83
|
-
return {browser, page};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
interface Config {
|
|
88
|
-
servers: {
|
|
89
|
-
[alias: string]: {
|
|
90
|
-
url: string,
|
|
91
|
-
key: string
|
|
92
|
-
}
|
|
93
|
-
},
|
|
94
|
-
default: string,
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
interface Indexable { [key: string]: any }
|