graphdb-workbench-tests 2.4.0-TR8 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fixtures/locale-en.json +22 -2
- package/fixtures/monitoring/backup-and-restore.json +18 -68
- package/fixtures/monitoring/global-operation-statuses.json +30 -0
- package/integration/explore/similarity.spec.js +10 -7
- package/integration/monitor/global-operation-statuses-component.spec.js +106 -0
- package/integration/monitor/monitor.backup-and-restore.spec.js +6 -2
- package/integration/setup/aclmanagement/create-rule.spec.js +18 -0
- package/integration/setup/aclmanagement/revert-rules.spec.js +4 -0
- package/integration/setup/aclmanagement/update-rules.spec.js +57 -0
- package/integration/setup/my-settings.spec.js +7 -7
- package/integration/setup/sparql-templates.spec.js +1 -1
- package/integration/sparql/main.menu.spec.js +5 -6
- package/integration/sparql/sparql.menu.spec.js +9 -0
- package/integration-flaky/setup/sparql-templates.spec.js +1 -1
- package/package.json +1 -1
- package/steps/application-steps.js +5 -0
- package/steps/operations-statuses-component-steps.js +21 -0
- package/steps/sparql-steps.js +1 -1
- package/stubs/backup-and-restore-stubs.js +3 -5
- package/stubs/global-operations-statuses-stub.js +7 -0
- package/stubs/stubs.js +5 -0
- package/support/repository-commands.js +13 -5
- package/support/sparql-commands.js +11 -8
package/fixtures/locale-en.json
CHANGED
|
@@ -162,7 +162,8 @@
|
|
|
162
162
|
"delete_rule_confirmation": "Are you sure you want to delete the selected rule #{{index}}?",
|
|
163
163
|
"revert_acl_list": "This operation will revert all the changes done in the ACL. Are you sure you want to proceed?",
|
|
164
164
|
"rules_updated": "ACL was updated successfully",
|
|
165
|
-
"rules_reverted": "ACL was reverted successfully"
|
|
165
|
+
"rules_reverted": "ACL was reverted successfully",
|
|
166
|
+
"unsaved_changes_confirmation": "You have unsaved changes. Are you sure that you want to exit?"
|
|
166
167
|
}
|
|
167
168
|
},
|
|
168
169
|
"errors": {
|
|
@@ -231,6 +232,7 @@
|
|
|
231
232
|
"closes.config.no.save": "Closes the configuration without saving the changes.",
|
|
232
233
|
"refresh.to.retry": "Refresh the page to retry.",
|
|
233
234
|
"temp.pause": "Temporarily pauses query monitoring so you can copy text",
|
|
235
|
+
"temp.pause.backup_and_restore": "Temporarily pauses backup and restore monitoring so you can copy text",
|
|
234
236
|
"paused.btn": "Paused",
|
|
235
237
|
"pause.btn": "Pause",
|
|
236
238
|
"node.label": "node",
|
|
@@ -1912,5 +1914,23 @@
|
|
|
1912
1914
|
"ttyg.settings.topk": "Number of top results",
|
|
1913
1915
|
"ttyg.settings.topk.tooltip": "Number of results returned to the chat bot when it requests more information. More results will provide more information but they may also introduce noise.",
|
|
1914
1916
|
"ttyg.settings.echo.vector.query": "Echo vector query",
|
|
1915
|
-
"ttyg.settings.echo.vector.query.tooltip": "If enabled the bot will use the generated queries as feedback to the GPT API."
|
|
1917
|
+
"ttyg.settings.echo.vector.query.tooltip": "If enabled the bot will use the generated queries as feedback to the GPT API.",
|
|
1918
|
+
"global.operations_statuses.queries.title": "Running query",
|
|
1919
|
+
"global.operations_statuses.queries.title.plural": "Running queries",
|
|
1920
|
+
"global.operations_statuses.updates.title": "Running update",
|
|
1921
|
+
"global.operations_statuses.updates.title.plural": "Running updates",
|
|
1922
|
+
"global.operations_statuses.imports.title": "Running import",
|
|
1923
|
+
"global.operations_statuses.imports.title.plural": "Running imports",
|
|
1924
|
+
"global.operations_statuses.CREATE_BACKUP_IN_PROGRESS.title": "Creating backup",
|
|
1925
|
+
"global.operations_statuses.CREATE_BACKUP_IN_PROGRESS.title.plural": "Creating backups",
|
|
1926
|
+
"global.operations_statuses.RESTORE_BACKUP_IN_PROGRESS.title": "Restoring backup",
|
|
1927
|
+
"global.operations_statuses.RESTORE_BACKUP_IN_PROGRESS.title.plural": "Restoring backups",
|
|
1928
|
+
"global.operations_statuses.CREATE_CLOUD_BACKUP_IN_PROGRESS.title": "Creating cloud backup",
|
|
1929
|
+
"global.operations_statuses.CREATE_CLOUD_BACKUP_IN_PROGRESS.title.plural": "Creating cloud backups",
|
|
1930
|
+
"global.operations_statuses.RESTORE_CLOUD_BACKUP_IN_PROGRESS.title": "Restoring cloud backup",
|
|
1931
|
+
"global.operations_statuses.RESTORE_CLOUD_BACKUP_IN_PROGRESS.title.plural": "Restoring cloud backups",
|
|
1932
|
+
"global.operations_statuses.IN_SYNC.title": "In sync",
|
|
1933
|
+
"global.operations_statuses.RECOVERING.title": "Recovering",
|
|
1934
|
+
"global.operations_statuses.OUT_OF_SYNC.title": "Out of sync",
|
|
1935
|
+
"global.operations_statuses.UNAVAILABLE_NODES.title": "Unavailable nodes"
|
|
1916
1936
|
}
|
|
@@ -1,69 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
"replicationTimeoutMs": null
|
|
18
|
-
},
|
|
19
|
-
"nodePerformingClusterBackup": null
|
|
1
|
+
{
|
|
2
|
+
"id": "1",
|
|
3
|
+
"username": "admin",
|
|
4
|
+
"operation": "CREATE_CLOUD_BACKUP",
|
|
5
|
+
"affectedRepositories": [
|
|
6
|
+
"1"
|
|
7
|
+
],
|
|
8
|
+
"msSinceCreated": 23416,
|
|
9
|
+
"snapshotOptions": {
|
|
10
|
+
"withRepositoryData": true,
|
|
11
|
+
"withSystemData": false,
|
|
12
|
+
"withClusterData": false,
|
|
13
|
+
"cleanDataDir": true,
|
|
14
|
+
"removeCluster": false,
|
|
15
|
+
"repositories": null,
|
|
16
|
+
"replicationTimeoutMs": null
|
|
20
17
|
},
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
"username": "admin",
|
|
24
|
-
"operation": "CREATE_CLOUD_BACKUP",
|
|
25
|
-
"affectedRepositories": [
|
|
26
|
-
"1",
|
|
27
|
-
"test Repository 2"
|
|
28
|
-
],
|
|
29
|
-
"msSinceCreated": 3423,
|
|
30
|
-
"snapshotOptions": {
|
|
31
|
-
"withRepositoryData": true,
|
|
32
|
-
"withSystemData": false,
|
|
33
|
-
"withClusterData": false,
|
|
34
|
-
"cleanDataDir": true,
|
|
35
|
-
"removeCluster": false,
|
|
36
|
-
"repositories": null,
|
|
37
|
-
"replicationTimeoutMs": null
|
|
38
|
-
},
|
|
39
|
-
"nodePerformingClusterBackup": "node Performing Cluster Backup"
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
"id": "3",
|
|
43
|
-
"username": "admin",
|
|
44
|
-
"operation": "CREATE_CLOUD_BACKUP",
|
|
45
|
-
"affectedRepositories": [
|
|
46
|
-
"1",
|
|
47
|
-
"test Repository 2",
|
|
48
|
-
"test Repository 3",
|
|
49
|
-
"test Repository 4",
|
|
50
|
-
"test Repository 5",
|
|
51
|
-
"test Repository 6",
|
|
52
|
-
"test Repository 7",
|
|
53
|
-
"test Repository 8",
|
|
54
|
-
"test Repository 9",
|
|
55
|
-
"test Repository 10"
|
|
56
|
-
],
|
|
57
|
-
"msSinceCreated": 12334,
|
|
58
|
-
"snapshotOptions": {
|
|
59
|
-
"withRepositoryData": true,
|
|
60
|
-
"withSystemData": false,
|
|
61
|
-
"withClusterData": false,
|
|
62
|
-
"cleanDataDir": true,
|
|
63
|
-
"removeCluster": false,
|
|
64
|
-
"repositories": null,
|
|
65
|
-
"replicationTimeoutMs": null
|
|
66
|
-
},
|
|
67
|
-
"nodePerformingClusterBackup": "node Performing Cluster Backup"
|
|
68
|
-
}
|
|
69
|
-
]
|
|
18
|
+
"nodePerformingClusterBackup": null
|
|
19
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "WARNING",
|
|
3
|
+
"allRunningOperations": [
|
|
4
|
+
{
|
|
5
|
+
"value": "25",
|
|
6
|
+
"status": "INFORMATION",
|
|
7
|
+
"type": "queries"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"value": "1",
|
|
11
|
+
"status": "INFORMATION",
|
|
12
|
+
"type": "updates"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"value": "1",
|
|
16
|
+
"status": "CRITICAL",
|
|
17
|
+
"type": "imports"
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
"value": "CREATE_BACKUP_IN_PROGRESS",
|
|
21
|
+
"status": "WARNING",
|
|
22
|
+
"type": "backupAndRestore"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"value": "UNAVAILABLE_NODES",
|
|
26
|
+
"status": "WARNING",
|
|
27
|
+
"type": "clusterHealth"
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
@@ -193,7 +193,7 @@ describe('Similarity screen validation', () => {
|
|
|
193
193
|
|
|
194
194
|
cy.visit('/sparql', {
|
|
195
195
|
onBeforeLoad: (win) => {
|
|
196
|
-
win.localStorage.setItem('
|
|
196
|
+
win.localStorage.setItem('ls.repository-id', repositoryId);
|
|
197
197
|
}
|
|
198
198
|
});
|
|
199
199
|
cy.window();
|
|
@@ -244,7 +244,7 @@ describe('Similarity screen validation', () => {
|
|
|
244
244
|
initRepository();
|
|
245
245
|
cy.visit('/similarity', {
|
|
246
246
|
onBeforeLoad: (win) => {
|
|
247
|
-
win.localStorage.setItem('
|
|
247
|
+
win.localStorage.setItem('ls.repository-id', repositoryId);
|
|
248
248
|
}
|
|
249
249
|
});
|
|
250
250
|
cy.window()
|
|
@@ -269,6 +269,7 @@ describe('Similarity screen validation', () => {
|
|
|
269
269
|
|
|
270
270
|
function disableSimilarityPlugin() {
|
|
271
271
|
const disableSimilarityPluginQuery = 'INSERT DATA { <u:a> <http://www.ontotext.com/owlim/system#stopplugin> \'similarity\' . }';
|
|
272
|
+
cy.waitUntilQueryIsVisible();
|
|
272
273
|
cy.pasteQuery(disableSimilarityPluginQuery);
|
|
273
274
|
cy.executeQuery();
|
|
274
275
|
}
|
|
@@ -365,12 +366,9 @@ describe('Similarity screen validation', () => {
|
|
|
365
366
|
cy.url().should('eq', Cypress.config('baseUrl') + '/similarity');
|
|
366
367
|
cy.get('.clone-index-btn').click()
|
|
367
368
|
.then(() => cy.url().should('contain', `${Cypress.config('baseUrl')}/similarity/index/create`));
|
|
368
|
-
cy.window();
|
|
369
|
-
// This is just an implicit wait in order to allow the view to catch up with the rendering
|
|
370
|
-
// before trying to click the button. Its needed because the button doesn't always accept
|
|
371
|
-
// the click most likely due to some async behavior
|
|
372
|
-
cy.contains('Sample queries:').next('.list-group').should('be.visible');
|
|
373
369
|
|
|
370
|
+
// Makes sure YASQE has loaded before we click the Create button
|
|
371
|
+
cy.waitUntilQueryIsVisible();
|
|
374
372
|
getCreateIndexButton().should('be.visible').click();
|
|
375
373
|
|
|
376
374
|
getExistingIndexesPanel();
|
|
@@ -414,6 +412,7 @@ describe('Similarity screen validation', () => {
|
|
|
414
412
|
let shouldAnalogicalTabBeVisible = (isPredication ? '' : 'not.') + 'be.visible';
|
|
415
413
|
getAnalogicalQueryTab().should(shouldAnalogicalTabBeVisible);
|
|
416
414
|
if (isPredication) {
|
|
415
|
+
cy.waitUntilQueryIsVisible();
|
|
417
416
|
cy.verifyQueryAreaContains('SELECT ?entity ?score {');
|
|
418
417
|
}
|
|
419
418
|
}
|
|
@@ -424,6 +423,7 @@ describe('Similarity screen validation', () => {
|
|
|
424
423
|
'filter(isLiteral(?documentText)) \n' +
|
|
425
424
|
'}order by asc(str(?documentID))';
|
|
426
425
|
|
|
426
|
+
cy.waitUntilQueryIsVisible();
|
|
427
427
|
cy.pasteQuery(MODIFIED_DATA_QUERY);
|
|
428
428
|
cy.get('.test-query-btn').click();
|
|
429
429
|
cy.get('.sparql-loader').should('not.exist');
|
|
@@ -433,6 +433,7 @@ describe('Similarity screen validation', () => {
|
|
|
433
433
|
|
|
434
434
|
function changeSearchQuery() {
|
|
435
435
|
getSearchQueryTab().scrollIntoView().should('be.visible').click();
|
|
436
|
+
cy.waitUntilQueryIsVisible();
|
|
436
437
|
cy.pasteQuery(MODIFIED_SEARCH_QUERY);
|
|
437
438
|
}
|
|
438
439
|
|
|
@@ -441,6 +442,7 @@ describe('Similarity screen validation', () => {
|
|
|
441
442
|
.scrollIntoView()
|
|
442
443
|
.should('be.visible').click()
|
|
443
444
|
.then(() => {
|
|
445
|
+
cy.waitUntilQueryIsVisible();
|
|
444
446
|
cy.pasteQuery(MODIFIED_ANALOGICAL_QUERY);
|
|
445
447
|
});
|
|
446
448
|
}
|
|
@@ -479,6 +481,7 @@ describe('Similarity screen validation', () => {
|
|
|
479
481
|
|
|
480
482
|
function verifyQueryIsChanged() {
|
|
481
483
|
const query = 'OPTIONAL { ?result <http://dbpedia.org/ontology/birthPlace> ?birthDate .';
|
|
484
|
+
cy.waitUntilQueryIsVisible();
|
|
482
485
|
cy.verifyQueryAreaContains(query);
|
|
483
486
|
}
|
|
484
487
|
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import HomeSteps from "../../steps/home-steps";
|
|
2
|
+
import {OperationsStatusesComponentSteps} from "../../steps/operations-statuses-component-steps";
|
|
3
|
+
import ImportSteps from "../../steps/import-steps";
|
|
4
|
+
import {GlobalOperationsStatusesStub} from "../../stubs/global-operations-statuses-stub";
|
|
5
|
+
|
|
6
|
+
describe('Operations Status Component', () => {
|
|
7
|
+
|
|
8
|
+
const repositoryId = 'backup-and-restore-' + Date.now();
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
cy.createRepository({id: repositoryId});
|
|
11
|
+
cy.presetRepository(repositoryId);
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
afterEach(() => {
|
|
15
|
+
cy.deleteRepository(repositoryId);
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should not display the operation status component if there are not run operations.', () => {
|
|
19
|
+
// When I visit some page and there are no running operations.
|
|
20
|
+
HomeSteps.visitAndWaitLoader();
|
|
21
|
+
// Then I expect "Global Operations Component" to not be visible.
|
|
22
|
+
OperationsStatusesComponentSteps.getOperationsStatusesComponent().should('not.exist');
|
|
23
|
+
|
|
24
|
+
// When I visit some page and there are not running operations.
|
|
25
|
+
ImportSteps.visitUserImport(repositoryId);
|
|
26
|
+
// Then I expect "Global Operations Component" to not be visible.
|
|
27
|
+
OperationsStatusesComponentSteps.getOperationsStatusesComponent().should('not.exist');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('should redirect to query and update view wen click on queries operation element', () => {
|
|
31
|
+
// When I visit some page and there are running operations.
|
|
32
|
+
GlobalOperationsStatusesStub.stubGlobalOperationsStatusesResponse(repositoryId);
|
|
33
|
+
HomeSteps.visitAndWaitLoader();
|
|
34
|
+
// Then I expect "Global Operations Component" to be displayed.
|
|
35
|
+
OperationsStatusesComponentSteps.getOperationsStatusesComponent().should('exist');
|
|
36
|
+
|
|
37
|
+
OperationsStatusesComponentSteps.openOperationStatusesDialog();
|
|
38
|
+
// When I click on "Running query" operation element.
|
|
39
|
+
// Then I expect to be redirected to "Query and Update monitoring" view.
|
|
40
|
+
OperationsStatusesComponentSteps.checkOperationElementUrl('monitor/queries', 3);
|
|
41
|
+
// Then I expect "Global Operations Component" to still be displayed.
|
|
42
|
+
OperationsStatusesComponentSteps.getOperationsStatusesComponent().should('exist');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should redirect to query and update view wen click on updates operation element', () => {
|
|
46
|
+
// When I visit some page and there are running operations.
|
|
47
|
+
GlobalOperationsStatusesStub.stubGlobalOperationsStatusesResponse(repositoryId);
|
|
48
|
+
HomeSteps.visitAndWaitLoader();
|
|
49
|
+
// Then I expect "Global Operations Component" to be displayed.
|
|
50
|
+
OperationsStatusesComponentSteps.getOperationsStatusesComponent().should('exist');
|
|
51
|
+
|
|
52
|
+
OperationsStatusesComponentSteps.openOperationStatusesDialog();
|
|
53
|
+
// When I click on "Running updates" operation element.
|
|
54
|
+
// Then I expect to be redirected to "Query and Update monitoring" view.
|
|
55
|
+
OperationsStatusesComponentSteps.checkOperationElementUrl('monitor/queries', 4);
|
|
56
|
+
// Then I expect "Global Operations Component" to still be displayed.
|
|
57
|
+
OperationsStatusesComponentSteps.getOperationsStatusesComponent().should('exist');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should redirect to query and update view wen click on imports operation element', () => {
|
|
61
|
+
// When I visit some page and there are running operations.
|
|
62
|
+
GlobalOperationsStatusesStub.stubGlobalOperationsStatusesResponse(repositoryId);
|
|
63
|
+
HomeSteps.visitAndWaitLoader();
|
|
64
|
+
// Then I expect "Global Operations Component" to be displayed.
|
|
65
|
+
OperationsStatusesComponentSteps.getOperationsStatusesComponent().should('exist');
|
|
66
|
+
|
|
67
|
+
OperationsStatusesComponentSteps.openOperationStatusesDialog();
|
|
68
|
+
// When I click on "Running imports" operation element.
|
|
69
|
+
// Then I expect to be redirected to "Query and Update monitoring" view.
|
|
70
|
+
OperationsStatusesComponentSteps.checkOperationElementUrl('import', 2);
|
|
71
|
+
// Then I expect "Global Operations Component" to still be displayed.
|
|
72
|
+
OperationsStatusesComponentSteps.getOperationsStatusesComponent().should('exist');
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should redirect to query and update view wen click on backup and restore operation element', () => {
|
|
76
|
+
// When I visit some page and there are running operations.
|
|
77
|
+
GlobalOperationsStatusesStub.stubGlobalOperationsStatusesResponse(repositoryId);
|
|
78
|
+
HomeSteps.visitAndWaitLoader();
|
|
79
|
+
// Then I expect "Global Operations Component" to be displayed.
|
|
80
|
+
OperationsStatusesComponentSteps.getOperationsStatusesComponent().should('exist');
|
|
81
|
+
|
|
82
|
+
OperationsStatusesComponentSteps.openOperationStatusesDialog();
|
|
83
|
+
// When I click on "Creating backup" operation element.
|
|
84
|
+
// Then I expect to be redirected to "Backup and Restore" view.
|
|
85
|
+
OperationsStatusesComponentSteps.checkOperationElementUrl('monitor/backup-and-restore', 1);
|
|
86
|
+
// Then I expect "Global Operations Component" to still be displayed.
|
|
87
|
+
OperationsStatusesComponentSteps.getOperationsStatusesComponent().should('exist');
|
|
88
|
+
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('should redirect to query and update view wen click on cluster operation element', () => {
|
|
92
|
+
// When I visit some page and there are running operations.
|
|
93
|
+
GlobalOperationsStatusesStub.stubGlobalOperationsStatusesResponse(repositoryId);
|
|
94
|
+
HomeSteps.visitAndWaitLoader();
|
|
95
|
+
// Then I expect "Global Operations Component" to be displayed.
|
|
96
|
+
OperationsStatusesComponentSteps.getOperationsStatusesComponent().should('exist');
|
|
97
|
+
|
|
98
|
+
OperationsStatusesComponentSteps.openOperationStatusesDialog();
|
|
99
|
+
// When I click on "Unavailable nodes" operation element.
|
|
100
|
+
// Then I expect to be redirected to "Cluster Monitoring" view.
|
|
101
|
+
OperationsStatusesComponentSteps.checkOperationElementUrl('cluster', 0);
|
|
102
|
+
// Then I expect "Global Operations Component" to still be displayed.
|
|
103
|
+
OperationsStatusesComponentSteps.getOperationsStatusesComponent().should('exist');
|
|
104
|
+
|
|
105
|
+
});
|
|
106
|
+
});
|
|
@@ -3,12 +3,16 @@ import {BackupAndRestoreStubs} from "../../stubs/backup-and-restore-stubs";
|
|
|
3
3
|
|
|
4
4
|
describe("Monitoring 'Backup And Restore'", () => {
|
|
5
5
|
|
|
6
|
+
const repositoryId = 'backup-and-restore-' + Date.now();
|
|
6
7
|
beforeEach(() => {
|
|
7
|
-
const repositoryId = 'backup-and-restore-' + Date.now();
|
|
8
8
|
cy.createRepository({id: repositoryId});
|
|
9
9
|
cy.presetRepository(repositoryId);
|
|
10
10
|
});
|
|
11
11
|
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
cy.deleteRepository(repositoryId);
|
|
14
|
+
});
|
|
15
|
+
|
|
12
16
|
it('should show running backup or restore operations', () => {
|
|
13
17
|
// When visit the "Backup and restore page",
|
|
14
18
|
BackupAndRestoreSteps.visit();
|
|
@@ -16,6 +20,6 @@ describe("Monitoring 'Backup And Restore'", () => {
|
|
|
16
20
|
BackupAndRestoreStubs.stubBackupAndRestoreResponse();
|
|
17
21
|
|
|
18
22
|
// Then I expect to see information for all run operations.
|
|
19
|
-
BackupAndRestoreSteps.getBackupAndRestoreResults().should('have.length',
|
|
23
|
+
BackupAndRestoreSteps.getBackupAndRestoreResults().should('have.length', 1);
|
|
20
24
|
});
|
|
21
25
|
});
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {AclManagementSteps} from "../../../steps/setup/acl-management-steps";
|
|
2
2
|
import {ACL} from "../../../steps/setup/acl-management-steps";
|
|
3
|
+
import {ToasterSteps} from "../../../steps/toaster-steps";
|
|
4
|
+
import {ApplicationSteps} from "../../../steps/application-steps";
|
|
3
5
|
|
|
4
6
|
describe('ACL Management: create rule', () => {
|
|
5
7
|
|
|
@@ -103,5 +105,21 @@ describe('ACL Management: create rule', () => {
|
|
|
103
105
|
AclManagementSteps.editRuleButtons().should('have.length', 0);
|
|
104
106
|
AclManagementSteps.createRuleButtons().should('have.length', 0);
|
|
105
107
|
});
|
|
108
|
+
|
|
109
|
+
it('should not allow creating of a new rule if it is not unique', () => {
|
|
110
|
+
// When I am on "ACL Management" page and create a rule that exist,
|
|
111
|
+
AclManagementSteps.addRuleInBeginning();
|
|
112
|
+
AclManagementSteps.fillSubject(0, '<urn:Mary>');
|
|
113
|
+
AclManagementSteps.fillPredicate(0, '*');
|
|
114
|
+
AclManagementSteps.fillObject(0, '*');
|
|
115
|
+
AclManagementSteps.fillContext(0, '*');
|
|
116
|
+
AclManagementSteps.fillRole(0, '!CUSTOM_ROLE2');
|
|
117
|
+
AclManagementSteps.selectPolicy(0, 'allow');
|
|
118
|
+
// and try to save it.
|
|
119
|
+
AclManagementSteps.saveRule(0);
|
|
120
|
+
|
|
121
|
+
// Then I expect an error notification to be displayed that describe me that ACL have to be unique.
|
|
122
|
+
ApplicationSteps.getErrorNotifications().contains('Every ACL rule should be unique.');
|
|
123
|
+
});
|
|
106
124
|
});
|
|
107
125
|
|
|
@@ -52,5 +52,9 @@ describe('ACL Management: revert rules', () => {
|
|
|
52
52
|
ApplicationSteps.getSuccessNotifications().should('be.visible');
|
|
53
53
|
AclManagementSteps.getAclRules().should('have.length', 5);
|
|
54
54
|
AclManagementSteps.checkRules(ACL);
|
|
55
|
+
// And the model should become pristine again after the revert
|
|
56
|
+
// I should be able to navigate away from the page without any confirmation
|
|
57
|
+
ApplicationSteps.openImportPage();
|
|
58
|
+
cy.url().should('contain', '/import');
|
|
55
59
|
});
|
|
56
60
|
});
|
|
@@ -72,4 +72,61 @@ describe('ACL Management: update rules', () => {
|
|
|
72
72
|
};
|
|
73
73
|
AclManagementSteps.checkRules([ACL[0], newRule, editedRule, ACL[2], ACL[3]]);
|
|
74
74
|
});
|
|
75
|
+
|
|
76
|
+
it('Should prevent leaving the page when there is new rule added', () => {
|
|
77
|
+
// Given I have opened ACL management page
|
|
78
|
+
// When I don't change anything and try to leave the page
|
|
79
|
+
ApplicationSteps.openImportPage();
|
|
80
|
+
// Then I expect to be redirected to the new page without confirmation
|
|
81
|
+
cy.url().should('contain', '/import');
|
|
82
|
+
// When I add a new rule
|
|
83
|
+
AclManagementSteps.visit();
|
|
84
|
+
AclManagementSteps.addRule(1);
|
|
85
|
+
ApplicationSteps.openImportPage();
|
|
86
|
+
// Then I expect a confirmation dialog
|
|
87
|
+
ModalDialogSteps.getDialog().should('be.visible');
|
|
88
|
+
// When I cancel confirmation
|
|
89
|
+
ModalDialogSteps.clickOnCancelButton();
|
|
90
|
+
// Then I expect dialog to be closed and to stay on the current page
|
|
91
|
+
ModalDialogSteps.getDialog().should('not.exist');
|
|
92
|
+
cy.url().should('contain', '/aclmanagement');
|
|
93
|
+
// When I try to leave the page and I confirm the operation
|
|
94
|
+
ApplicationSteps.openImportPage();
|
|
95
|
+
ModalDialogSteps.clickOnConfirmButton();
|
|
96
|
+
// Then I expect to be redirected to the new page
|
|
97
|
+
cy.url().should('contain', '/import');
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it('Should prevent leaving the page when there is an edited rule', () => {
|
|
101
|
+
// Given I have opened ACL management page
|
|
102
|
+
// When I edit a rule
|
|
103
|
+
AclManagementSteps.editRule(1);
|
|
104
|
+
AclManagementSteps.fillSubject(1, '<urn:Me>');
|
|
105
|
+
AclManagementSteps.saveRule(1);
|
|
106
|
+
// And I try to leave the page
|
|
107
|
+
ApplicationSteps.openImportPage();
|
|
108
|
+
// Then I expect a confirmation dialog
|
|
109
|
+
ModalDialogSteps.getDialog().should('be.visible');
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('Should prevent leaving the page when there is a deleted rule', () => {
|
|
113
|
+
// Given I have opened ACL management page
|
|
114
|
+
// When I delete a rule
|
|
115
|
+
AclManagementSteps.deleteRule(1);
|
|
116
|
+
ModalDialogSteps.clickOnConfirmButton();
|
|
117
|
+
// And I try to leave the page
|
|
118
|
+
ApplicationSteps.openImportPage();
|
|
119
|
+
// Then I expect a confirmation dialog
|
|
120
|
+
ModalDialogSteps.getDialog().should('be.visible');
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('Should prevent leaving the page when there is a moved rule', () => {
|
|
124
|
+
// Given I have opened ACL management page
|
|
125
|
+
// When I move a rule
|
|
126
|
+
AclManagementSteps.moveRuleDown(1);
|
|
127
|
+
// And I try to leave the page
|
|
128
|
+
ApplicationSteps.openImportPage();
|
|
129
|
+
// Then I expect a confirmation dialog
|
|
130
|
+
ModalDialogSteps.getDialog().should('be.visible');
|
|
131
|
+
});
|
|
75
132
|
});
|
|
@@ -128,12 +128,12 @@ describe('My Settings', () => {
|
|
|
128
128
|
|
|
129
129
|
//clear default query and paste a new one that will generate more than 1000 results
|
|
130
130
|
cy.get('#queryEditor .CodeMirror').find('textarea')
|
|
131
|
-
.type(Cypress.env('modifierKey') + 'a{backspace}', {force: true})
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
131
|
+
.type(Cypress.env('modifierKey') + 'a{backspace}', {force: true});
|
|
132
|
+
|
|
133
|
+
cy.get('#queryEditor .CodeMirror').find('textarea')
|
|
134
|
+
.invoke('val', testResultCountQuery).trigger('change', {force: true})
|
|
135
|
+
cy.waitUntilQueryIsVisible();
|
|
136
|
+
cy.verifyQueryAreaContains(testResultCountQuery);
|
|
137
137
|
|
|
138
138
|
cy.get('#wb-sparql-runQuery')
|
|
139
139
|
.should('be.visible')
|
|
@@ -293,7 +293,7 @@ describe('My Settings', () => {
|
|
|
293
293
|
function visitSettingsView() {
|
|
294
294
|
cy.visit('/settings', {
|
|
295
295
|
onBeforeLoad: (win) => {
|
|
296
|
-
win.localStorage.setItem('
|
|
296
|
+
win.localStorage.setItem('ls.repository-id', repositoryId);
|
|
297
297
|
}
|
|
298
298
|
});
|
|
299
299
|
cy.window()
|
|
@@ -36,7 +36,7 @@ describe('SPARQL Templates', () => {
|
|
|
36
36
|
beforeEach(() => {
|
|
37
37
|
cy.visit('/sparql-templates', {
|
|
38
38
|
onBeforeLoad: (win) => {
|
|
39
|
-
win.localStorage.setItem('
|
|
39
|
+
win.localStorage.setItem('ls.repository-id', repositoryId);
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
cy.window()
|
|
@@ -109,12 +109,11 @@ describe('Main menu tests', function () {
|
|
|
109
109
|
visible: false,
|
|
110
110
|
redirect: '/cluster'
|
|
111
111
|
},
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
// },
|
|
112
|
+
{
|
|
113
|
+
name: 'Plugins',
|
|
114
|
+
visible: false,
|
|
115
|
+
redirect: '/plugins'
|
|
116
|
+
},
|
|
118
117
|
{
|
|
119
118
|
name: 'Namespaces',
|
|
120
119
|
visible: false,
|
|
@@ -225,6 +225,7 @@ describe('SPARQL screen validation', () => {
|
|
|
225
225
|
|
|
226
226
|
let describeQuery = 'describe ?t {bind (<<?s ?p ?o>> as ?t) .}';
|
|
227
227
|
|
|
228
|
+
cy.waitUntilQueryIsVisible();
|
|
228
229
|
cy.pasteQuery(describeQuery);
|
|
229
230
|
|
|
230
231
|
SparqlSteps.executeQuery();
|
|
@@ -305,6 +306,7 @@ describe('SPARQL screen validation', () => {
|
|
|
305
306
|
it('Test execute (Describe) query', () => {
|
|
306
307
|
let describeQuery = 'DESCRIBE <http://www.ontotext.com/SYSINFO> FROM <http://www.ontotext.com/SYSINFO>';
|
|
307
308
|
|
|
309
|
+
cy.waitUntilQueryIsVisible();
|
|
308
310
|
cy.pasteQuery(describeQuery);
|
|
309
311
|
|
|
310
312
|
SparqlSteps.executeQuery();
|
|
@@ -332,6 +334,7 @@ describe('SPARQL screen validation', () => {
|
|
|
332
334
|
it('Test execute (ASK) query', () => {
|
|
333
335
|
let askQuery = 'ASK WHERE { ?s ?p ?o .FILTER (regex(?o, "ontotext.com")) }';
|
|
334
336
|
|
|
337
|
+
cy.waitUntilQueryIsVisible();
|
|
335
338
|
cy.pasteQuery(askQuery);
|
|
336
339
|
SparqlSteps.executeQuery();
|
|
337
340
|
|
|
@@ -347,6 +350,7 @@ describe('SPARQL screen validation', () => {
|
|
|
347
350
|
// This test depends on external service http://factforge.net/repositories/ff-news which can occasionally fail.
|
|
348
351
|
it.skip('Test execute (CONSTRUCT) query', () => {
|
|
349
352
|
cy.fixture('queries/construct-query.sparql').then(constructQuery => {
|
|
353
|
+
cy.waitUntilQueryIsVisible();
|
|
350
354
|
cy.pasteQuery(constructQuery);
|
|
351
355
|
});
|
|
352
356
|
|
|
@@ -367,6 +371,7 @@ describe('SPARQL screen validation', () => {
|
|
|
367
371
|
});
|
|
368
372
|
|
|
369
373
|
it('should test text mining plugin', () => {
|
|
374
|
+
cy.waitUntilQueryIsVisible();
|
|
370
375
|
cy.pasteQuery(GATE_CLIENT_CREATE_QUERY);
|
|
371
376
|
cy.executeQuery();
|
|
372
377
|
cy.pasteQuery(GATE_CLIENT_SEARCH_QUERY);
|
|
@@ -412,6 +417,7 @@ describe('SPARQL screen validation', () => {
|
|
|
412
417
|
'\t?s ?p ?o .\n' +
|
|
413
418
|
'}';
|
|
414
419
|
|
|
420
|
+
cy.waitUntilQueryIsVisible();
|
|
415
421
|
cy.pasteQuery(defaultQueryWithoutLimit);
|
|
416
422
|
SparqlSteps.executeQuery();
|
|
417
423
|
|
|
@@ -446,6 +452,7 @@ describe('SPARQL screen validation', () => {
|
|
|
446
452
|
' :a ?p ?o .\n' +
|
|
447
453
|
'}';
|
|
448
454
|
|
|
455
|
+
cy.waitUntilQueryIsVisible();
|
|
449
456
|
cy.pasteQuery(updateToExecute);
|
|
450
457
|
SparqlSteps.executeQuery();
|
|
451
458
|
getUpdateMessage()
|
|
@@ -687,6 +694,7 @@ describe('SPARQL screen validation', () => {
|
|
|
687
694
|
it('Test create, edit and delete saved query', () => {
|
|
688
695
|
let savedQueryName = 'Saved query - ' + Date.now();
|
|
689
696
|
|
|
697
|
+
cy.waitUntilQueryIsVisible();
|
|
690
698
|
cy.pasteQuery(QUERY_FOR_SAVING);
|
|
691
699
|
|
|
692
700
|
saveQuery();
|
|
@@ -885,6 +893,7 @@ describe('SPARQL screen validation', () => {
|
|
|
885
893
|
|
|
886
894
|
it('Test URL to current query', () => {
|
|
887
895
|
const query = 'SELECT ?sub ?pred ?obj WHERE {?sub ?pred ?obj .} LIMIT 100';
|
|
896
|
+
cy.waitUntilQueryIsVisible();
|
|
888
897
|
cy.pasteQuery(query);
|
|
889
898
|
|
|
890
899
|
// Press the link icon to generate a link for a query
|
|
@@ -36,7 +36,7 @@ describe('SPARQL Templates', () => {
|
|
|
36
36
|
beforeEach(() => {
|
|
37
37
|
cy.visit('/sparql-templates', {
|
|
38
38
|
onBeforeLoad: (win) => {
|
|
39
|
-
win.localStorage.setItem('
|
|
39
|
+
win.localStorage.setItem('ls.repository-id', repositoryId);
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
cy.window()
|
package/package.json
CHANGED
|
@@ -19,4 +19,9 @@ export class ApplicationSteps {
|
|
|
19
19
|
static getWarningNotification() {
|
|
20
20
|
return this.getNotifications().find('.toast-warning');
|
|
21
21
|
}
|
|
22
|
+
|
|
23
|
+
// navigation via main menu
|
|
24
|
+
static openImportPage() {
|
|
25
|
+
cy.get('.main-menu .menu-element-root[href=import]').click();
|
|
26
|
+
}
|
|
22
27
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export class OperationsStatusesComponentSteps {
|
|
2
|
+
|
|
3
|
+
static getOperationsStatusesComponent() {
|
|
4
|
+
return cy.get('.operations-statuses');
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
static getOperationStatuses() {
|
|
8
|
+
return cy.get('.operation-status-content');
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static openOperationStatusesDialog() {
|
|
12
|
+
OperationsStatusesComponentSteps.getOperationsStatusesComponent().click();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
static checkOperationElementUrl(expectedUrl, operationIndex = 0) {
|
|
16
|
+
OperationsStatusesComponentSteps.getOperationStatuses().eq(operationIndex).then(($operationElement) => {
|
|
17
|
+
expect($operationElement).to.have.attr('target', '_blank');
|
|
18
|
+
expect($operationElement).to.have.attr('href', expectedUrl);
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
package/steps/sparql-steps.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import {Stubs} from "./stubs";
|
|
2
|
+
|
|
3
|
+
export class BackupAndRestoreStubs extends Stubs {
|
|
2
4
|
static stubBackupAndRestoreResponse(withDelay = 0) {
|
|
3
5
|
BackupAndRestoreStubs.stubQueryResponse('/rest/monitor/backup', '/monitoring/backup-and-restore.json', 'backup-and-restore-response', withDelay);
|
|
4
6
|
}
|
|
5
|
-
|
|
6
|
-
static stubQueryResponse(url, fixture, alias, withDelay = 0) {
|
|
7
|
-
cy.intercept(url, {fixture, delay: withDelay}).as(alias);
|
|
8
|
-
}
|
|
9
7
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import {Stubs} from "./stubs";
|
|
2
|
+
|
|
3
|
+
export class GlobalOperationsStatusesStub extends Stubs {
|
|
4
|
+
static stubGlobalOperationsStatusesResponse(repositoryId, withDelay = 0) {
|
|
5
|
+
GlobalOperationsStatusesStub.stubQueryResponse(`/rest/monitor/${repositoryId}/operations`, '/monitoring/global-operation-statuses.json', 'backup-and-restore-response', withDelay);
|
|
6
|
+
}
|
|
7
|
+
}
|
package/stubs/stubs.js
ADDED
|
@@ -3,7 +3,7 @@ import repoTemplate from '../fixtures/repo-template.json';
|
|
|
3
3
|
export const REPOSITORIES_URL = '/rest/repositories/';
|
|
4
4
|
const AUTOCOMPLETE_URL = '/rest/autocomplete/';
|
|
5
5
|
|
|
6
|
-
const PRESET_REPO = '
|
|
6
|
+
const PRESET_REPO = 'ls.repository-id';
|
|
7
7
|
|
|
8
8
|
Cypress.Commands.add('createRepository', (options = {}) => {
|
|
9
9
|
cy.request({
|
|
@@ -21,14 +21,22 @@ Cypress.Commands.add('createRepository', (options = {}) => {
|
|
|
21
21
|
Cypress.Commands.add('deleteRepository', (id) => {
|
|
22
22
|
// Note: Going through /rest/repositories because it would not fail if the repo is missing
|
|
23
23
|
const url = REPOSITORIES_URL + id;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
|
|
25
|
+
// Navigates to the home view => helps by cancelling any pending requests
|
|
26
|
+
// if a test completes too fast and the tested view was about to load something
|
|
27
|
+
// that needs the just deleted repo.
|
|
28
|
+
cy.visit('/', {failOnStatusCode: false});
|
|
29
|
+
|
|
30
|
+
cy.request({
|
|
31
|
+
method: 'DELETE',
|
|
32
|
+
url: url,
|
|
33
|
+
// Prevent Cypress from failing the test on non-2xx status codes
|
|
34
|
+
failOnStatusCode: false
|
|
27
35
|
});
|
|
28
36
|
});
|
|
29
37
|
|
|
30
38
|
Cypress.Commands.add('presetRepository', (id) => {
|
|
31
|
-
cy.setLocalStorage('
|
|
39
|
+
cy.setLocalStorage('ls.repository-id', id);
|
|
32
40
|
cy.waitUntil(() =>
|
|
33
41
|
cy.getLocalStorage(PRESET_REPO)
|
|
34
42
|
.then((preset) => preset && preset === id));
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
Cypress.Commands.add('pasteQuery', (query) => {
|
|
2
|
-
|
|
3
|
-
//
|
|
4
|
-
getQueryTextArea().invoke('val', query)
|
|
5
|
-
|
|
2
|
+
// Setting the textarea and the calling setValue seems to work
|
|
3
|
+
// more reliably then other strategies (see history)
|
|
4
|
+
getQueryTextArea().invoke('val', query);
|
|
5
|
+
getQueryArea().then(codeMirrorEl => {
|
|
6
|
+
codeMirrorEl[0].CodeMirror.setValue(query);
|
|
7
|
+
});
|
|
6
8
|
});
|
|
7
9
|
|
|
8
10
|
Cypress.Commands.add('executeQuery', () => {
|
|
@@ -18,8 +20,8 @@ Cypress.Commands.add('verifyResultsPageLength', (resultLength) => {
|
|
|
18
20
|
|
|
19
21
|
Cypress.Commands.add('verifyResultsMessage', (msg) => {
|
|
20
22
|
cy.waitUntil(() =>
|
|
21
|
-
getResultsMessage()
|
|
22
|
-
|
|
23
|
+
getResultsMessage().then((resultInfo) => resultInfo && resultInfo.text().trim().length > 0));
|
|
24
|
+
getResultsMessage().should('contain', msg);
|
|
23
25
|
});
|
|
24
26
|
|
|
25
27
|
Cypress.Commands.add('getResultsMessage', () => {
|
|
@@ -58,10 +60,11 @@ function waitUntilQueryIsVisible() {
|
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
function verifyQueryAreaContains(query) {
|
|
61
|
-
// Using the CodeMirror instance because getting the value from the DOM is very cumbersome
|
|
62
63
|
cy.waitUntil(() =>
|
|
63
64
|
getQueryArea()
|
|
64
|
-
.then(codeMirrorEl => codeMirrorEl && codeMirrorEl[0].CodeMirror.getValue()
|
|
65
|
+
.then(codeMirrorEl => codeMirrorEl && typeof codeMirrorEl[0].CodeMirror.getValue() === 'string'));
|
|
66
|
+
// Using the CodeMirror instance because getting the value from the DOM is very cumbersome
|
|
67
|
+
getQueryArea().then(codeMirrorEl => codeMirrorEl && codeMirrorEl[0].CodeMirror.getValue()).should('contain', query);
|
|
65
68
|
}
|
|
66
69
|
|
|
67
70
|
function getRunQueryButton() {
|