graphdb-workbench-tests 4.0.0-TR1 → 4.0.0-TR10
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/e2e-flaky/import/import-server-files-operations.spec.js +8 -30
- package/e2e-flaky/import/import-user-data-batch-operations.spec.js +7 -7
- package/e2e-flaky/import/import-user-data-url.spec.js +1 -1
- package/e2e-legacy/cluster/cluster-configuration/cluster-configuration-multi-region.spec.js +27 -0
- package/e2e-legacy/cluster/edit-cluster-nodes-modal.spec.js +1 -1
- package/e2e-legacy/explore/graphs-overview/graphs.overview.spec.js +31 -2
- package/e2e-legacy/explore/visual-graph/visual.graph.spec.js +35 -4
- package/e2e-legacy/graph-navigator/graph-navigator-restrictions.spec.js +202 -0
- package/e2e-legacy/graph-navigator/graph-navigator.spec.js +243 -0
- package/e2e-legacy/guides/import-rdf-file/confirm-duplicate-rdf-file.spec.js +1 -1
- package/e2e-legacy/guides/main-menu/main-menu-guide.spec.js +6 -14
- package/e2e-legacy/guides/ttyg/configure-agent/configure-agent-guide.spec.js +26 -30
- package/e2e-legacy/guides/ttyg/edit-agent/edit-ttyg-agent-guide.spec.js +12 -20
- package/e2e-legacy/import/import-server-files-batch-operations.spec.js +5 -5
- package/e2e-legacy/import/import-server-files.spec.js +21 -23
- package/e2e-legacy/import/import-user-data-file-upload.spec.js +47 -22
- package/e2e-legacy/import/import-user-data-text-snippet.spec.js +6 -45
- package/e2e-legacy/import/import-user-data-url.spec.js +9 -6
- package/e2e-legacy/import/import-view.spec.js +2 -2
- package/e2e-legacy/rdf-version/rdf-version-accept-header.spec.js +145 -0
- package/e2e-legacy/repository/rename-repository-restrictions.spec.js +129 -0
- package/e2e-legacy/repository/repositories.spec.js +3 -3
- package/e2e-legacy/resource/resource.spec.js +176 -39
- package/e2e-legacy/setup/aclmanagement/create-rule.spec.js +14 -25
- package/e2e-legacy/setup/aclmanagement/delete-rule.spec.js +6 -6
- package/e2e-legacy/setup/aclmanagement/edit-rule.spec.js +15 -15
- package/e2e-legacy/setup/aclmanagement/render-rules.spec.js +1 -1
- package/e2e-legacy/setup/aclmanagement/reorder-rules.spec.js +2 -2
- package/e2e-legacy/setup/aclmanagement/revert-rules.spec.js +2 -2
- package/e2e-legacy/setup/aclmanagement/update-rules.spec.js +3 -3
- package/e2e-legacy/setup/aclmanagement/validate-uri.spec.js +152 -0
- package/e2e-legacy/setup/settings/my-settings-initial-state.spec.js +5 -11
- package/e2e-legacy/setup/settings/my-settings.spec.js +25 -15
- package/e2e-legacy/setup/users-and-access/user-and-access.spec.js +44 -24
- package/e2e-legacy/sparql-editor/yasr/download-as.spec.js +4 -7
- package/e2e-legacy/ttyg/create-agent.spec.js +111 -0
- package/e2e-legacy/ttyg/edit-agent.spec.js +57 -0
- package/e2e-legacy/ttyg/ttyg-initial-state-with-configured-api-key.spec.js +1 -1
- package/e2e-legacy/ttyg/ttyg-initial-state-with-selected-repository.spec.js +1 -1
- package/e2e-legacy/ttyg/ttyg-initial-state-without-repositories.spec.js +1 -1
- package/e2e-security/setup/users-and-access/user-and-access.spec.js +0 -1
- package/fixtures/cluster/3-nodes-cluster-group-status-no-leader.json +41 -0
- package/fixtures/cluster/cluster-config-with-tag.json +17 -0
- package/fixtures/graphdb-import/wine.rdf +279 -285
- package/fixtures/repositories/get-repositories-with-unsupported-graphql-types.json +46 -0
- package/npm-shrinkwrap.json +1283 -1643
- package/package.json +10 -1
- package/steps/base-steps.js +4 -0
- package/steps/cluster/cluster-configuration-steps.js +4 -0
- package/steps/error-steps.js +1 -1
- package/steps/explore/graphs-overview-steps.js +44 -0
- package/steps/graph-navigator-steps.js +116 -0
- package/steps/import/import-steps.js +65 -12
- package/steps/import/import-test-constants.js +1 -1
- package/steps/main-menu-steps.js +14 -14
- package/steps/page-restrictions-steps.js +24 -0
- package/steps/repository-picker-list-steps.js +38 -0
- package/steps/repository-steps.js +4 -0
- package/steps/resource/resource-steps.js +72 -5
- package/steps/setup/acl-management-steps.js +3 -23
- package/steps/setup/settings-steps.js +46 -0
- package/steps/setup/user-and-access-steps.js +44 -19
- package/steps/ttyg/ttyg-agent-settings-modal.steps.js +16 -0
- package/stubs/cluster/cluster-stubs.js +15 -1
- package/stubs/repositories/repositories-stubs.js +4 -0
- package/fixtures/graphdb-import/test-trigstar.trigs +0 -32
- package/fixtures/graphdb-import/test_turtlestar.ttls +0 -6
- package/fixtures/graphdb-import/turtlestar-data.ttls +0 -77
|
@@ -9,8 +9,6 @@ describe('Import server files - Operations', () => {
|
|
|
9
9
|
const CONTEXT = 'http://example.org/context';
|
|
10
10
|
const FILE_FOR_IMPORT = 'italian_public_schools_links.nt.gz';
|
|
11
11
|
const FILE_FROM_DIRECTORY_FOR_IMPORT = 'rdfxml.rdf';
|
|
12
|
-
const TTLS_FOR_IMPORT = 'test_turtlestar.ttls';
|
|
13
|
-
const TRIGS_FOR_IMPORT = 'test-trigstar.trigs';
|
|
14
12
|
const JSONLD_FILE_FOR_IMPORT = '0007-import-file.jsonld';
|
|
15
13
|
const JSONLD_CONTEXT = 'https://w3c.github.io/json-ld-api/tests/compact/0007-context.jsonld';
|
|
16
14
|
|
|
@@ -18,7 +16,7 @@ describe('Import server files - Operations', () => {
|
|
|
18
16
|
repositoryId = 'server-import-' + Date.now();
|
|
19
17
|
cy.createRepository({id: repositoryId});
|
|
20
18
|
ImportServerFilesSteps.visitServerImport(repositoryId);
|
|
21
|
-
ImportServerFilesSteps.getResources().should('have.length',
|
|
19
|
+
ImportServerFilesSteps.getResources().should('have.length', 17);
|
|
22
20
|
});
|
|
23
21
|
|
|
24
22
|
afterEach(() => {
|
|
@@ -31,7 +29,7 @@ describe('Import server files - Operations', () => {
|
|
|
31
29
|
ImportServerFilesSteps.importResourceByName(FILE_FOR_IMPORT);
|
|
32
30
|
ImportSettingsDialogSteps.import();
|
|
33
31
|
// Then I should see the file imported successfully
|
|
34
|
-
ImportServerFilesSteps.
|
|
32
|
+
ImportServerFilesSteps.checkImportedResourceByIndex(0, FILE_FOR_IMPORT);
|
|
35
33
|
// TODO: this and all similar check in the tests below are a checking for the default import settings which we probably should not verify here.
|
|
36
34
|
// ImportServerFilesSteps.verifyImportStatusDetails(FILE_FOR_IMPORT, '"preserveBNodeIds": false,');
|
|
37
35
|
});
|
|
@@ -42,7 +40,7 @@ describe('Import server files - Operations', () => {
|
|
|
42
40
|
ImportServerFilesSteps.importResourceByName(FILE_FROM_DIRECTORY_FOR_IMPORT);
|
|
43
41
|
ImportSettingsDialogSteps.import();
|
|
44
42
|
// Then I should see the file imported successfully
|
|
45
|
-
ImportServerFilesSteps.
|
|
43
|
+
ImportServerFilesSteps.checkImportedResourceByIndex(0, FILE_FROM_DIRECTORY_FOR_IMPORT);
|
|
46
44
|
});
|
|
47
45
|
|
|
48
46
|
it('Should import Server files successfully with changing settings', () => {
|
|
@@ -57,7 +55,7 @@ describe('Import server files - Operations', () => {
|
|
|
57
55
|
ImportSettingsDialogSteps.enablePreserveBNodes();
|
|
58
56
|
ImportSettingsDialogSteps.import();
|
|
59
57
|
// Then I should see the file imported successfully
|
|
60
|
-
ImportServerFilesSteps.
|
|
58
|
+
ImportServerFilesSteps.checkImportedResourceByIndex(0, FILE_FOR_IMPORT);
|
|
61
59
|
// ImportSteps.verifyImportStatusDetails(FILE_FOR_IMPORT, [CONTEXT, BASE_URI, '"preserveBNodeIds": true,']);
|
|
62
60
|
});
|
|
63
61
|
|
|
@@ -75,7 +73,7 @@ describe('Import server files - Operations', () => {
|
|
|
75
73
|
ImportSettingsDialogSteps.enablePreserveBNodes();
|
|
76
74
|
ImportSettingsDialogSteps.import();
|
|
77
75
|
// Then I should see the file imported successfully
|
|
78
|
-
ImportServerFilesSteps.
|
|
76
|
+
ImportServerFilesSteps.checkImportedResourceByIndex(0, JSONLD_FILE_FOR_IMPORT);
|
|
79
77
|
// ImportSteps.verifyImportStatusDetails(JSONLD_FILE_FOR_IMPORT, [CONTEXT, BASE_URI, '"preserveBNodeIds": true,', JSONLD_CONTEXT]);
|
|
80
78
|
});
|
|
81
79
|
|
|
@@ -92,7 +90,7 @@ describe('Import server files - Operations', () => {
|
|
|
92
90
|
ImportSettingsDialogSteps.enablePreserveBNodes();
|
|
93
91
|
ImportSettingsDialogSteps.import();
|
|
94
92
|
// Then I should see the file imported successfully
|
|
95
|
-
ImportServerFilesSteps.
|
|
93
|
+
ImportServerFilesSteps.checkImportedResourceByIndex(0, JSONLD_FILE_FOR_IMPORT);
|
|
96
94
|
// ImportSteps.verifyImportStatusDetails(JSONLD_FILE_FOR_IMPORT, [CONTEXT, BASE_URI, '"preserveBNodeIds": true,']);
|
|
97
95
|
});
|
|
98
96
|
|
|
@@ -101,7 +99,7 @@ describe('Import server files - Operations', () => {
|
|
|
101
99
|
// And I have imported a file
|
|
102
100
|
ImportServerFilesSteps.importResourceByName(FILE_FOR_IMPORT);
|
|
103
101
|
ImportSettingsDialogSteps.import();
|
|
104
|
-
ImportServerFilesSteps.
|
|
102
|
+
ImportServerFilesSteps.checkImportedResourceByIndex(0, FILE_FOR_IMPORT);
|
|
105
103
|
// When I reset the status of the imported file
|
|
106
104
|
ImportServerFilesSteps.resetResourceStatusByName(FILE_FOR_IMPORT);
|
|
107
105
|
// Then Import status of the file should not be visible
|
|
@@ -113,30 +111,10 @@ describe('Import server files - Operations', () => {
|
|
|
113
111
|
// And I have imported a file
|
|
114
112
|
ImportServerFilesSteps.importResourceByName(FILE_FROM_DIRECTORY_FOR_IMPORT);
|
|
115
113
|
ImportSettingsDialogSteps.import();
|
|
116
|
-
ImportServerFilesSteps.
|
|
114
|
+
ImportServerFilesSteps.checkImportedResourceByIndex(0, FILE_FROM_DIRECTORY_FOR_IMPORT);
|
|
117
115
|
// When I reset the status of the imported file
|
|
118
116
|
ImportServerFilesSteps.resetResourceStatusByName(FILE_FROM_DIRECTORY_FOR_IMPORT);
|
|
119
117
|
// Then Import status of the file should not be visible
|
|
120
118
|
ImportServerFilesSteps.getResourceStatus(FILE_FROM_DIRECTORY_FOR_IMPORT).should('be.hidden');
|
|
121
119
|
});
|
|
122
|
-
|
|
123
|
-
it('Should import turtlestar from Server files successfully without changing settings', () => {
|
|
124
|
-
// Given I have opened the server files tab
|
|
125
|
-
ImportServerFilesSteps.importResourceByName(TTLS_FOR_IMPORT);
|
|
126
|
-
// When I select to import a ttl file without changing settings
|
|
127
|
-
ImportSettingsDialogSteps.import();
|
|
128
|
-
// Then I should see the file imported successfully
|
|
129
|
-
ImportServerFilesSteps.checkImportedResource(0, TTLS_FOR_IMPORT);
|
|
130
|
-
// ImportSteps.verifyImportStatusDetails(TTLS_FOR_IMPORT, '"preserveBNodeIds": false,');
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
it('Should import trigstar from Server files successfully without changing settings', () => {
|
|
134
|
-
// Given I have opened the server files tab
|
|
135
|
-
ImportServerFilesSteps.importResourceByName(TRIGS_FOR_IMPORT);
|
|
136
|
-
// When I select to import a trigstar file without changing settings
|
|
137
|
-
ImportSettingsDialogSteps.import();
|
|
138
|
-
// Then I should see the file imported successfully
|
|
139
|
-
ImportServerFilesSteps.checkImportedResource(0, TRIGS_FOR_IMPORT);
|
|
140
|
-
// ImportSteps.verifyImportStatusDetails(TRIGS_FOR_IMPORT, '"preserveBNodeIds": false,');
|
|
141
|
-
});
|
|
142
120
|
});
|
|
@@ -56,7 +56,7 @@ describe('Import user data: Batch operations', () => {
|
|
|
56
56
|
ImportSettingsDialogSteps.getDialog().should('be.visible');
|
|
57
57
|
ImportSettingsDialogSteps.import();
|
|
58
58
|
ImportUserDataSteps.getResources().should('have.length', 3);
|
|
59
|
-
ImportUserDataSteps.
|
|
59
|
+
ImportUserDataSteps.checkImportedResourceByIndex(0, 'jsonld-2.jsonld');
|
|
60
60
|
// When I select Imported from the menu
|
|
61
61
|
ImportUserDataSteps.selectImportedResources();
|
|
62
62
|
// Then I should see only imported files selected
|
|
@@ -83,7 +83,7 @@ describe('Import user data: Batch operations', () => {
|
|
|
83
83
|
ImportUserDataSteps.batchImport();
|
|
84
84
|
ImportSettingsDialogSteps.import();
|
|
85
85
|
// Then the file should be imported
|
|
86
|
-
ImportUserDataSteps.
|
|
86
|
+
ImportUserDataSteps.checkImportedResourceByIndex(0, 'jsonld-2.jsonld');
|
|
87
87
|
ImportUserDataSteps.selectImportedResources();
|
|
88
88
|
ImportUserDataSteps.getSelectedResources().should('have.length', 1);
|
|
89
89
|
ImportUserDataSteps.deselectAllResources();
|
|
@@ -94,8 +94,8 @@ describe('Import user data: Batch operations', () => {
|
|
|
94
94
|
ImportUserDataSteps.batchImport();
|
|
95
95
|
ImportSettingsDialogSteps.import();
|
|
96
96
|
// Then the files should be imported
|
|
97
|
-
ImportUserDataSteps.
|
|
98
|
-
ImportUserDataSteps.
|
|
97
|
+
ImportUserDataSteps.checkImportedResourceByIndex(1, 'jsonld.jsonld');
|
|
98
|
+
ImportUserDataSteps.checkImportedResourceByIndex(2, 'bnodes.ttl');
|
|
99
99
|
ImportUserDataSteps.selectImportedResources();
|
|
100
100
|
ImportUserDataSteps.getSelectedResources().should('have.length', 3);
|
|
101
101
|
});
|
|
@@ -162,9 +162,9 @@ function uploadWithImportFiles(files) {
|
|
|
162
162
|
ImportUserDataSteps.selectFile([file1, file2, file3]);
|
|
163
163
|
ImportSettingsDialogSteps.import();
|
|
164
164
|
ImportUserDataSteps.getResources().should('have.length', 3);
|
|
165
|
-
ImportUserDataSteps.
|
|
166
|
-
ImportUserDataSteps.
|
|
167
|
-
ImportUserDataSteps.
|
|
165
|
+
ImportUserDataSteps.checkImportedResourceByIndex(0, 'jsonld-2.jsonld');
|
|
166
|
+
ImportUserDataSteps.checkImportedResourceByIndex(1, 'jsonld.jsonld');
|
|
167
|
+
ImportUserDataSteps.checkImportedResourceByIndex(2, 'bnodes.ttl');
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
function uploadFiles(data) {
|
|
@@ -58,6 +58,6 @@ describe('Import user data: URL import', () => {
|
|
|
58
58
|
return xhr.response.body[0]?.status === 'ERROR'
|
|
59
59
|
}), {timeout: 10000, interval: 1000}
|
|
60
60
|
)
|
|
61
|
-
ImportUserDataSteps.
|
|
61
|
+
ImportUserDataSteps.checkImportedResourceByIndex(0, IMPORT_JSONLD_URL, 'https://example.com/0007-context.jsonld');
|
|
62
62
|
});
|
|
63
63
|
});
|
|
@@ -42,7 +42,9 @@ describe('Cluster configuration', () => {
|
|
|
42
42
|
});
|
|
43
43
|
|
|
44
44
|
ClusterStubs.stubClusterGroupStatusWithTag();
|
|
45
|
+
ClusterStubs.stubClusterConfigWithTag();
|
|
45
46
|
cy.wait('@3-nodes-cluster-group-status-tag');
|
|
47
|
+
cy.wait('@cluster-config-with-tag');
|
|
46
48
|
// Assert the tags table contains the expected tag
|
|
47
49
|
ClusterConfigurationSteps.getTagsTable().should('be.visible');
|
|
48
50
|
ClusterConfigurationSteps.getTagsTableRows().should('contain.text', tagName);
|
|
@@ -62,6 +64,31 @@ describe('Cluster configuration', () => {
|
|
|
62
64
|
cy.wait('@delete-tag').then((interception) => {
|
|
63
65
|
expect(interception.request.body).to.deep.equal({tag: tagName});
|
|
64
66
|
});
|
|
67
|
+
ClusterStubs.stubClusterGroupStatus();
|
|
68
|
+
ClusterStubs.stubClusterConfig();
|
|
69
|
+
cy.wait('@3-nodes-cluster-group-status');
|
|
70
|
+
cy.wait('@cluster-config');
|
|
71
|
+
ClusterConfigurationSteps.getTagsTable().should('not.exist');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should show an alert when there is no elected leader in the cluster', () => {
|
|
75
|
+
// Given there is no elected leader in the cluster
|
|
76
|
+
ClusterStubs.stubClusterGroupStatusWithoutLeader();
|
|
77
|
+
|
|
78
|
+
// When I have opened the cluster management page
|
|
79
|
+
ClusterPageSteps.visit();
|
|
80
|
+
// And I click on edit properties and open Multi-region tab
|
|
81
|
+
ClusterPageSteps.previewClusterConfig();
|
|
82
|
+
ClusterConfigurationSteps.selectMultiRegionConfigTab();
|
|
83
|
+
|
|
84
|
+
// Then I expect to see an alert that the leader is not elected
|
|
85
|
+
ClusterConfigurationSteps.getNoLeaderAlert().should('be.visible')
|
|
86
|
+
.and('contain.text', 'Leader is not elected');
|
|
87
|
+
// And no primary or secondary cluster configuration should be rendered
|
|
88
|
+
ClusterConfigurationSteps.getMultiRegionHeader().should('not.exist');
|
|
89
|
+
ClusterConfigurationSteps.getAddTagButton().should('not.exist');
|
|
90
|
+
ClusterConfigurationSteps.getEnableSecondaryModeButton().should('not.exist');
|
|
91
|
+
ClusterConfigurationSteps.getTagsTable().should('not.exist');
|
|
65
92
|
});
|
|
66
93
|
|
|
67
94
|
it('should be able to switch modes', () => {
|
|
@@ -460,7 +460,7 @@ describe('Cluster management', () => {
|
|
|
460
460
|
"verificationTimeout": 1500,
|
|
461
461
|
"transactionLogMaximumSizeGB": 50.0,
|
|
462
462
|
"batchUpdateInterval": 5000,
|
|
463
|
-
"nodes": ['http://pc-desktop:7200', 'http://pc-desktop:7203']
|
|
463
|
+
"nodes": ['http://pc-desktop:7200', 'http://pc-desktop:7203'],
|
|
464
464
|
});
|
|
465
465
|
});
|
|
466
466
|
// And expect success message to be displayed.
|
|
@@ -18,7 +18,7 @@ describe('Graphs overview screen validation', () => {
|
|
|
18
18
|
cy.window();
|
|
19
19
|
|
|
20
20
|
cy.fixture('graph/rdf.txt').then((rdf) => {
|
|
21
|
-
return new Cypress.Promise((resolve
|
|
21
|
+
return new Cypress.Promise((resolve) => {
|
|
22
22
|
cy.importRDFTextSnippet(repositoryId, rdf, {format: "application/x-trig"});
|
|
23
23
|
resolve();
|
|
24
24
|
});
|
|
@@ -76,6 +76,7 @@ describe('Graphs overview screen validation', () => {
|
|
|
76
76
|
it('Should switch pages', () => {
|
|
77
77
|
// Makes this less flaky - is it possible the page elements don't have an event attached
|
|
78
78
|
// yet when this fails? It looks like the click has never happened
|
|
79
|
+
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
79
80
|
cy.wait(100);
|
|
80
81
|
|
|
81
82
|
// Switch through pages and verify that the respective pager button is active.
|
|
@@ -111,6 +112,33 @@ describe('Graphs overview screen validation', () => {
|
|
|
111
112
|
verifyGraphExistence('urn:11', false);
|
|
112
113
|
});
|
|
113
114
|
|
|
115
|
+
it('Should give the controls on the page accessible names', () => {
|
|
116
|
+
// Then the search field should have a screen reader label and a placeholder
|
|
117
|
+
GraphsOverviewSteps.getGraphsSearchLabel()
|
|
118
|
+
.should('have.class', 'sr-only')
|
|
119
|
+
.and('contain.text', 'Search Graphs');
|
|
120
|
+
GraphsOverviewSteps.getGraphsSearchInput()
|
|
121
|
+
.should('have.attr', 'id', 'search-graphs')
|
|
122
|
+
.and('have.attr', 'placeholder', 'Search Graphs');
|
|
123
|
+
// And the table and the header controls should have accessible names
|
|
124
|
+
GraphsOverviewSteps.getResultsElement().should('have.attr', 'aria-label', 'Graphs')
|
|
125
|
+
.and('not.have.attr', 'aria-describedby');
|
|
126
|
+
GraphsOverviewSteps.getSelectAllGraphsCheckbox().should('have.attr', 'aria-label', 'Select all graphs');
|
|
127
|
+
GraphsOverviewSteps.getExportSelectedGraphsButton().should('have.attr', 'aria-label', 'Export selected graphs');
|
|
128
|
+
GraphsOverviewSteps.getDeleteSelectedGraphsButton().should('have.attr', 'aria-label', 'Removes all data from the selected graphs');
|
|
129
|
+
GraphsOverviewSteps.getActionsColumnHeader().should('contain.text', 'Actions');
|
|
130
|
+
// And no empty label should wrap the checkbox
|
|
131
|
+
GraphsOverviewSteps.getResultsHeader().find('label').should('not.exist');
|
|
132
|
+
// And the controls in each row should include the graph name
|
|
133
|
+
GraphsOverviewSteps.getSelectGraphCheckbox('urn:9').should('have.attr', 'aria-label', 'Select graph urn:9');
|
|
134
|
+
GraphsOverviewSteps.getExportGraphButton('urn:9').should('have.attr', 'aria-label', 'Export graph urn:9');
|
|
135
|
+
GraphsOverviewSteps.getDeleteGraphButton('urn:9').should('have.attr', 'aria-label', 'Remove all data from graph urn:9');
|
|
136
|
+
GraphsOverviewSteps.getGraphRow('urn:9').find('label').should('not.exist');
|
|
137
|
+
// And the default graph row should use the translated graph name
|
|
138
|
+
GraphsOverviewSteps.getDefaultGraphRow().find('.select-graph-checkbox')
|
|
139
|
+
.should('have.attr', 'aria-label', 'Select graph The default graph');
|
|
140
|
+
});
|
|
141
|
+
|
|
114
142
|
it('Delete graph', () => {
|
|
115
143
|
let graphToDelete = 'urn:9';
|
|
116
144
|
cy.get(`${EXPORT_GRAPHS_TABLE_ID} tbody a[title="${graphToDelete}"]`)
|
|
@@ -125,7 +153,8 @@ describe('Graphs overview screen validation', () => {
|
|
|
125
153
|
verifyVisibleGraphsCount(1);
|
|
126
154
|
verifyGraphExistence('The default graph');
|
|
127
155
|
// open default graph through the link and verify that the table view is rendered
|
|
128
|
-
cy.getByTestId('graph-is-not-shaql').contains('The default graph').trigger('mouseover')
|
|
156
|
+
cy.getByTestId('graph-is-not-shaql').contains('The default graph').trigger('mouseover');
|
|
157
|
+
cy.getByTestId('graph-is-not-shaql').contains('The default graph').click();
|
|
129
158
|
cy.url().should('contain', Cypress.config('baseUrl') + '/resource');
|
|
130
159
|
YasrSteps.getResultTableHeader().should('be.visible');
|
|
131
160
|
YasrSteps.getResultTableHeaderColumns().should('have.length', 5);
|
|
@@ -8,6 +8,19 @@ import HomeSteps from '../../../steps/home-steps.js';
|
|
|
8
8
|
const FILE_TO_IMPORT = 'wine.rdf';
|
|
9
9
|
const VALID_RESOURCE = 'USRegion';
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Updates the links limit and waits for the graph reload it triggers to complete.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} value the new links limit
|
|
15
|
+
*/
|
|
16
|
+
function updateLinksLimit(value) {
|
|
17
|
+
VisualGraphSteps.updateLinksLimitField(value);
|
|
18
|
+
VisualGraphSteps.getLinksNumberField().should('have.value', value);
|
|
19
|
+
VisualGraphSteps.getUrl().should('match', new RegExp(`[?&]linksLimit=${value}(&|$)`));
|
|
20
|
+
VisualGraphSteps.getGraphVisualizationPane().should('be.visible');
|
|
21
|
+
VisualGraphSteps.getNodes();
|
|
22
|
+
}
|
|
23
|
+
|
|
11
24
|
describe('Visual graph screen validation', () => {
|
|
12
25
|
|
|
13
26
|
let repositoryId;
|
|
@@ -311,6 +324,20 @@ describe('Visual graph screen validation', () => {
|
|
|
311
324
|
VisualGraphSteps.getPredicates().should('have.length', 36);
|
|
312
325
|
});
|
|
313
326
|
|
|
327
|
+
it('Should close the settings panel when navigating away from the graph', () => {
|
|
328
|
+
// Given I have opened a graph
|
|
329
|
+
VisualGraphSteps.openUSRegionUri();
|
|
330
|
+
// And I have opened the visual graph settings
|
|
331
|
+
VisualGraphSteps.openVisualGraphSettings();
|
|
332
|
+
VisualGraphSteps.getSettingsPanel().should('be.visible');
|
|
333
|
+
|
|
334
|
+
// When I click the visual graph submenu
|
|
335
|
+
MainMenuSteps.clickOnSubmenuVisualGraph();
|
|
336
|
+
|
|
337
|
+
// Then I expect the settings panel to be closed
|
|
338
|
+
VisualGraphSteps.getSettingsPanel().should('not.exist');
|
|
339
|
+
});
|
|
340
|
+
|
|
314
341
|
it('Test include inferred Statements', () => {
|
|
315
342
|
VisualGraphSteps.openUSRegionUri();
|
|
316
343
|
// Check include inferred
|
|
@@ -361,9 +388,11 @@ describe('Visual graph screen validation', () => {
|
|
|
361
388
|
// Pick a type that is displayed in the diagram for example "vin:Zinfandel"
|
|
362
389
|
VisualGraphSteps.getNodes().and('contain', 'Zinfandel');
|
|
363
390
|
|
|
391
|
+
// Set the connections limit to 10 and wait for the graph reload it triggers,
|
|
392
|
+
// so that the settings are opened after the navigation has completed
|
|
393
|
+
updateLinksLimit('10');
|
|
394
|
+
|
|
364
395
|
VisualGraphSteps.openVisualGraphSettings();
|
|
365
|
-
// Set the connections limit to 10
|
|
366
|
-
VisualGraphSteps.updateLinksLimitField('10');
|
|
367
396
|
// Go to Settings and set "vin:Zinfandel" as an ignored type
|
|
368
397
|
VisualGraphSteps.getIgnoredTypesField().clear().type('vin:Zinfandel').type('{enter}');
|
|
369
398
|
|
|
@@ -395,12 +424,14 @@ describe('Visual graph screen validation', () => {
|
|
|
395
424
|
// Pick a type that is displayed in the diagram for example "vin:Zinfandel"
|
|
396
425
|
VisualGraphSteps.getPredicates().should('contain', 'hasSugar');
|
|
397
426
|
|
|
427
|
+
// Set the connections limit to 10 and wait for the graph reload it triggers,
|
|
428
|
+
// so that the settings are opened after the navigation has completed
|
|
429
|
+
updateLinksLimit('10');
|
|
430
|
+
|
|
398
431
|
VisualGraphSteps.openVisualGraphSettings();
|
|
399
432
|
// Go to predicates tab
|
|
400
433
|
VisualGraphSteps.openPredicatesTab();
|
|
401
434
|
|
|
402
|
-
// Set the connections limit to 10
|
|
403
|
-
VisualGraphSteps.updateLinksLimitField('10');
|
|
404
435
|
// Set "vin:hasSugar" as an ignored predicate
|
|
405
436
|
VisualGraphSteps.getIgnoredPredicatesField().clear().type('vin:hasSugar').type('{enter}');
|
|
406
437
|
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import {GraphNavigatorSteps} from '../../steps/graph-navigator-steps.js';
|
|
2
|
+
import {PageRestrictionsSteps} from '../../steps/page-restrictions-steps.js';
|
|
3
|
+
import {RepositoryPickerListSteps} from '../../steps/repository-picker-list-steps.js';
|
|
4
|
+
import {LicenseStubs} from '../../stubs/license-stubs.js';
|
|
5
|
+
import {RepositorySteps} from '../../steps/repository-steps.js';
|
|
6
|
+
|
|
7
|
+
const NO_REPOSITORY_MESSAGE = 'you are not connected to any repository';
|
|
8
|
+
const INVALID_LICENSE_MESSAGE = 'your license is not valid';
|
|
9
|
+
const SELECT_OR_CREATE_REPOSITORY_MESSAGE = 'Select a repository below or create a new one.';
|
|
10
|
+
const SELECT_REPOSITORY_MESSAGE = 'Select a repository below.';
|
|
11
|
+
|
|
12
|
+
describe('Graph Navigator view restrictions', () => {
|
|
13
|
+
let repositoryId;
|
|
14
|
+
|
|
15
|
+
beforeEach(() => {
|
|
16
|
+
repositoryId = 'graph-navigator-view-restrictions-' + Date.now();
|
|
17
|
+
cy.createRepository({id: repositoryId});
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
cy.deleteRepository(repositoryId);
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should show the repository picker when no repository is selected', () => {
|
|
25
|
+
// GIVEN no repository is selected
|
|
26
|
+
|
|
27
|
+
// WHEN I open the Graph Navigator view
|
|
28
|
+
GraphNavigatorSteps.visit();
|
|
29
|
+
// THEN I expect the repository restriction is shown
|
|
30
|
+
PageRestrictionsSteps.getMessages().should('have.length', 1);
|
|
31
|
+
PageRestrictionsSteps.getMessage(NO_REPOSITORY_MESSAGE).should('be.visible');
|
|
32
|
+
// AND the existing repository is available in the picker
|
|
33
|
+
RepositoryPickerListSteps.getRepositoryRow(repositoryId).should('be.visible');
|
|
34
|
+
// AND its location is not shown, because only the local repositories are listed
|
|
35
|
+
RepositoryPickerListSteps.getRepositoryLocation(repositoryId).should('not.exist');
|
|
36
|
+
// AND the graph is not rendered
|
|
37
|
+
GraphNavigatorSteps.getComponent().should('not.exist');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should render the graph when a repository is selected from the picker', () => {
|
|
41
|
+
// GIVEN the Graph Navigator view is open with no repository selected
|
|
42
|
+
GraphNavigatorSteps.visit();
|
|
43
|
+
|
|
44
|
+
// WHEN I select a repository
|
|
45
|
+
RepositoryPickerListSteps.selectRepository(repositoryId);
|
|
46
|
+
// THEN I expect the restriction is removed and the graph is rendered
|
|
47
|
+
PageRestrictionsSteps.getRestrictions().should('not.exist');
|
|
48
|
+
GraphNavigatorSteps.getWorkspace().should('exist');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('should not restrict the view when the license is valid and a repository is selected', () => {
|
|
52
|
+
// GIVEN a valid license and a selected repository
|
|
53
|
+
cy.presetRepository(repositoryId);
|
|
54
|
+
|
|
55
|
+
// WHEN I open the Graph Navigator view
|
|
56
|
+
GraphNavigatorSteps.visit();
|
|
57
|
+
// THEN I expect the view is not restricted
|
|
58
|
+
GraphNavigatorSteps.getWorkspace().should('exist');
|
|
59
|
+
PageRestrictionsSteps.getRestrictions().should('not.exist');
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
context('when the license is invalid', () => {
|
|
63
|
+
beforeEach(() => {
|
|
64
|
+
LicenseStubs.stubNoValidLicense();
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('should show the license restriction when a repository is selected', () => {
|
|
68
|
+
// GIVEN an invalid license and a selected repository
|
|
69
|
+
cy.presetRepository(repositoryId);
|
|
70
|
+
|
|
71
|
+
// WHEN I open the Graph Navigator view
|
|
72
|
+
GraphNavigatorSteps.visit();
|
|
73
|
+
// THEN I expect the license restriction is shown
|
|
74
|
+
PageRestrictionsSteps.getMessages().should('have.length', 1);
|
|
75
|
+
PageRestrictionsSteps.getMessage(INVALID_LICENSE_MESSAGE).should('be.visible');
|
|
76
|
+
// AND the "Set a new license" link is displayed
|
|
77
|
+
PageRestrictionsSteps.getInternalLink()
|
|
78
|
+
.should('contain.text', 'Set a new license')
|
|
79
|
+
.and('have.attr', 'href')
|
|
80
|
+
.and('include', '/license');
|
|
81
|
+
// AND the repository picker and graph are not rendered
|
|
82
|
+
RepositoryPickerListSteps.getRepositoryPickerList().should('not.exist');
|
|
83
|
+
GraphNavigatorSteps.getComponent().should('not.exist');
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it('should show both restrictions when no repository is selected', () => {
|
|
87
|
+
// GIVEN an invalid license and no repository selected
|
|
88
|
+
|
|
89
|
+
// WHEN I open the Graph Navigator view
|
|
90
|
+
GraphNavigatorSteps.visit();
|
|
91
|
+
// THEN both restrictions are shown
|
|
92
|
+
PageRestrictionsSteps.getMessages().should('have.length', 2);
|
|
93
|
+
PageRestrictionsSteps.getMessage(INVALID_LICENSE_MESSAGE).should('be.visible');
|
|
94
|
+
PageRestrictionsSteps.getMessage(NO_REPOSITORY_MESSAGE)
|
|
95
|
+
.should('be.visible')
|
|
96
|
+
.and('not.contain.text', 'create a new one');
|
|
97
|
+
// AND the existing repository is available, but repository creation is not
|
|
98
|
+
RepositoryPickerListSteps.getRepositoryRow(repositoryId).should('be.visible');
|
|
99
|
+
RepositoryPickerListSteps.getCreateRepositoryButton().should('not.exist');
|
|
100
|
+
// AND the graph is not rendered
|
|
101
|
+
GraphNavigatorSteps.getComponent().should('not.exist');
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
context('with security enabled', () => {
|
|
106
|
+
const readOnlyUser = 'graph-navigator-reader-' + Date.now();
|
|
107
|
+
const repoManagerUser = 'graph-navigator-repo-manager-' + Date.now();
|
|
108
|
+
const repoMaintainerUser = 'graph-navigator-repo-maintainer-' + Date.now();
|
|
109
|
+
const password = 'root';
|
|
110
|
+
|
|
111
|
+
beforeEach(() => {
|
|
112
|
+
cy.createUser({
|
|
113
|
+
username: readOnlyUser,
|
|
114
|
+
password,
|
|
115
|
+
grantedAuthorities: ['ROLE_USER', `READ_REPO_${repositoryId}`]
|
|
116
|
+
});
|
|
117
|
+
cy.createUser({
|
|
118
|
+
username: repoManagerUser,
|
|
119
|
+
password,
|
|
120
|
+
grantedAuthorities: ['ROLE_USER', 'ROLE_REPO_MANAGER']
|
|
121
|
+
});
|
|
122
|
+
cy.createUser({
|
|
123
|
+
username: repoMaintainerUser,
|
|
124
|
+
password,
|
|
125
|
+
grantedAuthorities: [
|
|
126
|
+
'ROLE_USER',
|
|
127
|
+
`READ_REPO_${repositoryId}`,
|
|
128
|
+
`WRITE_REPO_${repositoryId}`,
|
|
129
|
+
`MAINTAIN_REPO_${repositoryId}`
|
|
130
|
+
]
|
|
131
|
+
});
|
|
132
|
+
cy.switchOnSecurity();
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
afterEach(() => {
|
|
136
|
+
cy.loginAsAdmin().then(() => {
|
|
137
|
+
cy.deleteUser(readOnlyUser, true);
|
|
138
|
+
cy.deleteUser(repoManagerUser, true);
|
|
139
|
+
cy.deleteUser(repoMaintainerUser, true);
|
|
140
|
+
cy.switchOffSecurity(true);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should not restrict the view for a user without write permission', () => {
|
|
145
|
+
// GIVEN a user with read-only access to the selected repository
|
|
146
|
+
cy.loginAs(readOnlyUser, password);
|
|
147
|
+
cy.presetRepository(repositoryId);
|
|
148
|
+
|
|
149
|
+
// WHEN I open the Graph Navigator view
|
|
150
|
+
GraphNavigatorSteps.visit();
|
|
151
|
+
// THEN I expect the view is not restricted
|
|
152
|
+
GraphNavigatorSteps.getWorkspace().should('exist');
|
|
153
|
+
PageRestrictionsSteps.getRestrictions().should('not.exist');
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('should offer repository creation to the administrator', () => {
|
|
157
|
+
// GIVEN the administrator is logged in with no repository selected
|
|
158
|
+
cy.loginAs('admin', password);
|
|
159
|
+
|
|
160
|
+
// WHEN I open the Graph Navigator view
|
|
161
|
+
GraphNavigatorSteps.visit();
|
|
162
|
+
// THEN I expect the option to select or create a repository is displayed
|
|
163
|
+
PageRestrictionsSteps.getMessage(SELECT_OR_CREATE_REPOSITORY_MESSAGE).should('be.visible');
|
|
164
|
+
RepositoryPickerListSteps.getRepositoryRow(repositoryId).should('be.visible');
|
|
165
|
+
RepositoryPickerListSteps.getCreateRepositoryButton().should('be.visible');
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it('should offer repository creation to a repository manager', () => {
|
|
169
|
+
// GIVEN a repository manager is logged in with no repository selected
|
|
170
|
+
cy.loginAs(repoManagerUser, password);
|
|
171
|
+
|
|
172
|
+
// WHEN I open the Graph Navigator view
|
|
173
|
+
GraphNavigatorSteps.visit();
|
|
174
|
+
// THEN the option to select or create a repository is displayed
|
|
175
|
+
PageRestrictionsSteps.getMessage(SELECT_OR_CREATE_REPOSITORY_MESSAGE).should('be.visible');
|
|
176
|
+
RepositoryPickerListSteps.getRepositoryRow(repositoryId).should('be.visible');
|
|
177
|
+
|
|
178
|
+
// WHEN I click the create repository button
|
|
179
|
+
RepositoryPickerListSteps.clickCreateRepositoryButton();
|
|
180
|
+
// THEN the create repository view is opened
|
|
181
|
+
RepositorySteps.verifyRepositoryCreateViewUrl().and('include', 'previous=%2Fgraph-navigator');
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
[
|
|
185
|
+
{role: 'a read-only user', username: readOnlyUser},
|
|
186
|
+
{role: 'a repository maintainer', username: repoMaintainerUser},
|
|
187
|
+
].forEach(({role, username}) => {
|
|
188
|
+
it(`should not offer repository creation to ${role}`, () => {
|
|
189
|
+
// GIVEN a user without repository management rights is logged in with no repository selected
|
|
190
|
+
cy.loginAs(username, password);
|
|
191
|
+
|
|
192
|
+
// WHEN I open the Graph Navigator view
|
|
193
|
+
GraphNavigatorSteps.visit();
|
|
194
|
+
// THEN only the option to select a repository is displayed
|
|
195
|
+
PageRestrictionsSteps.getMessage(SELECT_REPOSITORY_MESSAGE).should('be.visible');
|
|
196
|
+
PageRestrictionsSteps.getMessages().should('not.contain.text', 'create a new one');
|
|
197
|
+
RepositoryPickerListSteps.getRepositoryRow(repositoryId).should('be.visible');
|
|
198
|
+
RepositoryPickerListSteps.getCreateRepositoryButton().should('not.exist');
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
});
|