use crate::application::services::action_service::{ActionService, ActionServiceImpl};
use crate::application::services::bookmark_service::BookmarkService;
use crate::application::services::interpolation_service::InterpolationService;
use crate::application::services::tag_service::TagService;
use crate::application::services::template_service::TemplateService;
use crate::application::{
BookmarkServiceImpl, InterpolationServiceImpl, TagServiceImpl, TemplateServiceImpl,
};
use crate::domain::action::BookmarkAction;
use crate::domain::action_resolver::{ActionResolver, SystemTagActionResolver};
use crate::domain::embedding::Embedder;
use crate::domain::services::clipboard::ClipboardService;
use crate::infrastructure::clipboard::ClipboardServiceImpl;
use crate::infrastructure::embeddings::DummyEmbedding;
use crate::infrastructure::interpolation::minijinja_engine::{MiniJinjaEngine, SafeShellExecutor};
use crate::infrastructure::repositories::file_import_repository::FileImportRepository;
use crate::infrastructure::repositories::sqlite::repository::SqliteBookmarkRepository;
use crate::lsp::backend::BkmrConfig;
use crate::lsp::services::snippet_service::LspSnippetService;
use crate::util::testing::EnvGuard;
use std::sync::Arc;
pub struct TestServiceContainer {
pub _env_guard: EnvGuard,
pub bookmark_repository: Arc<SqliteBookmarkRepository>,
pub embedder: Arc<dyn Embedder>,
pub bookmark_service: Arc<dyn BookmarkService>,
pub tag_service: Arc<dyn TagService>,
pub action_service: Arc<dyn ActionService>,
pub clipboard_service: Arc<dyn ClipboardService>,
pub interpolation_service: Arc<dyn InterpolationService>,
pub template_service: Arc<dyn TemplateService>,
}
impl TestServiceContainer {
pub fn new() -> Self {
let env_guard = EnvGuard::new();
let bookmark_repository = Self::create_shared_test_db();
let embedder = Self::create_test_embedder();
let clipboard_service = Arc::new(ClipboardServiceImpl::new());
let interpolation_service = Self::create_interpolation_service();
let template_service = Self::create_template_service();
let bookmark_service = Arc::new(BookmarkServiceImpl::new(
bookmark_repository.clone(),
embedder.clone(),
Arc::new(FileImportRepository::new()),
));
let tag_service = Arc::new(TagServiceImpl::new(bookmark_repository.clone()));
let action_service = Self::create_test_action_service(
&bookmark_repository,
&interpolation_service,
&(clipboard_service.clone() as Arc<dyn ClipboardService>),
&embedder,
);
Self {
_env_guard: env_guard,
bookmark_repository,
embedder,
bookmark_service,
tag_service,
action_service,
clipboard_service,
interpolation_service,
template_service,
}
}
fn create_shared_test_db() -> Arc<SqliteBookmarkRepository> {
Arc::new(crate::util::testing::setup_test_db())
}
fn create_test_embedder() -> Arc<dyn Embedder> {
Arc::new(DummyEmbedding)
}
fn create_interpolation_service() -> Arc<dyn InterpolationService> {
let shell_executor = Arc::new(SafeShellExecutor::new());
let interpolation_engine = Arc::new(MiniJinjaEngine::new(shell_executor));
Arc::new(InterpolationServiceImpl::new(interpolation_engine))
}
fn create_template_service() -> Arc<dyn TemplateService> {
Arc::new(TemplateServiceImpl::new())
}
fn create_test_action_service(
repository: &Arc<SqliteBookmarkRepository>,
interpolation_service: &Arc<dyn InterpolationService>,
clipboard_service: &Arc<dyn ClipboardService>,
embedder: &Arc<dyn Embedder>,
) -> Arc<dyn ActionService> {
let resolver = Self::create_test_action_resolver(
repository,
interpolation_service,
clipboard_service,
embedder,
);
Arc::new(ActionServiceImpl::new(resolver, repository.clone()))
}
fn create_test_action_resolver(
repository: &Arc<SqliteBookmarkRepository>,
interpolation_service: &Arc<dyn InterpolationService>,
clipboard_service: &Arc<dyn ClipboardService>,
embedder: &Arc<dyn Embedder>,
) -> Arc<dyn ActionResolver> {
let uri_action: Box<dyn BookmarkAction> = Box::new(
crate::application::actions::UriAction::new(interpolation_service.clone()),
);
let snippet_action: Box<dyn BookmarkAction> =
Box::new(crate::application::actions::SnippetAction::new(
clipboard_service.clone(),
interpolation_service.clone(),
));
let text_action: Box<dyn BookmarkAction> =
Box::new(crate::application::actions::TextAction::new(
clipboard_service.clone(),
interpolation_service.clone(),
));
let shell_action: Box<dyn BookmarkAction> =
Box::new(crate::application::actions::ShellAction::new(
interpolation_service.clone(),
false, ));
let markdown_action: Box<dyn BookmarkAction> = Box::new(
crate::application::actions::MarkdownAction::new_with_repository(
repository.clone(),
embedder.clone(),
),
);
let env_action: Box<dyn BookmarkAction> = Box::new(
crate::application::actions::EnvAction::new(interpolation_service.clone()),
);
let default_action: Box<dyn BookmarkAction> = Box::new(
crate::application::actions::DefaultAction::new(interpolation_service.clone()),
);
Arc::new(SystemTagActionResolver::new(
uri_action,
snippet_action,
text_action,
shell_action,
markdown_action,
env_action,
default_action,
))
}
pub fn create_lsp_services(&self) -> LspServiceBundle {
let snippet_service = Arc::new(LspSnippetService::with_services(
self.bookmark_service.clone(),
self.interpolation_service.clone(),
));
let completion_service =
crate::lsp::services::completion_service::CompletionService::with_config(
snippet_service.clone(),
BkmrConfig::default(),
);
let document_service = crate::lsp::services::document_service::DocumentService::new();
let command_service = crate::lsp::services::command_service::CommandService::with_service(
self.bookmark_service.clone(),
);
LspServiceBundle {
snippet_service,
completion_service,
document_service,
command_service,
}
}
}
pub struct LspServiceBundle {
pub snippet_service: Arc<LspSnippetService>,
pub completion_service: crate::lsp::services::completion_service::CompletionService,
pub document_service: crate::lsp::services::document_service::DocumentService,
pub command_service: crate::lsp::services::command_service::CommandService,
}
impl Default for TestServiceContainer {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Debug for TestServiceContainer {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("TestServiceContainer")
.field("bookmark_repository", &"Arc<SqliteBookmarkRepository>")
.field("embedder", &"Arc<dyn Embedder>")
.field("bookmark_service", &"Arc<dyn BookmarkService>")
.field("tag_service", &"Arc<dyn TagService>")
.field("action_service", &"Arc<dyn ActionService>")
.field("clipboard_service", &"Arc<dyn ClipboardService>")
.field("interpolation_service", &"Arc<dyn InterpolationService>")
.field("template_service", &"Arc<dyn TemplateService>")
.finish()
}
}