test(backend,plugins): ajoute un test de non-résidu runtime après uninstall/reinstall (#120)

- plugin_install_load.rs: test uninstalls_then_reinstalls_sdk_hello_plugin_without_runtime_residue()
- application/src/plugin/mod.rs: refactor FakePackages pour supporter plusieurs staged packages et nettoyer les manifests sur uninstall
- Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-01 19:11:54 +02:00
parent 0061685b08
commit 5baf5821d4
2 changed files with 148 additions and 11 deletions

View File

@ -5,7 +5,7 @@ use std::sync::Arc;
use application::{
InstallPluginFromDirectory, JsonPluginManifestValidator, ListPluginRuntimeContributions,
ListPlugins,
ListPlugins, UninstallPlugin, UninstallPluginInput,
};
use infrastructure::{
ExternalMcpPluginSupervisor, FsPluginPackageStore, FsPluginRegistryStore,
@ -154,6 +154,79 @@ async fn installs_sdk_hello_plugin_and_loads_runtime_catalog() {
let _ = fs::remove_dir_all(app_data);
}
#[tokio::test]
async fn uninstalls_then_reinstalls_sdk_hello_plugin_without_runtime_residue() {
let app_data = temp_dir("hello-reinstall-app-data");
let hello_plugin = sdk_hello_plugin_path();
let packages = Arc::new(FsPluginPackageStore::new(&app_data));
let registry = Arc::new(FsPluginRegistryStore::new(&app_data));
let validator = Arc::new(JsonPluginManifestValidator::new("0.3.0"));
let events = Arc::new(TokioBroadcastEventBus::new());
let mcp = Arc::new(ExternalMcpPluginSupervisor::new());
let install = InstallPluginFromDirectory::new(
packages.clone(),
registry.clone(),
validator.clone(),
events.clone(),
mcp.clone(),
);
let uninstall = UninstallPlugin::new(packages.clone(), registry.clone(), events, mcp);
install
.execute(hello_plugin.to_string_lossy().into_owned())
.await
.unwrap();
let uninstall_result = uninstall
.execute(UninstallPluginInput {
plugin_id: "com.example.hello-plugin".to_owned(),
})
.await
.unwrap();
assert_eq!(
uninstall_result.removal_outcome,
domain::RemovalOutcome::Removed
);
assert!(!app_data
.join("plugins/installed/com.example.hello-plugin")
.exists());
assert!(
ListPlugins::new(packages.clone(), registry.clone(), validator.clone())
.execute()
.await
.unwrap()
.is_empty()
);
assert!(ListPluginRuntimeContributions::new(
packages.clone(),
registry.clone(),
validator.clone()
)
.execute()
.await
.unwrap()
.plugins
.is_empty());
let reinstall = install
.execute(hello_plugin.to_string_lossy().into_owned())
.await
.unwrap();
assert_eq!(reinstall.plugin.id, "com.example.hello-plugin");
assert_eq!(
reinstall.plugin.lifecycle_state,
domain::PluginLifecycleState::Enabled
);
let catalog = ListPluginRuntimeContributions::new(packages, registry, validator)
.execute()
.await
.unwrap();
assert_eq!(catalog.plugins.len(), 1);
assert_eq!(catalog.plugins[0].id, "com.example.hello-plugin");
assert!(catalog.plugins[0].bundle_url.ends_with("/dist/index.js"));
let _ = fs::remove_dir_all(app_data);
}
#[tokio::test]
async fn installed_plugin_with_missing_main_is_isolated_from_runtime_catalog() {
let app_data = temp_dir("missing-main-app-data");