diff --git a/src/PostIt/PostIt.Tests/MyFilesPageHeadlessTests.cs b/src/PostIt/PostIt.Tests/MyFilesPageHeadlessTests.cs
new file mode 100644
index 000000000..72619f3c5
--- /dev/null
+++ b/src/PostIt/PostIt.Tests/MyFilesPageHeadlessTests.cs
@@ -0,0 +1,208 @@
+using System.Net.Http;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Headless.XUnit;
+using Avalonia.VisualTree;
+using CommunityToolkit.Mvvm.Input;
+using PostIt.ViewModels;
+using PostIt.Views;
+using Yavsc.Api.Client;
+
+namespace PostIt.Tests;
+
+///
+/// Headless UI coverage for the "Mes fichiers" page
+/// (). The user reported that once a file
+/// is listed, "l'item est inerte au click, et ses boutons restent
+/// grisés, désactivés" — neither the row nor its action buttons
+/// (Télécharger / Supprimer) respond to a click.
+///
+/// These tests mount a real under
+/// the Avalonia headless platform with a stub
+/// that lists one file, then walk the
+/// realised visual tree to find the row's action buttons and
+/// assert the two things that would silently break and reproduce
+/// the "grayed / inert" symptom:
+///
+/// The Command binding
+/// ($parent[vm:MyFilesViewModel].DownloadFileCommand)
+/// resolved to a non-null command — a null command leaves the
+/// button disabled (grayed) and click-silent.
+/// The command is armed
+/// (CanExecute true) for the listed file — an
+/// AsyncRelayCommand with
+/// AllowConcurrentExecutions=false (the
+///
+/// default) disables itself while running; a button stuck
+/// "running" is exactly the grayed-and-inert report.
+/// Executing the command actually invokes the
+/// file download / delete on the API client — the row
+/// "activates" on click instead of being inert.
+///
+/// The OS save picker is absent under headless, so
+/// FileSaveHelpers.SaveAsync throws or cancels and the
+/// download command's catch sets an error status — but the
+/// API download is awaited before the picker, so the call
+/// is recorded regardless. We do not await the command's
+/// ExecutionTask to completion, to avoid blocking on the
+/// (platform-dependent) picker.
+///
+public class MyFilesPageHeadlessTests
+{
+ private static (MyFilesPage page, MyFilesViewModel vm, StubFsApi api) CreatePage()
+ {
+ var api = new StubFsApi();
+ var fsClient = new UserFilesApiClient(api, "https://blogs.example/api/v1/");
+ var vm = new MyFilesViewModel(fsClient);
+ var page = new MyFilesPage { DataContext = vm };
+ return (page, vm, api);
+ }
+
+ ///
+ /// Mount the page the way the app does — pushed onto a
+ /// shown in a
+ /// (a realizes its content template via
+ /// the navigation host, cf. RdvPageHeadlessTests) — after
+ /// listing a single file by awaiting
+ /// . Populating
+ /// before the first layout
+ /// pass lets the ItemsControl realise its item templates
+ /// under headless.
+ ///
+ private static async Task<(MyFilesPage page, MyFilesViewModel vm, StubFsApi api)> MountAsync()
+ {
+ var (page, vm, api) = CreatePage();
+ await vm.InitializeAsync();
+ var nav = new NavigationPage();
+ nav.PushAsync(page).GetAwaiter().GetResult();
+ var window = new Window { Content = nav };
+ window.Show();
+ // Let bindings / the ItemsControl item templates apply.
+ await Task.Delay(50);
+ return (page, vm, api);
+ }
+
+ ///
+ /// Find the first action button in a file row whose content
+ /// matches . The file rows live in an
+ /// ItemsControl DataTemplate (no x:Name), so we
+ /// walk the visual tree.
+ ///
+ private static Button? FindRowButton(MyFilesPage page, string content)
+ => page.GetVisualDescendants()
+ .OfType