Compare commits
2 Commits
b5dbf99e50
...
eeaebdd2ba
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eeaebdd2ba
|
||
|
|
23a73b222a
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
e2e/target
|
||||||
1343
e2e/Cargo.lock
generated
Normal file
1343
e2e/Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
16
e2e/Cargo.toml
Normal file
16
e2e/Cargo.toml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "e2e"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
postgres = {path = "../api/postgres/postgres"}
|
||||||
|
toad = "1.0.0-beta.4"
|
||||||
|
toad-msg = "1.0.0-beta.2"
|
||||||
|
nb = "1.1"
|
||||||
|
simple_logger = "4.2"
|
||||||
|
serde_json = "1"
|
||||||
|
no-std-net = "0.6.0"
|
||||||
|
log = "0.4"
|
||||||
24
e2e/rustfmt.toml
Normal file
24
e2e/rustfmt.toml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# General
|
||||||
|
max_width = 100
|
||||||
|
newline_style = "Unix"
|
||||||
|
tab_spaces = 2
|
||||||
|
indent_style = "Visual"
|
||||||
|
format_code_in_doc_comments = true
|
||||||
|
format_macro_bodies = true
|
||||||
|
|
||||||
|
# Match statements
|
||||||
|
match_arm_leading_pipes = "Always"
|
||||||
|
match_block_trailing_comma = true
|
||||||
|
|
||||||
|
# Structs
|
||||||
|
use_field_init_shorthand = true
|
||||||
|
struct_field_align_threshold = 0
|
||||||
|
|
||||||
|
# Enums
|
||||||
|
enum_discrim_align_threshold = 0
|
||||||
|
|
||||||
|
# Imports
|
||||||
|
group_imports = "StdExternalCrate"
|
||||||
|
imports_granularity = "Module"
|
||||||
|
imports_indent = "Visual"
|
||||||
|
imports_layout = "HorizontalVertical"
|
||||||
122
e2e/src/lib.rs
Normal file
122
e2e/src/lib.rs
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
#![cfg(test)]
|
||||||
|
|
||||||
|
mod __toad_aliases {
|
||||||
|
use toad::std::{dtls, Platform};
|
||||||
|
use toad::step::runtime::std::Runtime;
|
||||||
|
pub type Toad = Platform<dtls::N, Runtime<dtls::N>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
mod user_signup;
|
||||||
|
|
||||||
|
use std::fs::OpenOptions;
|
||||||
|
use std::io::{Read, Write};
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
|
use std::sync::Once;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
pub use __toad_aliases::Toad;
|
||||||
|
|
||||||
|
pub fn run<S, F, R>(script: S, init: R, mut fold_lines: F) -> R
|
||||||
|
where S: AsRef<str>,
|
||||||
|
F: FnMut(R, &str) -> R
|
||||||
|
{
|
||||||
|
let temppath = Command::new("mktemp").output().unwrap().stdout;
|
||||||
|
let temppath = String::from_utf8_lossy(&temppath);
|
||||||
|
let temppath = temppath.trim();
|
||||||
|
|
||||||
|
let mut child = Command::new("sh").args(["-c", script.as_ref()])
|
||||||
|
.current_dir("../")
|
||||||
|
.stdout(OpenOptions::new().read(true)
|
||||||
|
.write(true)
|
||||||
|
.open(temppath)
|
||||||
|
.unwrap())
|
||||||
|
.stderr(Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let mut r: R = init;
|
||||||
|
let mut line_ix = 0usize;
|
||||||
|
|
||||||
|
macro_rules! do_fold {
|
||||||
|
() => {{
|
||||||
|
let out = std::fs::read_to_string(temppath).unwrap();
|
||||||
|
|
||||||
|
#[allow(unused_assignments)]
|
||||||
|
while let Some(line) = out.split('\n').nth(line_ix) {
|
||||||
|
line_ix += 1;
|
||||||
|
if !line.trim().is_empty() {
|
||||||
|
r = fold_lines(r, line);
|
||||||
|
std::io::stdout().flush().unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
std::thread::sleep(Duration::from_micros(500));
|
||||||
|
|
||||||
|
do_fold!();
|
||||||
|
|
||||||
|
let exit = child.try_wait().unwrap();
|
||||||
|
if exit.map(|e| e.success()) == Some(false) {
|
||||||
|
let mut e = String::new();
|
||||||
|
child.stderr.take().unwrap().read_to_string(&mut e).unwrap();
|
||||||
|
panic!("{}", e);
|
||||||
|
} else if exit.is_some() {
|
||||||
|
do_fold!();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
r
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Fixture {
|
||||||
|
pub toad: &'static Toad,
|
||||||
|
pub api_addr: no_std_net::SocketAddr,
|
||||||
|
pub pg: postgres::Client,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init() -> Fixture {
|
||||||
|
static mut SHARED: Option<Toad> = None;
|
||||||
|
|
||||||
|
static INIT: Once = Once::new();
|
||||||
|
INIT.call_once(|| {
|
||||||
|
simple_logger::init().unwrap();
|
||||||
|
|
||||||
|
log::info!("[init] sync repos");
|
||||||
|
run("git fetch --recurse-submodules 2>&1; git submodule update --init --recursive 2>&1",
|
||||||
|
(),
|
||||||
|
|_, _| print!("."));
|
||||||
|
println!();
|
||||||
|
|
||||||
|
log::info!("[init] build db");
|
||||||
|
run("cd db; docker compose up -d 2>&1; ./scripts/build.sh 2>&1",
|
||||||
|
(),
|
||||||
|
|_, _| print!("."));
|
||||||
|
println!();
|
||||||
|
|
||||||
|
log::info!("[init] start api");
|
||||||
|
std::thread::spawn(|| {
|
||||||
|
run("cd api; cargo run", (), |_, line| println!("{line}"));
|
||||||
|
});
|
||||||
|
|
||||||
|
let toad = Toad::try_new("127.0.0.1:4445".parse::<SocketAddr>().unwrap(),
|
||||||
|
Default::default()).unwrap();
|
||||||
|
unsafe {
|
||||||
|
SHARED = Some(toad);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Fixture {
|
||||||
|
toad: unsafe {SHARED.as_ref()}.unwrap(),
|
||||||
|
api_addr: "127.0.0.1:4444".parse().unwrap(),
|
||||||
|
pg: postgres::Client::connect("host=127.0.0.1 port=5432 dbname=dnim user=postgres password=password", postgres::NoTls).unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn init_works() {
|
||||||
|
init();
|
||||||
|
}
|
||||||
80
e2e/src/user_signup.rs
Normal file
80
e2e/src/user_signup.rs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
use toad::net::Addrd;
|
||||||
|
use toad::platform::Platform;
|
||||||
|
use toad_msg::{Code, ContentFormat, Message, MessageOptions, Type};
|
||||||
|
|
||||||
|
use crate::{init, Fixture};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
pub fn user_signup() {
|
||||||
|
let fx = init();
|
||||||
|
|
||||||
|
let msg =
|
||||||
|
Message::builder(Type::Con, Code::POST).path("users")
|
||||||
|
.accept(ContentFormat::Json)
|
||||||
|
.content_format(ContentFormat::Json)
|
||||||
|
.payload(serde_json::to_vec(&serde_json::json!({
|
||||||
|
"tag": "foo",
|
||||||
|
"email": "foo@bar.baz",
|
||||||
|
"password": "bingus"
|
||||||
|
})).unwrap())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let msg = Addrd(msg, fx.api_addr);
|
||||||
|
|
||||||
|
let rep = nb::block!({
|
||||||
|
std::thread::sleep(std::time::Duration::from_micros(500));
|
||||||
|
fx.toad.send_req(&msg)
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(rep.data().code, toad::resp::code::CONTENT);
|
||||||
|
assert_eq!(rep.data().content_format(), Some(ContentFormat::Json));
|
||||||
|
let rep_json =
|
||||||
|
serde_json::from_slice::<serde_json::Value>(rep.data().payload().as_bytes()).unwrap();
|
||||||
|
|
||||||
|
let signup_link = rep_json.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("links")
|
||||||
|
.unwrap()
|
||||||
|
.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("user_signup")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let session = rep_json.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("session_id")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let get_signup =
|
||||||
|
Message::builder(Type::Con, Code::GET).path(signup_link)
|
||||||
|
.accept(ContentFormat::Json)
|
||||||
|
.content_format(ContentFormat::Json)
|
||||||
|
.payload(serde_json::to_vec(&serde_json::json!({
|
||||||
|
session: session
|
||||||
|
})).unwrap())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let get_signup = Addrd(get_signup, fx.api_addr);
|
||||||
|
|
||||||
|
let rep = nb::block!({
|
||||||
|
std::thread::sleep(std::time::Duration::from_micros(500));
|
||||||
|
fx.toad.send_req(&get_signup)
|
||||||
|
}).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(rep.data().code, toad::resp::code::CONTENT);
|
||||||
|
assert_eq!(rep.data().content_format(), Some(ContentFormat::Json));
|
||||||
|
let rep_json =
|
||||||
|
serde_json::from_slice::<serde_json::Value>(rep.data().payload().as_bytes()).unwrap();
|
||||||
|
|
||||||
|
let status = rep_json.as_object()
|
||||||
|
.unwrap()
|
||||||
|
.get("status")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(status, "email_verification_pending");
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user