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

Commit

Permalink
Adds webui-tester crate.
Browse files Browse the repository at this point in the history
- 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.
  • Loading branch information
gz committed May 5, 2023
1 parent 713e35c commit a356006
Show file tree
Hide file tree
Showing 18 changed files with 1,166 additions and 42 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ lcov.info

.idea
*.iml
.DS_Store

benches/galen_data/
benches/gdelt-data/
Expand Down
12 changes: 12 additions & 0 deletions crates/webui-tester/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "webui-tester"
version = "0.1.0"
edition = "2021"

[dev-dependencies]
thirtyfour = "0.32.0-rc.7"
tokio = "1.28"
anyhow = "1.0"
futures = "0.3.28"
log = "0.4"
env_logger = "0.10"
4 changes: 4 additions & 0 deletions crates/webui-tester/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#[cfg(test)]
mod smoke;
#[cfg(test)]
mod ui;
131 changes: 131 additions & 0 deletions crates/webui-tester/src/smoke.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// A basic UI workflow test.
//
// This test will:
// 1. Create a program.
// 2. Create a connector.
// 3. Create a pipeline.
// 4. Start the pipeline.

use anyhow::Result;
use thirtyfour::prelude::*;
use thirtyfour::TimeoutConfiguration;
use tokio::time::Duration;

use std::time::{SystemTime, UNIX_EPOCH};

use crate::ui::*;

/// This is the SQL code that will be saved.
///
/// I noticed that if you put newlines immediately after the braces, the code
/// editor might add another brace to complete it, and then the code won't be
/// correct anymore.
const SQL_CODE: &str = "
CREATE TABLE USERS ( name varchar );
CREATE VIEW OUTPUT_USERS as SELECT * from USERS;
";

/// A config for a HTTP endpoint.
///
/// The \x08 is a backspace character, which is needed to remove the space that
/// is inserted by the editor.
const HTTP_ENDPOINT_CONFIG: &str = "
transport:
name: http
\x08format:
name: csv
";

#[tokio::test]
async fn smoke_workflow() -> Result<()> {
//let caps = DesiredCapabilities::firefox();
//let mut driver = WebDriver::new("http://localhost:4444", caps).await?;
let nanos = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Can't get time")
.subsec_nanos();

let caps = DesiredCapabilities::chrome();
let driver = WebDriver::new("http://localhost:9515", caps).await?;

let timeouts =
TimeoutConfiguration::new(None, None, Some(std::time::Duration::from_millis(2000)));
driver.update_timeouts(timeouts).await?;

driver.goto("http://localhost:3000").await?;
let elem = driver.find(By::Id("navigation")).await?;
let menu = VerticalMenu::from(elem);

// First we make a program, then we compile it.
menu.navigate_to("SQL Editor").await?;
let code_page = SqlEditor::from(driver.find(By::Id("editor-content")).await?);
let program_name = format!("My Program {}", nanos);
code_page.set_code(SQL_CODE, &driver).await?;
code_page.set_name(&program_name).await?;
code_page.set_description("This is a program").await?;
code_page.wait_until_saved(Duration::from_secs(20)).await?;
code_page
.wait_until_compiled(Duration::from_secs(20))
.await?;

// Next we make a connector.
menu.navigate_to("Connector Creator").await?;
let connector_creator =
ConnectorCreator::from(driver.find(By::Id("connector-creator-content")).await?);
connector_creator
.add_generic_connector(
&driver,
"My HTTP Connector",
"This is a HTTP connector",
HTTP_ENDPOINT_CONFIG,
)
.await?;

// Finally we make a pipeline.
menu.navigate_to("Pipeline Builder").await?;
let pipeline_builder =
PipelineBuilder::from(driver.find(By::Id("pipeline-builder-content")).await?);
let pipeline_name = format!("My Pipeline {}", nanos);
pipeline_builder.set_name(&pipeline_name).await?;
pipeline_builder
.set_description("This is a pipeline")
.await?;
pipeline_builder.set_program(&program_name).await?;
pipeline_builder
.add_input(&driver, "My HTTP Connector")
.await?;
pipeline_builder
.add_output(&driver, "My HTTP Connector")
.await?;
pipeline_builder
.connect_input(&driver, "My HTTP Connector", "USERS")
.await?;
pipeline_builder
.connect_output(&driver, "OUTPUT_USERS", "My HTTP Connector")
.await?;
pipeline_builder
.wait_until_saved(Duration::from_secs(3))
.await?;

// Start the pipeline.
menu.navigate_to("Pipeline Management").await?;
let pipeline_management =
PipelineManagementTable::from(driver.find(By::Id("pipeline-management-content")).await?);
pipeline_management.start(&pipeline_name).await?;
pipeline_management
.wait_until_running(&pipeline_name, Duration::from_secs(10))
.await?;

let details = pipeline_management
.open_details(&driver, &pipeline_name)
.await?;
assert_eq!(details.get_records_for_table("USERS").await?, 0);
assert_eq!(details.get_records_for_view("OUTPUT_USERS").await?, 0);
// TODO: send some stuff

pipeline_management.pause(&pipeline_name).await?;

driver.quit().await?;

Ok(())
}
Loading

0 comments on commit a356006

Please sign in to comment.