graphdb-workbench-tests 4.0.0-TR12 → 4.0.0-TR14
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-legacy/graph-navigator/graph-navigator-restrictions.spec.js +14 -0
- package/e2e-legacy/graph-navigator/graph-navigator.spec.js +34 -7
- package/e2e-legacy/import/import-server-files-batch-operations.spec.js +33 -0
- package/e2e-legacy/import/import-server-files.spec.js +18 -0
- package/e2e-legacy/import/import-user-data-settings-dialog.spec.js +81 -10
- package/e2e-legacy/import/import-user-data-url.spec.js +9 -8
- package/e2e-legacy/repository/ontop-repository.spec.js +3 -3
- package/e2e-legacy/setup/connectors/connectors-initial-state-with-selected-repository.spec.js +1 -1
- package/e2e-legacy/setup/users-and-access/user-and-access.spec.js +11 -5
- package/e2e-legacy/ttyg/chat-list.spec.js +1 -1
- package/e2e-legacy/ttyg/create-chat.spec.js +1 -1
- package/fixtures/connectors/get-connectors.json +0 -1
- package/fixtures/graph-navigator/graph-navigator-settings.ttl +148 -0
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/steps/graph-navigator-steps.js +3 -4
- package/steps/import/import-server-files-steps.js +8 -0
- package/steps/import/import-settings-dialog-steps.js +16 -0
- package/steps/import/import-steps.js +16 -3
- package/steps/import/import-user-data-steps.js +24 -24
- package/steps/repository-steps.js +9 -9
- package/steps/ttyg/ttyg-view-steps.js +1 -14
- package/stubs/license-stubs.js +0 -3
- package/e2e-legacy/home/solr-banner/solr-banner.spec.js +0 -137
- package/steps/deprecation-banner/deprecation-banner-steps.js +0 -13
- package/steps/deprecation-steps.js +0 -13
|
@@ -8,10 +8,24 @@ const NO_REPOSITORY_MESSAGE = 'you are not connected to any repository';
|
|
|
8
8
|
const INVALID_LICENSE_MESSAGE = 'your license is not valid';
|
|
9
9
|
const SELECT_OR_CREATE_REPOSITORY_MESSAGE = 'Select a repository below or create a new one.';
|
|
10
10
|
const SELECT_REPOSITORY_MESSAGE = 'Select a repository below.';
|
|
11
|
+
// TODO: Remove once GraphDB creates the system repository itself.
|
|
12
|
+
// The graph-navigator settings endpoint requires this repository.
|
|
13
|
+
const SYSTEM_REPOSITORY_ID = 'SystemRepository';
|
|
11
14
|
|
|
12
15
|
describe('Graph Navigator view restrictions', () => {
|
|
13
16
|
let repositoryId;
|
|
14
17
|
|
|
18
|
+
// TODO: Remove once GraphDB creates the system repository itself.
|
|
19
|
+
before(() => {
|
|
20
|
+
cy.deleteRepository(SYSTEM_REPOSITORY_ID);
|
|
21
|
+
cy.createRepository({id: SYSTEM_REPOSITORY_ID});
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// TODO: Remove once GraphDB creates the system repository itself.
|
|
25
|
+
after(() => {
|
|
26
|
+
cy.deleteRepository(SYSTEM_REPOSITORY_ID);
|
|
27
|
+
});
|
|
28
|
+
|
|
15
29
|
beforeEach(() => {
|
|
16
30
|
repositoryId = 'graph-navigator-view-restrictions-' + Date.now();
|
|
17
31
|
cy.createRepository({id: repositoryId});
|
|
@@ -9,13 +9,29 @@ import {ToasterSteps} from '../../steps/toaster-steps.js';
|
|
|
9
9
|
const FILE_TO_IMPORT = 'resource-test-data.ttl';
|
|
10
10
|
const SEED_RESOURCE_ENCODED = 'http:%2F%2Fexample.com%2Fontology%23CustomerLoyalty';
|
|
11
11
|
const SEED_RESOURCE_LABEL = 'CustomerLoyalty';
|
|
12
|
+
const SETTINGS_FILE_NAME = 'graph-navigator-settings.ttl';
|
|
13
|
+
const SETTINGS_FILE = `fixtures/graph-navigator/${SETTINGS_FILE_NAME}`;
|
|
12
14
|
|
|
13
15
|
const CONSTRUCT_QUERY = 'CONSTRUCT { <http://example.com/ontology#CustomerLoyalty> ?p ?o } WHERE { <http://example.com/ontology#CustomerLoyalty> ?p ?o }';
|
|
14
16
|
const CONSTRUCT_TARGET_LABEL = 'Metric';
|
|
17
|
+
// TODO: Remove once GraphDB creates the system repository itself.
|
|
18
|
+
// The graph-navigator settings endpoint requires this repository.
|
|
19
|
+
const SYSTEM_REPOSITORY_ID = 'SystemRepository';
|
|
15
20
|
|
|
16
21
|
describe('Graph Navigator', () => {
|
|
17
22
|
let repositoryId;
|
|
18
23
|
|
|
24
|
+
// TODO: Remove once GraphDB creates the system repository itself.
|
|
25
|
+
before(() => {
|
|
26
|
+
cy.deleteRepository(SYSTEM_REPOSITORY_ID);
|
|
27
|
+
cy.createRepository({id: SYSTEM_REPOSITORY_ID});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// TODO: Remove once GraphDB creates the system repository itself.
|
|
31
|
+
after(() => {
|
|
32
|
+
cy.deleteRepository(SYSTEM_REPOSITORY_ID);
|
|
33
|
+
});
|
|
34
|
+
|
|
19
35
|
beforeEach(() => {
|
|
20
36
|
repositoryId = 'repository-' + Date.now();
|
|
21
37
|
cy.createRepository({id: repositoryId});
|
|
@@ -48,6 +64,18 @@ describe('Graph Navigator', () => {
|
|
|
48
64
|
GraphNavigatorSteps.getElement(SEED_RESOURCE_LABEL).should('exist');
|
|
49
65
|
});
|
|
50
66
|
|
|
67
|
+
it('should show an error toast, when a graph request fails', () => {
|
|
68
|
+
// Given the repository's SPARQL requests fail.
|
|
69
|
+
cy.intercept('POST', `/repositories/${repositoryId}`, {statusCode: 500}).as('graphRequest');
|
|
70
|
+
|
|
71
|
+
// When I open the Graph Navigator view with a start resource.
|
|
72
|
+
GraphNavigatorSteps.visit(SEED_RESOURCE_ENCODED);
|
|
73
|
+
cy.wait('@graphRequest');
|
|
74
|
+
|
|
75
|
+
// Then I expect an error toast about the graph data.
|
|
76
|
+
ToasterSteps.getToasterMessage().should('contain', 'Could not load the graph data.');
|
|
77
|
+
});
|
|
78
|
+
|
|
51
79
|
it('should seed the canvas with the graph computed from a CONSTRUCT query', () => {
|
|
52
80
|
// Given I open the Graph Navigator view with a CONSTRUCT query, as sent from the SPARQL editor.
|
|
53
81
|
GraphNavigatorSteps.visitWithQuery(CONSTRUCT_QUERY);
|
|
@@ -124,7 +152,6 @@ describe('Graph Navigator', () => {
|
|
|
124
152
|
GraphNavigatorSteps.getElements().should('not.exist');
|
|
125
153
|
});
|
|
126
154
|
|
|
127
|
-
// These run against the in-code REST stub. TODO: GDB-15242 switch to intercepts when the endpoints are available.
|
|
128
155
|
describe('Settings', () => {
|
|
129
156
|
it('should open the settings popover', () => {
|
|
130
157
|
// Given I open the Graph Navigator view.
|
|
@@ -152,14 +179,14 @@ describe('Graph Navigator', () => {
|
|
|
152
179
|
// Given I have selected a settings file.
|
|
153
180
|
GraphNavigatorSteps.visit();
|
|
154
181
|
GraphNavigatorSteps.openSettings();
|
|
155
|
-
GraphNavigatorSteps.selectSettingsFile();
|
|
156
|
-
GraphNavigatorSteps.getSelectedSettingsFile().should('exist');
|
|
182
|
+
GraphNavigatorSteps.selectSettingsFile(SETTINGS_FILE);
|
|
183
|
+
GraphNavigatorSteps.getSelectedSettingsFile(SETTINGS_FILE_NAME).should('exist');
|
|
157
184
|
|
|
158
185
|
// When I cancel it.
|
|
159
186
|
GraphNavigatorSteps.clickCancelFile();
|
|
160
187
|
|
|
161
188
|
// Then I expect the file to be removed.
|
|
162
|
-
GraphNavigatorSteps.getSettingsPopover().should('not.contain',
|
|
189
|
+
GraphNavigatorSteps.getSettingsPopover().should('not.contain', SETTINGS_FILE_NAME);
|
|
163
190
|
GraphNavigatorSteps.getUploadButton().should('be.disabled');
|
|
164
191
|
});
|
|
165
192
|
|
|
@@ -167,7 +194,7 @@ describe('Graph Navigator', () => {
|
|
|
167
194
|
// Given I have selected a settings file.
|
|
168
195
|
GraphNavigatorSteps.visit();
|
|
169
196
|
GraphNavigatorSteps.openSettings();
|
|
170
|
-
GraphNavigatorSteps.selectSettingsFile();
|
|
197
|
+
GraphNavigatorSteps.selectSettingsFile(SETTINGS_FILE);
|
|
171
198
|
|
|
172
199
|
// When I upload it.
|
|
173
200
|
GraphNavigatorSteps.clickUpload();
|
|
@@ -181,7 +208,7 @@ describe('Graph Navigator', () => {
|
|
|
181
208
|
|
|
182
209
|
// Then I expect the popover to stay open with the file still selected.
|
|
183
210
|
GraphNavigatorSteps.getSettingsPopover().should('be.visible');
|
|
184
|
-
GraphNavigatorSteps.getSelectedSettingsFile().should('exist');
|
|
211
|
+
GraphNavigatorSteps.getSelectedSettingsFile(SETTINGS_FILE_NAME).should('exist');
|
|
185
212
|
|
|
186
213
|
// When I upload and confirm.
|
|
187
214
|
GraphNavigatorSteps.clickUpload();
|
|
@@ -196,7 +223,7 @@ describe('Graph Navigator', () => {
|
|
|
196
223
|
// Given the repository has uploaded settings.
|
|
197
224
|
GraphNavigatorSteps.visit();
|
|
198
225
|
GraphNavigatorSteps.openSettings();
|
|
199
|
-
GraphNavigatorSteps.selectSettingsFile();
|
|
226
|
+
GraphNavigatorSteps.selectSettingsFile(SETTINGS_FILE);
|
|
200
227
|
GraphNavigatorSteps.clickUpload();
|
|
201
228
|
GraphNavigatorSteps.confirmDialog();
|
|
202
229
|
ToasterSteps.verifySuccess('The settings were uploaded');
|
|
@@ -87,6 +87,39 @@ describe('Import server files - Batch operations', () => {
|
|
|
87
87
|
ImportServerFilesSteps.getSelectedResources().should('have.length', 0);
|
|
88
88
|
});
|
|
89
89
|
|
|
90
|
+
it('Should select all displayed resources with the select all checkbox', () => {
|
|
91
|
+
// When I check the select all checkbox
|
|
92
|
+
ImportServerFilesSteps.toggleSelectAllResources();
|
|
93
|
+
// Then I should see all files selected
|
|
94
|
+
ImportServerFilesSteps.getSelectedResources().should('have.length', SERVER_FILES_COUNT);
|
|
95
|
+
ImportServerFilesSteps.getSelectAllCheckbox().should('be.checked');
|
|
96
|
+
// When I uncheck the select all checkbox
|
|
97
|
+
ImportServerFilesSteps.toggleSelectAllResources();
|
|
98
|
+
// Then I should see no files selected
|
|
99
|
+
ImportServerFilesSteps.getSelectedResources().should('have.length', 0);
|
|
100
|
+
ImportServerFilesSteps.getSelectAllCheckbox().should('not.be.checked');
|
|
101
|
+
// When I select a directory via the checkbox on the row
|
|
102
|
+
ImportServerFilesSteps.selectFileByName('more-files');
|
|
103
|
+
// Then the select all checkbox should be partially selected
|
|
104
|
+
ImportServerFilesSteps.getSelectAllCheckbox().should('have.prop', 'indeterminate', true);
|
|
105
|
+
// When I check the select all checkbox
|
|
106
|
+
ImportServerFilesSteps.toggleSelectAllResources();
|
|
107
|
+
// Then I should see all files selected
|
|
108
|
+
ImportServerFilesSteps.getSelectedResources().should('have.length', SERVER_FILES_COUNT);
|
|
109
|
+
ImportServerFilesSteps.getSelectAllCheckbox().should('be.checked').and('have.prop', 'indeterminate', false);
|
|
110
|
+
// When I deselect all and filter the files by name
|
|
111
|
+
ImportServerFilesSteps.toggleSelectAllResources();
|
|
112
|
+
ImportServerFilesSteps.typeInFilterField('bnodes');
|
|
113
|
+
ImportServerFilesSteps.getResources().should('have.length', 1);
|
|
114
|
+
// and check the select all checkbox
|
|
115
|
+
ImportServerFilesSteps.toggleSelectAllResources();
|
|
116
|
+
// Then only the displayed file should be selected
|
|
117
|
+
ImportServerFilesSteps.clearFilterField();
|
|
118
|
+
ImportServerFilesSteps.getResources().should('have.length', SERVER_FILES_COUNT);
|
|
119
|
+
ImportServerFilesSteps.getSelectedResources().should('have.length', 1);
|
|
120
|
+
ImportServerFilesSteps.getSelectedResourceName(0).should('contain', 'bnodes.ttl');
|
|
121
|
+
});
|
|
122
|
+
|
|
90
123
|
it('Should perform batch import and reset of selected server files with changing settings', () => {
|
|
91
124
|
// Given I have opened the server files tab
|
|
92
125
|
// When I select couple of files for import
|
|
@@ -206,4 +206,22 @@ describe('Import server files', () => {
|
|
|
206
206
|
// Then: I expect the import button be enabled, because the "JSON-LD Context" is not mandatory field.
|
|
207
207
|
ImportSettingsDialogSteps.getImportButton().should('be.enabled');
|
|
208
208
|
});
|
|
209
|
+
|
|
210
|
+
it('should send the DOCTYPE declarations option with the import settings', () => {
|
|
211
|
+
// Given: The server files tab is loaded and the import requests are intercepted
|
|
212
|
+
ImportServerFilesSteps.interceptServerFilesImport(repositoryId);
|
|
213
|
+
|
|
214
|
+
// When: I open the import dialog for a file,
|
|
215
|
+
ImportServerFilesSteps.importResourceByName('bnodes.ttl');
|
|
216
|
+
ImportSettingsDialogSteps.expandAdvancedSettings();
|
|
217
|
+
// Then: I expect DOCTYPE declarations to be disallowed by default.
|
|
218
|
+
ImportSettingsDialogSteps.getDisallowDoctypeDeclCheckbox().should('be.checked');
|
|
219
|
+
|
|
220
|
+
// When: I allow DOCTYPE declarations and start the import
|
|
221
|
+
ImportSettingsDialogSteps.allowDoctypeDeclarations();
|
|
222
|
+
ImportSettingsDialogSteps.import();
|
|
223
|
+
// Then: I expect DOCTYPE declarations to be allowed in the request.
|
|
224
|
+
ImportServerFilesSteps.waitForServerFilesImportSettings()
|
|
225
|
+
.its('parserSettings.disallowDoctypeDecl').should('equal', false);
|
|
226
|
+
});
|
|
209
227
|
});
|
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import {ImportUserDataSteps} from "../../steps/import/import-user-data-steps";
|
|
2
|
+
import {ImportSettingsDialogSteps} from "../../steps/import/import-settings-dialog-steps";
|
|
2
3
|
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"ab:email": "richard491@hotmail.com"
|
|
12
|
-
});
|
|
4
|
+
const RDF_TEXT_SNIPPET = '<urn:s1> <urn:p1> <urn:o1>.';
|
|
5
|
+
const RDF_XML_WITH_DOCTYPE_SNIPPET = '<?xml version="1.0"?>\n' +
|
|
6
|
+
'<!DOCTYPE rdf:RDF [<!ENTITY ex "http://example.com/">]>\n' +
|
|
7
|
+
'<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:ex="http://example.com/">\n' +
|
|
8
|
+
' <rdf:Description rdf:about="&ex;subject"><ex:predicate>object</ex:predicate></rdf:Description>\n' +
|
|
9
|
+
'</rdf:RDF>';
|
|
10
|
+
const RDF_XML_FORMAT = 'RDF/XML';
|
|
11
|
+
const TEXT_SNIPPET = 'Text snippet';
|
|
13
12
|
|
|
14
13
|
describe('Import user data: Import settings dialog', () => {
|
|
15
14
|
|
|
@@ -31,6 +30,78 @@ describe('Import user data: Import settings dialog', () => {
|
|
|
31
30
|
cy.deleteRepository(repositoryId);
|
|
32
31
|
});
|
|
33
32
|
|
|
33
|
+
it('Should disallow DOCTYPE declarations by default', () => {
|
|
34
|
+
// Given I have opened the import settings dialog for a text snippet
|
|
35
|
+
ImportUserDataSteps.interceptTextSnippetImport(repositoryId);
|
|
36
|
+
ImportUserDataSteps.openTextSnippetImportSettings(RDF_TEXT_SNIPPET);
|
|
37
|
+
// When I expand the advanced settings
|
|
38
|
+
ImportSettingsDialogSteps.expandAdvancedSettings();
|
|
39
|
+
// Then the DOCTYPE declarations option should be checked
|
|
40
|
+
ImportSettingsDialogSteps.getDisallowDoctypeDeclCheckbox().should('be.checked');
|
|
41
|
+
// When I start the import
|
|
42
|
+
ImportSettingsDialogSteps.import();
|
|
43
|
+
// Then DOCTYPE declarations should be disallowed in the request
|
|
44
|
+
ImportUserDataSteps.waitForTextSnippetImportSettings()
|
|
45
|
+
.its('parserSettings.disallowDoctypeDecl').should('equal', true);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('Should allow DOCTYPE declarations when the option is unchecked', () => {
|
|
49
|
+
// Given I have opened the import settings dialog for a text snippet
|
|
50
|
+
ImportUserDataSteps.interceptTextSnippetImport(repositoryId);
|
|
51
|
+
ImportUserDataSteps.openTextSnippetImportSettings(RDF_TEXT_SNIPPET);
|
|
52
|
+
ImportSettingsDialogSteps.expandAdvancedSettings();
|
|
53
|
+
// When I uncheck the DOCTYPE declarations option and start the import
|
|
54
|
+
ImportSettingsDialogSteps.allowDoctypeDeclarations();
|
|
55
|
+
ImportSettingsDialogSteps.import();
|
|
56
|
+
// Then DOCTYPE declarations should be allowed in the request
|
|
57
|
+
ImportUserDataSteps.waitForTextSnippetImportSettings()
|
|
58
|
+
.its('parserSettings.disallowDoctypeDecl').should('equal', false);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
it('Should restore the DOCTYPE declarations option to its default', () => {
|
|
62
|
+
// Given I have opened the import settings dialog for a text snippet
|
|
63
|
+
ImportUserDataSteps.openTextSnippetImportSettings(RDF_TEXT_SNIPPET);
|
|
64
|
+
ImportSettingsDialogSteps.expandAdvancedSettings();
|
|
65
|
+
// And I have unchecked the DOCTYPE declarations option
|
|
66
|
+
ImportSettingsDialogSteps.allowDoctypeDeclarations();
|
|
67
|
+
ImportSettingsDialogSteps.getDisallowDoctypeDeclCheckbox().should('not.be.checked');
|
|
68
|
+
// When I restore the default settings
|
|
69
|
+
ImportSettingsDialogSteps.restoreDefaults();
|
|
70
|
+
// Then the DOCTYPE declarations option should be checked again
|
|
71
|
+
ImportSettingsDialogSteps.getDisallowDoctypeDeclCheckbox().should('be.checked');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('Should reject RDF/XML with a DOCTYPE declaration by default', () => {
|
|
75
|
+
// Given I have opened the import settings dialog for an RDF/XML snippet with a DOCTYPE declaration
|
|
76
|
+
ImportUserDataSteps.openTextSnippetImportSettings(RDF_XML_WITH_DOCTYPE_SNIPPET, RDF_XML_FORMAT);
|
|
77
|
+
// When I start the import with the default settings
|
|
78
|
+
ImportSettingsDialogSteps.import();
|
|
79
|
+
// Then the import should fail, because DOCTYPE declarations are disallowed
|
|
80
|
+
ImportUserDataSteps.checkImportedResourceByIndex(0, TEXT_SNIPPET, 'DOCTYPE is disallowed');
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it('Should import RDF/XML with a DOCTYPE declaration when DOCTYPE declarations are allowed', () => {
|
|
84
|
+
// Given I have opened the import settings dialog for an RDF/XML snippet with a DOCTYPE declaration
|
|
85
|
+
ImportUserDataSteps.openTextSnippetImportSettings(RDF_XML_WITH_DOCTYPE_SNIPPET, RDF_XML_FORMAT);
|
|
86
|
+
ImportSettingsDialogSteps.expandAdvancedSettings();
|
|
87
|
+
// When I allow DOCTYPE declarations and start the import
|
|
88
|
+
ImportSettingsDialogSteps.allowDoctypeDeclarations();
|
|
89
|
+
ImportSettingsDialogSteps.import();
|
|
90
|
+
// Then the import should succeed
|
|
91
|
+
ImportUserDataSteps.checkImportedResourceByIndex(0, TEXT_SNIPPET);
|
|
92
|
+
|
|
93
|
+
// When I open the import settings dialog for the same snippet again
|
|
94
|
+
ImportUserDataSteps.importFile(0);
|
|
95
|
+
ImportSettingsDialogSteps.expandAdvancedSettings();
|
|
96
|
+
// Then the saved DOCTYPE declarations option should be restored
|
|
97
|
+
ImportSettingsDialogSteps.getDisallowDoctypeDeclCheckbox().should('not.be.checked');
|
|
98
|
+
|
|
99
|
+
// When I restore the default settings
|
|
100
|
+
ImportSettingsDialogSteps.restoreDefaults();
|
|
101
|
+
// Then the DOCTYPE declarations option should be reset to the backend default, not to the saved value
|
|
102
|
+
ImportSettingsDialogSteps.getDisallowDoctypeDeclCheckbox().should('be.checked');
|
|
103
|
+
});
|
|
104
|
+
|
|
34
105
|
it.skip('Should prevent import when there are missing or invalid settings', () => {
|
|
35
106
|
// Given I have uploaded a file
|
|
36
107
|
|
|
@@ -9,7 +9,6 @@ describe('Import user data: URL import', () => {
|
|
|
9
9
|
const JSONLD_FORMAT = 'JSON-LD';
|
|
10
10
|
const VALID_URL_RDF_FORMAT = 'RDF/XML';
|
|
11
11
|
const RDF_ERROR_MESSAGE = 'RDF Parse Error:';
|
|
12
|
-
const IMPORT_JSONLD_URL = 'https://example.com/0007-context.jsonld';
|
|
13
12
|
|
|
14
13
|
beforeEach(() => {
|
|
15
14
|
repositoryId = 'user-import-' + Date.now();
|
|
@@ -54,17 +53,17 @@ describe('Import user data: URL import', () => {
|
|
|
54
53
|
});
|
|
55
54
|
|
|
56
55
|
|
|
57
|
-
|
|
58
|
-
it.skip('Test import file via URL successfully with Auto format selected', () => {
|
|
56
|
+
it('Test import file via URL successfully with Auto format selected', () => {
|
|
59
57
|
ImportUserDataSteps.openImportURLDialog(IMPORT_URL);
|
|
60
58
|
ImportUserDataSteps.clickImportUrlButton();
|
|
61
|
-
//
|
|
59
|
+
// wine.rdf contains a DOCTYPE declaration, which is disallowed by default
|
|
60
|
+
ImportSettingsDialogSteps.expandAdvancedSettings();
|
|
61
|
+
ImportSettingsDialogSteps.allowDoctypeDeclarations();
|
|
62
62
|
ImportSettingsDialogSteps.import();
|
|
63
63
|
ImportUserDataSteps.checkImportedResourceByIndex(0, IMPORT_URL);
|
|
64
64
|
});
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
it.skip('Test import file via URL with invalid RDF format selected', () => {
|
|
66
|
+
it('Test import file via URL with invalid RDF format selected', () => {
|
|
68
67
|
ImportUserDataSteps.openImportURLDialog(IMPORT_URL);
|
|
69
68
|
ImportUserDataSteps.selectRDFFormat(JSONLD_FORMAT);
|
|
70
69
|
ImportUserDataSteps.clickImportUrlButton();
|
|
@@ -72,11 +71,13 @@ describe('Import user data: URL import', () => {
|
|
|
72
71
|
ImportUserDataSteps.checkImportedResourceByIndex(0, IMPORT_URL, RDF_ERROR_MESSAGE);
|
|
73
72
|
});
|
|
74
73
|
|
|
75
|
-
|
|
76
|
-
it.skip('Test import file via URL successfully with valid RDF format selected', () => {
|
|
74
|
+
it('Test import file via URL successfully with valid RDF format selected', () => {
|
|
77
75
|
ImportUserDataSteps.openImportURLDialog(IMPORT_URL);
|
|
78
76
|
ImportUserDataSteps.selectRDFFormat(VALID_URL_RDF_FORMAT);
|
|
79
77
|
ImportUserDataSteps.clickImportUrlButton();
|
|
78
|
+
// wine.rdf contains a DOCTYPE declaration, which is disallowed by default
|
|
79
|
+
ImportSettingsDialogSteps.expandAdvancedSettings();
|
|
80
|
+
ImportSettingsDialogSteps.allowDoctypeDeclarations();
|
|
80
81
|
ImportSettingsDialogSteps.import();
|
|
81
82
|
ImportUserDataSteps.checkImportedResourceByIndex(0, IMPORT_URL);
|
|
82
83
|
});
|
|
@@ -287,7 +287,7 @@ describe('Ontop repositories', () => {
|
|
|
287
287
|
|
|
288
288
|
// WHEN: I log in as a user with maintenance permission
|
|
289
289
|
cy.loginAs(REPOSITORY_MAINTAINER_USERNAME, PASSWORD);
|
|
290
|
-
RepositorySteps.visit(
|
|
290
|
+
RepositorySteps.visit();
|
|
291
291
|
|
|
292
292
|
// THEN: The repository is visible because the user can maintain it
|
|
293
293
|
RepositorySteps.getRepositoryFromList(repositoryId).should('exist');
|
|
@@ -312,7 +312,7 @@ describe('Ontop repositories', () => {
|
|
|
312
312
|
ModalDialogSteps.clickOnConfirmButton();
|
|
313
313
|
|
|
314
314
|
// THEN: The changes are persisted
|
|
315
|
-
RepositorySteps.visit(
|
|
315
|
+
RepositorySteps.visit();
|
|
316
316
|
RepositorySteps.getRepositoryFromList(repositoryId).should('exist');
|
|
317
317
|
RepositorySteps.editRepository(repositoryId);
|
|
318
318
|
cy.wait('@getJDBCProperties');
|
|
@@ -348,7 +348,7 @@ describe('Ontop repositories', () => {
|
|
|
348
348
|
ModalDialogSteps.clickOnConfirmButton();
|
|
349
349
|
|
|
350
350
|
// THEN: The OBDA file changes are persisted
|
|
351
|
-
RepositorySteps.visit(
|
|
351
|
+
RepositorySteps.visit();
|
|
352
352
|
RepositorySteps.getRepositoryFromList(repositoryId).should('exist');
|
|
353
353
|
RepositorySteps.editRepository(repositoryId);
|
|
354
354
|
cy.wait('@getJDBCProperties');
|
package/e2e-legacy/setup/connectors/connectors-initial-state-with-selected-repository.spec.js
CHANGED
|
@@ -2,7 +2,7 @@ import {ConnectorsSteps} from "../../../steps/setup/connectors-steps";
|
|
|
2
2
|
import HomeSteps from "../../../steps/home-steps";
|
|
3
3
|
import {MainMenuSteps} from "../../../steps/main-menu-steps";
|
|
4
4
|
|
|
5
|
-
const expectedButtons = ['elasticsearch', 'opensearch', '
|
|
5
|
+
const expectedButtons = ['elasticsearch', 'opensearch', 'lucene', 'kafka', 'chatgpt-retrieval'];
|
|
6
6
|
|
|
7
7
|
function verifyConnectorsPage() {
|
|
8
8
|
expectedButtons.forEach(buttonId => {
|
|
@@ -18,7 +18,7 @@ describe('User and Access', () => {
|
|
|
18
18
|
const DEFAULT_ADMIN_PASSWORD = 'root';
|
|
19
19
|
|
|
20
20
|
context('User and access management', () => {
|
|
21
|
-
const user = 'user';
|
|
21
|
+
const user = 'user' + Date.now();
|
|
22
22
|
let repoName;
|
|
23
23
|
|
|
24
24
|
before(() => {
|
|
@@ -428,7 +428,7 @@ describe('User and Access', () => {
|
|
|
428
428
|
let repositoryId1;
|
|
429
429
|
let repositoryId2;
|
|
430
430
|
let repositoryId3;
|
|
431
|
-
const graphqlUser = 'graphqlUser';
|
|
431
|
+
const graphqlUser = 'graphqlUser' + Date.now();
|
|
432
432
|
|
|
433
433
|
beforeEach(() => {
|
|
434
434
|
RepositoriesStubs.spyGetRepositories();
|
|
@@ -649,7 +649,7 @@ describe('User and Access', () => {
|
|
|
649
649
|
let writeRepositoryId;
|
|
650
650
|
let graphQLOnlyRepositoryId;
|
|
651
651
|
let maintainedRepositoryId;
|
|
652
|
-
const maintainerUser = 'maintainerUser';
|
|
652
|
+
const maintainerUser = 'maintainerUser' + Date.now();
|
|
653
653
|
|
|
654
654
|
beforeEach(() => {
|
|
655
655
|
RepositoriesStubs.spyGetRepositories();
|
|
@@ -690,6 +690,8 @@ describe('User and Access', () => {
|
|
|
690
690
|
// 2. Read permission for one repository.
|
|
691
691
|
UserAndAccessSteps.openEditUserPage(maintainerUser);
|
|
692
692
|
cy.wait('@get-user');
|
|
693
|
+
// Wait until the loaded user is bound to the form, otherwise toggling a right fails.
|
|
694
|
+
UserAndAccessSteps.getUsernameField().should('have.value', maintainerUser);
|
|
693
695
|
setUserAuths({repo: readRepositoryId, read: true});
|
|
694
696
|
// 3. Write permission for one repository.
|
|
695
697
|
setUserAuths({repo: writeRepositoryId, write: true});
|
|
@@ -700,8 +702,10 @@ describe('User and Access', () => {
|
|
|
700
702
|
// When I log in as a user with repository maintain permission.
|
|
701
703
|
UserAndAccessSteps.toggleSecurity();
|
|
702
704
|
LoginSteps.loginWithUser(maintainerUser, PASSWORD);
|
|
705
|
+
// Wait for the login to complete, otherwise visiting another page aborts it.
|
|
706
|
+
cy.url().should('not.include', '/login');
|
|
703
707
|
// And navigate to the repository list view.
|
|
704
|
-
RepositorySteps.visit(
|
|
708
|
+
RepositorySteps.visit();
|
|
705
709
|
|
|
706
710
|
// Then I should see all repositories for which the user has at least read permission.
|
|
707
711
|
RepositorySteps.getRepositories().should('have.length', 4);
|
|
@@ -760,7 +764,9 @@ describe('User and Access', () => {
|
|
|
760
764
|
createUser(maintainerUser, PASSWORD, ROLE_USER, {maintain: true, repoName: maintainedRepositoryId});
|
|
761
765
|
UserAndAccessSteps.toggleSecurity();
|
|
762
766
|
LoginSteps.loginWithUser(maintainerUser, PASSWORD);
|
|
763
|
-
|
|
767
|
+
// Wait for the login to complete, otherwise visiting another page aborts it.
|
|
768
|
+
cy.url().should('not.include', '/login');
|
|
769
|
+
RepositorySteps.visit();
|
|
764
770
|
|
|
765
771
|
// When the user opens the edit page of the repository they can maintain.
|
|
766
772
|
RepositorySteps.getEditRepositoryButton(maintainedRepositoryId).should('be.visible');
|
|
@@ -230,7 +230,7 @@ describe('TTYG chat list', () => {
|
|
|
230
230
|
HomeSteps.visit();
|
|
231
231
|
cy.wait('@get-chat');
|
|
232
232
|
// and came back to the ttyg page
|
|
233
|
-
TTYGViewSteps.visit(
|
|
233
|
+
TTYGViewSteps.visit();
|
|
234
234
|
|
|
235
235
|
// Then I expect to last used chat be selected.
|
|
236
236
|
TTYGViewSteps.getChatFromGroup(0, 2).should('have.class', 'selected');
|
|
@@ -61,7 +61,7 @@ describe('TTYG create chat', () => {
|
|
|
61
61
|
// and returns to the TTYG page
|
|
62
62
|
TTYGStubs.stubChatsListGet("/ttyg/chats/create/get-chats-after-create.json");
|
|
63
63
|
TTYGStubs.stubAgentGet();
|
|
64
|
-
TTYGViewSteps.visit(
|
|
64
|
+
TTYGViewSteps.visit();
|
|
65
65
|
cy.wait('@get-chat-list');
|
|
66
66
|
// Then I expect newly created chat be selected.
|
|
67
67
|
TTYGViewSteps.getChatFromGroup(0, 0).should('contain', 'New chat of Han Solo is a character');
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"Elasticsearch": "http://www.ontotext.com/connectors/elasticsearch#",
|
|
3
3
|
"OpenSearch": "http://www.ontotext.com/connectors/opensearch#",
|
|
4
|
-
"Solr": "http://www.ontotext.com/connectors/solr#",
|
|
5
4
|
"Lucene": "http://www.ontotext.com/connectors/lucene#",
|
|
6
5
|
"Kafka": "http://www.ontotext.com/connectors/kafka#",
|
|
7
6
|
"ChatGPT Retrieval": "http://www.ontotext.com/connectors/retrieval#"
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
@prefix gn: <http://www.ontotext.com/graph-navigator#> .
|
|
2
|
+
|
|
3
|
+
gn:settings gn:defaultPrefix """PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
|
4
|
+
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
|
|
5
|
+
PREFIX owl: <http://www.w3.org/2002/07/owl#>
|
|
6
|
+
""";
|
|
7
|
+
gn:schemaLabelProperty "rdfs:label";
|
|
8
|
+
gn:dataLabelProperty "rdfs:label";
|
|
9
|
+
gn:classTreeQuery """
|
|
10
|
+
SELECT ?class ?label ?parent
|
|
11
|
+
WHERE {
|
|
12
|
+
{
|
|
13
|
+
?class a rdfs:Class
|
|
14
|
+
} UNION {
|
|
15
|
+
?class a owl:Class
|
|
16
|
+
}
|
|
17
|
+
FILTER ISIRI(?class)
|
|
18
|
+
OPTIONAL {
|
|
19
|
+
?class rdfs:label ?label
|
|
20
|
+
${labelLanguageFilter}
|
|
21
|
+
}
|
|
22
|
+
OPTIONAL {?class rdfs:subClassOf ?parent. FILTER ISIRI(?parent)}
|
|
23
|
+
}
|
|
24
|
+
""";
|
|
25
|
+
gn:classInfoQuery """SELECT ?class ?label ?instcount WHERE {
|
|
26
|
+
VALUES(?class) {${ids}}
|
|
27
|
+
OPTIONAL {
|
|
28
|
+
?class ${schemaLabelProperty} ?label
|
|
29
|
+
${labelLanguageFilter}
|
|
30
|
+
}
|
|
31
|
+
BIND(\"\" as ?instcount)
|
|
32
|
+
}""";
|
|
33
|
+
gn:linkTypesQuery """SELECT DISTINCT ?link ?instcount ?label WHERE {
|
|
34
|
+
${linkTypesPattern}
|
|
35
|
+
OPTIONAL {
|
|
36
|
+
?link ${schemaLabelProperty} ?label
|
|
37
|
+
${labelLanguageFilter}
|
|
38
|
+
}
|
|
39
|
+
}""";
|
|
40
|
+
gn:linkTypesPattern """
|
|
41
|
+
{ ?link a rdf:Property }
|
|
42
|
+
UNION
|
|
43
|
+
{ ?link a owl:ObjectProperty }
|
|
44
|
+
BIND('' as ?instcount)
|
|
45
|
+
""";
|
|
46
|
+
gn:linkTypesInfoQuery """SELECT ?link ?label WHERE {
|
|
47
|
+
VALUES(?link) {${ids}}
|
|
48
|
+
OPTIONAL {
|
|
49
|
+
?link ${schemaLabelProperty} ?label
|
|
50
|
+
${labelLanguageFilter}
|
|
51
|
+
}
|
|
52
|
+
}""";
|
|
53
|
+
gn:propertyInfoQuery """SELECT ?property ?label WHERE {
|
|
54
|
+
VALUES(?property) {${ids}}
|
|
55
|
+
OPTIONAL {
|
|
56
|
+
?property ${schemaLabelProperty} ?label
|
|
57
|
+
${labelLanguageFilter}
|
|
58
|
+
}
|
|
59
|
+
}""";
|
|
60
|
+
gn:elementInfoQuery """
|
|
61
|
+
CONSTRUCT {
|
|
62
|
+
?inst <urn:reactodia:sparql:type> ?class .
|
|
63
|
+
?inst <urn:reactodia:sparql:label> ?label .
|
|
64
|
+
?inst ?propType ?propValue.
|
|
65
|
+
} WHERE {
|
|
66
|
+
VALUES (?inst) {${ids}}
|
|
67
|
+
OPTIONAL { ?inst a ?class }
|
|
68
|
+
OPTIONAL {
|
|
69
|
+
?inst ${dataLabelProperty} ?label
|
|
70
|
+
${labelLanguageFilter}
|
|
71
|
+
}
|
|
72
|
+
OPTIONAL {
|
|
73
|
+
${propertyConfigurations}
|
|
74
|
+
FILTER (isLiteral(?propValue))
|
|
75
|
+
${valueLanguageFilter}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
""";
|
|
79
|
+
gn:linksInfoQuery """SELECT ?source ?type ?target
|
|
80
|
+
WHERE {
|
|
81
|
+
${linkConfigurations}
|
|
82
|
+
VALUES (?source) {${sourceIris}}
|
|
83
|
+
VALUES (?target) {${targetIris}}
|
|
84
|
+
}""";
|
|
85
|
+
gn:imageQueryPattern "{ ?inst ?linkType ?image } UNION { [] ?linkType ?inst. BIND(?inst as ?image) }";
|
|
86
|
+
gn:linkTypesOfQuery """
|
|
87
|
+
SELECT DISTINCT ?link ?direction
|
|
88
|
+
WHERE {
|
|
89
|
+
${linkConfigurations}
|
|
90
|
+
}
|
|
91
|
+
""";
|
|
92
|
+
gn:linkTypesStatisticsQuery """
|
|
93
|
+
SELECT ?link ?outCount ?inCount
|
|
94
|
+
WHERE {
|
|
95
|
+
{
|
|
96
|
+
SELECT (${linkId} as ?link) (count(?outObject) as ?outCount) WHERE {
|
|
97
|
+
${linkConfigurationOut}
|
|
98
|
+
${navigateElementFilterOut}
|
|
99
|
+
} LIMIT 101
|
|
100
|
+
} {
|
|
101
|
+
SELECT (${linkId} as ?link) (count(?inObject) as ?inCount) WHERE {
|
|
102
|
+
${linkConfigurationIn}
|
|
103
|
+
${navigateElementFilterIn}
|
|
104
|
+
} LIMIT 101
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
""";
|
|
108
|
+
gn:lookupQuery """SELECT ${outerProjection} WHERE {
|
|
109
|
+
${filterInnerPrelude}
|
|
110
|
+
{
|
|
111
|
+
SELECT DISTINCT ${innerProjection} WHERE {
|
|
112
|
+
${filterByType}
|
|
113
|
+
${filterByRefElementLink}
|
|
114
|
+
${filterByText}
|
|
115
|
+
${filterAdditionalRestriction}
|
|
116
|
+
} ${orderBy} ${limit}
|
|
117
|
+
}
|
|
118
|
+
${queryTypes}
|
|
119
|
+
${queryElementInfo}
|
|
120
|
+
} ${orderBy}""";
|
|
121
|
+
gn:filterInnerPrelude "";
|
|
122
|
+
gn:filterRefElementLinkPattern "";
|
|
123
|
+
gn:filterTypePattern "?inst a ?instType. ?instType rdfs:subClassOf* ?class";
|
|
124
|
+
gn:filterElementInfoPattern """
|
|
125
|
+
OPTIONAL {?inst rdf:type ?foundClass}
|
|
126
|
+
BIND (coalesce(?foundClass, owl:Thing) as ?class)
|
|
127
|
+
OPTIONAL {
|
|
128
|
+
?inst ${dataLabelProperty} ?label
|
|
129
|
+
${labelLanguageFilter}
|
|
130
|
+
}
|
|
131
|
+
""";
|
|
132
|
+
gn:filterAdditionalRestriction "";
|
|
133
|
+
gn:openWorldLinks false;
|
|
134
|
+
gn:openWorldProperties false;
|
|
135
|
+
gn:acceptBlankNodes false;
|
|
136
|
+
gn:blankNodeStatementLimit "20"^^<http://www.w3.org/2001/XMLSchema#int>;
|
|
137
|
+
gn:filterOnlyLanguages [ a <http://www.w3.org/1999/02/22-rdf-syntax-ns#List>;
|
|
138
|
+
<http://www.w3.org/1999/02/22-rdf-syntax-ns#first> "en";
|
|
139
|
+
<http://www.w3.org/1999/02/22-rdf-syntax-ns#rest> <http://www.w3.org/1999/02/22-rdf-syntax-ns#nil>
|
|
140
|
+
];
|
|
141
|
+
gn:fullTextSearch [
|
|
142
|
+
gn:prefix "";
|
|
143
|
+
gn:queryPattern """?inst ${dataLabelProperty} ?search1
|
|
144
|
+
FILTER regex(COALESCE(str(?search1)), \"${text}\", \"i\")
|
|
145
|
+
BIND(0 as ?score)
|
|
146
|
+
""";
|
|
147
|
+
gn:extractLabel true
|
|
148
|
+
] .
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "graphdb-workbench-tests",
|
|
3
|
-
"version": "4.0.0-
|
|
3
|
+
"version": "4.0.0-TR14",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "graphdb-workbench-tests",
|
|
9
|
-
"version": "4.0.0-
|
|
9
|
+
"version": "4.0.0-TR14",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"devDependencies": {
|
|
12
12
|
"@bahmutov/cypress-code-coverage": "^2.7.2",
|
package/package.json
CHANGED
|
@@ -64,13 +64,12 @@ export class GraphNavigatorSteps extends BaseSteps {
|
|
|
64
64
|
return this.getByTestId('graph-navigator-settings-upload').find('.p-fileupload-choose-button input[type=file]');
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
static selectSettingsFile(
|
|
67
|
+
static selectSettingsFile(file) {
|
|
68
68
|
// PrimeNG hides the file input (display: none), so force is needed to select a file on it.
|
|
69
|
-
this.getSettingsFileInput()
|
|
70
|
-
.selectFile({contents: Cypress.Buffer.from(contents), fileName, mimeType: 'text/turtle'}, {force: true});
|
|
69
|
+
this.getSettingsFileInput().selectFile(file, {force: true});
|
|
71
70
|
}
|
|
72
71
|
|
|
73
|
-
static getSelectedSettingsFile(fileName
|
|
72
|
+
static getSelectedSettingsFile(fileName) {
|
|
74
73
|
return GraphNavigatorSteps.getSettingsPopover().contains(fileName);
|
|
75
74
|
}
|
|
76
75
|
|
|
@@ -10,6 +10,14 @@ export class ImportServerFilesSteps extends ImportSteps {
|
|
|
10
10
|
return this.getView().find('.server-files-import-help');
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
static interceptServerFilesImport(repositoryId) {
|
|
14
|
+
cy.intercept('POST', `/rest/repositories/${repositoryId}/import/server`).as('importServerFiles');
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static waitForServerFilesImportSettings() {
|
|
18
|
+
return cy.wait('@importServerFiles').its('request.body.importSettings');
|
|
19
|
+
}
|
|
20
|
+
|
|
13
21
|
static getSelectedTypeFilterButton() {
|
|
14
22
|
return this.getResourcesTable().find('.import-resource-type-filter .active');
|
|
15
23
|
}
|
|
@@ -64,6 +64,22 @@ export class ImportSettingsDialogSteps extends ModalDialogSteps {
|
|
|
64
64
|
this.getSettingsForm().find('input[name="preserveBNodeIDs"]').check();
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
+
static getDisallowDoctypeDeclCheckbox() {
|
|
68
|
+
return this.getSettingsForm().find('input[name="disallowDoctypeDecl"]');
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
static allowDoctypeDeclarations() {
|
|
72
|
+
this.getDisallowDoctypeDeclCheckbox().uncheck();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
static getRestoreDefaultsButton() {
|
|
76
|
+
return this.getDialog().find('.restore-defaults-btn');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
static restoreDefaults() {
|
|
80
|
+
this.getRestoreDefaultsButton().click();
|
|
81
|
+
}
|
|
82
|
+
|
|
67
83
|
static fillContextLink(contextLink) {
|
|
68
84
|
this.getSettingsForm().find('input[name="contextLink"]').type(contextLink).should('have.value', contextLink);
|
|
69
85
|
}
|
|
@@ -92,6 +92,10 @@ class ImportSteps {
|
|
|
92
92
|
return this.getFilterField().type(query);
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
static clearFilterField() {
|
|
96
|
+
return this.getFilterField().clear();
|
|
97
|
+
}
|
|
98
|
+
|
|
95
99
|
static getTabs() {
|
|
96
100
|
return this.getView().find('.nav-tabs .nav-item');
|
|
97
101
|
}
|
|
@@ -266,7 +270,16 @@ class ImportSteps {
|
|
|
266
270
|
}
|
|
267
271
|
|
|
268
272
|
static openStatusSelectMenu() {
|
|
269
|
-
|
|
273
|
+
this.getStatusSelectMenuToggle().click();
|
|
274
|
+
return this.getStatusSelectMenu().find('.dropdown-menu .dropdown-item');
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
static getSelectAllCheckbox() {
|
|
278
|
+
return this.getStatusSelectMenu().find('.select-all-checkbox');
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
static toggleSelectAllResources() {
|
|
282
|
+
this.getSelectAllCheckbox().click();
|
|
270
283
|
}
|
|
271
284
|
|
|
272
285
|
static selectAllResources() {
|
|
@@ -339,7 +352,7 @@ class ImportSteps {
|
|
|
339
352
|
}
|
|
340
353
|
|
|
341
354
|
static openFileUploadDialog() {
|
|
342
|
-
this.getUploadRdfFilesButton().
|
|
355
|
+
this.getUploadRdfFilesButton().click();
|
|
343
356
|
}
|
|
344
357
|
|
|
345
358
|
static selectFile(files) {
|
|
@@ -518,7 +531,7 @@ class ImportSteps {
|
|
|
518
531
|
}
|
|
519
532
|
|
|
520
533
|
static orderBySize() {
|
|
521
|
-
ImportSteps.getSizeCell().click();
|
|
534
|
+
ImportSteps.getSizeCell().find('button').click();
|
|
522
535
|
}
|
|
523
536
|
}
|
|
524
537
|
|
|
@@ -15,9 +15,9 @@ export class ImportUserDataSteps extends ImportSteps {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
static openImportTextSnippetDialog() {
|
|
18
|
-
cy.get('#import-user .import-rdf-snippet-btn').click()
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
cy.get('#import-user .import-rdf-snippet-btn').click();
|
|
19
|
+
// Forces the popover to disappear as it covers the modal and Cypress refuses to continue
|
|
20
|
+
cy.get('#import-user .import-rdf-snippet-btn').trigger('mouseleave', {force: true});
|
|
21
21
|
this.getModal().find('#wb-import-textarea').should('be.visible');
|
|
22
22
|
return this;
|
|
23
23
|
}
|
|
@@ -34,7 +34,8 @@ export class ImportUserDataSteps extends ImportSteps {
|
|
|
34
34
|
static selectRDFFormat(rdfFormat) {
|
|
35
35
|
cy.get('.modal-footer .import-format-dropdown').within(() => {
|
|
36
36
|
cy.get('.import-format-dropdown-btn').click();
|
|
37
|
-
cy.get('.dropdown-item').contains(rdfFormat).click()
|
|
37
|
+
cy.get('.dropdown-item').contains(rdfFormat).click();
|
|
38
|
+
cy.get('.dropdown-item').contains(rdfFormat).should('not.be.visible');
|
|
38
39
|
});
|
|
39
40
|
return this;
|
|
40
41
|
}
|
|
@@ -48,6 +49,24 @@ export class ImportUserDataSteps extends ImportSteps {
|
|
|
48
49
|
cy.intercept('POST', `/rest/repositories/${repositoryId}/import/upload/url`).as('postJsonldUrl');
|
|
49
50
|
}
|
|
50
51
|
|
|
52
|
+
static openTextSnippetImportSettings(snippet, rdfFormat) {
|
|
53
|
+
this.openImportTextSnippetDialog();
|
|
54
|
+
this.pasteRDFTextSnippet(snippet);
|
|
55
|
+
if (rdfFormat) {
|
|
56
|
+
this.selectRDFFormat(rdfFormat);
|
|
57
|
+
}
|
|
58
|
+
this.clickImportTextSnippetButton();
|
|
59
|
+
return this;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
static interceptTextSnippetImport(repositoryId) {
|
|
63
|
+
cy.intercept('POST', `/rest/repositories/${repositoryId}/import/upload/text`).as('importTextSnippet');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
static waitForTextSnippetImportSettings() {
|
|
67
|
+
return cy.wait('@importTextSnippet').its('request.body');
|
|
68
|
+
}
|
|
69
|
+
|
|
51
70
|
static getErrors() {
|
|
52
71
|
return cy.get('.text-danger');
|
|
53
72
|
}
|
|
@@ -64,30 +83,11 @@ export class ImportUserDataSteps extends ImportSteps {
|
|
|
64
83
|
return this.getModal().find('#wb-import-textarea');
|
|
65
84
|
}
|
|
66
85
|
|
|
67
|
-
static getImportFromDataRadioButton() {
|
|
68
|
-
return this.getModal().find('#wb-import-from-data');
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
static getImportInDefaultGraphRadioButton() {
|
|
72
|
-
return this.getModal().find('#wb-import-in-default-graph');
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
static getExistingDataReplacementCheckbox() {
|
|
76
|
-
return this.getModal().find('#wb-import-existing-data-replacement');
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
static getReplacedGraphsInputField() {
|
|
80
|
-
return this.getModal().find('#wb-import-replaced-graphs');
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
static getAddGraphToReplaceButton() {
|
|
84
|
-
return this.getModal().find('#wb-import-add-graph-to-replace');
|
|
85
|
-
}
|
|
86
|
-
|
|
87
86
|
//verifies that the data has been inserted in the given graph and that the new data has replaced the old one.
|
|
88
87
|
static verifyGraphData(graphName, s, p, o, c, checkForReplacedData, oldData) {
|
|
89
88
|
cy.visit('/graphs');
|
|
90
89
|
// wait a bit to give chance page loaded.
|
|
90
|
+
// eslint-disable-next-line cypress/no-unnecessary-waiting
|
|
91
91
|
cy.wait(1000);
|
|
92
92
|
cy.get(`#export-graphs td a:contains(${graphName})`).click();
|
|
93
93
|
cy.get(`.uri-cell:contains(${s})`).should('be.visible');
|
|
@@ -3,17 +3,14 @@ import {BaseSteps} from "./base-steps.js";
|
|
|
3
3
|
|
|
4
4
|
export class RepositorySteps extends BaseSteps {
|
|
5
5
|
|
|
6
|
-
static visit(
|
|
6
|
+
static visit() {
|
|
7
7
|
cy.intercept('/rest/locations').as('getLocations');
|
|
8
8
|
cy.intercept(REPOSITORIES_URL + '/all').as('getRepositories');
|
|
9
9
|
cy.visit('/repository');
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
RepositorySteps.waitUntilRepositoriesPageIsLoaded();
|
|
11
|
+
// Consumes the initial locations request, so a later cy.wait('@getLocations') in a test matches the next one.
|
|
12
|
+
// It must stay after the page-loaded check, which has a longer timeout than cy.wait for the request to start.
|
|
13
13
|
cy.wait('@getLocations');
|
|
14
|
-
if (waitPageLoaded) {
|
|
15
|
-
RepositorySteps.waitUntilRepositoriesPageIsLoaded();
|
|
16
|
-
}
|
|
17
14
|
}
|
|
18
15
|
|
|
19
16
|
static visitEditPage(repositoryId) {
|
|
@@ -36,9 +33,12 @@ export class RepositorySteps extends BaseSteps {
|
|
|
36
33
|
return cy.get('#wb-repositories-addRepositoryLink');
|
|
37
34
|
}
|
|
38
35
|
|
|
36
|
+
// The page loader is hidden once the locations are loaded, regardless of the user's role.
|
|
39
37
|
static waitUntilRepositoriesPageIsLoaded() {
|
|
40
|
-
RepositorySteps.
|
|
41
|
-
|
|
38
|
+
RepositorySteps.getRepositoriesPage()
|
|
39
|
+
.should('be.visible')
|
|
40
|
+
.find('.ot-loader-new-content')
|
|
41
|
+
.should('not.be.visible');
|
|
42
42
|
}
|
|
43
43
|
|
|
44
44
|
static getRepositoriesDropdown() {
|
|
@@ -1,21 +1,8 @@
|
|
|
1
1
|
import {BaseSteps} from "../base-steps";
|
|
2
|
-
import {DeprecationSteps} from '../deprecation-banner/deprecation-banner-steps.js';
|
|
3
2
|
|
|
4
3
|
export class TTYGViewSteps extends BaseSteps {
|
|
5
|
-
|
|
6
|
-
* Visits the TTYG page and closes the Solr deprecation banner by default.
|
|
7
|
-
*
|
|
8
|
-
* @param {boolean} closeSolrBanner Whether to close the banner. Set to `false`
|
|
9
|
-
* when revisiting the page after the banner has already been closed.
|
|
10
|
-
*/
|
|
11
|
-
static visit(closeSolrBanner = true) {
|
|
4
|
+
static visit() {
|
|
12
5
|
cy.visit('/ttyg');
|
|
13
|
-
// Temporary workaround until the Solr deprecation banner is removed.
|
|
14
|
-
// The banner changes the page layout, causing tests to fail randomly.
|
|
15
|
-
// This quick fix prevents GraphDB build failures and should be deleted together with the banner.
|
|
16
|
-
if (closeSolrBanner) {
|
|
17
|
-
DeprecationSteps.closeBanner();
|
|
18
|
-
}
|
|
19
6
|
}
|
|
20
7
|
|
|
21
8
|
static getTtygView() {
|
package/stubs/license-stubs.js
CHANGED
|
@@ -50,7 +50,6 @@ export class LicenseStubs {
|
|
|
50
50
|
"productType": "enterprise",
|
|
51
51
|
"licenseCapabilities": [
|
|
52
52
|
"Lucene connector",
|
|
53
|
-
"Solr connector",
|
|
54
53
|
"Elasticsearch connector",
|
|
55
54
|
"OpenSearch connector",
|
|
56
55
|
"Kafka connector",
|
|
@@ -114,7 +113,6 @@ export class LicenseStubs {
|
|
|
114
113
|
"OpenSearch connector",
|
|
115
114
|
"Lucene connector",
|
|
116
115
|
"Kafka connector",
|
|
117
|
-
"Solr connector",
|
|
118
116
|
"Cluster",
|
|
119
117
|
"Elasticsearch connector"
|
|
120
118
|
],
|
|
@@ -140,7 +138,6 @@ export class LicenseStubs {
|
|
|
140
138
|
"OpenSearch connector",
|
|
141
139
|
"Lucene connector",
|
|
142
140
|
"Kafka connector",
|
|
143
|
-
"Solr connector",
|
|
144
141
|
"Cluster",
|
|
145
142
|
"Elasticsearch connector"
|
|
146
143
|
],
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
import HomeSteps from '../../../steps/home-steps.js';
|
|
2
|
-
import {DeprecationSteps} from '../../../steps/deprecation-steps.js';
|
|
3
|
-
import {LoginSteps} from '../../../steps/login-steps.js';
|
|
4
|
-
import {GuidesStubs} from '../../../stubs/guides/guides-stubs.js';
|
|
5
|
-
import {GuideSteps} from '../../../steps/guides/guide-steps.js';
|
|
6
|
-
import {GuideDialogSteps} from '../../../steps/guides/guide-dialog-steps.js';
|
|
7
|
-
|
|
8
|
-
describe('Solr deprecation banner', () => {
|
|
9
|
-
context('Security disabled', () => {
|
|
10
|
-
it('should keep the Solr deprecation banner hidden after the anonymous user dismisses it', () => {
|
|
11
|
-
// GIVEN: I have opened the application with security disabled.
|
|
12
|
-
HomeSteps.visit();
|
|
13
|
-
|
|
14
|
-
// THEN: I expect the Solr deprecation banner to be visible.
|
|
15
|
-
DeprecationSteps.getDeprecationBanner()
|
|
16
|
-
.should('be.visible')
|
|
17
|
-
.should('contain.text', 'The Solr connector is deprecated and will be removed in GraphDB 12');
|
|
18
|
-
|
|
19
|
-
// WHEN: I dismiss the Solr deprecation banner.
|
|
20
|
-
DeprecationSteps.closeBanner();
|
|
21
|
-
// THEN: I expect the Solr deprecation banner to be hidden.
|
|
22
|
-
DeprecationSteps.getDeprecationBanner().should('not.exist');
|
|
23
|
-
|
|
24
|
-
// WHEN: I reload the application.
|
|
25
|
-
HomeSteps.visit();
|
|
26
|
-
// THEN: I expect the Solr deprecation banner to remain hidden.
|
|
27
|
-
DeprecationSteps.getDeprecationBanner().should('not.exist');
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
context('Security enabled', () => {
|
|
32
|
-
const PASSWORD = 'root';
|
|
33
|
-
const USER_USERNAME = 'username';
|
|
34
|
-
|
|
35
|
-
beforeEach(() => {
|
|
36
|
-
cy.createUser({
|
|
37
|
-
username: USER_USERNAME,
|
|
38
|
-
password: PASSWORD
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
cy.switchOnSecurity()
|
|
42
|
-
.then(() => cy.loginAsAdmin())
|
|
43
|
-
.then(() => cy.switchOnFreeAccess(true));
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
afterEach(() => {
|
|
47
|
-
cy.loginAsAdmin()
|
|
48
|
-
.then(() => {
|
|
49
|
-
cy.deleteUser(USER_USERNAME, true);
|
|
50
|
-
cy.switchOffFreeAccess(true);
|
|
51
|
-
cy.switchOffSecurity(true);
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it('should persist separate Solr banner states for anonymous and logged-in users', () => {
|
|
56
|
-
// GIVEN: Security and free access are enabled, and no user is logged in.
|
|
57
|
-
HomeSteps.visit();
|
|
58
|
-
|
|
59
|
-
// THEN: I expect the Solr deprecation banner to be visible for the anonymous user.
|
|
60
|
-
DeprecationSteps.getDeprecationBanner()
|
|
61
|
-
.should('be.visible')
|
|
62
|
-
.should('contain.text', 'The Solr connector is deprecated and will be removed in GraphDB 12');
|
|
63
|
-
|
|
64
|
-
// WHEN: The anonymous user dismisses the banner.
|
|
65
|
-
DeprecationSteps.closeBanner();
|
|
66
|
-
// THEN: I expect the banner to be hidden for the anonymous user.
|
|
67
|
-
DeprecationSteps.getDeprecationBanner().should('not.exist');
|
|
68
|
-
|
|
69
|
-
// WHEN: I log in as a user who has not dismissed the banner.
|
|
70
|
-
cy.loginAs(USER_USERNAME, PASSWORD);
|
|
71
|
-
HomeSteps.visit();
|
|
72
|
-
|
|
73
|
-
// THEN: I expect the banner to be visible for the logged-in user.
|
|
74
|
-
DeprecationSteps.getDeprecationBanner()
|
|
75
|
-
.should('be.visible')
|
|
76
|
-
.should('contain.text', 'The Solr connector is deprecated and will be removed in GraphDB 12');
|
|
77
|
-
|
|
78
|
-
// WHEN: The logged-in user dismisses the banner.
|
|
79
|
-
DeprecationSteps.closeBanner();
|
|
80
|
-
// THEN: I expect the banner to be hidden for the logged-in user.
|
|
81
|
-
DeprecationSteps.getDeprecationBanner().should('not.exist');
|
|
82
|
-
|
|
83
|
-
// WHEN: The user logs out.
|
|
84
|
-
LoginSteps.logout();
|
|
85
|
-
// THEN: I expect the banner to remain hidden because the anonymous user has already dismissed it.
|
|
86
|
-
DeprecationSteps.getDeprecationBanner().should('not.exist');
|
|
87
|
-
|
|
88
|
-
// WHEN: I log in as the administrator, who has not dismissed the banner.
|
|
89
|
-
cy.loginAs('admin', 'root');
|
|
90
|
-
HomeSteps.visit();
|
|
91
|
-
// THEN: I expect the banner to be visible for the administrator.
|
|
92
|
-
DeprecationSteps.getDeprecationBanner()
|
|
93
|
-
.should('be.visible')
|
|
94
|
-
.should('contain.text', 'The Solr connector is deprecated and will be removed in GraphDB 12');
|
|
95
|
-
|
|
96
|
-
// WHEN: The administrator logs out.
|
|
97
|
-
LoginSteps.logout();
|
|
98
|
-
// THEN: I expect the banner to remain hidden because the anonymous user has already dismissed it.
|
|
99
|
-
DeprecationSteps.getDeprecationBanner().should('not.exist');
|
|
100
|
-
|
|
101
|
-
// WHEN: I log in again as the user who previously dismissed the banner.
|
|
102
|
-
cy.loginAs(USER_USERNAME, PASSWORD);
|
|
103
|
-
HomeSteps.visit();
|
|
104
|
-
// THEN: I expect the banner to remain hidden for the logged-in user.
|
|
105
|
-
DeprecationSteps.getDeprecationBanner().should('not.exist');
|
|
106
|
-
});
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
context('User guides', () => {
|
|
110
|
-
it('should hide the Solr deprecation banner while a guide is running', () => {
|
|
111
|
-
// GIVEN: The guides are loaded and ready to be started.
|
|
112
|
-
GuidesStubs.stubMainMenuGuide();
|
|
113
|
-
GuideSteps.visit();
|
|
114
|
-
GuideSteps.verifyGuidesListExists();
|
|
115
|
-
cy.wait('@getGuides');
|
|
116
|
-
|
|
117
|
-
// WHEN: I am on an application page, and the Solr deprecation banner has not been dismissed by the current user.
|
|
118
|
-
// THEN: I expect the Solr deprecation banner to be visible because it has not been dismissed by the current user.
|
|
119
|
-
DeprecationSteps.getDeprecationBanner()
|
|
120
|
-
.should('be.visible')
|
|
121
|
-
.should('contain.text', 'The Solr connector is deprecated and will be removed in GraphDB 12');
|
|
122
|
-
|
|
123
|
-
// WHEN: I start a guide.
|
|
124
|
-
GuideSteps.runFirstGuide();
|
|
125
|
-
// THEN: I expect the Solr deprecation banner to be hidden while the guide is running.
|
|
126
|
-
DeprecationSteps.getDeprecationBanner().should('not.exist');
|
|
127
|
-
|
|
128
|
-
// WHEN: I cancel the guide.
|
|
129
|
-
GuideDialogSteps.clickOnCancelButton();
|
|
130
|
-
GuideDialogSteps.clickConfirmCancelDialogExitButton();
|
|
131
|
-
// THEN: I expect the Solr deprecation banner to be visible again.
|
|
132
|
-
DeprecationSteps.getDeprecationBanner()
|
|
133
|
-
.should('be.visible')
|
|
134
|
-
.should('contain.text', 'The Solr connector is deprecated and will be removed in GraphDB 12');
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
});
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export class DeprecationSteps {
|
|
2
|
-
static getDeprecationBanner() {
|
|
3
|
-
return cy.get('onto-deprecation-banner');
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
static getCloseButton() {
|
|
7
|
-
return DeprecationSteps.getDeprecationBanner().find('.close-button');
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
static closeBanner() {
|
|
11
|
-
DeprecationSteps.getCloseButton().click();
|
|
12
|
-
}
|
|
13
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export class DeprecationSteps {
|
|
2
|
-
static getDeprecationBanner() {
|
|
3
|
-
return cy.get('onto-deprecation-banner');
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
static getCloseButton() {
|
|
7
|
-
return DeprecationSteps.getDeprecationBanner().find('.close-button');
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
static closeBanner() {
|
|
11
|
-
DeprecationSteps.getCloseButton().click();
|
|
12
|
-
}
|
|
13
|
-
}
|