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 mod config;
93pub mod context;
94pub mod ct;
95pub mod discovery;
96pub mod dispatcher;
97pub mod expect;
98pub mod fixture;
99pub mod git_info;
100pub mod interactive;
101pub mod logging;
102pub mod model;
103pub mod reporter;
104pub mod retry;
105pub mod runner;
106pub mod server;
107pub mod shard;
108pub mod snapshot;
109pub mod tracing;
110pub mod tui;
111pub mod tui_reporter;
112pub mod watch;
113pub mod worker;
114
115pub use config::{CliOverrides, TestConfig, parse_common_cli_args};
117pub use context::TestContext;
118pub use discovery::{HookKindTag, HookRegistration as InventoryHookRegistration, TestRegistration};
119pub use expect::{ToPassOptions, expect, expect_configured, expect_poll, to_pass, to_pass_with_options};
120pub use fixture::FixturePool;
121pub use model::{
122 HookDef, HookKind, HookOwner, HookPhase, HookRegistration, HookScope, SuiteDef, SuiteMode, TestAnnotation, TestCase,
123 TestFailure, TestFixtures, TestFn, TestId, TestInfo, TestModifiers, TestOutcome, TestPlan, TestPlanBuilder,
124 TestStatus, TestStep,
125};
126pub use reporter::{EventBus, EventBusBuilder, Reporter, ReporterDriver, ReporterEvent, ReporterSet, Subscription};
127pub use runner::TestRunner;
128
129pub use ferridriver_test_macros::{after_all, after_each, before_all, before_each, ferritest, ferritest_each};
131
132pub use inventory;
134
135#[macro_export]
152macro_rules! main {
153 () => {
154 fn main() {
155 $crate::run_harness();
156 }
157 };
158}
159
160pub fn run_harness() {
163 logging::init_from_env();
164
165 let rt = tokio::runtime::Builder::new_multi_thread()
166 .enable_all()
167 .build()
168 .expect("failed to build tokio runtime");
169
170 let exit_code = rt.block_on(async {
171 let overrides = config::parse_common_cli_args();
172 let config = config::resolve_config(&overrides).unwrap_or_else(|e| {
173 eprintln!("config error: {e}");
174 std::process::exit(1);
175 });
176 let plan = discovery::collect_rust_tests(&config);
177 let mut runner = runner::TestRunner::new(config, overrides);
178 Box::pin(runner.run(plan)).await
179 });
180
181 rt.shutdown_timeout(std::time::Duration::from_secs(5));
186
187 std::process::exit(exit_code);
188}
189
190pub mod prelude {
192 pub use ferridriver::{Browser, ContextRef as BrowserContext, Locator, Page};
193
194 pub use crate::context::TestContext;
195 pub use crate::expect::{expect, expect_configured, expect_poll, to_pass};
196 pub use crate::fixture::FixturePool;
197 pub use crate::model::{TestFailure, TestInfo};
198 pub use ferridriver_test_macros::{after_all, after_each, before_all, before_each, ferritest, ferritest_each};
199}