Skip to content
This repository was archived by the owner on Jul 3, 2023. It is now read-only.

Commit a356006

Browse files
committed
Adds webui-tester crate.
- A framework for writing selenium test against the WebUI. - Also contains an initial test for the UI. - Brings various annotations for IDs in critical UI elements to simplify testing.
1 parent 713e35c commit a356006

File tree

18 files changed

+1166
-42
lines changed

18 files changed

+1166
-42
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ lcov.info
2424

2525
.idea
2626
*.iml
27+
.DS_Store
2728

2829
benches/galen_data/
2930
benches/gdelt-data/

crates/webui-tester/Cargo.toml

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "webui-tester"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dev-dependencies]
7+
thirtyfour = "0.32.0-rc.7"
8+
tokio = "1.28"
9+
anyhow = "1.0"
10+
futures = "0.3.28"
11+
log = "0.4"
12+
env_logger = "0.10"

crates/webui-tester/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#[cfg(test)]
2+
mod smoke;
3+
#[cfg(test)]
4+
mod ui;

crates/webui-tester/src/smoke.rs

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// A basic UI workflow test.
2+
//
3+
// This test will:
4+
// 1. Create a program.
5+
// 2. Create a connector.
6+
// 3. Create a pipeline.
7+
// 4. Start the pipeline.
8+
9+
use anyhow::Result;
10+
use thirtyfour::prelude::*;
11+
use thirtyfour::TimeoutConfiguration;
12+
use tokio::time::Duration;
13+
14+
use std::time::{SystemTime, UNIX_EPOCH};
15+
16+
use crate::ui::*;
17+
18+
/// This is the SQL code that will be saved.
19+
///
20+
/// I noticed that if you put newlines immediately after the braces, the code
21+
/// editor might add another brace to complete it, and then the code won't be
22+
/// correct anymore.
23+
const SQL_CODE: &str = "
24+
CREATE TABLE USERS ( name varchar );
25+
CREATE VIEW OUTPUT_USERS as SELECT * from USERS;
26+
";
27+
28+
/// A config for a HTTP endpoint.
29+
///
30+
/// The \x08 is a backspace character, which is needed to remove the space that
31+
/// is inserted by the editor.
32+
const HTTP_ENDPOINT_CONFIG: &str = "
33+
transport:
34+
name: http
35+
\x08format:
36+
name: csv
37+
";
38+
39+
#[tokio::test]
40+
async fn smoke_workflow() -> Result<()> {
41+
//let caps = DesiredCapabilities::firefox();
42+
//let mut driver = WebDriver::new("http://localhost:4444", caps).await?;
43+
let nanos = SystemTime::now()
44+
.duration_since(UNIX_EPOCH)
45+
.expect("Can't get time")
46+
.subsec_nanos();
47+
48+
let caps = DesiredCapabilities::chrome();
49+
let driver = WebDriver::new("http://localhost:9515", caps).await?;
50+
51+
let timeouts =
52+
TimeoutConfiguration::new(None, None, Some(std::time::Duration::from_millis(2000)));
53+
driver.update_timeouts(timeouts).await?;
54+
55+
driver.goto("http://localhost:3000").await?;
56+
let elem = driver.find(By::Id("navigation")).await?;
57+
let menu = VerticalMenu::from(elem);
58+
59+
// First we make a program, then we compile it.
60+
menu.navigate_to("SQL Editor").await?;
61+
let code_page = SqlEditor::from(driver.find(By::Id("editor-content")).await?);
62+
let program_name = format!("My Program {}", nanos);
63+
code_page.set_code(SQL_CODE, &driver).await?;
64+
code_page.set_name(&program_name).await?;
65+
code_page.set_description("This is a program").await?;
66+
code_page.wait_until_saved(Duration::from_secs(20)).await?;
67+
code_page
68+
.wait_until_compiled(Duration::from_secs(20))
69+
.await?;
70+
71+
// Next we make a connector.
72+
menu.navigate_to("Connector Creator").await?;
73+
let connector_creator =
74+
ConnectorCreator::from(driver.find(By::Id("connector-creator-content")).await?);
75+
connector_creator
76+
.add_generic_connector(
77+
&driver,
78+
"My HTTP Connector",
79+
"This is a HTTP connector",
80+
HTTP_ENDPOINT_CONFIG,
81+
)
82+
.await?;
83+
84+
// Finally we make a pipeline.
85+
menu.navigate_to("Pipeline Builder").await?;
86+
let pipeline_builder =
87+
PipelineBuilder::from(driver.find(By::Id("pipeline-builder-content")).await?);
88+
let pipeline_name = format!("My Pipeline {}", nanos);
89+
pipeline_builder.set_name(&pipeline_name).await?;
90+
pipeline_builder
91+
.set_description("This is a pipeline")
92+
.await?;
93+
pipeline_builder.set_program(&program_name).await?;
94+
pipeline_builder
95+
.add_input(&driver, "My HTTP Connector")
96+
.await?;
97+
pipeline_builder
98+
.add_output(&driver, "My HTTP Connector")
99+
.await?;
100+
pipeline_builder
101+
.connect_input(&driver, "My HTTP Connector", "USERS")
102+
.await?;
103+
pipeline_builder
104+
.connect_output(&driver, "OUTPUT_USERS", "My HTTP Connector")
105+
.await?;
106+
pipeline_builder
107+
.wait_until_saved(Duration::from_secs(3))
108+
.await?;
109+
110+
// Start the pipeline.
111+
menu.navigate_to("Pipeline Management").await?;
112+
let pipeline_management =
113+
PipelineManagementTable::from(driver.find(By::Id("pipeline-management-content")).await?);
114+
pipeline_management.start(&pipeline_name).await?;
115+
pipeline_management
116+
.wait_until_running(&pipeline_name, Duration::from_secs(10))
117+
.await?;
118+
119+
let details = pipeline_management
120+
.open_details(&driver, &pipeline_name)
121+
.await?;
122+
assert_eq!(details.get_records_for_table("USERS").await?, 0);
123+
assert_eq!(details.get_records_for_view("OUTPUT_USERS").await?, 0);
124+
// TODO: send some stuff
125+
126+
pipeline_management.pause(&pipeline_name).await?;
127+
128+
driver.quit().await?;
129+
130+
Ok(())
131+
}

0 commit comments

Comments
 (0)