@prostgles/app 2.3.6-dev.1789048658 → 2.3.6-dev.1789068015

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.
Files changed (93) hide show
  1. package/client/build/js/main.bundle.js +1 -1
  2. package/dist/server/package.json +1 -1
  3. package/dist/server/src/ConnectionManager/ConnectionManager.d.ts.map +1 -1
  4. package/dist/server/src/ConnectionManager/ConnectionManager.js +13 -6
  5. package/dist/server/src/ConnectionManager/ConnectionManager.js.map +1 -1
  6. package/dist/server/src/ConnectionManager/getConnectionPublish.d.ts +1 -2
  7. package/dist/server/src/ConnectionManager/getConnectionPublish.d.ts.map +1 -1
  8. package/dist/server/src/ConnectionManager/getConnectionPublish.js +3 -5
  9. package/dist/server/src/ConnectionManager/getConnectionPublish.js.map +1 -1
  10. package/dist/server/src/ConnectionManager/getConnectionServerFunctions.d.ts.map +1 -1
  11. package/dist/server/src/ConnectionManager/getConnectionServerFunctions.js +6 -1
  12. package/dist/server/src/ConnectionManager/getConnectionServerFunctions.js.map +1 -1
  13. package/dist/server/src/ConnectionManager/getHotReloadConfigs.d.ts +4 -5
  14. package/dist/server/src/ConnectionManager/getHotReloadConfigs.d.ts.map +1 -1
  15. package/dist/server/src/ConnectionManager/getHotReloadConfigs.js +1 -10
  16. package/dist/server/src/ConnectionManager/getHotReloadConfigs.js.map +1 -1
  17. package/dist/server/src/ConnectionManager/startConnection.d.ts.map +1 -1
  18. package/dist/server/src/ConnectionManager/startConnection.js +2 -6
  19. package/dist/server/src/ConnectionManager/startConnection.js.map +1 -1
  20. package/dist/server/src/ConnectionManager/syncSchemaConfig.d.ts.map +1 -1
  21. package/dist/server/src/ConnectionManager/syncSchemaConfig.js +2 -9
  22. package/dist/server/src/ConnectionManager/syncSchemaConfig.js.map +1 -1
  23. package/dist/server/src/ConnectionManager/syncSchemaConfigAccessControl.d.ts +5 -0
  24. package/dist/server/src/ConnectionManager/syncSchemaConfigAccessControl.d.ts.map +1 -0
  25. package/dist/server/src/ConnectionManager/syncSchemaConfigAccessControl.js +108 -0
  26. package/dist/server/src/ConnectionManager/syncSchemaConfigAccessControl.js.map +1 -0
  27. package/dist/server/src/cli/cliTemplateFiles.js +3 -3
  28. package/dist/server/src/cli/cliTemplateFiles.js.map +1 -1
  29. package/dist/server/src/schemaConfig.d.ts +18 -3
  30. package/dist/server/src/schemaConfig.d.ts.map +1 -1
  31. package/dist/server/src/schemaConfig.js.map +1 -1
  32. package/dist/server/src/serverFunctions/insertConfigWorkspaces.d.ts +2 -1
  33. package/dist/server/src/serverFunctions/insertConfigWorkspaces.d.ts.map +1 -1
  34. package/dist/server/src/serverFunctions/insertConfigWorkspaces.js +14 -8
  35. package/dist/server/src/serverFunctions/insertConfigWorkspaces.js.map +1 -1
  36. package/dist/server/src/tableConfig/tableConfigLlm/tableConfigLlm.js +1 -1
  37. package/dist/server/src/tableConfig/tableConfigLlm/tableConfigLlm.js.map +1 -1
  38. package/dist/server/src/tableHooks/tableHooks.d.ts.map +1 -1
  39. package/dist/server/src/tableHooks/tableHooks.js +0 -2
  40. package/dist/server/src/tableHooks/tableHooks.js.map +1 -1
  41. package/package.json +1 -1
  42. package/dist/common/constants.d.ts.map +0 -1
  43. package/dist/common/constants.js.map +0 -1
  44. package/dist/e2e/shared/Testing.d.ts +0 -665
  45. package/dist/e2e/shared/Testing.js +0 -584
  46. package/dist/e2e/shared/constants.d.ts +0 -19
  47. package/dist/e2e/shared/constants.js +0 -23
  48. package/dist/e2e/shared/fixtures.d.ts +0 -4
  49. package/dist/e2e/shared/fixtures.js +0 -40
  50. package/dist/e2e/shared/goTo.d.ts +0 -2
  51. package/dist/e2e/shared/goTo.js +0 -85
  52. package/dist/e2e/shared/utils/constants.d.ts +0 -19
  53. package/dist/e2e/shared/utils/constants.js +0 -23
  54. package/dist/e2e/shared/utils/goTo.d.ts +0 -2
  55. package/dist/e2e/shared/utils/goTo.js +0 -85
  56. package/dist/e2e/shared/utils/utils.d.ts +0 -144
  57. package/dist/e2e/shared/utils/utils.js +0 -1041
  58. package/dist/e2e/shared/utils.d.ts +0 -144
  59. package/dist/e2e/shared/utils.js +0 -1041
  60. package/dist/e2e/tests/Testing.d.ts +0 -665
  61. package/dist/e2e/tests/Testing.d.ts.map +0 -1
  62. package/dist/e2e/tests/Testing.js +0 -584
  63. package/dist/e2e/tests/Testing.js.map +0 -1
  64. package/dist/e2e/tests/fixtures.d.ts +0 -4
  65. package/dist/e2e/tests/fixtures.d.ts.map +0 -1
  66. package/dist/e2e/tests/fixtures.js +0 -40
  67. package/dist/e2e/tests/fixtures.js.map +0 -1
  68. package/dist/e2e/tests/utils/constants.d.ts.map +0 -1
  69. package/dist/e2e/tests/utils/constants.js.map +0 -1
  70. package/dist/e2e/tests/utils/goTo.d.ts.map +0 -1
  71. package/dist/e2e/tests/utils/goTo.js.map +0 -1
  72. package/dist/e2e/tests/utils/utils.d.ts.map +0 -1
  73. package/dist/e2e/tests/utils/utils.js.map +0 -1
  74. package/dist/server/src/cli/testing/e2e/index.d.ts +0 -18
  75. package/dist/server/src/cli/testing/e2e/index.d.ts.map +0 -1
  76. package/dist/server/src/cli/testing/e2e/index.js +0 -70
  77. package/dist/server/src/cli/testing/e2e/index.js.map +0 -1
  78. package/dist/server/src/cli/testing/e2e/template.d.ts +0 -13
  79. package/dist/server/src/cli/testing/e2e/template.d.ts.map +0 -1
  80. package/dist/server/src/cli/testing/e2e/template.js +0 -57
  81. package/dist/server/src/cli/testing/e2e/template.js.map +0 -1
  82. package/dist/server/src/cli/testing/ui/index.d.ts +0 -7
  83. package/dist/server/src/cli/testing/ui/index.d.ts.map +0 -1
  84. package/dist/server/src/cli/testing/ui/index.js +0 -67
  85. package/dist/server/src/cli/testing/ui/index.js.map +0 -1
  86. package/dist/server/src/cli/testing/ui/template.d.ts +0 -13
  87. package/dist/server/src/cli/testing/ui/template.d.ts.map +0 -1
  88. package/dist/server/src/cli/testing/ui/template.js +0 -49
  89. package/dist/server/src/cli/testing/ui/template.js.map +0 -1
  90. package/dist/server/src/tableHooks/accessControl.tableHooks.d.ts +0 -4
  91. package/dist/server/src/tableHooks/accessControl.tableHooks.d.ts.map +0 -1
  92. package/dist/server/src/tableHooks/accessControl.tableHooks.js +0 -54
  93. package/dist/server/src/tableHooks/accessControl.tableHooks.js.map +0 -1
