graphdb-workbench-tests 4.0.0-SPARQL12-TEST-FIX → 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-legacy/explore/graphs-overview/graphs.overview.spec.js +31 -2
- 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/import/import-user-data-file-upload.spec.js +26 -0
- package/e2e-legacy/rdf-version/rdf-version-accept-header.spec.js +145 -0
- package/e2e-legacy/resource/resource.spec.js +25 -12
- package/e2e-legacy/setup/settings/my-settings.spec.js +25 -15
- package/e2e-security/setup/users-and-access/user-and-access.spec.js +0 -1
- package/npm-shrinkwrap.json +1276 -1277
- package/package.json +10 -1
- package/steps/base-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 +39 -6
- package/steps/main-menu-steps.js +9 -0
- 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 +8 -0
- package/steps/setup/settings-steps.js +42 -0
|
@@ -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);
|
|
@@ -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
|
+
});
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import {GraphNavigatorSteps} from '../../steps/graph-navigator-steps.js';
|
|
2
|
+
import {LanguageSelectorSteps} from '../../steps/language-selector-steps.js';
|
|
3
|
+
import {RepositorySelectorSteps} from '../../steps/repository-selector-steps.js';
|
|
4
|
+
import {MainMenuSteps} from '../../steps/main-menu-steps.js';
|
|
5
|
+
import {YasqeSteps} from '../../steps/yasgui/yasqe-steps.js';
|
|
6
|
+
import {ToasterSteps} from '../../steps/toaster-steps.js';
|
|
7
|
+
|
|
8
|
+
const FILE_TO_IMPORT = 'resource-test-data.ttl';
|
|
9
|
+
const SEED_RESOURCE_ENCODED = 'http:%2F%2Fexample.com%2Fontology%23CustomerLoyalty';
|
|
10
|
+
const SEED_RESOURCE_LABEL = 'CustomerLoyalty';
|
|
11
|
+
|
|
12
|
+
const CONSTRUCT_QUERY = 'CONSTRUCT { <http://example.com/ontology#CustomerLoyalty> ?p ?o } WHERE { <http://example.com/ontology#CustomerLoyalty> ?p ?o }';
|
|
13
|
+
const CONSTRUCT_TARGET_LABEL = 'Metric';
|
|
14
|
+
|
|
15
|
+
describe('Graph Navigator', () => {
|
|
16
|
+
let repositoryId;
|
|
17
|
+
|
|
18
|
+
beforeEach(() => {
|
|
19
|
+
repositoryId = 'repository-' + Date.now();
|
|
20
|
+
cy.createRepository({id: repositoryId});
|
|
21
|
+
cy.presetRepository(repositoryId);
|
|
22
|
+
cy.importServerFile(repositoryId, FILE_TO_IMPORT);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
cy.deleteRepository(repositoryId);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should mount the Graph Navigator workspace when a repository is active', () => {
|
|
30
|
+
// Given I open the Graph Navigator view without a start resource.
|
|
31
|
+
GraphNavigatorSteps.visit();
|
|
32
|
+
|
|
33
|
+
// Then I expect the Graph Navigator workspace and its canvas to be rendered.
|
|
34
|
+
GraphNavigatorSteps.getWorkspace().should('exist');
|
|
35
|
+
GraphNavigatorSteps.getCanvas().should('exist');
|
|
36
|
+
|
|
37
|
+
// And I expect the canvas to start empty because no start resource was provided.
|
|
38
|
+
GraphNavigatorSteps.getElements().should('not.exist');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should place the start resource on the canvas as a seed', () => {
|
|
42
|
+
// Given I open the Graph Navigator view with a start resource.
|
|
43
|
+
GraphNavigatorSteps.visit(SEED_RESOURCE_ENCODED);
|
|
44
|
+
|
|
45
|
+
// Then I expect the start resource to be placed on the canvas as a seed element.
|
|
46
|
+
GraphNavigatorSteps.getElements().should('have.length', 1);
|
|
47
|
+
GraphNavigatorSteps.getElement(SEED_RESOURCE_LABEL).should('exist');
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should seed the canvas with the graph computed from a CONSTRUCT query', () => {
|
|
51
|
+
// Given I open the Graph Navigator view with a CONSTRUCT query, as sent from the SPARQL editor.
|
|
52
|
+
GraphNavigatorSteps.visitWithQuery(CONSTRUCT_QUERY);
|
|
53
|
+
|
|
54
|
+
// Then I expect the computed graph to be seeded on the canvas: the subject and its related resource.
|
|
55
|
+
GraphNavigatorSteps.getElements().should('have.length', 2);
|
|
56
|
+
GraphNavigatorSteps.getElement(SEED_RESOURCE_LABEL).should('exist');
|
|
57
|
+
GraphNavigatorSteps.getElement(CONSTRUCT_TARGET_LABEL).should('exist');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should keep the displayed resources when the language is switched', () => {
|
|
61
|
+
// Given the Graph Navigator view is opened with a start resource that gets seeded on the canvas.
|
|
62
|
+
GraphNavigatorSteps.visit(SEED_RESOURCE_ENCODED);
|
|
63
|
+
GraphNavigatorSteps.getElement(SEED_RESOURCE_LABEL).should('exist');
|
|
64
|
+
GraphNavigatorSteps.getElements().should('have.length', 1);
|
|
65
|
+
|
|
66
|
+
// When I switch the language.
|
|
67
|
+
LanguageSelectorSteps.switchToFr();
|
|
68
|
+
|
|
69
|
+
// Then I expect the same resources to remain visible because the layout is carried across the remount.
|
|
70
|
+
GraphNavigatorSteps.getElements().should('have.length', 1);
|
|
71
|
+
GraphNavigatorSteps.getElement(SEED_RESOURCE_LABEL).should('exist');
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it('should keep the diagram on refresh but clear it when navigating away and back', () => {
|
|
75
|
+
// Given the Graph Navigator view is opened with a start resource that gets seeded on the canvas.
|
|
76
|
+
GraphNavigatorSteps.visit(SEED_RESOURCE_ENCODED);
|
|
77
|
+
GraphNavigatorSteps.getElements().should('have.length', 1);
|
|
78
|
+
GraphNavigatorSteps.getElement(SEED_RESOURCE_LABEL).should('exist');
|
|
79
|
+
|
|
80
|
+
// When I refresh the page.
|
|
81
|
+
cy.reload();
|
|
82
|
+
|
|
83
|
+
// Then I expect the diagram state to be preserved across the refresh.
|
|
84
|
+
GraphNavigatorSteps.getElements().should('have.length', 1);
|
|
85
|
+
GraphNavigatorSteps.getElement(SEED_RESOURCE_LABEL).should('exist');
|
|
86
|
+
|
|
87
|
+
// When I navigate to another view via the navigation bar.
|
|
88
|
+
MainMenuSteps.clickOnSparqlMenu();
|
|
89
|
+
GraphNavigatorSteps.getComponent().should('not.exist');
|
|
90
|
+
|
|
91
|
+
// Wait for the SPARQL Query & Update view to be loaded before continuing.
|
|
92
|
+
// Without this wait, Cypress may try to click the Graph Navigator menu item before the page is fully loaded,
|
|
93
|
+
// causing the test to fail intermittently with the error:
|
|
94
|
+
// "This element `<li.sub-menu-item>` is not visible because it has CSS property: `display: none`"
|
|
95
|
+
// when trying to click the Graph Navigator submenu.
|
|
96
|
+
YasqeSteps.getEditor().should('be.visible');
|
|
97
|
+
// And I return to the Graph Navigator view via the navigation bar.
|
|
98
|
+
MainMenuSteps.clickOnGraphNavigator();
|
|
99
|
+
|
|
100
|
+
// Then I expect the canvas to be cleared, because leaving the view drops the persisted diagram state.
|
|
101
|
+
GraphNavigatorSteps.getWorkspace().should('exist');
|
|
102
|
+
GraphNavigatorSteps.getElements().should('not.exist');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// These run against the in-code REST stub. TODO: GDB-15242 switch to intercepts when the endpoints are available.
|
|
106
|
+
describe('Settings', () => {
|
|
107
|
+
it('should open the settings popover', () => {
|
|
108
|
+
// Given I open the Graph Navigator view.
|
|
109
|
+
GraphNavigatorSteps.visit();
|
|
110
|
+
|
|
111
|
+
// When I click the Settings button.
|
|
112
|
+
GraphNavigatorSteps.openSettings();
|
|
113
|
+
|
|
114
|
+
// Then I expect the settings popover to be open.
|
|
115
|
+
GraphNavigatorSteps.getSettingsPopover().should('be.visible');
|
|
116
|
+
GraphNavigatorSteps.getBrowseButton().should('contain', 'Browse');
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it('should not offer reset when the default settings are in use', () => {
|
|
120
|
+
// Given I open the settings of a repository without uploaded settings.
|
|
121
|
+
GraphNavigatorSteps.visit();
|
|
122
|
+
GraphNavigatorSteps.openSettings();
|
|
123
|
+
|
|
124
|
+
// Then I expect no reset action, because there is nothing to reset to.
|
|
125
|
+
GraphNavigatorSteps.getSettingsPopover().should('be.visible');
|
|
126
|
+
GraphNavigatorSteps.getResetButton().should('not.exist');
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it('should cancel a selected file', () => {
|
|
130
|
+
// Given I have selected a settings file.
|
|
131
|
+
GraphNavigatorSteps.visit();
|
|
132
|
+
GraphNavigatorSteps.openSettings();
|
|
133
|
+
GraphNavigatorSteps.selectSettingsFile();
|
|
134
|
+
GraphNavigatorSteps.getSelectedSettingsFile().should('exist');
|
|
135
|
+
|
|
136
|
+
// When I cancel it.
|
|
137
|
+
GraphNavigatorSteps.clickCancelFile();
|
|
138
|
+
|
|
139
|
+
// Then I expect the file to be removed.
|
|
140
|
+
GraphNavigatorSteps.getSettingsPopover().should('not.contain', 'settings.ttl');
|
|
141
|
+
GraphNavigatorSteps.getUploadButton().should('be.disabled');
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
it('should ask for confirmation before uploading', () => {
|
|
145
|
+
// Given I have selected a settings file.
|
|
146
|
+
GraphNavigatorSteps.visit();
|
|
147
|
+
GraphNavigatorSteps.openSettings();
|
|
148
|
+
GraphNavigatorSteps.selectSettingsFile();
|
|
149
|
+
|
|
150
|
+
// When I upload it.
|
|
151
|
+
GraphNavigatorSteps.clickUpload();
|
|
152
|
+
|
|
153
|
+
// Then I expect a confirmation that warns the diagram may behave unexpectedly.
|
|
154
|
+
GraphNavigatorSteps.getConfirmDialog().should('be.visible')
|
|
155
|
+
.and('contain', 'The diagram might behave unexpectedly with the new settings.');
|
|
156
|
+
|
|
157
|
+
// When I cancel.
|
|
158
|
+
GraphNavigatorSteps.cancelDialog();
|
|
159
|
+
|
|
160
|
+
// Then I expect the popover to stay open with the file still selected.
|
|
161
|
+
GraphNavigatorSteps.getSettingsPopover().should('be.visible');
|
|
162
|
+
GraphNavigatorSteps.getSelectedSettingsFile().should('exist');
|
|
163
|
+
|
|
164
|
+
// When I upload and confirm.
|
|
165
|
+
GraphNavigatorSteps.clickUpload();
|
|
166
|
+
GraphNavigatorSteps.confirmDialog();
|
|
167
|
+
|
|
168
|
+
// Then I expect a success message and the diagram to be rendered.
|
|
169
|
+
ToasterSteps.verifySuccess('The settings were uploaded');
|
|
170
|
+
GraphNavigatorSteps.getWorkspace().should('exist');
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('should ask for confirmation before resetting', () => {
|
|
174
|
+
// Given the repository has uploaded settings.
|
|
175
|
+
GraphNavigatorSteps.visit();
|
|
176
|
+
GraphNavigatorSteps.openSettings();
|
|
177
|
+
GraphNavigatorSteps.selectSettingsFile();
|
|
178
|
+
GraphNavigatorSteps.clickUpload();
|
|
179
|
+
GraphNavigatorSteps.confirmDialog();
|
|
180
|
+
ToasterSteps.verifySuccess('The settings were uploaded');
|
|
181
|
+
|
|
182
|
+
// When I click outside the settings.
|
|
183
|
+
GraphNavigatorSteps.closeSettings();
|
|
184
|
+
|
|
185
|
+
// Then I expect the popover to close.
|
|
186
|
+
GraphNavigatorSteps.getSettingsPopover().should('not.exist');
|
|
187
|
+
|
|
188
|
+
// When I reset them.
|
|
189
|
+
GraphNavigatorSteps.openSettings();
|
|
190
|
+
GraphNavigatorSteps.getResetButton().should('be.visible');
|
|
191
|
+
GraphNavigatorSteps.clickReset();
|
|
192
|
+
|
|
193
|
+
// Then I expect a confirmation that warns the diagram may behave unexpectedly.
|
|
194
|
+
GraphNavigatorSteps.getConfirmDialog().should('be.visible')
|
|
195
|
+
.and('contain', 'The diagram might behave unexpectedly with the default settings.');
|
|
196
|
+
|
|
197
|
+
// When I confirm.
|
|
198
|
+
GraphNavigatorSteps.confirmDialog();
|
|
199
|
+
|
|
200
|
+
// Then I expect a success message and the diagram to be rendered.
|
|
201
|
+
ToasterSteps.verifySuccess('The settings were reset to the defaults');
|
|
202
|
+
GraphNavigatorSteps.getWorkspace().should('exist');
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('should export the current settings as a .ttl file', () => {
|
|
206
|
+
// Given I open the settings.
|
|
207
|
+
GraphNavigatorSteps.visit();
|
|
208
|
+
GraphNavigatorSteps.openSettings();
|
|
209
|
+
|
|
210
|
+
// When I export them.
|
|
211
|
+
GraphNavigatorSteps.clickExport();
|
|
212
|
+
|
|
213
|
+
// Then I expect a .ttl file named after the repository to be downloaded.
|
|
214
|
+
GraphNavigatorSteps.verifyFileDownloaded(`graph-navigator-settings-${repositoryId}.ttl`);
|
|
215
|
+
});
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
describe('Repository switch', () => {
|
|
219
|
+
let secondRepositoryId;
|
|
220
|
+
|
|
221
|
+
beforeEach(() => {
|
|
222
|
+
secondRepositoryId = 'repository-second-' + Date.now();
|
|
223
|
+
cy.createRepository({id: secondRepositoryId});
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
afterEach(() => {
|
|
227
|
+
cy.deleteRepository(secondRepositoryId);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it('should clear the canvas when the repository is switched', () => {
|
|
231
|
+
// Given the Graph Navigator view is opened with a start resource that gets seeded on the canvas.
|
|
232
|
+
GraphNavigatorSteps.visit(SEED_RESOURCE_ENCODED);
|
|
233
|
+
GraphNavigatorSteps.getElements().should('have.length', 1);
|
|
234
|
+
|
|
235
|
+
// When I switch to another repository.
|
|
236
|
+
RepositorySelectorSteps.selectRepository(secondRepositoryId);
|
|
237
|
+
|
|
238
|
+
// Then I expect the workspace to still be mounted, but the canvas to be cleared.
|
|
239
|
+
GraphNavigatorSteps.getWorkspace().should('exist');
|
|
240
|
+
GraphNavigatorSteps.getElements().should('not.exist');
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
});
|
|
@@ -152,6 +152,32 @@ describe('Import user data: File upload', () => {
|
|
|
152
152
|
ImportUserDataSteps.getResources().should('have.length', 1);
|
|
153
153
|
});
|
|
154
154
|
|
|
155
|
+
it('Should give the controls on the page accessible names', () => {
|
|
156
|
+
// Given I have uploaded a file without importing it
|
|
157
|
+
const file = ImportUserDataSteps.createFile(testFiles[0], bnodes);
|
|
158
|
+
ImportUserDataSteps.selectFile(file);
|
|
159
|
+
ImportSettingsDialogSteps.uploadOnly();
|
|
160
|
+
ImportUserDataSteps.getResources().should('have.length', 1);
|
|
161
|
+
// Then the icon-only buttons and the row checkbox should have accessible names
|
|
162
|
+
ImportUserDataSteps.getHelpToggleButton().should('have.attr', 'aria-label', 'Get help on import');
|
|
163
|
+
ImportUserDataSteps.getStatusSelectMenuToggle().should('have.attr', 'aria-label', 'Select resources by status');
|
|
164
|
+
ImportUserDataSteps.getResourceSelectCheckbox('bnodes.ttl').should('have.attr', 'aria-label', 'Select bnodes.ttl');
|
|
165
|
+
ImportUserDataSteps.getResourceImportButton('bnodes.ttl').should('have.attr', 'aria-label', 'Import bnodes.ttl');
|
|
166
|
+
ImportUserDataSteps.getResourceRemoveButton('bnodes.ttl').should('have.attr', 'aria-label', 'Remove bnodes.ttl');
|
|
167
|
+
// And no empty context link should be rendered
|
|
168
|
+
ImportUserDataSteps.getResourceContextLink('bnodes.ttl').should('not.exist');
|
|
169
|
+
// And the filter field should have a screen reader label
|
|
170
|
+
ImportUserDataSteps.getFilterFieldLabel()
|
|
171
|
+
.should('have.class', 'sr-only')
|
|
172
|
+
.and('contain.text', 'Filter by name');
|
|
173
|
+
// When I import the file
|
|
174
|
+
ImportUserDataSteps.importFile(0);
|
|
175
|
+
ImportSettingsDialogSteps.import();
|
|
176
|
+
ImportUserDataSteps.checkImportedResourceByIndex(0, 'bnodes.ttl');
|
|
177
|
+
// Then the reset status button should have an accessible name
|
|
178
|
+
ImportUserDataSteps.getResourceResetButton('bnodes.ttl').should('have.attr', 'aria-label', 'Reset status of bnodes.ttl');
|
|
179
|
+
});
|
|
180
|
+
|
|
155
181
|
it('Should be able to upload multiple unique files', () => {
|
|
156
182
|
// Given there are no files uploaded yet
|
|
157
183
|
ImportUserDataSteps.getResourcesTable().should('be.hidden');
|