actor.rs
1 use playwright_rs::{expect, expect_page, Page}; 2 use std::time::Duration; 3 4 use crate::locators::Locator; 5 6 pub type Result = std::result::Result<(), Box<dyn std::error::Error>>; 7 8 pub trait Task { 9 async fn perform(self, page: &Page) -> Result; 10 } 11 12 pub struct Actor { 13 page: Page, 14 } 15 16 impl Actor { 17 pub fn new(page: Page) -> Self { 18 Self { page } 19 } 20 21 pub async fn attempts_to(&self, task: impl Task) -> Result { 22 task.perform(&self.page).await 23 } 24 25 pub fn expect(&self, locator: Locator) -> PendingExpectation<'_> { 26 PendingExpectation { 27 page: &self.page, 28 locator, 29 negate: false, 30 timeout: None, 31 } 32 } 33 34 pub fn expect_page(&self) -> playwright_rs::PageExpectation { 35 expect_page(&self.page) 36 } 37 38 pub async fn locate(&self, locator: Locator) -> playwright_rs::Locator { 39 locator.resolve(&self.page).await 40 } 41 42 pub fn page(&self) -> &Page { 43 &self.page 44 } 45 } 46 47 pub struct PendingExpectation<'a> { 48 page: &'a Page, 49 locator: Locator, 50 negate: bool, 51 timeout: Option<Duration>, 52 } 53 54 macro_rules! expect_method { 55 ($name:ident) => { 56 pub async fn $name(self) -> Result { 57 let (el, negate, timeout) = self.resolve().await; 58 let mut e = expect(el); 59 if negate { e = e.not(); } 60 if let Some(t) = timeout { e = e.with_timeout(t); } 61 e.$name().await?; 62 Ok(()) 63 } 64 }; 65 ($name:ident, $arg:ident: $ty:ty) => { 66 pub async fn $name(self, $arg: $ty) -> Result { 67 let (el, negate, timeout) = self.resolve().await; 68 let mut e = expect(el); 69 if negate { e = e.not(); } 70 if let Some(t) = timeout { e = e.with_timeout(t); } 71 e.$name($arg).await?; 72 Ok(()) 73 } 74 }; 75 } 76 77 impl PendingExpectation<'_> { 78 pub fn not(mut self) -> Self { 79 self.negate = true; 80 self 81 } 82 83 pub fn with_timeout(mut self, timeout: Duration) -> Self { 84 self.timeout = Some(timeout); 85 self 86 } 87 88 async fn resolve(self) -> (playwright_rs::Locator, bool, Option<Duration>) { 89 let el = self.locator.resolve(self.page).await; 90 (el, self.negate, self.timeout) 91 } 92 93 expect_method!(to_be_visible); 94 expect_method!(to_be_hidden); 95 expect_method!(to_be_enabled); 96 expect_method!(to_be_disabled); 97 expect_method!(to_be_checked); 98 expect_method!(to_be_unchecked); 99 expect_method!(to_be_editable); 100 expect_method!(to_be_focused); 101 expect_method!(to_have_text, expected: &str); 102 expect_method!(to_have_text_regex, pattern: &str); 103 expect_method!(to_contain_text, expected: &str); 104 expect_method!(to_contain_text_regex, pattern: &str); 105 expect_method!(to_have_value, expected: &str); 106 expect_method!(to_have_value_regex, pattern: &str); 107 108 pub async fn to_have_screenshot( 109 self, 110 baseline_path: impl AsRef<std::path::Path>, 111 options: Option<playwright_rs::ScreenshotAssertionOptions>, 112 ) -> Result { 113 let (el, negate, timeout) = self.resolve().await; 114 let mut e = expect(el); 115 if negate { e = e.not(); } 116 if let Some(t) = timeout { e = e.with_timeout(t); } 117 e.to_have_screenshot(baseline_path, options).await?; 118 Ok(()) 119 } 120 }