@@ -1,1041 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.deleteAllWorkspaces = exports.deleteExistingLLMChat = exports.setupProstglesLLMProvider = exports.setModelByText = exports.setPromptByText = exports.getDashboardUtils = exports.restoreFromBackup = exports.loginWhenSignupIsEnabled = exports.openConnection = exports.toggleMCPTools = exports.getLLMResponses = exports.sendAskLLMMessage = exports.getAskLLMLastMessage = exports.enableAskLLM = exports.createAccessRuleForTestDB = exports.createAccessRule = exports.disablePwdlessAdminAndCreateUser = exports.setWspColLayout = exports.getTableWindow = exports.getSearchListItem = exports.isEmpty = exports.uploadFile = exports.fileName = exports.TWENTY_SECONDS_OR_MORE = exports.getTimeout = exports.selectAndUpsertFile = exports.dropConnectionAndDatabase = exports.createDatabase = exports.MINUTE = exports.addExistingDatabase = exports.openTable = exports.runDbSql = exports.runDbsMethod = exports.runDbsSql = exports.setTableRule = exports.getSelector = exports.getTestId = exports.closeWorkspaceWindows = exports.forEachLocator = exports.typeConfirmationCode = exports.login = exports.fillLoginFormAndSubmit = exports.insertRow = exports.clickInsertRow = exports.fillSmartFormAndInsert = exports.fillSmartForm = exports.runSql = exports.monacoType = exports.getMonacoValue = exports.getMonacoEditorBySelector = void 0;
37
- exports.allowOnce = exports.deletePreviousMessages = exports.enableMCPServers = exports.clickAndWait = exports.setupMagicLinkAuth = exports.newChat = exports.setOrAddWorkspace = void 0;
38
- exports.scrollElementIntoView = scrollElementIntoView;
39
- const test_1 = require("@playwright/test");
40
- const path = __importStar(require("path"));
41
- const Testing_1 = require("../Testing");
42
- const goTo_1 = require("./goTo");
43
- const constants_1 = require("./constants");
44
- const getMonacoEditorBySelector = async (page, parentSelector) => {
45
- const monacoEditor = await page
46
- .locator(`${parentSelector} .monaco-editor`)
47
- .first();
48
- return monacoEditor;
49
- };
50
- exports.getMonacoEditorBySelector = getMonacoEditorBySelector;
51
- const getMonacoValue = async (page, parentSelector) => {
52
- await page.keyboard.press("Control+A");
53
- await page.waitForTimeout(1500);
54
- const monacoNode = await (0, exports.getMonacoEditorBySelector)(page, parentSelector);
55
- const text = await monacoNode.evaluate((node) => {
56
- //@ts-ignore
57
- return node.parentElement._getValue();
58
- });
59
- // const text = await page.evaluate(
60
- // () => window.getSelection()?.toString() ?? "",
61
- // );
62
- const normalizedText = text?.replace(/\u00A0/g, " "); // Replace char 160 with char 32
63
- return normalizedText;
64
- };
65
- exports.getMonacoValue = getMonacoValue;
66
- /**
67
- * Will overwrite all previous content
68
- */
69
- const monacoType = async (page, parentSelector, text, { deleteAll, deleteAllAndFill, pressBeforeTyping, pressAfterTyping, keyPressDelay = 100, } = { deleteAll: true }) => {
70
- const monacoEditor = await (0, exports.getMonacoEditorBySelector)(page, parentSelector);
71
- await monacoEditor.click();
72
- await page.waitForTimeout(500);
73
- if (deleteAll || deleteAllAndFill) {
74
- await page.keyboard.press("Control+A");
75
- await page.waitForTimeout(500);
76
- await page.keyboard.press("Delete");
77
- }
78
- await page.waitForTimeout(500);
79
- await monacoEditor.click();
80
- await monacoEditor.blur();
81
- await page.waitForTimeout(500);
82
- await monacoEditor.click();
83
- await page.waitForTimeout(500);
84
- for (const key of pressBeforeTyping ?? []) {
85
- await page.keyboard.press(key);
86
- await page.waitForTimeout(50);
87
- }
88
- if (!keyPressDelay) {
89
- await monacoEditor.evaluate((node, text) => {
90
- //@ts-ignore
91
- console.log(node.parentElement.editorRef);
92
- //@ts-ignore
93
- node.parentElement.editorRef.setValue(text);
94
- }, text);
95
- // await monacoEditor.fill(text, { force: true });
96
- }
97
- else if (deleteAllAndFill) {
98
- await page.keyboard.insertText(text);
99
- }
100
- else {
101
- await page.keyboard.type(text, { delay: keyPressDelay });
102
- }
103
- for (const key of pressAfterTyping ?? []) {
104
- await page.keyboard.press(key);
105
- await page.waitForTimeout(50);
106
- }
107
- await page.waitForTimeout(500);
108
- };
109
- exports.monacoType = monacoType;
110
- const runSql = async (page, query) => {
111
- await (0, exports.monacoType)(page, `.ProstglesSQL`, query);
112
- await page.waitForTimeout(300);
113
- await page.getByTestId("W_SQLBottomBar.runQuery").click();
114
- await page.waitForTimeout(200);
115
- await page.getByTestId("W_SQLBottomBar.runQuery").isEnabled({ timeout: 5e3 });
116
- await page.waitForTimeout(1e3);
117
- };
118
- exports.runSql = runSql;
119
- const fillSmartForm = async (page, tableName, values) => {
120
- const smartFormLocator = `${(0, exports.getTestId)("SmartForm")}${(0, Testing_1.getDataKey)(tableName)}`;
121
- for (const [key, valueOrRowOrRows] of Object.entries(values)) {
122
- const unescapedSelector = `${tableName}-${key}`;
123
- const escapedSelector = await page.evaluate((unescapedSelector) => CSS.escape(unescapedSelector), unescapedSelector);
124
- if (typeof valueOrRowOrRows === "string") {
125
- const value = valueOrRowOrRows;
126
- const elem = await page.locator("input#" + escapedSelector);
127
- await elem.fill(value);
128
- const selectElem = await page.locator(`[data-key=${JSON.stringify(key)}] .FormField_Select`);
129
- if (await selectElem.isVisible()) {
130
- await selectElem.click();
131
- await page
132
- .getByTestId("SearchList.List")
133
- .locator(`[data-key=${JSON.stringify(value)}]`)
134
- .click();
135
- }
136
- /** Joined records */
137
- }
138
- else if (Array.isArray(valueOrRowOrRows)) {
139
- const nestedTableName = key;
140
- // const tabItem = await page.locator(
141
- // `${smartFormLocator} ${getTestId("JoinedRecords")} ${getDataKey(nestedTableName)}`,
142
- // );
143
- // const isActive = await tabItem.getAttribute("aria-current");
144
- // if (isActive !== "true") {
145
- // await tabItem.click();
146
- // }
147
- for (const nestedRow of valueOrRowOrRows) {
148
- await page
149
- .locator(`${(0, exports.getTestId)("JoinedRecords.AddRow")}${(0, Testing_1.getDataKey)(nestedTableName)}`)
150
- .click();
151
- await (0, exports.fillSmartFormAndInsert)(page, nestedTableName, nestedRow);
152
- }
153
- /** Nested insert into fkey */
154
- }
155
- else if (typeof valueOrRowOrRows === "object") {
156
- const nestedInsertBtn = await page
157
- .locator(`${(0, exports.getTestId)("SmartFormField")}${(0, Testing_1.getDataKey)(key)} ${(0, exports.getTestId)("SmartFormFieldOptions.NestedInsert")}`)
158
- .first();
159
- const nestedTableName = await nestedInsertBtn.getAttribute("data-key");
160
- if (!nestedTableName)
161
- throw `nestedTableName not found for ${key}`;
162
- await nestedInsertBtn.click();
163
- await (0, exports.fillSmartFormAndInsert)(page, nestedTableName, valueOrRowOrRows);
164
- }
165
- }
166
- return page.locator(smartFormLocator);
167
- };
168
- exports.fillSmartForm = fillSmartForm;
169
- const fillSmartFormAndInsert = async (page, tableName, values) => {
170
- const form = await (0, exports.fillSmartForm)(page, tableName, values);
171
- await page.waitForTimeout(200);
172
- await form.getByTestId("SmartForm.insert").click();
173
- await page.waitForTimeout(1200);
174
- await (0, test_1.expect)(form).not.toBeVisible((0, exports.getTimeout)(2 * exports.MINUTE));
175
- };
176
- exports.fillSmartFormAndInsert = fillSmartFormAndInsert;
177
- const clickInsertRow = async (page, tableName, useTopBtn = false) => {
178
- await page
179
- .getByTestId(useTopBtn ?
180
- "dashboard.window.rowInsertTop"
181
- : "dashboard.window.rowInsert")
182
- .and(page.locator(`[data-key=${JSON.stringify(tableName)}]`))
183
- .click();
184
- await page.waitForTimeout(200);
185
- };
186
- exports.clickInsertRow = clickInsertRow;
187
- const insertRow = async (page, tableName, row, useTopBtn = false) => {
188
- await (0, exports.clickInsertRow)(page, tableName, useTopBtn);
189
- await (0, exports.fillSmartFormAndInsert)(page, tableName, row);
190
- await page.waitForTimeout(2200);
191
- };
192
- exports.insertRow = insertRow;
193
- const fillLoginFormAndSubmit = async (page, userNameAndPassword = "test_user") => {
194
- await page.locator("#username").waitFor({ state: "visible", timeout: 30e3 });
195
- await page.locator("#username").fill("");
196
- await page.locator("#username").fill(userNameAndPassword);
197
- const continueBtn = page.getByRole("button", { name: "Continue" });
198
- let isContinueBtnVisible = false;
199
- if (await continueBtn.count()) {
200
- isContinueBtnVisible = true;
201
- await continueBtn.click();
202
- }
203
- await page.locator("#password").fill(userNameAndPassword);
204
- if (isContinueBtnVisible) {
205
- await continueBtn.click();
206
- }
207
- else {
208
- await page.getByRole("button", { name: "Sign in", exact: true }).click();
209
- }
210
- };
211
- exports.fillLoginFormAndSubmit = fillLoginFormAndSubmit;
212
- const login = async (page, userNameAndPassword = "test_user", url = "localhost:3004") => {
213
- await (0, goTo_1.goTo)(page, url);
214
- await (0, exports.fillLoginFormAndSubmit)(page, userNameAndPassword);
215
- await page.locator("#username").waitFor({ state: "detached", timeout: 30e3 });
216
- };
217
- exports.login = login;
218
- const typeConfirmationCode = async (page) => {
219
- await page.waitForTimeout(200);
220
- const code = await page.getByTitle("confirmation-code").textContent();
221
- await page.waitForTimeout(200);
222
- await page
223
- .locator(`input[name="confirmation"]`)
224
- .fill(code ?? "code not found on the page");
225
- await page.waitForTimeout(200);
226
- };
227
- exports.typeConfirmationCode = typeConfirmationCode;
228
- const forEachLocator = async (page, match, onMatch) => {
229
- let items = [];
230
- do {
231
- items = await (await match()).all();
232
- const firstItem = items[0];
233
- if (firstItem) {
234
- await onMatch(firstItem);
235
- await page.waitForTimeout(220);
236
- }
237
- } while (items.length);
238
- };
239
- exports.forEachLocator = forEachLocator;
240
- const closeWorkspaceWindows = async (page) => {
241
- await (0, exports.forEachLocator)(page, () => page.getByTestId("dashboard.window.close"), async (closeBtn) => {
242
- await closeBtn.click();
243
- /** SQL windows need save or delete confirmation */
244
- const deleteSqlBtn = await page.getByRole("button", {
245
- name: "Delete",
246
- exact: true,
247
- });
248
- if (await deleteSqlBtn.count()) {
249
- await deleteSqlBtn.click();
250
- }
251
- await page.waitForTimeout(220);
252
- });
253
- const closeBtnsCount = await page
254
- .getByTestId("dashboard.window.close")
255
- .count();
256
- if (closeBtnsCount) {
257
- throw `${closeBtnsCount} windows are still opened`;
258
- }
259
- await page.waitForTimeout(100);
260
- };
261
- exports.closeWorkspaceWindows = closeWorkspaceWindows;
262
- const getTestId = (testid) => `[data-command=${JSON.stringify(testid)}]`;
263
- exports.getTestId = getTestId;
264
- const getSelector = ({ testid, dataKey, }) => [
265
- testid && `[data-command=${JSON.stringify(testid)}]`,
266
- dataKey && `[data-key=${JSON.stringify(dataKey)}]`,
267
- ]
268
- .filter(Boolean)
269
- .join("");
270
- exports.getSelector = getSelector;
271
- const setTableRule = async (page, tableName, rule, isFileTable) => {
272
- const tableRow = await page.locator((0, Testing_1.getDataKey)(tableName));
273
- const addSmartFilter = async ({ fieldName, value, }) => {
274
- await page.getByTestId("SmartAddFilter").click();
275
- await page.locator((0, Testing_1.getDataKey)(fieldName)).click();
276
- const filterWrapperSelector = `${(0, exports.getTestId)("FilterWrapper")}${(0, Testing_1.getDataKey)(fieldName)}`;
277
- await page
278
- .locator(`${filterWrapperSelector} input[type="text"]`)
279
- .fill(value);
280
- await page.waitForTimeout(500);
281
- await page.keyboard.press("Enter");
282
- await page.waitForTimeout(200);
283
- };
284
- const setForcedFilter = async (forcedFilter) => {
285
- if (!forcedFilter)
286
- return;
287
- await page.getByTestId("ForcedFilterControl.type").click();
288
- await page.getByTestId("ForcedFilterControl.type.enabled").click();
289
- for (const { fieldName, value } of forcedFilter) {
290
- await addSmartFilter({ fieldName, value });
291
- }
292
- };
293
- const setExcludedFields = async (excludedFields) => {
294
- if (!excludedFields?.length)
295
- return;
296
- await page.getByTestId("FieldFilterControl.type").click();
297
- await page.getByTestId("FieldFilterControl.type.except").click();
298
- await page.getByTestId("FieldFilterControl.select").click();
299
- await page.getByTestId("SearchList.toggleAll").click();
300
- for (const field of excludedFields) {
301
- await page.locator(`[data-key=${JSON.stringify(field)}]`).click();
302
- await page.waitForTimeout(500);
303
- }
304
- await page.keyboard.press("Escape");
305
- };
306
- const setForcedData = async (forcedData) => {
307
- if (!forcedData)
308
- return;
309
- // await page.getByTestId("ForcedDataControl.toggle").click();
310
- // for(const [fieldName, value] of Object.entries(forcedData)){
311
- // await page.getByTestId("ForcedDataControl.addColumn").click();
312
- // await page.locator(`[data-key=${JSON.stringify(fieldName)}]`).click();
313
- // await page.locator(`input#${tableName}-${fieldName}`).type(value);
314
- // await page.waitForTimeout(500);
315
- // }
316
- await page.getByTestId("CheckFilterControl.type").click();
317
- await page.getByTestId("CheckFilterControl.type.enabled").click();
318
- for (const [fieldName, value] of Object.entries(forcedData)) {
319
- await addSmartFilter({ fieldName, value });
320
- }
321
- };
322
- const toggleFileRule = async () => {
323
- const ruleToggle = await page.getByTestId("RuleToggle");
324
- if (isFileTable) {
325
- await ruleToggle.click();
326
- await page.getByTestId("TablePermissionControls.close").click();
327
- }
328
- };
329
- if (rule.select) {
330
- await tableRow.getByTestId("selectRule").click();
331
- await toggleFileRule();
332
- await page.waitForTimeout(500);
333
- if (!(0, exports.isEmpty)(rule.select)) {
334
- await tableRow.getByTestId("selectRuleAdvanced").click();
335
- await setExcludedFields(rule.select.excludedFields);
336
- await setForcedFilter(rule.select.forcedFilter);
337
- await page.getByTestId("TablePermissionControls.close").click();
338
- await page.waitForTimeout(500);
339
- }
340
- }
341
- if (rule.insert) {
342
- await tableRow.getByTestId("insertRule").click();
343
- await toggleFileRule();
344
- await page.waitForTimeout(500);
345
- if (!(0, exports.isEmpty)(rule.select)) {
346
- await tableRow.getByTestId("insertRuleAdvanced").click();
347
- await setExcludedFields(rule.insert.excludedFields);
348
- await setForcedData(rule.insert.forcedData);
349
- await page.getByTestId("TablePermissionControls.close").click();
350
- await page.waitForTimeout(500);
351
- }
352
- }
353
- if (rule.update) {
354
- await tableRow.getByTestId("updateRule").click();
355
- await toggleFileRule();
356
- await page.waitForTimeout(500);
357
- if (!(0, exports.isEmpty)(rule.select)) {
358
- await tableRow.getByTestId("updateRuleAdvanced").click();
359
- await setExcludedFields(rule.update.excludedFields);
360
- await setForcedFilter(rule.update.forcedFilter);
361
- await setForcedData(rule.update.forcedData);
362
- await page.getByTestId("TablePermissionControls.close").click();
363
- await page.waitForTimeout(500);
364
- }
365
- }
366
- if (rule.delete) {
367
- await tableRow.getByTestId("deleteRule").click();
368
- await toggleFileRule();
369
- await page.waitForTimeout(500);
370
- if (!(0, exports.isEmpty)(rule.select)) {
371
- await tableRow.getByTestId("deleteRuleAdvanced").click();
372
- await setForcedFilter(rule.delete.forcedFilter);
373
- await page.getByTestId("TablePermissionControls.close").click();
374
- await page.waitForTimeout(500);
375
- }
376
- }
377
- await page.waitForTimeout(500);
378
- };
379
- exports.setTableRule = setTableRule;
380
- const runDbsSql = async (page, query, args, opts) => {
381
- return (0, exports.runDbSql)(page, query, args, opts, "dbs");
382
- };
383
- exports.runDbsSql = runDbsSql;
384
- const runDbsMethod = async (page, methodName, args) => {
385
- /** Wait for dbsMethod to become available */
386
- await page.waitForFunction(() => {
387
- return window.dbsMethods !== undefined;
388
- });
389
- const result = await page.evaluate(async ([methodName, args]) => {
390
- const dbsMethods = window.dbsMethods;
391
- if (!dbsMethods)
392
- throw "dbsMethods is missing";
393
- const method = dbsMethods[methodName];
394
- if (!method)
395
- throw `Method ${methodName} is missing in dbsMethods`;
396
- const [data, err] = await method(args)
397
- .then((data) => [data, undefined])
398
- .catch((err) => {
399
- console.error(`Error running dbs method ${methodName}:`, err);
400
- return [undefined, err];
401
- });
402
- return [data, err];
403
- }, [methodName, args]);
404
- const [data, err] = result;
405
- if (err) {
406
- throw err;
407
- }
408
- return data;
409
- };
410
- exports.runDbsMethod = runDbsMethod;
411
- const runDbSql = async (page, query, args, opts, dbType = "db") => {
412
- /** Wait for handle to become available */
413
- await page.waitForFunction(({ dbType }) => {
414
- return window[dbType] !== undefined;
415
- }, { dbType });
416
- const [error, sqlResult] = (await page.evaluate(async ([query, args, opts, dbType]) => {
417
- try {
418
- const sql = window[dbType === "db" ? "sql" : "dbsSql"];
419
- if (!sql)
420
- throw dbType === "db" ? "db is missing" : "dbs is missing";
421
- const data = await sql(query, args, opts);
422
- return [undefined, data];
423
- }
424
- catch (error) {
425
- return [error];
426
- }
427
- }, [query, args, opts, dbType]));
428
- if (error) {
429
- console.error(`Error running sql:`, error);
430
- throw error;
431
- }
432
- return sqlResult;
433
- };
434
- exports.runDbSql = runDbSql;
435
- const openTable = async (page, namePartStart, exact = false) => {
436
- await page.getByTestId("dashboard.menu").waitFor({ state: "visible" });
437
- await page.keyboard.press("Control+KeyP");
438
- await page.waitForTimeout(200);
439
- const searchAlLInput = await page.getByTestId("SearchAll");
440
- await searchAlLInput.waitFor({ state: "visible" });
441
- await searchAlLInput.fill(namePartStart);
442
- await page.waitForTimeout(200);
443
- await page.keyboard.press("Enter");
444
- await page.waitForTimeout(500);
445
- /** Ensure table was opened */
446
- const table = page.locator(`[data-table-name${exact ? "=" : "^="}${JSON.stringify(namePartStart)}]`);
447
- /** Used for debugging */
448
- if (!(await table.isVisible())) {
449
- const v_triggers = await (0, exports.runDbsSql)(page, `SELECT * FROM prostgles.v_triggers;`, {}, { returnType: "rows" });
450
- console.log(JSON.stringify({ v_triggers, namePartStart, expect: test_1.expect }));
451
- await page.waitForTimeout(500);
452
- }
453
- await (0, test_1.expect)(table).toBeVisible();
454
- await page.waitForTimeout(1000);
455
- };
456
- exports.openTable = openTable;
457
- const addExistingDatabase = async (page, dbName) => {
458
- await (0, goTo_1.goTo)(page, "localhost:3004/connections");
459
- await page.getByTestId("ConnectionServer.add").click();
460
- await page
461
- .locator(`[data-label="Select a database from this server"]`)
462
- .click();
463
- await page.getByTestId("ConnectionServer.add.existingDatabase").click();
464
- await page
465
- .getByTestId("ConnectionServer.add.existingDatabase")
466
- .locator((0, Testing_1.getDataKey)(dbName))
467
- .click();
468
- await page.getByTestId("ConnectionServer.add.confirm").click();
469
- };
470
- exports.addExistingDatabase = addExistingDatabase;
471
- exports.MINUTE = 60e3;
472
- const createDatabase = async (dbName, page, fromTemplates = false, owner) => {
473
- await (0, goTo_1.goTo)(page, "localhost:3004/connections");
474
- await page
475
- .locator(`[data-command="ConnectionServer.add"][data-key^="usr@localhost"]`)
476
- .first()
477
- .click();
478
- // await page.waitForTimeout(3000);
479
- if (fromTemplates) {
480
- await page.getByTestId("ConnectionServer.add.newDatabase").click();
481
- await page.getByTestId("ConnectionServer.SampleSchemas").click();
482
- await page
483
- .getByTestId("ConnectionServer.SampleSchemas")
484
- .locator(`[data-key=${JSON.stringify(dbName)}]`)
485
- .click();
486
- }
487
- else {
488
- await page.getByTestId("ConnectionServer.add.newDatabase").click();
489
- await page
490
- .getByTestId("ConnectionServer.NewDbName")
491
- .locator("input")
492
- .fill(dbName);
493
- }
494
- if (owner) {
495
- await page.getByTestId("ConnectionServer.withNewOwnerToggle").click();
496
- await page.waitForTimeout(500);
497
- await page
498
- .getByTestId("ConnectionServer.NewUserName")
499
- .locator("input")
500
- .fill(owner.name);
501
- await page
502
- .getByTestId("ConnectionServer.NewUserPassword")
503
- .locator("input")
504
- .fill(owner.pass);
505
- await page.waitForTimeout(500);
506
- }
507
- await page.getByTestId("ConnectionServer.add.confirm").click();
508
- /* Wait until db is created */
509
- const databaseCreationTime = (fromTemplates ? 4 : 1) * exports.MINUTE;
510
- const workspaceCreationAndLoatTime = 3 * exports.MINUTE;
511
- await page
512
- .getByTestId("ConnectionServer.add.confirm")
513
- .waitFor({ state: "detached", timeout: databaseCreationTime });
514
- await page
515
- .getByTestId("dashboard.menu")
516
- .waitFor({ state: "visible", timeout: workspaceCreationAndLoatTime });
517
- };
518
- exports.createDatabase = createDatabase;
519
- const dropConnectionAndDatabase = async (dbName, page, andDatabase = true) => {
520
- await page.waitForTimeout(2000);
521
- const connectionSelector = `[data-key=${JSON.stringify(dbName)}]`;
522
- await page.locator(connectionSelector).getByTestId("Connection.edit").click();
523
- await page.getByTestId("Connection.edit.delete").click();
524
- if (andDatabase) {
525
- await page.getByTestId("Connection.edit.delete.dropDatabase").click();
526
- }
527
- await (0, exports.typeConfirmationCode)(page);
528
- await page.getByTestId("Connection.edit.delete.confirm").click();
529
- await page.waitForTimeout(5000);
530
- return { connectionSelector };
531
- };
532
- exports.dropConnectionAndDatabase = dropConnectionAndDatabase;
533
- const selectAndUpsertFile = async (page, onOpenFileDialog, onBeforePressInsert, isUpdate = false) => {
534
- // Start waiting for file chooser before clicking. Note no await.
535
- const fileChooserPromise = page.waitForEvent("filechooser");
536
- await onOpenFileDialog(page);
537
- const fileChooser = await fileChooserPromise;
538
- const resolvedPath = path.resolve(path.join(__dirname, "../../" + exports.fileName));
539
- await fileChooser.setFiles(resolvedPath);
540
- await onBeforePressInsert?.();
541
- await page
542
- .getByRole("button", { name: isUpdate ? "Update" : "Insert", exact: true })
543
- .click();
544
- if (isUpdate) {
545
- await page
546
- .getByRole("button", { name: "Update row!", exact: true })
547
- .click();
548
- }
549
- };
550
- exports.selectAndUpsertFile = selectAndUpsertFile;
551
- const getTimeout = (base) => ({
552
- timeout: base * (process.env.CI ? 3 : 1),
553
- });
554
- exports.getTimeout = getTimeout;
555
- exports.TWENTY_SECONDS_OR_MORE = (0, exports.getTimeout)(20_000);
556
- exports.fileName = "icon512.png";
557
- const uploadFile = async (page) => {
558
- await (0, exports.clickInsertRow)(page, "files");
559
- await page.waitForTimeout(200);
560
- await (0, exports.selectAndUpsertFile)(page, (page) => page.getByTestId("FileBtn").click());
561
- const MINUTE = 60e3;
562
- await page
563
- .getByTestId("Popup.content")
564
- .waitFor({ state: "detached", ...(0, exports.getTimeout)(2 * MINUTE) });
565
- };
566
- exports.uploadFile = uploadFile;
567
- const isEmpty = (obj) => {
568
- return !obj || Object.keys(obj).length === 0;
569
- };
570
- exports.isEmpty = isEmpty;
571
- const getSearchListItem = (page, { dataKey }) => {
572
- return page.getByTestId("SearchList.List").locator((0, Testing_1.getDataKey)(dataKey));
573
- };
574
- exports.getSearchListItem = getSearchListItem;
575
- const getTableWindow = (page, tableName) => {
576
- return page.locator(`[data-table-name=${JSON.stringify(tableName)}]`);
577
- };
578
- exports.getTableWindow = getTableWindow;
579
- const setWspColLayout = async (page) => {
580
- await page.getByTestId("dashboard.menu").waitFor({ state: "visible" });
581
- await page.getByTestId("dashboard.menu.settingsToggle").click();
582
- await page.getByTestId("dashboard.menu.settings.defaultLayoutType").click();
583
- await page
584
- .getByTestId("dashboard.menu.settings.defaultLayoutType")
585
- .locator(`[data-key="col"]`)
586
- .click();
587
- await page.getByTestId("Popup.close").click();
588
- };
589
- exports.setWspColLayout = setWspColLayout;
590
- const disablePwdlessAdminAndCreateUser = async (page) => {
591
- await page
592
- .getByRole("link", { name: "Users" })
593
- .waitFor({ state: "visible", timeout: 60e3 });
594
- await page.getByRole("link", { name: "Users" }).click();
595
- await (0, test_1.expect)(page).toHaveURL(/.*users/);
596
- // const currentUrl = page.url();
597
- // await page.goto();
598
- // await page.goto(`${currentUrl}users`, {
599
- // waitUntil: "networkidle",
600
- // timeout: 10e3,
601
- // });
602
- await page.getByRole("button", { name: "Create admin user" }).click();
603
- await page.locator("#username").fill(constants_1.USERS.test_user);
604
- await page.locator("#new-password").fill(constants_1.USERS.test_user);
605
- await page.locator("#confirm_password").fill(constants_1.USERS.test_user);
606
- await page.getByRole("button", { name: "Create", exact: true }).click();
607
- await page.waitForTimeout(5e3);
608
- };
609
- exports.disablePwdlessAdminAndCreateUser = disablePwdlessAdminAndCreateUser;
610
- const createAccessRule = async (page, userType) => {
611
- /** Set permissions */
612
- await page.getByTestId("config.ac").click();
613
- await page.waitForTimeout(1e3);
614
- await page.getByTestId("config.ac.create").click();
615
- /** Setting user type to default */
616
- await page.getByTestId("config.ac.edit.user").click();
617
- await page.getByRole("option").getByText(userType).click();
618
- await page.getByRole("button", { name: "Done", exact: true }).click();
619
- /** Setting AC Type to custom */
620
- await page
621
- .getByTestId("config.ac.edit.type")
622
- .locator(`button[value="Custom"]`)
623
- .click();
624
- };
625
- exports.createAccessRule = createAccessRule;
626
- const createAccessRuleForTestDB = async (page, userType) => {
627
- await (0, exports.login)(page);
628
- await page.getByRole("link", { name: "Connections" }).click();
629
- await page.getByRole("link", { name: constants_1.TEST_DB_NAME }).click();
630
- await page
631
- .getByTestId("dashboard.goToConnConfig")
632
- .waitFor({ state: "visible", timeout: 10e3 });
633
- await page.getByTestId("dashboard.goToConnConfig").click();
634
- await (0, exports.createAccessRule)(page, userType);
635
- };
636
- exports.createAccessRuleForTestDB = createAccessRuleForTestDB;
637
- const enableAskLLM = async (page, maxRequestsPerDay, credsProvided = false) => {
638
- await page.getByTestId("AskLLMAccessControl").click();
639
- if (!credsProvided) {
640
- await page.getByTestId("SetupLLMCredentials.api").click();
641
- // await page.getByTestId("AddLLMCredentialForm").click();
642
- await page.getByTestId("dashboard.window.rowInsertTop").click();
643
- // await page.getByTestId("AddLLMCredentialForm.Provider").click();
644
- // await page
645
- // .getByTestId("AddLLMCredentialForm.Provider")
646
- // .locator(`[data-key="Custom"]`)
647
- // .click();
648
- await (0, exports.runDbsSql)(page, "DELETE FROM llm_providers WHERE id = 'Custom' ");
649
- await (0, exports.fillSmartFormAndInsert)(page, "llm_credentials", {
650
- name: "my credential",
651
- api_key: "nothing",
652
- provider_id: {
653
- id: "Custom",
654
- api_url: "http://localhost:3004/mocked-llm",
655
- logo_url: "/icons/CloudQuestionOutline.svg",
656
- llm_models: [
657
- {
658
- name: "mymodel",
659
- },
660
- ],
661
- },
662
- });
663
- // await page.locator(`#endpoint`).fill("http://localhost:3004/mocked-llm");
664
- // await page.getByTestId("AddLLMCredentialForm.Save").click();
665
- }
666
- await page.getByTestId("AskLLMAccessControl.AllowAll").click();
667
- await page.waitForTimeout(1e3);
668
- if (maxRequestsPerDay) {
669
- await page
670
- .getByTestId("AskLLMAccessControl.llm_daily_limit")
671
- .locator("input")
672
- .fill(maxRequestsPerDay.toString());
673
- }
674
- await page.getByTestId("Popup.close").click();
675
- };
676
- exports.enableAskLLM = enableAskLLM;
677
- const getAskLLMLastMessage = async (page) => {
678
- const lastIncomingMessage = page
679
- .getByTestId("AskLLM.popup")
680
- .locator(".message.incoming")
681
- .last();
682
- /** Await any in progress tool calls */
683
- const toolCallBtns = await lastIncomingMessage
684
- .getByTestId("ToolUseMessage.toggle")
685
- .all();
686
- await Promise.all([...toolCallBtns, lastIncomingMessage].map((btn) => btn
687
- .getByTestId("Loading")
688
- .waitFor({ state: "detached", timeout: 30_000 })));
689
- await page.waitForTimeout(1500);
690
- return lastIncomingMessage;
691
- };
692
- exports.getAskLLMLastMessage = getAskLLMLastMessage;
693
- const waitForAllMatchingLocatorsToDisappear = async (locator, timeout = 30_000) => {
694
- const start = Date.now();
695
- let tries = 0;
696
- while (true) {
697
- const count = await locator.count();
698
- if (!count) {
699
- if (tries > 2) {
700
- return;
701
- }
702
- else {
703
- tries++;
704
- }
705
- }
706
- else if (Date.now() - start > timeout) {
707
- throw new Error(`Timeout waiting for locators to disappear. Still ${count} remaining.`);
708
- }
709
- await new Promise((resolve) => setTimeout(resolve, 100));
710
- }
711
- };
712
- const sendAskLLMMessage = async (page, msg, waitForLoadingToStop = false) => {
713
- const textArea = page
714
- .getByTestId("AskLLM.popup")
715
- .getByTestId("Chat.textarea");
716
- await (0, test_1.expect)(textArea).toBeEnabled(exports.TWENTY_SECONDS_OR_MORE);
717
- await textArea.fill(msg);
718
- await page.keyboard.press("Enter");
719
- await page.waitForTimeout(500);
720
- if (waitForLoadingToStop) {
721
- if (typeof waitForLoadingToStop === "object") {
722
- await waitForLoadingToStop.onAfterSend();
723
- }
724
- await waitForAllMatchingLocatorsToDisappear(page
725
- .getByTestId("Chat.messageList")
726
- .getByTestId("Loading")
727
- // .locator(".message.incoming .Loading")
728
- .last());
729
- }
730
- };
731
- exports.sendAskLLMMessage = sendAskLLMMessage;
732
- const getLLMResponses = async (page, questions, openWindow = true) => {
733
- if (openWindow) {
734
- await page.getByTestId("AskLLM").click();
735
- }
736
- await page.getByTestId("AskLLM.popup").waitFor({ state: "visible" });
737
- await page.waitForTimeout(2e3);
738
- const result = [];
739
- for (const question of questions) {
740
- await (0, exports.sendAskLLMMessage)(page, question);
741
- const responseMessage = await (0, exports.getAskLLMLastMessage)(page);
742
- const response = await responseMessage.textContent();
743
- result.push({
744
- response,
745
- isOk: !!response?.includes("Mocked response"),
746
- });
747
- await page.waitForTimeout(3000);
748
- }
749
- if (openWindow) {
750
- await page.getByTestId("Popup.close").click();
751
- }
752
- return result;
753
- };
754
- exports.getLLMResponses = getLLMResponses;
755
- const toggleMCPTools = async (page, toolNames, toggleAutoApprove) => {
756
- await page.getByTestId("LLMChatOptions.MCPTools").click({ timeout: 10e3 });
757
- await page.waitForTimeout(1000);
758
- for (const toolName of toolNames) {
759
- await page
760
- .getByTestId("LLMChatOptions.MCPTools")
761
- .getByTestId("MCPServerTools")
762
- .getByText(toolName, { exact: true })
763
- .click({ timeout: 30e3 });
764
- await page.waitForTimeout(1500);
765
- }
766
- if (toggleAutoApprove) {
767
- const node = page.getByTestId("MCPServers.toggleAutoApprove");
768
- await node.waitFor({ state: "visible", timeout: 10e3 });
769
- if ((await node.textContent())?.includes(": ON")) {
770
- await node.click();
771
- }
772
- await page.waitForTimeout(1000);
773
- await node.click();
774
- }
775
- await page.getByTestId("Popup.close").last().click();
776
- await page.waitForTimeout(500);
777
- };
778
- exports.toggleMCPTools = toggleMCPTools;
779
- const openConnection = async (page, connectionName) => {
780
- await (0, goTo_1.goTo)(page, "/connections");
781
- await page
782
- .locator((0, Testing_1.getDataKey)(connectionName))
783
- .getByTestId("Connection.openConnection")
784
- .click();
785
- await page.waitForTimeout(1000);
786
- };
787
- exports.openConnection = openConnection;
788
- const loginWhenSignupIsEnabled = async (page, userNameAndPassword = "test_user") => {
789
- await (0, goTo_1.goTo)(page, "/login");
790
- await page.locator("#username").fill(userNameAndPassword);
791
- await page.getByRole("button", { name: "Continue" }).click();
792
- await page.locator("#password").waitFor({ state: "visible" });
793
- await page.locator("#password").fill(userNameAndPassword);
794
- await page.getByRole("button", { name: "Continue" }).click();
795
- await page.getByTestId("App.colorScheme").waitFor({ state: "visible" });
796
- await page.waitForTimeout(500);
797
- };
798
- exports.loginWhenSignupIsEnabled = loginWhenSignupIsEnabled;
799
- const backupNames = "Demo";
800
- const restoreFromBackup = async (page, backupFileName) => {
801
- const backupListItems = await page
802
- .getByTestId("BackupsControls.Completed")
803
- .locator(".SmartCard");
804
- await backupListItems.first().waitFor({ state: "visible" });
805
- const backupItem = backupFileName ?
806
- backupListItems.filter({ hasText: `Backup name${backupFileName}` })
807
- : backupListItems;
808
- await backupItem
809
- .getByRole("button", { name: "Restore...", exact: true })
810
- .click();
811
- await (0, exports.typeConfirmationCode)(page);
812
- await page.getByRole("button", { name: "Restore", exact: true }).click();
813
- };
814
- exports.restoreFromBackup = restoreFromBackup;
815
- const getDashboardUtils = (page) => {
816
- const _open = exports.openConnection.bind(null, page);
817
- const openMenuIfClosed = async (closeMenu = false) => {
818
- await page.waitForTimeout(1500);
819
- const menuCloseButton = await page
820
- .getByTestId("DashboardMenu")
821
- .getByTestId("Popup.close");
822
- const menuPinnedButton = await page.locator((0, Testing_1.getCommandElemSelector)("DashboardMenuHeader.togglePinned") +
823
- (0, Testing_1.getDataKey)("pinned"));
824
- const menuIsOpen = (await menuCloseButton.count()) ? "close"
825
- : (await menuPinnedButton.count()) ? "unpinn"
826
- : undefined;
827
- if (menuIsOpen) {
828
- if (closeMenu) {
829
- if (menuIsOpen === "close") {
830
- await menuCloseButton.click();
831
- }
832
- else {
833
- await menuPinnedButton.click();
834
- }
835
- }
836
- return;
837
- }
838
- const menuBtn = await page.getByTestId("dashboard.menu");
839
- if ((await menuBtn.count()) && (await menuBtn.isEnabled())) {
840
- await menuBtn.click();
841
- }
842
- };
843
- const toggleMenuPinned = async (shouldBePinned) => {
844
- await page.waitForTimeout(1500);
845
- const toggleBtn = await page.getByTestId("DashboardMenuHeader.togglePinned");
846
- const menuBtn = await page.getByTestId("dashboard.menu");
847
- const menuIsPinned = await menuBtn.isDisabled();
848
- if ((await toggleBtn.count()) && (await toggleBtn.isEnabled())) {
849
- if (menuIsPinned && shouldBePinned) {
850
- return;
851
- }
852
- await toggleBtn.click();
853
- }
854
- else if (shouldBePinned) {
855
- await menuBtn.click();
856
- await page.getByTestId("DashboardMenuHeader.togglePinned").click();
857
- }
858
- };
859
- return {
860
- openConnection: _open,
861
- openMenuIfClosed,
862
- toggleMenuPinned,
863
- };
864
- };
865
- exports.getDashboardUtils = getDashboardUtils;
866
- const setPromptByText = async (page, text, closePopup = true) => {
867
- await page.getByTestId("LLMChatOptions.Prompt").click();
868
- const promptBtn = page
869
- .locator(".SmartCard button", { hasText: text })
870
- .first();
871
- if ((await promptBtn.getAttribute("data-color")) !== "action") {
872
- await promptBtn.click();
873
- await (0, test_1.expect)(promptBtn).not.toBeDisabled(exports.TWENTY_SECONDS_OR_MORE);
874
- }
875
- await page.waitForTimeout(3e3); // wait for prompt tools to be set
876
- if (!closePopup)
877
- return;
878
- await page
879
- .getByTestId("LLMChatOptions.Prompt")
880
- .getByTestId("Popup.close")
881
- .click();
882
- };
883
- exports.setPromptByText = setPromptByText;
884
- const setModelByText = async (page, text) => {
885
- await page.getByTestId("LLMChatOptions.Model").click();
886
- await page.waitForTimeout(500);
887
- await page.keyboard.type(text);
888
- await page.keyboard.press("Enter");
889
- await page.waitForTimeout(1e3); // wait for model to be set
890
- };
891
- exports.setModelByText = setModelByText;
892
- const setupProstglesLLMProvider = async (page) => {
893
- const aiDemoDBName = "prostgles_video_demo";
894
- await (0, exports.openConnection)(page, "cloud");
895
- await (0, exports.openConnection)(page, aiDemoDBName);
896
- await (0, exports.runDbsSql)(page, "TRUNCATE llm_chats CASCADE");
897
- await (0, exports.runDbsSql)(page, `
898
- DELETE FROM llm_credentials WHERE provider_id = 'Prostgles';
899
- UPDATE llm_providers
900
- SET api_url = 'http://localhost:3005/rest-api/methods/askLLM'
901
- WHERE id = 'Prostgles';
902
- /*
903
- UPDATE published_methods
904
- SET connection_id = (
905
- SELECT id FROM connections WHERE "name" = '${aiDemoDBName}'
906
- )
907
- WHERE name = 'askLLM';
908
- */
909
- `);
910
- const activeSession = await (0, exports.runDbsSql)(page, `SELECT *
911
- FROM sessions
912
- WHERE user_id = (SELECT id FROM users WHERE username = 'test_user')
913
- AND active = true
914
- ORDER BY id_num DESC
915
- LIMIT 1`, {}, { returnType: "rows" });
916
- if (!activeSession.length) {
917
- throw new Error("No active session found for test_user");
918
- }
919
- await (0, exports.runDbsSql)(page, `INSERT INTO llm_credentials(provider_id, api_key, user_id)
920
- VALUES('Prostgles', \${api_key} , \${user_id} )
921
- `, { api_key: btoa(activeSession[0].id), user_id: activeSession[0].user_id });
922
- };
923
- exports.setupProstglesLLMProvider = setupProstglesLLMProvider;
924
- /** Delete existing chat during local testing */
925
- const deleteExistingLLMChat = async (page) => {
926
- const optsToggle = page.getByTestId("LLMChatOptions.toggle");
927
- if ((await optsToggle.count()) === 0) {
928
- await page.getByTestId("AskLLM").click();
929
- }
930
- await page.getByTestId("LLMChatOptions.toggle").click();
931
- await page.getByTestId("SmartForm.delete").click();
932
- await page.getByTestId("SmartForm.delete.confirm").click();
933
- await page.waitForTimeout(1e3);
934
- };
935
- exports.deleteExistingLLMChat = deleteExistingLLMChat;
936
- const deleteAllWorkspaces = async (page) => {
937
- const list = page.getByTestId("WorkspaceMenu.list");
938
- await list.waitFor({ state: "visible", timeout: 10e3 });
939
- await page.waitForTimeout(1500);
940
- const listTextContent = await list.textContent();
941
- if (listTextContent?.trim().toLowerCase() === "default")
942
- return; // only default workspace exists
943
- await page.getByTestId("WorkspaceMenuDropDown").click();
944
- await page.getByTestId("WorkspaceDeleteBtn").last().click();
945
- await page.getByTestId("WorkspaceDeleteBtn.Confirm").click();
946
- await page.waitForTimeout(555);
947
- await page.reload();
948
- return (0, exports.deleteAllWorkspaces)(page);
949
- };
950
- exports.deleteAllWorkspaces = deleteAllWorkspaces;
951
- const setOrAddWorkspace = async (page, workspaceName) => {
952
- const workspaceList = await page.getByTestId("WorkspaceMenu.list");
953
- await workspaceList.waitFor({ state: "visible", timeout: 10e3 });
954
- await page.waitForTimeout(1500);
955
- const toggleBtn = await page
956
- .getByTestId("WorkspaceMenu.list")
957
- .getByText(workspaceName, { exact: true });
958
- if (await toggleBtn.count()) {
959
- await toggleBtn.click();
960
- }
961
- else {
962
- await page.getByTestId("WorkspaceMenuDropDown").click();
963
- await page.getByTestId("WorkspaceMenuDropDown.WorkspaceAddBtn").click();
964
- await page.getByLabel("New workspace name").fill(workspaceName);
965
- await page.getByTestId("WorkspaceAddBtn.Create").click();
966
- }
967
- await page.waitForTimeout(1e3);
968
- };
969
- exports.setOrAddWorkspace = setOrAddWorkspace;
970
- const newChat = async (page) => {
971
- await page.getByTestId("AskLLMChat.NewChat").click();
972
- await page.waitForTimeout(2e3);
973
- };
974
- exports.newChat = newChat;
975
- let setupAuthCount = 0;
976
- const setupMagicLinkAuth = async (page) => {
977
- await page.getByTestId("EmailAuthSetup").locator("button").click();
978
- await page.getByTestId("EmailAuthSetup.SignupType").click();
979
- await page.locator(`[data-key="withMagicLink"]`).click();
980
- await page.getByTestId("EmailSMTPAndTemplateSetup").locator("button").click();
981
- await page.getByTestId("EmailSMTPSetup").locator("button").click();
982
- await page.locator("input#smtp-Port").fill((465 + setupAuthCount).toString());
983
- await page.locator(`[data-label="Host"] input`).fill("prostgles-test-mock");
984
- await page.getByTestId("EmailSMTPAndTemplateSetup.save").click();
985
- await page.waitForTimeout(1500);
986
- const errNodeCount = await page.getByTestId("EmailAuthSetup.error").count();
987
- await (0, test_1.expect)(errNodeCount).toBe(0);
988
- setupAuthCount++;
989
- };
990
- exports.setupMagicLinkAuth = setupMagicLinkAuth;
991
- const clickAndWait = async (btnLocator, timeout = constants_1.IS_GITHUB_WORKER ? 220_000 : 120_000) => {
992
- await btnLocator.click();
993
- await btnLocator.page().waitForTimeout(200);
994
- await (0, test_1.expect)(btnLocator).toBeDisabled();
995
- await (0, test_1.expect)(btnLocator).toBeEnabled({ timeout }); // waits until loading finishes
996
- };
997
- exports.clickAndWait = clickAndWait;
998
- const enableMCPServers = async (page, serverNames, needsConfigSetup = false, toggleOn = true) => {
999
- await page.getByTestId("LLMChatOptions.MCPTools").click({ timeout: 10e3 });
1000
- for (const serverName of serverNames) {
1001
- const toggleCheckbox = page
1002
- .locator((0, Testing_1.getDataKey)(serverName))
1003
- .getByTestId("MCPServerFooterActions.enableToggle");
1004
- await toggleCheckbox.scrollIntoViewIfNeeded();
1005
- await page.waitForTimeout(500);
1006
- await toggleCheckbox.click();
1007
- await page.waitForTimeout(500);
1008
- if (!needsConfigSetup) {
1009
- if (toggleOn) {
1010
- await (0, test_1.expect)(toggleCheckbox).toBeChecked({ timeout: 15e3 });
1011
- }
1012
- else {
1013
- await (0, test_1.expect)(toggleCheckbox).not.toBeChecked({ timeout: 15e3 });
1014
- }
1015
- }
1016
- }
1017
- };
1018
- exports.enableMCPServers = enableMCPServers;
1019
- const deletePreviousMessages = async (page) => {
1020
- const firstMessage = await page.getByTestId("AskLLM.DeleteMessage").first();
1021
- if (await firstMessage.count()) {
1022
- await firstMessage.click();
1023
- await page.locator((0, Testing_1.getDataKey)("allToBottom")).click();
1024
- }
1025
- };
1026
- exports.deletePreviousMessages = deletePreviousMessages;
1027
- const allowOnce = async (page, doClick = true) => {
1028
- const allowOnceBtn = await page
1029
- .getByTestId("AskLLMToolApprover.AllowOnce")
1030
- .last();
1031
- await allowOnceBtn.waitFor({ state: "visible", timeout: 15000 });
1032
- doClick && (await allowOnceBtn.click());
1033
- await page.waitForTimeout(2500);
1034
- };
1035
- exports.allowOnce = allowOnce;
1036
- // This function is used to scroll an element into view, playwright's version of this scrollIntoViewIfNeeded() results in flaky tests
1037
- async function scrollElementIntoView(locator) {
1038
- await locator.evaluate((element) => {
1039
- element.scrollIntoView({ block: "center" });
1040
- });
1041
- }