Skip to content
This repository was archived by the owner on Mar 4, 2025. It is now read-only.

Commit e5e6694

Browse files
committed
cypress, webui: Add live visualisation to the webUI, with Cypress tests
1 parent 041338f commit e5e6694

File tree

5 files changed

+1196
-15
lines changed

5 files changed

+1196
-15
lines changed
Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
import path from "path";
2+
3+
// Sometimes we need a delay between making a change, and testing it, otherwise the AngularJS changes are missed
4+
let waitTime = 250;
5+
6+
// TODO: Add a database with a 3rd column, so we can test the Y column change drop down
7+
8+
describe('live visualisation', () => {
9+
before(() => {
10+
// Seed data
11+
cy.request('/x/test/seed')
12+
})
13+
14+
// Save a visualisation
15+
it('save a visualisation using non-default name', () => {
16+
cy.visit('/vis/default/Join Testing with index.sqlite')
17+
cy.get('[data-cy="sqltab"]').click()
18+
cy.get('[data-cy="usersqltext"]').type(
19+
'SELECT table1.Name, table2.value\n' +
20+
'FROM table1 JOIN table2\n' +
21+
'ON table1.id = table2.id\n' +
22+
'ORDER BY table1.id')
23+
cy.get('[data-cy="nameinput"]').type('{selectall}{backspace}').type('livetest1')
24+
cy.get('[data-cy="savebtn"]').click()
25+
cy.get('[data-cy="statusmsg"]').should('contain.text', 'Visualisation \'livetest1\' saved')
26+
27+
// Verify the visualisation - it should be automatically selected in the drop down list as it's the only one
28+
cy.visit('/vis/default/Join Testing with index.sqlite')
29+
cy.get('[data-cy="selectedvis"]').should('contain.text', 'livetest1')
30+
})
31+
32+
// Check if 'default' visualisation is still chosen by default even when created after non-default ones
33+
it('save a visualisation using default name', () => {
34+
cy.visit('/vis/default/Join Testing with index.sqlite')
35+
cy.get('[data-cy="sqltab"]').click()
36+
cy.get('[data-cy="usersqltext"]').type('{selectall}{backspace}').type(
37+
'SELECT table1.Name, table2.value\n' +
38+
'FROM table1 JOIN table2\n' +
39+
'USING (id)\n' +
40+
'ORDER BY table1.id')
41+
cy.get('[data-cy="nameinput"]').type('{selectall}{backspace}').type('default')
42+
cy.get('[data-cy="savebtn"]').click()
43+
cy.get('[data-cy="statusmsg"]').should('contain.text', 'Visualisation \'default\' saved')
44+
45+
// Verify the visualisation - it should be automatically selected in the drop down list as it's the default
46+
cy.visit('/vis/default/Join Testing with index.sqlite')
47+
cy.get('[data-cy="selectedvis"]').should('contain.text', 'default')
48+
cy.get('[data-cy="usersqltext"]').should('contain.text',
49+
'SELECT table1.Name, table2.value\n' +
50+
'FROM table1 JOIN table2\n' +
51+
'USING (id)\n' +
52+
'ORDER BY table1.id')
53+
})
54+
55+
// Save a visualisation
56+
it('save a visualisation with name alphabetically lower than \'default\'', () => {
57+
cy.visit('/vis/default/Join Testing with index.sqlite')
58+
cy.get('[data-cy="sqltab"]').click()
59+
cy.get('[data-cy="usersqltext"]').type('{selectall}{backspace}').type(
60+
'SELECT table1.Name, table2.value\n' +
61+
'FROM table1, table2\n' +
62+
'WHERE table1.id = table2.id\n' +
63+
'ORDER BY table2.value;')
64+
cy.get('[data-cy="nameinput"]').type('{selectall}{backspace}').type('abc')
65+
cy.get('[data-cy="savebtn"]').click()
66+
cy.get('[data-cy="statusmsg"]').should('contain.text', 'Visualisation \'abc\' saved')
67+
68+
// Check that the visualisation is present, but not automatically selected when the page loads
69+
cy.visit('/vis/default/Join Testing with index.sqlite')
70+
cy.get('[data-cy="selectedvis"]').should('not.contain.text', 'abc')
71+
})
72+
73+
// Save over an existing visualisation
74+
it('save over an existing visualisation', () => {
75+
cy.visit('/vis/default/Join Testing with index.sqlite')
76+
cy.get('[data-cy="sqltab"]').click()
77+
cy.get('[data-cy="usersqltext"]').type('{selectall}{backspace}').type(
78+
'SELECT table1.Name, table2.value\n' +
79+
'FROM table1, table2\n' +
80+
'WHERE table1.id = table2.id\n' +
81+
'ORDER BY table1.id;')
82+
cy.get('[data-cy="nameinput"]').type('{selectall}{backspace}').type('livetest1')
83+
cy.get('[data-cy="savebtn"]').click()
84+
cy.get('[data-cy="statusmsg"]').should('contain.text', 'Visualisation \'livetest1\' saved')
85+
86+
// Verify the new visualisation text
87+
cy.visit('/vis/default/Join Testing with index.sqlite')
88+
cy.get('[data-cy="visdropdown"]').click()
89+
cy.get('[data-cy="vis-livetest1"]').click()
90+
cy.get('[data-cy="usersqltext"]').should('contain',
91+
'SELECT table1.Name, table2.value\n' +
92+
'FROM table1, table2\n' +
93+
'WHERE table1.id = table2.id\n' +
94+
'ORDER BY table1.id;')
95+
})
96+
97+
// * Chart settings tab *
98+
99+
// Chart type drop down
100+
it('chart type drop down', () => {
101+
// Start with the existing "livetest1" test
102+
cy.visit('/vis/default/Join Testing with index.sqlite')
103+
cy.get('[data-cy="visdropdown"]').click()
104+
cy.get('[data-cy="vis-livetest1"]').click()
105+
106+
// Switch to the chart settings tab
107+
cy.get('[data-cy="charttab"]').click()
108+
109+
// Change the chart type
110+
cy.get('[data-cy="chartdropdown"]').click()
111+
cy.get('[data-cy="chartpie"]').click()
112+
113+
// Verify the change
114+
cy.wait(waitTime)
115+
cy.get('[data-cy="charttype"]').should('contain', 'Pie chart')
116+
cy.get('[data-cy="showxaxis"]').should('not.exist')
117+
118+
// Switch to a different chart type
119+
cy.get('[data-cy="chartdropdown"]').click()
120+
cy.get('[data-cy="charthbc"]').click()
121+
122+
// Verify the change
123+
cy.wait(waitTime)
124+
cy.get('[data-cy="charttype"]').should('contain', 'Horizontal bar chart')
125+
cy.get('[data-cy="showxaxis"]').should('exist')
126+
})
127+
128+
// X axis column drop down
129+
it('X axis column drop down', () => {
130+
// Start with the existing "livetest1" test
131+
cy.visit('/vis/default/Join Testing with index.sqlite')
132+
cy.get('[data-cy="visdropdown"]').click()
133+
cy.get('[data-cy="vis-livetest1"]').click()
134+
135+
// Switch to the chart settings tab
136+
cy.get('[data-cy="charttab"]').click()
137+
138+
// Change the X axis column value
139+
cy.get('[data-cy="xaxisdropdown"]').click()
140+
cy.get('[data-cy="xcol-value"]').click()
141+
142+
// Verify the change
143+
cy.wait(waitTime)
144+
cy.get('[data-cy="xaxiscol"]').should('contain', 'value')
145+
cy.get('[data-cy="yaxiscol"]').should('contain', 'Name')
146+
147+
// Switch to a different X axis column value
148+
cy.get('[data-cy="xaxisdropdown"]').click()
149+
cy.get('[data-cy="xcol-Name"]').click()
150+
151+
// Verify the change
152+
cy.wait(waitTime)
153+
cy.get('[data-cy="xaxiscol"]').should('contain', 'Name')
154+
cy.get('[data-cy="yaxiscol"]').should('contain', 'value')
155+
})
156+
157+
//// Y axis column drop down
158+
// TODO: We'll need a database with a third column before this test can be done
159+
//it('Y axis column drop down', () => {
160+
// // Start with the existing "livetest1" test
161+
// cy.visit('/vis/default/Join Testing with index.sqlite')
162+
// cy.get('[data-cy="visdropdown"]').click()
163+
// cy.get('[data-cy="vis-livetest1"]').click()
164+
//
165+
// // Switch to the chart settings tab
166+
// cy.get('[data-cy="charttab"]').click()
167+
//
168+
// // Change the Y axis column value
169+
// cy.get('[data-cy="yaxisdropdown"]').click()
170+
// cy.get('[data-cy="ycol-Turnout_pct"]').click()
171+
//
172+
// // Verify the change
173+
// cy.wait(waitTime)
174+
// cy.get('[data-cy="yaxiscol"]').should('contain', 'Turnout_pct')
175+
// //cy.get('[data-cy="xaxiscol"]').should('contain', 'Constituency_Name')
176+
//
177+
// // Switch to a different Y axis column value
178+
// cy.get('[data-cy="yaxisdropdown"]').click()
179+
// cy.get('[data-cy="ycol-Constituency_Number"]').click()
180+
//
181+
// // Verify the change
182+
// cy.wait(waitTime)
183+
// cy.get('[data-cy="yaxiscol"]').should('contain', 'Constituency_Number')
184+
//})
185+
186+
// "Show result table" button works
187+
it('Shows results table button works', () => {
188+
// Start with the existing "livetest1" test
189+
cy.visit('/vis/default/Join Testing with index.sqlite')
190+
cy.get('[data-cy="visdropdown"]').click()
191+
cy.get('[data-cy="vis-livetest1"]').click()
192+
193+
// Verify the button starts closed
194+
cy.get('[data-cy="resultsbtn"]').should('contain', 'Show result table')
195+
196+
// Open the results table
197+
cy.get('[data-cy="resultsbtn"]').click()
198+
cy.get('[data-cy="resultsbtn"]').should('contain', 'Hide result table')
199+
})
200+
201+
// "Download as CSV" button
202+
const downloadsFolder = Cypress.config('downloadsFolder')
203+
it('"Download as CSV" button', () => {
204+
// Start with the existing "livetest1" test
205+
cy.visit('/vis/default/Join Testing with index.sqlite')
206+
cy.get('[data-cy="visdropdown"]').click()
207+
cy.get('[data-cy="vis-livetest1"]').click()
208+
209+
// Click the download button
210+
cy.get('[data-cy="downcsvbtn"]').click()
211+
212+
// Simple sanity check of the downloaded file
213+
// TODO - Implement a better check. Maybe keep the "correct" csv in the repo as test data too, and compare against it?
214+
const csv = path.join(downloadsFolder, 'results.csv')
215+
cy.readFile(csv, 'binary', { timeout: 5000 }).should('have.length', 51)
216+
cy.task('rmFile', { path: csv })
217+
})
218+
219+
// "Format SQL" button
220+
it('"Format SQL" button', () => {
221+
// Start with the existing "livetest1" test
222+
cy.visit('/vis/default/Join Testing with index.sqlite')
223+
cy.get('[data-cy="visdropdown"]').click()
224+
cy.get('[data-cy="vis-livetest1"]').click()
225+
226+
// Click the format button
227+
cy.get('[data-cy="formatsqlbtn"]').click()
228+
229+
// Verify the changed text
230+
cy.get('[data-cy="usersqltext"]').should('contain',
231+
'SELECT table1.Name,\n' +
232+
' table2.value\n' +
233+
'FROM table1,\n' +
234+
' table2\n' +
235+
'WHERE table1.id = table2.id\n' +
236+
'ORDER BY table1.id')
237+
})
238+
239+
// "Run SQL" button
240+
it('"Run SQL" button', () => {
241+
// Start with the existing "livetest1" test
242+
cy.visit('/vis/default/Join Testing with index.sqlite')
243+
cy.get('[data-cy="visdropdown"]').click()
244+
cy.get('[data-cy="vis-livetest1"]').click()
245+
246+
// Click the Run SQL button
247+
cy.get('[data-cy="runsqlbtn"]').click()
248+
249+
// Verify the result
250+
// TODO: Probably need to add cypress attributes to the rows and columns of the results table, then
251+
// check against known good return values for the testing
252+
})
253+
254+
// "Delete" button
255+
it('Delete button', () => {
256+
// Start with the existing "livetest1" test
257+
cy.visit('/vis/default/Join Testing with index.sqlite')
258+
cy.get('[data-cy="visdropdown"]').click()
259+
cy.get('[data-cy="vis-abc"]').click()
260+
261+
// Click the Delete button
262+
cy.get('[data-cy="delvisbtn"]').click()
263+
264+
// Verify the result
265+
cy.wait(waitTime)
266+
cy.get('[data-cy="visdropdown"]').click()
267+
cy.get('[data-cy="vis-abc"]').should('not.exist')
268+
})
269+
270+
// Verify only the owner can see this visualisation
271+
it('Verify private visualisation is indeed private', () => {
272+
// Switch to a different user
273+
cy.request('/x/test/switchfirst')
274+
275+
// Try accessing a private database's visualisation page
276+
cy.visit({url: '/vis/default/Join Testing with index.sqlite', failOnStatusCode: false})
277+
cy.get('[data-cy="errormsg"').should('contain', 'doesn\'t seem to exist')
278+
279+
// Switch back to the default user
280+
cy.request('/x/test/switchdefault')
281+
})
282+
})

