// use crate::{ git, repo::{ messages::{CloneRepo, MessageToken}, ActorLog, RepoActor, }, }; use git_next_core::{ git::{ commit::Sha, repository::{ factory::{mock, MockRepositoryFactory, RepositoryFactory}, open::{MockOpenRepositoryLike, OpenRepositoryLike}, Direction, }, Commit, ForgeLike, Generation, MockForgeLike, RepoDetails, }, message, webhook::{forge_notification::Body, Push}, BranchName, ForgeAlias, ForgeConfig, ForgeNotification, ForgeType, GitDir, Hostname, RegisteredWebhook, RemoteUrl, RepoAlias, RepoBranches, RepoConfig, RepoConfigSource, ServerRepoConfig, StoragePathType, WebhookAuth, WebhookId, }; use assert2::let_assert; use kameo::{ message::{Context, Message}, Reply, }; use mockall::predicate::eq; use tracing::{debug, error}; use std::{ collections::{BTreeMap, HashMap}, sync::{Arc, RwLock}, time::Duration, }; type TestResult = Result<(), Box>; mod branch; mod expect; pub mod given; mod handlers; mod load; mod when; pub async fn tick(millis: u64) { tokio::time::sleep(Duration::from_millis(millis)).await; } impl ActorLog { pub async fn no_message_contains( &self, needle: impl AsRef + Send + std::fmt::Display, ) -> TestResult { if self.find_in_messages(needle.as_ref()).await? { error!(?self, ""); panic!("found unexpected message: {needle}"); } Ok(()) } pub async fn require_message_containing( &self, needle: impl AsRef + Send + std::fmt::Display, ) -> TestResult { if !self.find_in_messages(needle.as_ref()).await? { error!(?self, ""); panic!("expected message not found: {needle}"); } Ok(()) } async fn find_in_messages( &self, needle: impl AsRef + Send, ) -> Result> { // Very short sleep to allow tests to get a chance to tick // This should be enough for most tests. tokio::time::sleep(Duration::from_millis(5)).await; let found = self .read() .await .iter() .any(|message| message.contains(needle.as_ref())); Ok(found) } } message!(ExamineActor => RepoActorView, "Request a view of the current state of the [RepoActor]."); impl Message for RepoActor { type Reply = RepoActorView; async fn handle( &mut self, _msg: ExamineActor, _ctx: Context<'_, Self, Self::Reply>, ) -> Self::Reply { let repo_actor: &Self = self; Self::Reply::from(repo_actor) } } #[derive(Debug, Reply)] pub struct RepoActorView { pub repo_details: RepoDetails, pub webhook_id: Option, // INFO: if [None] then no webhook is configured pub webhook_auth: Option, // INFO: if [None] then no webhook is configured pub last_main_commit: Option, pub last_next_commit: Option, pub last_dev_commit: Option, } impl From<&RepoActor> for RepoActorView { fn from(repo_actor: &RepoActor) -> Self { Self { repo_details: repo_actor.repo_details.clone(), webhook_id: repo_actor.webhook_id.clone(), webhook_auth: repo_actor.webhook_auth.clone(), last_main_commit: repo_actor.last_main_commit.clone(), last_next_commit: repo_actor.last_next_commit.clone(), last_dev_commit: repo_actor.last_dev_commit.clone(), } } }