Split md_parser
This commit is contained in:
parent
9b192a92f2
commit
85875abd2b
|
@ -7,10 +7,16 @@ keywords = ["qbittorrent"]
|
|||
repository = "https://github.com/JoelWachsler/qbittorrent-web-api"
|
||||
description = "Generated web api for qBittorrent"
|
||||
exclude = ["*.txt", "tests"]
|
||||
# we use trybuild instead
|
||||
autotests = false
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[[test]]
|
||||
name = "tests"
|
||||
path = "tests/tests.rs"
|
||||
|
||||
[dependencies]
|
||||
syn = { version = "1.0.98", features = ["extra-traits"]}
|
||||
quote = "1.0.20"
|
||||
|
|
127
qbittorrent-web-api-gen/src/md_parser/md_token.rs
Normal file
127
qbittorrent-web-api-gen/src/md_parser/md_token.rs
Normal file
|
@ -0,0 +1,127 @@
|
|||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum MdContent {
|
||||
Text(String),
|
||||
Asterix(String),
|
||||
Table(Table),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Table {
|
||||
pub header: TableRow,
|
||||
pub split: String,
|
||||
pub rows: Vec<TableRow>,
|
||||
}
|
||||
|
||||
impl Table {
|
||||
fn raw(&self) -> String {
|
||||
let mut output = vec![self.header.raw.clone(), self.split.clone()];
|
||||
for row in self.rows.clone() {
|
||||
output.push(row.raw);
|
||||
}
|
||||
|
||||
output.join("\n")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Header {
|
||||
pub level: i32,
|
||||
pub content: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TableRow {
|
||||
raw: String,
|
||||
pub columns: Vec<String>,
|
||||
}
|
||||
|
||||
impl MdContent {
|
||||
pub fn inner_value_as_string(&self) -> String {
|
||||
match self {
|
||||
MdContent::Text(text) => text.into(),
|
||||
MdContent::Asterix(text) => text.into(),
|
||||
MdContent::Table(table) => table.raw(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MdToken {
|
||||
Header(Header),
|
||||
Content(MdContent),
|
||||
}
|
||||
|
||||
impl MdToken {
|
||||
fn parse_token(line: &str) -> MdToken {
|
||||
if line.starts_with('#') {
|
||||
let mut level = 0;
|
||||
for char in line.chars() {
|
||||
if char != '#' {
|
||||
break;
|
||||
}
|
||||
|
||||
level += 1;
|
||||
}
|
||||
|
||||
MdToken::Header(Header {
|
||||
level,
|
||||
content: line.trim_matches('#').trim().to_string(),
|
||||
})
|
||||
} else if line.starts_with('*') {
|
||||
MdToken::Content(MdContent::Asterix(
|
||||
line.trim_matches('*').trim().to_string(),
|
||||
))
|
||||
} else {
|
||||
MdToken::Content(MdContent::Text(line.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from(content: &str) -> Vec<MdToken> {
|
||||
let mut output = Vec::new();
|
||||
|
||||
let mut iter = content.lines();
|
||||
while let Some(line) = iter.next() {
|
||||
// assume this is a table
|
||||
if line.contains('|') {
|
||||
let to_columns = |column_line: &str| {
|
||||
column_line
|
||||
.replace('`', "")
|
||||
.split('|')
|
||||
.map(|s| s.trim().to_string())
|
||||
.collect()
|
||||
};
|
||||
|
||||
let table_header = TableRow {
|
||||
raw: line.into(),
|
||||
columns: to_columns(line),
|
||||
};
|
||||
let table_split = iter.next().unwrap();
|
||||
let mut table_rows = Vec::new();
|
||||
while let Some(row_line) = iter.next() {
|
||||
if !row_line.contains('|') {
|
||||
// we've reached the end of the table, let's go back one step
|
||||
iter.next_back();
|
||||
break;
|
||||
}
|
||||
|
||||
let table_row = TableRow {
|
||||
raw: row_line.into(),
|
||||
columns: to_columns(row_line),
|
||||
};
|
||||
|
||||
table_rows.push(table_row);
|
||||
}
|
||||
|
||||
output.push(MdToken::Content(MdContent::Table(Table {
|
||||
header: table_header,
|
||||
split: table_split.to_string(),
|
||||
rows: table_rows,
|
||||
})));
|
||||
} else {
|
||||
output.push(MdToken::parse_token(line));
|
||||
}
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
}
|
|
@ -1,316 +1,7 @@
|
|||
use std::{cell::RefCell, rc::Rc};
|
||||
mod md_token;
|
||||
mod token_tree;
|
||||
mod token_tree_factory;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum MdContent {
|
||||
Text(String),
|
||||
Asterix(String),
|
||||
Table(Table),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Table {
|
||||
pub header: TableRow,
|
||||
pub split: String,
|
||||
pub rows: Vec<TableRow>,
|
||||
}
|
||||
|
||||
impl Table {
|
||||
fn raw(&self) -> String {
|
||||
let mut output = vec![self.header.raw.clone(), self.split.clone()];
|
||||
for row in self.rows.clone() {
|
||||
output.push(row.raw);
|
||||
}
|
||||
|
||||
output.join("\n")
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TableRow {
|
||||
raw: String,
|
||||
pub columns: Vec<String>,
|
||||
}
|
||||
|
||||
impl MdContent {
|
||||
pub fn inner_value_as_string(&self) -> String {
|
||||
match self {
|
||||
MdContent::Text(text) => text.into(),
|
||||
MdContent::Asterix(text) => text.into(),
|
||||
MdContent::Table(table) => table.raw(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Header {
|
||||
level: i32,
|
||||
content: String,
|
||||
}
|
||||
|
||||
/// These are the only relevant tokens we need for the api generation.
|
||||
#[derive(Debug)]
|
||||
pub enum MdToken {
|
||||
Header(Header),
|
||||
Content(MdContent),
|
||||
}
|
||||
|
||||
impl MdToken {
|
||||
fn parse_token(line: &str) -> MdToken {
|
||||
if line.starts_with('#') {
|
||||
let mut level = 0;
|
||||
for char in line.chars() {
|
||||
if char != '#' {
|
||||
break;
|
||||
}
|
||||
|
||||
level += 1;
|
||||
}
|
||||
|
||||
MdToken::Header(Header {
|
||||
level,
|
||||
content: line.trim_matches('#').trim().to_string(),
|
||||
})
|
||||
} else if line.starts_with('*') {
|
||||
MdToken::Content(MdContent::Asterix(
|
||||
line.trim_matches('*').trim().to_string(),
|
||||
))
|
||||
} else {
|
||||
MdToken::Content(MdContent::Text(line.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
fn from(content: &str) -> Vec<MdToken> {
|
||||
let mut output = Vec::new();
|
||||
|
||||
let mut iter = content.lines();
|
||||
while let Some(line) = iter.next() {
|
||||
// assume this is a table
|
||||
if line.contains('|') {
|
||||
let to_columns = |column_line: &str| {
|
||||
column_line
|
||||
.replace('`', "")
|
||||
.split('|')
|
||||
.map(|s| s.trim().to_string())
|
||||
.collect()
|
||||
};
|
||||
|
||||
let table_header = TableRow {
|
||||
raw: line.into(),
|
||||
columns: to_columns(line),
|
||||
};
|
||||
let table_split = iter.next().unwrap();
|
||||
let mut table_rows = Vec::new();
|
||||
while let Some(row_line) = iter.next() {
|
||||
if !row_line.contains('|') {
|
||||
// we've reached the end of the table, let's go back one step
|
||||
iter.next_back();
|
||||
break;
|
||||
}
|
||||
|
||||
let table_row = TableRow {
|
||||
raw: row_line.into(),
|
||||
columns: to_columns(row_line),
|
||||
};
|
||||
|
||||
table_rows.push(table_row);
|
||||
}
|
||||
|
||||
output.push(MdToken::Content(MdContent::Table(Table {
|
||||
header: table_header,
|
||||
split: table_split.to_string(),
|
||||
rows: table_rows,
|
||||
})));
|
||||
} else {
|
||||
output.push(MdToken::parse_token(line));
|
||||
}
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TokenTree {
|
||||
pub title: Option<String>,
|
||||
pub content: Vec<MdContent>,
|
||||
pub children: Vec<TokenTree>,
|
||||
}
|
||||
|
||||
impl From<Rc<TokenTreeFactory>> for TokenTree {
|
||||
fn from(builder: Rc<TokenTreeFactory>) -> Self {
|
||||
let children = builder
|
||||
.children
|
||||
.clone()
|
||||
.into_inner()
|
||||
.into_iter()
|
||||
.map(|child| child.into())
|
||||
.collect::<Vec<TokenTree>>();
|
||||
|
||||
let content = builder.content.clone().into_inner();
|
||||
|
||||
TokenTree {
|
||||
title: builder.title.clone(),
|
||||
content,
|
||||
children,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TokenTreeFactory {
|
||||
title: Option<String>,
|
||||
content: RefCell<Vec<MdContent>>,
|
||||
children: RefCell<Vec<Rc<TokenTreeFactory>>>,
|
||||
level: i32,
|
||||
}
|
||||
|
||||
impl TokenTreeFactory {
|
||||
fn new(title: &str, level: i32) -> Self {
|
||||
Self {
|
||||
title: if title.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(title.to_string())
|
||||
},
|
||||
level,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn add_content(&self, content: MdContent) {
|
||||
self.content.borrow_mut().push(content);
|
||||
}
|
||||
|
||||
fn append(&self, child: &Rc<TokenTreeFactory>) {
|
||||
self.children.borrow_mut().push(child.clone());
|
||||
}
|
||||
|
||||
pub fn create(content: &str) -> TokenTree {
|
||||
let tokens = MdToken::from(content);
|
||||
|
||||
let mut stack = Vec::new();
|
||||
let root = Rc::new(TokenTreeFactory::default());
|
||||
stack.push(root.clone());
|
||||
|
||||
for token in tokens {
|
||||
match token {
|
||||
MdToken::Header(Header { level, content }) => {
|
||||
let new_header = Rc::new(TokenTreeFactory::new(&content, level));
|
||||
|
||||
// go back until we're at the same or lower level.
|
||||
while let Some(current) = stack.pop() {
|
||||
if current.level < level {
|
||||
current.append(&new_header);
|
||||
stack.push(current);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
stack.push(new_header.clone());
|
||||
}
|
||||
MdToken::Content(content) => {
|
||||
let current = stack.pop().unwrap();
|
||||
current.add_content(content);
|
||||
stack.push(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
root.into()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn should_remove_surrounding_asterix() {
|
||||
// given
|
||||
let input = r#"
|
||||
# A
|
||||
**B**
|
||||
"#
|
||||
.trim_matches('\n')
|
||||
.trim();
|
||||
|
||||
// when
|
||||
let tree = TokenTreeFactory::create(input);
|
||||
|
||||
// then
|
||||
println!("{:#?}", tree);
|
||||
let first = tree.children.first().unwrap();
|
||||
let content = first.content.first().unwrap();
|
||||
assert_eq!(*content, MdContent::Asterix("B".into()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_remove_surrounding_hash() {
|
||||
// given
|
||||
let input = r#"
|
||||
# A #
|
||||
"#
|
||||
.trim_matches('\n')
|
||||
.trim();
|
||||
|
||||
// when
|
||||
let tree = TokenTreeFactory::create(input);
|
||||
|
||||
// then
|
||||
println!("{:#?}", tree);
|
||||
assert_eq!(tree.children.first().unwrap().title, Some("A".into()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_level() {
|
||||
// given
|
||||
let input = r#"
|
||||
# A
|
||||
Foo
|
||||
"#
|
||||
.trim_matches('\n')
|
||||
.trim();
|
||||
|
||||
// when
|
||||
let tree = TokenTreeFactory::create(input);
|
||||
|
||||
// then
|
||||
println!("{:#?}", tree);
|
||||
assert_eq!(tree.title, None);
|
||||
let first_child = tree.children.first().unwrap();
|
||||
assert_eq!(first_child.title, Some("A".into()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn complex() {
|
||||
// given
|
||||
let input = r#"
|
||||
# A
|
||||
Foo
|
||||
## B
|
||||
# C
|
||||
## D
|
||||
Bar
|
||||
"#
|
||||
.trim_matches('\n')
|
||||
.trim();
|
||||
|
||||
// when
|
||||
let tree = TokenTreeFactory::create(input);
|
||||
|
||||
// then
|
||||
println!("{:#?}", tree);
|
||||
assert_eq!(tree.title, None);
|
||||
assert_eq!(tree.children.len(), 2);
|
||||
|
||||
let first = tree.children.get(0).unwrap();
|
||||
assert_eq!(first.title, Some("A".into()));
|
||||
assert_eq!(first.children.len(), 1);
|
||||
assert_eq!(first.children.first().unwrap().title, Some("B".into()));
|
||||
|
||||
let second = tree.children.get(1).unwrap();
|
||||
assert_eq!(second.title, Some("C".into()));
|
||||
assert_eq!(second.children.len(), 1);
|
||||
assert_eq!(second.children.first().unwrap().title, Some("D".into()));
|
||||
}
|
||||
}
|
||||
pub use md_token::*;
|
||||
pub use token_tree::TokenTree;
|
||||
pub use token_tree_factory::TokenTreeFactory;
|
||||
|
|
30
qbittorrent-web-api-gen/src/md_parser/token_tree.rs
Normal file
30
qbittorrent-web-api-gen/src/md_parser/token_tree.rs
Normal file
|
@ -0,0 +1,30 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
use super::{md_token::MdContent, token_tree_factory::TokenTreeFactory};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TokenTree {
|
||||
pub title: Option<String>,
|
||||
pub content: Vec<MdContent>,
|
||||
pub children: Vec<TokenTree>,
|
||||
}
|
||||
|
||||
impl From<Rc<TokenTreeFactory>> for TokenTree {
|
||||
fn from(builder: Rc<TokenTreeFactory>) -> Self {
|
||||
let children = builder
|
||||
.children
|
||||
.clone()
|
||||
.into_inner()
|
||||
.into_iter()
|
||||
.map(|child| child.into())
|
||||
.collect::<Vec<TokenTree>>();
|
||||
|
||||
let content = builder.content.clone().into_inner();
|
||||
|
||||
TokenTree {
|
||||
title: builder.title.clone(),
|
||||
content,
|
||||
children,
|
||||
}
|
||||
}
|
||||
}
|
166
qbittorrent-web-api-gen/src/md_parser/token_tree_factory.rs
Normal file
166
qbittorrent-web-api-gen/src/md_parser/token_tree_factory.rs
Normal file
|
@ -0,0 +1,166 @@
|
|||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use super::{
|
||||
md_token::{Header, MdContent, MdToken},
|
||||
token_tree::TokenTree,
|
||||
};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TokenTreeFactory {
|
||||
pub title: Option<String>,
|
||||
pub content: RefCell<Vec<MdContent>>,
|
||||
pub children: RefCell<Vec<Rc<TokenTreeFactory>>>,
|
||||
pub level: i32,
|
||||
}
|
||||
|
||||
impl TokenTreeFactory {
|
||||
fn new(title: &str, level: i32) -> Self {
|
||||
Self {
|
||||
title: if title.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(title.to_string())
|
||||
},
|
||||
level,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
fn add_content(&self, content: MdContent) {
|
||||
self.content.borrow_mut().push(content);
|
||||
}
|
||||
|
||||
fn append(&self, child: &Rc<TokenTreeFactory>) {
|
||||
self.children.borrow_mut().push(child.clone());
|
||||
}
|
||||
|
||||
pub fn create(content: &str) -> TokenTree {
|
||||
let tokens = MdToken::from(content);
|
||||
|
||||
let mut stack = Vec::new();
|
||||
let root = Rc::new(TokenTreeFactory::default());
|
||||
stack.push(root.clone());
|
||||
|
||||
for token in tokens {
|
||||
match token {
|
||||
MdToken::Header(Header { level, content }) => {
|
||||
let new_header = Rc::new(TokenTreeFactory::new(&content, level));
|
||||
|
||||
// go back until we're at the same or lower level.
|
||||
while let Some(current) = stack.pop() {
|
||||
if current.level < level {
|
||||
current.append(&new_header);
|
||||
stack.push(current);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
stack.push(new_header.clone());
|
||||
}
|
||||
MdToken::Content(content) => {
|
||||
let current = stack.pop().unwrap();
|
||||
current.add_content(content);
|
||||
stack.push(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
root.into()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn should_remove_surrounding_asterix() {
|
||||
// given
|
||||
let input = r#"
|
||||
# A
|
||||
**B**
|
||||
"#
|
||||
.trim_matches('\n')
|
||||
.trim();
|
||||
|
||||
// when
|
||||
let tree = TokenTreeFactory::create(input);
|
||||
|
||||
// then
|
||||
println!("{:#?}", tree);
|
||||
let first = tree.children.first().unwrap();
|
||||
let content = first.content.first().unwrap();
|
||||
assert_eq!(*content, MdContent::Asterix("B".into()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_remove_surrounding_hash() {
|
||||
// given
|
||||
let input = r#"
|
||||
# A #
|
||||
"#
|
||||
.trim_matches('\n')
|
||||
.trim();
|
||||
|
||||
// when
|
||||
let tree = TokenTreeFactory::create(input);
|
||||
|
||||
// then
|
||||
println!("{:#?}", tree);
|
||||
assert_eq!(tree.children.first().unwrap().title, Some("A".into()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_level() {
|
||||
// given
|
||||
let input = r#"
|
||||
# A
|
||||
Foo
|
||||
"#
|
||||
.trim_matches('\n')
|
||||
.trim();
|
||||
|
||||
// when
|
||||
let tree = TokenTreeFactory::create(input);
|
||||
|
||||
// then
|
||||
println!("{:#?}", tree);
|
||||
assert_eq!(tree.title, None);
|
||||
let first_child = tree.children.first().unwrap();
|
||||
assert_eq!(first_child.title, Some("A".into()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn complex() {
|
||||
// given
|
||||
let input = r#"
|
||||
# A
|
||||
Foo
|
||||
## B
|
||||
# C
|
||||
## D
|
||||
Bar
|
||||
"#
|
||||
.trim_matches('\n')
|
||||
.trim();
|
||||
|
||||
// when
|
||||
let tree = TokenTreeFactory::create(input);
|
||||
|
||||
// then
|
||||
println!("{:#?}", tree);
|
||||
assert_eq!(tree.title, None);
|
||||
assert_eq!(tree.children.len(), 2);
|
||||
|
||||
let first = tree.children.get(0).unwrap();
|
||||
assert_eq!(first.title, Some("A".into()));
|
||||
assert_eq!(first.children.len(), 1);
|
||||
assert_eq!(first.children.first().unwrap().title, Some("B".into()));
|
||||
|
||||
let second = tree.children.get(1).unwrap();
|
||||
assert_eq!(second.title, Some("C".into()));
|
||||
assert_eq!(second.children.len(), 1);
|
||||
assert_eq!(second.children.first().unwrap().title, Some("D".into()));
|
||||
}
|
||||
}
|
|
@ -1,9 +1,8 @@
|
|||
use anyhow::Result;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
mod common;
|
||||
|
||||
const USERNAME: &str = "admin";
|
||||
const PASSWORD: &str = "adminadmin";
|
||||
const BASE_URL: &str = "http://localhost:8080";
|
||||
use anyhow::Result;
|
||||
use common::*;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
|
||||
#[derive(QBittorrentApiGen)]
|
||||
struct Api {}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use anyhow::Result;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
mod common;
|
||||
|
||||
const USERNAME: &str = "admin";
|
||||
const PASSWORD: &str = "adminadmin";
|
||||
const BASE_URL: &str = "http://localhost:8080";
|
||||
use anyhow::Result;
|
||||
use common::*;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
|
||||
#[derive(QBittorrentApiGen)]
|
||||
struct Api {}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use anyhow::Result;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
mod common;
|
||||
|
||||
const USERNAME: &str = "admin";
|
||||
const PASSWORD: &str = "adminadmin";
|
||||
const BASE_URL: &str = "http://localhost:8080";
|
||||
use anyhow::Result;
|
||||
use common::*;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
|
||||
#[derive(QBittorrentApiGen)]
|
||||
struct Foo {}
|
||||
|
|
3
qbittorrent-web-api-gen/tests/common/mod.rs
Normal file
3
qbittorrent-web-api-gen/tests/common/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub const USERNAME: &str = "admin";
|
||||
pub const PASSWORD: &str = "adminadmin";
|
||||
pub const BASE_URL: &str = "http://localhost:8080";
|
|
@ -1,9 +1,8 @@
|
|||
use anyhow::Result;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
mod common;
|
||||
|
||||
const USERNAME: &str = "admin";
|
||||
const PASSWORD: &str = "adminadmin";
|
||||
const BASE_URL: &str = "http://localhost:8080";
|
||||
use anyhow::Result;
|
||||
use common::*;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
|
||||
#[derive(QBittorrentApiGen)]
|
||||
struct Api {}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use anyhow::Result;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
mod common;
|
||||
|
||||
const USERNAME: &str = "admin";
|
||||
const PASSWORD: &str = "adminadmin";
|
||||
const BASE_URL: &str = "http://localhost:8080";
|
||||
use anyhow::Result;
|
||||
use common::*;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
|
||||
#[derive(QBittorrentApiGen)]
|
||||
struct Api {}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use anyhow::Result;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
mod common;
|
||||
|
||||
const USERNAME: &str = "admin";
|
||||
const PASSWORD: &str = "adminadmin";
|
||||
const BASE_URL: &str = "http://localhost:8080";
|
||||
use anyhow::Result;
|
||||
use common::*;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
|
||||
#[derive(QBittorrentApiGen)]
|
||||
struct Api {}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use anyhow::Result;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
mod common;
|
||||
|
||||
const USERNAME: &str = "admin";
|
||||
const PASSWORD: &str = "adminadmin";
|
||||
const BASE_URL: &str = "http://localhost:8080";
|
||||
use anyhow::Result;
|
||||
use common::*;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
|
||||
#[derive(QBittorrentApiGen)]
|
||||
struct Api {}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use anyhow::Result;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
use tokio::time::{sleep, Duration};
|
||||
mod common;
|
||||
|
||||
const USERNAME: &str = "admin";
|
||||
const PASSWORD: &str = "adminadmin";
|
||||
const BASE_URL: &str = "http://localhost:8080";
|
||||
use anyhow::Result;
|
||||
use common::*;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
use tokio::time::*;
|
||||
|
||||
#[derive(QBittorrentApiGen)]
|
||||
struct Api {}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use anyhow::Result;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
use tokio::time::{sleep, Duration};
|
||||
mod common;
|
||||
|
||||
const USERNAME: &str = "admin";
|
||||
const PASSWORD: &str = "adminadmin";
|
||||
const BASE_URL: &str = "http://localhost:8080";
|
||||
use anyhow::Result;
|
||||
use common::*;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
use tokio::time::*;
|
||||
|
||||
#[derive(QBittorrentApiGen)]
|
||||
struct Api {}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#[test]
|
||||
fn tests() {
|
||||
let t = trybuild::TestCases::new();
|
||||
|
||||
// --- Auth ---
|
||||
t.pass("tests/login.rs");
|
||||
t.pass("tests/logout.rs");
|
||||
|
@ -19,5 +20,5 @@ fn tests() {
|
|||
t.pass("tests/add_torrent.rs");
|
||||
t.pass("tests/another_struct_name.rs");
|
||||
t.pass("tests/access_impl_types.rs");
|
||||
t.pass("tests/search_types.rs");
|
||||
// t.pass("tests/search_types.rs");
|
||||
}
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
use anyhow::Result;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
mod common;
|
||||
|
||||
const USERNAME: &str = "admin";
|
||||
const PASSWORD: &str = "adminadmin";
|
||||
const BASE_URL: &str = "http://localhost:8080";
|
||||
use anyhow::Result;
|
||||
use common::*;
|
||||
use qbittorrent_web_api_gen::QBittorrentApiGen;
|
||||
|
||||
#[derive(QBittorrentApiGen)]
|
||||
struct Api {}
|
||||
|
|
Loading…
Reference in New Issue
Block a user