1#![allow(
2 clippy::missing_errors_doc,
3 clippy::missing_panics_doc,
4 clippy::must_use_candidate,
5 clippy::must_use_unit,
6 clippy::return_self_not_must_use,
7 clippy::doc_markdown,
8 clippy::doc_link_with_quotes,
9 clippy::module_name_repetitions,
10 clippy::cast_possible_truncation,
11 clippy::cast_precision_loss,
12 clippy::redundant_closure_for_method_calls,
13 clippy::implicit_clone,
14 clippy::struct_excessive_bools,
15 clippy::large_enum_variant,
16 clippy::needless_raw_string_hashes,
17 clippy::should_implement_trait,
18 clippy::match_same_arms,
19 clippy::uninlined_format_args,
20 clippy::single_char_pattern,
21 clippy::unused_self,
22 clippy::unused_async,
23 clippy::bool_to_int_with_if,
24 clippy::manual_let_else,
25 clippy::too_many_lines,
26 clippy::impl_trait_in_params,
27 clippy::needless_pass_by_value,
28 clippy::match_wildcard_for_single_variants,
29 clippy::manual_string_new,
30 clippy::format_push_string,
31 clippy::trivially_copy_pass_by_ref,
32 clippy::unnecessary_wraps,
33 clippy::default_trait_access,
34 clippy::wildcard_imports,
35 clippy::items_after_statements,
36 clippy::field_reassign_with_default,
37 clippy::map_unwrap_or,
38 clippy::iter_on_single_items,
39 clippy::similar_names,
40 clippy::semicolon_if_nothing_returned,
41 clippy::inconsistent_struct_constructor,
42 clippy::derivable_impls,
43 clippy::used_underscore_items,
44 clippy::explicit_iter_loop,
45 clippy::iter_on_empty_collections,
46 clippy::wrong_self_convention,
47 clippy::unnecessary_sort_by,
48 clippy::iter_over_hash_type,
49 clippy::manual_assert,
50 clippy::explicit_deref_methods,
51 clippy::option_if_let_else,
52 clippy::match_bool,
53 clippy::ref_option,
54 clippy::needless_lifetimes,
55 clippy::type_complexity,
56 clippy::expect_used,
57 clippy::duration_subsec,
58 clippy::verbose_file_reads,
59 clippy::if_not_else,
60 clippy::implicit_hasher,
61 clippy::stable_sort_primitive
62)]
63pub type Result<T> = std::result::Result<T, model::TestFailure>;
94
95pub mod config;
97pub mod context;
98pub mod ct;
99pub mod discovery;
100pub mod dispatcher;
101pub mod expect;
102pub mod fixture;
103pub mod git_info;
104pub mod interactive;
105pub mod logging;
106pub mod model;
107pub mod reporter;
108pub mod retry;
109pub mod runner;
110pub mod server;
111pub mod shard;
112pub mod snapshot;
113pub mod tracing;
114pub mod tui;
115pub mod tui_reporter;
116pub mod watch;
117pub mod worker;
118
119pub use config::{CliOverrides, TestConfig, parse_common_cli_args};
121pub use context::TestContext;
122pub use discovery::{
123 FixtureRegistration, HookKindTag, HookRegistration as InventoryHookRegistration, SuiteModeRegistration,
124 TestRegistration, collect_rust_fixtures,
125};
126pub use expect::{ToPassOptions, expect, expect_configured, expect_poll, to_pass, to_pass_with_options};
127pub use fixture::{FixtureDef, FixturePool, FixtureScope};
128pub use model::{
129 HookDef, HookKind, HookOwner, HookPhase, HookRegistration, HookScope, SuiteDef, SuiteMode, TestAnnotation, TestCase,
130 TestFailure, TestFixtures, TestFn, TestId, TestInfo, TestModifiers, TestOutcome, TestPlan, TestPlanBuilder,
131 TestStatus, TestStep,
132};
133pub use reporter::{EventBus, EventBusBuilder, Reporter, ReporterDriver, ReporterEvent, ReporterSet, Subscription};
134pub use runner::TestRunner;
135
136pub use ferridriver_test_macros::{
138 after_all, after_each, before_all, before_each, ferritest, ferritest_each, ferritest_suite, fixture,
139};
140
141pub use inventory;
143
144#[macro_export]
162macro_rules! main {
163 () => {
164 fn main() {
165 $crate::run_harness();
166 }
167 };
168}
169
170pub fn run_harness() {
173 logging::init_from_env();
174
175 let rt = tokio::runtime::Builder::new_multi_thread()
176 .enable_all()
177 .build()
178 .expect("failed to build tokio runtime");
179
180 let exit_code = rt.block_on(async {
181 let overrides = config::parse_common_cli_args();
182 let config = config::resolve_config(&overrides).unwrap_or_else(|e| {
183 eprintln!("config error: {e}");
184 std::process::exit(1);
185 });
186 let plan = discovery::collect_rust_tests(&config);
187 let mut runner = runner::TestRunner::new(config, overrides);
188 Box::pin(runner.run(plan)).await
189 });
190
191 rt.shutdown_timeout(std::time::Duration::from_secs(5));
196
197 std::process::exit(exit_code);
198}
199
200pub mod prelude {
202 pub use ferridriver::{Browser, ContextRef as BrowserContext, Locator, Page};
203
204 pub use crate::context::TestContext;
205 pub use crate::expect::{expect, expect_configured, expect_poll, to_pass};
206 pub use crate::fixture::FixturePool;
207 pub use crate::model::{TestFailure, TestInfo};
208 pub use ferridriver_test_macros::{
209 after_all, after_each, before_all, before_each, ferritest, ferritest_each, ferritest_suite, fixture,
210 };
211}