cypress/e2e/1-webui/visualisation.cy.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,8 +263,8 @@ describe('visualisation', () => {
263263
cy.get('[data-cy="runsqlbtn"]').click()
264264

265265
// Verify the result
266-
// TODO: Probably need to add cypress to the rows and columns of the results table, then
267-
// check against known good return values
266+
// TODO: Probably need to add cypress attributes to the rows and columns of the results table, then
267+
// check against known good return values for the testing
268268
})
269269

270270
// "Delete" button

webui/templates/databaselive.html

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,24 +30,21 @@ <h2 id="viewdb" style="margin-top: 10px;">
3030
</h2>
3131
</div>
3232
</div>
33-
[[ if not .IsLive ]]
34-
<div class="row" style="padding-bottom: 5px; padding-top: 10px;">
35-
<div class="col-md-6">
36-
<label id="viewdata" style="font-weight: 600; font-family: 'arial black'; [[ if eq .Meta.PageSection "db_data" ]] border-bottom: 1px grey dashed; [[ end ]]"><a href="/[[ .Meta.Owner ]]/[[ .Meta.Database ]]" class="blackLink" title="Data" data-cy="datalink"><i class="fa fa-database"></i> Data</a></label>
37-
&nbsp; &nbsp; &nbsp;
38-
<label id="viewvis" style="font-weight: 600; font-family: 'arial black'; [[ if eq .Meta.PageSection "db_vis" ]] border-bottom: 1px grey dashed; [[ end ]]"><a href="/vis/[[ .Meta.Owner ]]/[[ .Meta.Database ]]" class="blackLink" title="Visualise" data-cy="vislink"><i class="fa fa-bar-chart"></i> Visualise</a></label>
33+
34+
<div class="row" style="padding-bottom: 5px; padding-top: 10px;">
35+
<div class="col-md-12">
36+
<label id="viewdata" style="font-weight: 600; font-family: 'arial black'; [[ if eq .Meta.PageSection "db_data" ]] border-bottom: 1px grey dashed; [[ end ]]"><a href="/[[ .Meta.Owner ]]/[[ .Meta.Database ]]" class="blackLink" title="Data" data-cy="datalink"><i class="fa fa-database"></i> Data</a></label>
37+
&nbsp; &nbsp; &nbsp;
38+
<label id="viewvis" style="font-weight: 600; font-family: 'arial black'; [[ if eq .Meta.PageSection "db_vis" ]] border-bottom: 1px grey dashed; [[ end ]]"><a href="/vis/[[ .Meta.Owner ]]/[[ .Meta.Database ]]" class="blackLink" title="Visualise" data-cy="vislink"><i class="fa fa-bar-chart"></i> Visualise</a></label>
39+
[[ if not .IsLive ]]
3940
&nbsp; &nbsp; &nbsp;
4041
[[ if eq .Meta.Owner .Meta.LoggedInUser ]]
4142
<label id="settings" style="font-weight: 600; font-family: 'arial black'; [[ if eq .Meta.PageSection "db_settings" ]] border-bottom: 1px grey dashed; [[ end ]]"><a href="/settings/[[ .Meta.Owner ]]/[[ .Meta.Database ]]" class="blackLink" title="Settings" data-cy="settingslink"><i class="fa fa-cog"></i> Settings</a></label>
4243
[[ end ]]
43-
</div>
44-
<div class="col-md-6">
45-
<div class="pull-right">
46-
<b>Size:</b> <span data-cy="size">{{ meta.Size / 1024 | number : 0 }} KB</span>
47-
</div>
48-
</div>
44+
[[ end ]]
4945
</div>
50-
[[ end ]]
46+
</div>
47+
5148
<!-- END of section copied from old headerdatabase template, then modified -->
5249

5350
[[ if not .IsLive ]]

webui/templates/visualise.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ <h4 style="color: {{ statusMessageColour }};" data-cy="statusmsg">&nbsp;{{ statu
243243
// Get the latest .value from the text area
244244
userSQL = document.getElementById("usersql").value;
245245
}
246+
updateSQL();
246247

247248
// * AngularJS pieces start here *
248249

0 commit comments

Comments
 (0)