Update bottest
This commit is contained in:
parent
706391b272
commit
7c6c48be3a
10 changed files with 222 additions and 115 deletions
20
Cargo.toml
20
Cargo.toml
|
|
@ -5,6 +5,9 @@ edition = "2021"
|
|||
description = "Comprehensive test suite for General Bots - Unit, Integration, and E2E testing"
|
||||
license = "AGPL-3.0"
|
||||
repository = "https://github.com/GeneralBots/BotServer"
|
||||
readme = "README.md"
|
||||
keywords = ["testing", "bot", "integration-testing", "e2e", "general-bots"]
|
||||
categories = ["development-tools::testing"]
|
||||
|
||||
[dependencies]
|
||||
# The server we're testing - include drive and cache for required deps
|
||||
|
|
@ -105,3 +108,20 @@ required-features = ["e2e"]
|
|||
[[bin]]
|
||||
name = "bottest"
|
||||
path = "src/main.rs"
|
||||
|
||||
[lints.rust]
|
||||
unused_imports = "warn"
|
||||
unused_variables = "warn"
|
||||
unused_mut = "warn"
|
||||
unsafe_code = "deny"
|
||||
missing_debug_implementations = "warn"
|
||||
|
||||
[lints.clippy]
|
||||
all = "warn"
|
||||
pedantic = "warn"
|
||||
nursery = "warn"
|
||||
cargo = "warn"
|
||||
unwrap_used = "warn"
|
||||
expect_used = "warn"
|
||||
panic = "warn"
|
||||
todo = "warn"
|
||||
|
|
|
|||
92
PROMPT.md
92
PROMPT.md
|
|
@ -5,6 +5,84 @@
|
|||
|
||||
---
|
||||
|
||||
## ZERO TOLERANCE POLICY
|
||||
|
||||
**This project has the strictest code quality requirements possible.**
|
||||
|
||||
**EVERY SINGLE WARNING MUST BE FIXED. NO EXCEPTIONS.**
|
||||
|
||||
---
|
||||
|
||||
## ABSOLUTE PROHIBITIONS
|
||||
|
||||
```
|
||||
❌ NEVER use #![allow()] or #[allow()] to silence warnings
|
||||
❌ NEVER use _ prefix for unused variables - DELETE the variable or USE it
|
||||
❌ NEVER use .unwrap() - use ? or proper error handling
|
||||
❌ NEVER use .expect() - use ? or proper error handling
|
||||
❌ NEVER use panic!() or unreachable!() - handle all cases
|
||||
❌ NEVER use todo!() or unimplemented!() - write real code
|
||||
❌ NEVER leave unused imports - DELETE them
|
||||
❌ NEVER leave dead code - DELETE it or IMPLEMENT it
|
||||
❌ NEVER use approximate constants (3.14159) - use std::f64::consts::PI
|
||||
❌ NEVER silence clippy - FIX THE CODE
|
||||
❌ NEVER add comments explaining what code does - code must be self-documenting
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MANDATORY CODE PATTERNS
|
||||
|
||||
### Error Handling - Use `?` Operator
|
||||
|
||||
```rust
|
||||
// ❌ WRONG
|
||||
let value = something.unwrap();
|
||||
let value = something.expect("msg");
|
||||
|
||||
// ✅ CORRECT
|
||||
let value = something?;
|
||||
let value = something.ok_or_else(|| Error::NotFound)?;
|
||||
```
|
||||
|
||||
### Self Usage in Impl Blocks
|
||||
|
||||
```rust
|
||||
// ❌ WRONG
|
||||
impl MyStruct {
|
||||
fn new() -> MyStruct { MyStruct { } }
|
||||
}
|
||||
|
||||
// ✅ CORRECT
|
||||
impl MyStruct {
|
||||
fn new() -> Self { Self { } }
|
||||
}
|
||||
```
|
||||
|
||||
### Format Strings - Inline Variables
|
||||
|
||||
```rust
|
||||
// ❌ WRONG
|
||||
format!("Hello {}", name)
|
||||
|
||||
// ✅ CORRECT
|
||||
format!("Hello {name}")
|
||||
```
|
||||
|
||||
### Derive Eq with PartialEq
|
||||
|
||||
```rust
|
||||
// ❌ WRONG
|
||||
#[derive(PartialEq)]
|
||||
struct MyStruct { }
|
||||
|
||||
// ✅ CORRECT
|
||||
#[derive(PartialEq, Eq)]
|
||||
struct MyStruct { }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Weekly Maintenance - EVERY MONDAY
|
||||
|
||||
### Package Review Checklist
|
||||
|
|
@ -214,3 +292,17 @@ Never create .md files at:
|
|||
- ✗ Any project root
|
||||
|
||||
All non-PROMPT.md documentation belongs in botbook.
|
||||
|
||||
---
|
||||
|
||||
## Remember
|
||||
|
||||
- **ZERO WARNINGS** - Every clippy warning must be fixed
|
||||
- **NO ALLOW ATTRIBUTES** - Never silence warnings, fix the code
|
||||
- **NO DEAD CODE** - Delete unused code, never prefix with _
|
||||
- **NO UNWRAP/EXPECT** - Use ? operator or proper error handling
|
||||
- **INLINE FORMAT ARGS** - format!("{name}") not format!("{}", name)
|
||||
- **USE SELF** - In impl blocks, use Self not the type name
|
||||
- **DERIVE EQ** - Always derive Eq with PartialEq
|
||||
- **Version**: Always 6.1.0 - do not change without approval
|
||||
- **Session Continuation**: When running out of context, create detailed summary: (1) what was done, (2) what remains, (3) specific files and line numbers, (4) exact next steps.
|
||||
|
|
|
|||
|
|
@ -312,28 +312,122 @@ impl BotRunner {
|
|||
}
|
||||
}
|
||||
|
||||
/// Execute bot logic (placeholder for actual implementation)
|
||||
async fn execute_bot_logic(
|
||||
&self,
|
||||
_session_id: Uuid,
|
||||
session_id: Uuid,
|
||||
message: &str,
|
||||
_state: &SessionState,
|
||||
state: &SessionState,
|
||||
) -> Result<BotResponse> {
|
||||
// In a real implementation, this would:
|
||||
// 1. Load the bot's BASIC script
|
||||
// 2. Execute it with the message as input
|
||||
// 3. Return the bot's response
|
||||
let start = Instant::now();
|
||||
|
||||
let bot = self.bot.as_ref().context("No bot configured")?;
|
||||
|
||||
let script_path = self
|
||||
.config
|
||||
.working_dir
|
||||
.join(&bot.name)
|
||||
.join("dialog")
|
||||
.join("start.bas");
|
||||
|
||||
let script_content = if script_path.exists() {
|
||||
tokio::fs::read_to_string(&script_path)
|
||||
.await
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
let cache = self.script_cache.lock().unwrap();
|
||||
cache.get("default").cloned().unwrap_or_default()
|
||||
};
|
||||
|
||||
let response_content = if script_content.is_empty() {
|
||||
format!("Received: {}", message)
|
||||
} else {
|
||||
self.evaluate_basic_script(&script_content, message, &state.context)
|
||||
.await
|
||||
.unwrap_or_else(|e| format!("Error: {}", e))
|
||||
};
|
||||
|
||||
let latency = start.elapsed().as_millis() as u64;
|
||||
|
||||
let mut metrics = self.metrics.lock().unwrap();
|
||||
metrics.total_requests += 1;
|
||||
metrics.successful_requests += 1;
|
||||
metrics.total_latency_ms += latency;
|
||||
|
||||
// For now, return a mock response
|
||||
Ok(BotResponse {
|
||||
id: Uuid::new_v4(),
|
||||
content: format!("Echo: {}", message),
|
||||
content: response_content,
|
||||
content_type: ResponseContentType::Text,
|
||||
metadata: HashMap::new(),
|
||||
latency_ms: 50,
|
||||
metadata: HashMap::from([
|
||||
(
|
||||
"session_id".to_string(),
|
||||
serde_json::Value::String(session_id.to_string()),
|
||||
),
|
||||
(
|
||||
"bot_name".to_string(),
|
||||
serde_json::Value::String(bot.name.clone()),
|
||||
),
|
||||
]),
|
||||
latency_ms: latency,
|
||||
})
|
||||
}
|
||||
|
||||
async fn evaluate_basic_script(
|
||||
&self,
|
||||
script: &str,
|
||||
input: &str,
|
||||
context: &HashMap<String, serde_json::Value>,
|
||||
) -> Result<String> {
|
||||
let mut output = String::new();
|
||||
let mut variables: HashMap<String, String> = HashMap::new();
|
||||
|
||||
variables.insert("INPUT".to_string(), input.to_string());
|
||||
for (key, value) in context {
|
||||
variables.insert(key.to_uppercase(), value.to_string());
|
||||
}
|
||||
|
||||
for line in script.lines() {
|
||||
let line = line.trim();
|
||||
if line.is_empty() || line.starts_with('\'') || line.starts_with("REM") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if line.to_uppercase().starts_with("TALK") {
|
||||
let content = line[4..].trim().trim_matches('"');
|
||||
let expanded = self.expand_variables(content, &variables);
|
||||
if !output.is_empty() {
|
||||
output.push('\n');
|
||||
}
|
||||
output.push_str(&expanded);
|
||||
} else if line.to_uppercase().starts_with("HEAR") {
|
||||
variables.insert("LAST_INPUT".to_string(), input.to_string());
|
||||
} else if line.contains('=') && !line.to_uppercase().starts_with("IF") {
|
||||
let parts: Vec<&str> = line.splitn(2, '=').collect();
|
||||
if parts.len() == 2 {
|
||||
let var_name = parts[0].trim().to_uppercase();
|
||||
let var_value = parts[1].trim().trim_matches('"').to_string();
|
||||
let expanded = self.expand_variables(&var_value, &variables);
|
||||
variables.insert(var_name, expanded);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if output.is_empty() {
|
||||
output = format!("Processed: {}", input);
|
||||
}
|
||||
|
||||
Ok(output)
|
||||
}
|
||||
|
||||
fn expand_variables(&self, text: &str, variables: &HashMap<String, String>) -> String {
|
||||
let mut result = text.to_string();
|
||||
for (key, value) in variables {
|
||||
result = result.replace(&format!("{{{}}}", key), value);
|
||||
result = result.replace(&format!("${}", key), value);
|
||||
result = result.replace(key, value);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Execute a BASIC script directly
|
||||
pub async fn execute_script(
|
||||
&mut self,
|
||||
|
|
@ -379,7 +473,6 @@ impl BotRunner {
|
|||
metrics.script_executions += 1;
|
||||
}
|
||||
|
||||
// Execute script (placeholder)
|
||||
let result = self.execute_script_internal(&script, input).await;
|
||||
|
||||
let execution_time = start.elapsed();
|
||||
|
|
@ -410,11 +503,9 @@ impl BotRunner {
|
|||
}
|
||||
}
|
||||
|
||||
/// Internal script execution (placeholder)
|
||||
async fn execute_script_internal(&self, _script: &str, input: &str) -> Result<String> {
|
||||
// In a real implementation, this would parse and execute the BASIC script
|
||||
// For now, just echo the input
|
||||
Ok(format!("Script output for: {}", input))
|
||||
async fn execute_script_internal(&self, script: &str, input: &str) -> Result<String> {
|
||||
let context = HashMap::new();
|
||||
self.evaluate_basic_script(script, input, &context).await
|
||||
}
|
||||
|
||||
/// Get current metrics
|
||||
|
|
|
|||
|
|
@ -296,9 +296,7 @@ impl Default for QueueStatus {
|
|||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Factory Functions
|
||||
// =============================================================================
|
||||
|
||||
/// Create an admin user
|
||||
pub fn admin_user() -> User {
|
||||
|
|
|
|||
|
|
@ -25,9 +25,7 @@ pub trait Page {
|
|||
async fn wait_for_load(&self, browser: &Browser) -> Result<()>;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Login Page
|
||||
// =============================================================================
|
||||
|
||||
/// Login page object
|
||||
pub struct LoginPage {
|
||||
|
|
@ -120,9 +118,7 @@ impl Page for LoginPage {
|
|||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Dashboard Page
|
||||
// =============================================================================
|
||||
|
||||
/// Dashboard home page object
|
||||
pub struct DashboardPage {
|
||||
|
|
@ -199,9 +195,7 @@ impl Page for DashboardPage {
|
|||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Chat Page
|
||||
// =============================================================================
|
||||
|
||||
/// Chat interface page object
|
||||
pub struct ChatPage {
|
||||
|
|
@ -359,9 +353,7 @@ impl Page for ChatPage {
|
|||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Queue Panel Page
|
||||
// =============================================================================
|
||||
|
||||
/// Queue management panel page object
|
||||
pub struct QueuePage {
|
||||
|
|
@ -431,9 +423,7 @@ impl Page for QueuePage {
|
|||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Bot Management Page
|
||||
// =============================================================================
|
||||
|
||||
/// Bot management page object
|
||||
pub struct BotManagementPage {
|
||||
|
|
@ -528,9 +518,7 @@ impl Page for BotManagementPage {
|
|||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Knowledge Base Page
|
||||
// =============================================================================
|
||||
|
||||
/// Knowledge base management page object
|
||||
pub struct KnowledgeBasePage {
|
||||
|
|
@ -599,9 +587,7 @@ impl Page for KnowledgeBasePage {
|
|||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Analytics Page
|
||||
// =============================================================================
|
||||
|
||||
/// Analytics dashboard page object
|
||||
pub struct AnalyticsPage {
|
||||
|
|
@ -656,9 +642,7 @@ impl Page for AnalyticsPage {
|
|||
}
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Tests
|
||||
// =============================================================================
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
use rhai::Engine;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
// =============================================================================
|
||||
// Test Utilities
|
||||
// =============================================================================
|
||||
|
||||
/// Create a Rhai engine with BASIC-like functions registered
|
||||
fn create_basic_engine() -> Engine {
|
||||
|
|
@ -158,9 +156,7 @@ fn create_conversation_engine(output: OutputCollector, input: InputProvider) ->
|
|||
engine
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// String Function Tests with Engine
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_string_concatenation_in_engine() {
|
||||
|
|
@ -229,9 +225,7 @@ fn test_replace_function() {
|
|||
assert_eq!(result, "bbb");
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Math Function Tests with Engine
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_math_operations_chain() {
|
||||
|
|
@ -300,9 +294,7 @@ fn test_val_function() {
|
|||
assert!((result - 0.0).abs() < f64::EPSILON);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// TALK/HEAR Conversation Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_talk_output() {
|
||||
|
|
@ -426,9 +418,7 @@ fn test_keyword_detection() {
|
|||
assert_eq!(messages[0], "I can help you! What do you need?");
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Variable and Expression Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_variable_assignment() {
|
||||
|
|
@ -480,9 +470,7 @@ fn test_numeric_expressions() {
|
|||
assert_eq!(result, 12);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Loop and Control Flow Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_for_loop() {
|
||||
|
|
@ -527,9 +515,7 @@ fn test_while_loop() {
|
|||
assert_eq!(result, 10); // 0 + 1 + 2 + 3 + 4 = 10
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Error Handling Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_division_by_zero() {
|
||||
|
|
@ -561,9 +547,7 @@ fn test_type_mismatch() {
|
|||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Script Fixture Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_greeting_script_logic() {
|
||||
|
|
@ -659,9 +643,7 @@ fn test_echo_bot_logic() {
|
|||
assert_eq!(messages[2], "You said: How are you?");
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Complex Scenario Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_order_lookup_simulation() {
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ async fn test_query_result_types() {
|
|||
9223372036854775807::bigint as bigint_val,
|
||||
'hello' as text_val,
|
||||
true as bool_val,
|
||||
3.14159 as float_val",
|
||||
3.125 as float_val",
|
||||
)
|
||||
.load(&mut conn)
|
||||
.expect("Query failed");
|
||||
|
|
@ -184,7 +184,7 @@ async fn test_query_result_types() {
|
|||
assert_eq!(result[0].bigint_val, 9223372036854775807_i64);
|
||||
assert_eq!(result[0].text_val, "hello");
|
||||
assert!(result[0].bool_val);
|
||||
assert!((result[0].float_val - 3.14159).abs() < 0.0001);
|
||||
assert!((result[0].float_val - 3.125).abs() < 0.0001);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
|
|||
|
|
@ -66,9 +66,7 @@ fn get_next_in_queue(entries: &[QueueEntry]) -> Option<&QueueEntry> {
|
|||
Some(best)
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Priority Comparison Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_priority_ordering() {
|
||||
|
|
@ -83,9 +81,7 @@ fn test_priority_equality() {
|
|||
assert_ne!(Priority::Normal, Priority::High);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Queue Entry Comparison Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_higher_priority_comes_first() {
|
||||
|
|
@ -125,9 +121,7 @@ fn test_urgent_beats_everything() {
|
|||
assert_eq!(compare_queue_entries(&urgent, &low), Ordering::Less);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Queue Sorting Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_sort_queue_by_priority() {
|
||||
|
|
@ -180,9 +174,7 @@ fn test_sort_single_entry() {
|
|||
assert_eq!(queue[0].id, 1);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Get Next in Queue Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_get_next_returns_highest_priority() {
|
||||
|
|
@ -222,9 +214,7 @@ fn test_get_next_single_entry() {
|
|||
assert_eq!(next.id, 42);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Real-world Scenario Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_scenario_customer_support_queue() {
|
||||
|
|
@ -314,9 +304,7 @@ fn test_estimated_wait_time() {
|
|||
assert_eq!(estimated_wait, 10); // 2 people * 5 minutes each
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Edge Case Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_large_queue() {
|
||||
|
|
|
|||
|
|
@ -5,9 +5,7 @@
|
|||
|
||||
use rhai::Engine;
|
||||
|
||||
// =============================================================================
|
||||
// ABS Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_abs_positive() {
|
||||
|
|
@ -46,9 +44,7 @@ fn test_abs_float() {
|
|||
assert!((result - 3.14).abs() < f64::EPSILON);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// ROUND Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_round_up() {
|
||||
|
|
@ -86,9 +82,7 @@ fn test_round_negative() {
|
|||
assert_eq!(result, -4);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// INT / FIX Function Tests (Truncation)
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_int_positive() {
|
||||
|
|
@ -117,9 +111,7 @@ fn test_fix_alias() {
|
|||
assert_eq!(result, 7);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// FLOOR / CEIL Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_floor_positive() {
|
||||
|
|
@ -157,9 +149,7 @@ fn test_ceil_negative() {
|
|||
assert_eq!(result, -3);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// MIN / MAX Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_max_basic() {
|
||||
|
|
@ -224,9 +214,7 @@ fn test_min_negative() {
|
|||
assert_eq!(result, -10);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// MOD Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_mod_basic() {
|
||||
|
|
@ -255,9 +243,7 @@ fn test_mod_smaller_dividend() {
|
|||
assert_eq!(result, 3);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// SGN Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_sgn_positive() {
|
||||
|
|
@ -286,9 +272,7 @@ fn test_sgn_zero() {
|
|||
assert_eq!(result, 0);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// SQRT / SQR Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_sqrt_perfect_square() {
|
||||
|
|
@ -317,9 +301,7 @@ fn test_sqr_alias() {
|
|||
assert!((result - 5.0).abs() < f64::EPSILON);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// POW Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_pow_basic() {
|
||||
|
|
@ -348,9 +330,7 @@ fn test_pow_square_root() {
|
|||
assert!((result - 3.0).abs() < 0.00001);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// LOG / LOG10 / EXP Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_log_e() {
|
||||
|
|
@ -389,9 +369,7 @@ fn test_exp_one() {
|
|||
assert!((result - std::f64::consts::E).abs() < 0.00001);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Trigonometric Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_sin_zero() {
|
||||
|
|
@ -429,9 +407,7 @@ fn test_pi_constant() {
|
|||
assert!((result - std::f64::consts::PI).abs() < f64::EPSILON);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// VAL Function Tests (String to Number)
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_val_integer() {
|
||||
|
|
@ -488,9 +464,7 @@ fn test_val_with_whitespace() {
|
|||
assert!((result - 42.0).abs() < f64::EPSILON);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Combined Math Expression Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_combined_abs_sqrt() {
|
||||
|
|
|
|||
|
|
@ -8,9 +8,7 @@
|
|||
|
||||
use rhai::Engine;
|
||||
|
||||
// =============================================================================
|
||||
// INSTR Function Tests - Testing the actual behavior
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_instr_finds_substring() {
|
||||
|
|
@ -67,9 +65,7 @@ fn test_instr_case_sensitive() {
|
|||
assert_eq!(result, 0); // Case sensitive, so not found
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// UPPER / UCASE Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_upper_basic() {
|
||||
|
|
@ -98,9 +94,7 @@ fn test_ucase_alias() {
|
|||
assert_eq!(result, "TEST");
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// LOWER / LCASE Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_lower_basic() {
|
||||
|
|
@ -120,9 +114,7 @@ fn test_lcase_alias() {
|
|||
assert_eq!(result, "test");
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// LEN Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_len_basic() {
|
||||
|
|
@ -151,9 +143,7 @@ fn test_len_with_spaces() {
|
|||
assert_eq!(result, 11);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// TRIM / LTRIM / RTRIM Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_trim_both_sides() {
|
||||
|
|
@ -182,9 +172,7 @@ fn test_rtrim() {
|
|||
assert_eq!(result, " hello");
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// LEFT Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_left_basic() {
|
||||
|
|
@ -222,9 +210,7 @@ fn test_left_zero() {
|
|||
assert_eq!(result, "");
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// RIGHT Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_right_basic() {
|
||||
|
|
@ -260,9 +246,7 @@ fn test_right_exceeds_length() {
|
|||
assert_eq!(result, "Hi");
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// MID Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_mid_with_length() {
|
||||
|
|
@ -294,9 +278,7 @@ fn test_mid_one_based_index() {
|
|||
assert_eq!(result, "C");
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// REPLACE Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_replace_basic() {
|
||||
|
|
@ -333,9 +315,7 @@ fn test_replace_not_found() {
|
|||
assert_eq!(result, "Hello");
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// IS_NUMERIC Function Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_is_numeric_integer() {
|
||||
|
|
@ -397,9 +377,7 @@ fn test_is_numeric_empty() {
|
|||
assert!(!result);
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Combined Expression Tests
|
||||
// =============================================================================
|
||||
|
||||
#[test]
|
||||
fn test_combined_string_operations() {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue