From 00b3087b8a194fba0a4243c353d65e4ea082492c Mon Sep 17 00:00:00 2001 From: KnifeLemon Date: Thu, 12 Nov 2026 03:42:08 +0900 Subject: [PATCH 1/2] feat(presets): put PDF to XLSX on the PDF donut PDF to XLSX works but sat on no PDF donut, so people couldn't find it (#1343, #1187). A new library has it on the PDF front after DOCX: the new-install back face is already at the eight-slice limit, and XLSX is a conversion. Settings schema 80 gives it to a PDF face that is still exactly as Filee made it: the front of a library made since the slot cleanup, or the back (after Compress PDF) of an older one, whose front is full. A face the user changed is left alone. Refs #1343, #1187 Co-Authored-By: Claude Opus 5.5 --- src/Filee.Core/Presets/BuiltInData.cs | 2 +- src/Filee.Core/Settings/AppSettings.cs | 2 +- src/Filee.Core/Settings/UserDataStore.cs | 29 ++++ .../BackFaceTests.SlotTable.cs | 5 +- tests/Filee.Core.Tests/BackFaceTests.cs | 8 +- tests/Filee.Core.Tests/MergeImagesTests.cs | 2 +- tests/Filee.Core.Tests/PdfXlsxSlotTests.cs | 127 ++++++++++++++++++ .../UserDataStoreTests.SlotTable.cs | 4 + tests/Filee.Core.Tests/UserDataStoreTests.cs | 6 +- 9 files changed, 174 insertions(+), 11 deletions(-) create mode 100644 tests/Filee.Core.Tests/PdfXlsxSlotTests.cs diff --git a/src/Filee.Core/Presets/BuiltInData.cs b/src/Filee.Core/Presets/BuiltInData.cs index e1c69d961..8e041b974 100644 --- a/src/Filee.Core/Presets/BuiltInData.cs +++ b/src/Filee.Core/Presets/BuiltInData.cs @@ -739,7 +739,7 @@ public static List CreateProfiles() { "images" => (["to-png", "to-jpg", "to-webp", "to-gif", "to-pdf", "trace-svg"], ["tool-crop", "rotate", "remove-background", "merge-images", "compress-image", "half-size", "tool-image-edit", "zip-all"]), - "pdf" => (["to-png", "to-jpg", "to-docx", "pdf-slides", "to-txt", "to-hwpx", "to-hwp"], + "pdf" => (["to-png", "to-jpg", "to-docx", "to-xlsx", "pdf-slides", "to-txt", "to-hwpx", "to-hwp"], ["pdf-edit", "pdf-split", "merge-pdf", "compress-pdf", "remove-metadata", "to-tiff", "to-html", "zip-all"]), "office" => (["to-pdf", "to-hwpx", "to-hwp", "to-docx", "to-txt", "to-png", "merge-pdf"], ["translate", "to-md", "pdf-long-image", "zip-all"]), diff --git a/src/Filee.Core/Settings/AppSettings.cs b/src/Filee.Core/Settings/AppSettings.cs index 1d7e2acd3..58bc862fd 100644 --- a/src/Filee.Core/Settings/AppSettings.cs +++ b/src/Filee.Core/Settings/AppSettings.cs @@ -139,7 +139,7 @@ public static bool IsFlipKeyAllowed(string key, IEnumerable gest public sealed class AppSettings { /// Current schema version. Increase when the format changes and add a migration. - public const int CurrentSchemaVersion = 79; + public const int CurrentSchemaVersion = 80; public int SchemaVersion { get; set; } = CurrentSchemaVersion; diff --git a/src/Filee.Core/Settings/UserDataStore.cs b/src/Filee.Core/Settings/UserDataStore.cs index 1311c1f3d..14283e4b9 100644 --- a/src/Filee.Core/Settings/UserDataStore.cs +++ b/src/Filee.Core/Settings/UserDataStore.cs @@ -1097,9 +1097,38 @@ public static bool ApplyToLibrary(int from, List presets, List p.Id != BuiltInData.RingtoneId)) changed |= AddLikeNewLibrary(presets, BuiltInData.RingtoneId); } + // v80: PDF → XLSX (#1343, #1187) was on no PDF donut, so people didn't find it. A PDF donut face that is still + // exactly as Filee made it gets the slot: the front of a library made since the slot cleanup, after + // "DOCX" as in a new library, or else the back of an older one, whose front is full, after "Compress + // PDF". A face the user changed stays as it is (#806). (Schema 80 may be renumbered if another change + // takes it first.) + if (from < 80) + changed |= AddPdfXlsx(presets, profiles); return changed; } + /// The PDF front of a new library from the slot cleanup (2.3.0) until XLSX joined it in schema 80. + private static readonly string[] PdfFrontBefore80 = ["to-png", "to-jpg", "to-docx", "pdf-slides", "to-txt", "to-hwpx", "to-hwp"]; + + private static bool AddPdfXlsx(List presets, List profiles) + { + const string id = "to-xlsx"; + if (presets.All(p => p.Id != id) || profiles.FirstOrDefault(p => p.Id == "pdf") is not { } pdf + || pdf.PresetIds.Contains(id) || pdf.BackPresetIds?.Contains(id) == true) + return false; + if (pdf.PresetIds.SequenceEqual(PdfFrontBefore80)) + { + pdf.PresetIds.Insert(pdf.PresetIds.IndexOf("to-docx") + 1, id); + return true; + } + if (pdf.BackPresetIds is { } back && back.SequenceEqual(BuiltInData.ProfilesSchema58().Single(p => p.Id == "pdf").BackPresetIds!)) + { + back.Insert(back.IndexOf("compress-pdf") + 1, id); + return true; + } + return false; + } + private static bool AddTranslatePreset(List presets) => AddLikeNewLibrary(presets, "translate"); /// Adds the built-in preset after the built-in preset before it in a new library. diff --git a/tests/Filee.Core.Tests/BackFaceTests.SlotTable.cs b/tests/Filee.Core.Tests/BackFaceTests.SlotTable.cs index a867d7a46..72a6648d9 100644 --- a/tests/Filee.Core.Tests/BackFaceTests.SlotTable.cs +++ b/tests/Filee.Core.Tests/BackFaceTests.SlotTable.cs @@ -6,11 +6,12 @@ namespace Filee.Core.Tests; public partial class BackFaceTests { // Slot table of #806, with Translate from #836 first on the document, text and e-book backs, and Crop video (#830) - // after Cut a clip. This is a new-install/reset contract, not migration input. + // after Cut a clip, and XLSX (#1343) after Word on the PDF front. This is a new-install/reset contract, not + // migration input. internal static readonly Dictionary ExpectedFaces = new() { ["images"] = (["to-png", "to-jpg", "to-webp", "to-gif", "to-pdf", "trace-svg"], ["tool-crop", "rotate", "remove-background", "merge-images", "compress-image", "half-size", "tool-image-edit", "zip-all"]), - ["pdf"] = (["to-png", "to-jpg", "to-docx", "pdf-slides", "to-txt", "to-hwpx", "to-hwp"], ["pdf-edit", "pdf-split", "merge-pdf", "compress-pdf", "remove-metadata", "to-tiff", "to-html", "zip-all"]), + ["pdf"] = (["to-png", "to-jpg", "to-docx", "to-xlsx", "pdf-slides", "to-txt", "to-hwpx", "to-hwp"], ["pdf-edit", "pdf-split", "merge-pdf", "compress-pdf", "remove-metadata", "to-tiff", "to-html", "zip-all"]), ["office"] = (["to-pdf", "to-hwpx", "to-hwp", "to-docx", "to-txt", "to-png", "merge-pdf"], ["translate", "to-md", "pdf-long-image", "zip-all"]), ["spreadsheets"] = (["to-pdf", "to-xlsx", "to-csv", "to-hwpx", "to-hwp", "merge-pdf"], ["tool-sheet-studio", "to-docx", "to-vcf", "to-ics", "zip-all"]), ["presentations"] = (["to-pdf", "to-png", "to-jpg", "to-pptx", "to-hwpx", "to-hwp", "merge-pdf"], ["to-odp", "pdf-long-image", "to-docx", "zip-all"]), diff --git a/tests/Filee.Core.Tests/BackFaceTests.cs b/tests/Filee.Core.Tests/BackFaceTests.cs index 767c0947f..8fff925d2 100644 --- a/tests/Filee.Core.Tests/BackFaceTests.cs +++ b/tests/Filee.Core.Tests/BackFaceTests.cs @@ -141,7 +141,9 @@ public void Version_29_libraries_get_the_built_in_back_faces_and_keep_their_fron foreach (var profile in profiles.Where(p => p != mine && p.Id != "folders")) { - var expected = Schema58(profile.Id).BackPresetIds!.Where(id => id != "to-gif"); + // Schema 80 then gives the untouched PDF back XLSX (#1343). + var expected = (profile.Id == "pdf" ? PdfXlsxSlotTests.Schema58PdfBackAt80() : Schema58(profile.Id).BackPresetIds!) + .Where(id => id != "to-gif"); Assert.Equal(expected, profile.BackPresetIds); } Assert.Null(mine.BackPresetIds); // the store gives it an empty one (below) @@ -235,8 +237,8 @@ public void Back_from_Filee_1_0_1_or_1_1_0_a_new_library_gets_its_new_back_faces // The fronts as read are the new ones, so the new back faces; the migrations before 30 then add front slots, and // v31, v33 and v37 back slots, as for any library of that schema. Assert.Equal(schema == 4 - ? ["to-png", "to-jpg", "pdf-long-image", "to-docx", "pdf-slides", "to-hwp", "to-md", "to-epub"] - : ["to-png", "to-jpg", "pdf-long-image", "to-docx", "pdf-slides", "to-txt", "to-md", "to-epub", "to-hwpx", "to-hwp"], + ? ["to-png", "to-jpg", "pdf-long-image", "to-docx", "to-xlsx", "pdf-slides", "to-hwp", "to-md", "to-epub"] + : ["to-png", "to-jpg", "pdf-long-image", "to-docx", "to-xlsx", "pdf-slides", "to-txt", "to-md", "to-epub", "to-hwpx", "to-hwp"], Profile(back, "pdf").PresetIds); Assert.Equal(["pdf-edit", "pdf-split", "merge-pdf", "compress-pdf", "remove-metadata", "to-tiff", "to-html", "zip-all"], Profile(back, "pdf").BackPresetIds); diff --git a/tests/Filee.Core.Tests/MergeImagesTests.cs b/tests/Filee.Core.Tests/MergeImagesTests.cs index e90d9689b..46b84d598 100644 --- a/tests/Filee.Core.Tests/MergeImagesTests.cs +++ b/tests/Filee.Core.Tests/MergeImagesTests.cs @@ -100,7 +100,7 @@ public void Schema_53_takes_a_free_slot_before_merge_pdf_and_leaves_gif() public void Schema_53_leaves_a_donut_where_the_user_put_merge_images_or_has_no_gif_to_give() { var presets = BuiltInData.CreatePresets(); - var profiles = BuiltInData.ProfilesSchema58(); + var profiles = PdfXlsxSlotTests.Schema58ProfilesAt80(); var images = profiles.Single(p => p.Id == "images"); images.PresetIds = ["merge-images", "to-png"]; images.BackPresetIds = [.. BackBefore53]; diff --git a/tests/Filee.Core.Tests/PdfXlsxSlotTests.cs b/tests/Filee.Core.Tests/PdfXlsxSlotTests.cs new file mode 100644 index 000000000..b4ce3221b --- /dev/null +++ b/tests/Filee.Core.Tests/PdfXlsxSlotTests.cs @@ -0,0 +1,127 @@ +// PDF → XLSX (#1343, #1187) works but was on no PDF donut, so people didn't find it. A new library has it on the PDF +// front, after DOCX; settings schema 80 gives it to a PDF donut face that is still exactly as Filee made it. + +using Filee.Core.Presets; +using Filee.Core.Profiles; +using Filee.Core.Settings; + +namespace Filee.Core.Tests; + +public class PdfXlsxSlotTests +{ + private const string Xlsx = "to-xlsx"; + + private static ToolbarProfile Pdf(List profiles) => profiles.Single(p => p.Id == "pdf"); + + internal static List Schema58PdfBack() => Pdf(BuiltInData.ProfilesSchema58()).BackPresetIds!; + + /// The schema 58 PDF back face as schema 80 leaves it: XLSX after "Compress PDF". + internal static List Schema58PdfBackAt80() + { + var back = Schema58PdfBack(); + back.Insert(back.IndexOf("compress-pdf") + 1, Xlsx); + return back; + } + + /// The schema 58 donuts with nothing left for schema 80 to do, for tests of older steps that expect no other change. + internal static List Schema58ProfilesAt80() + { + var profiles = BuiltInData.ProfilesSchema58(); + Pdf(profiles).BackPresetIds = Schema58PdfBackAt80(); + return profiles; + } + + [Fact] + public void A_new_library_has_XLSX_on_the_PDF_front_after_DOCX() + { + var front = Pdf(BuiltInData.CreateProfiles()).PresetIds; + + Assert.Equal(front.IndexOf("to-docx") + 1, front.IndexOf(Xlsx)); + Assert.DoesNotContain(Xlsx, Pdf(BuiltInData.CreateProfiles()).BackPresetIds!); + } + + [Fact] + public void A_version_79_library_from_the_slot_cleanup_gets_it_on_the_front_like_a_new_one() + { + var presets = BuiltInData.CreatePresets(); + var profiles = BuiltInData.CreateProfiles(); + var pdf = Pdf(profiles); + pdf.PresetIds.Remove(Xlsx); + var back = pdf.BackPresetIds!.ToList(); + + Assert.True(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); + + Assert.Equal(Pdf(BuiltInData.CreateProfiles()).PresetIds, pdf.PresetIds); + Assert.Equal(back, pdf.BackPresetIds); + Assert.False(SettingsMigrations.ApplyToLibrary(AppSettings.CurrentSchemaVersion, presets, profiles)); + } + + [Fact] + public void An_older_library_whose_front_is_full_gets_it_on_the_back_after_Compress_PDF() + { + var presets = BuiltInData.CreatePresets(); + var profiles = BuiltInData.ProfilesSchema58(); + var pdf = Pdf(profiles); + var front = pdf.PresetIds.ToList(); + Assert.Equal(ToolbarProfile.MaxSlices, front.Count); + + Assert.True(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); + + Assert.Equal(front, pdf.PresetIds); + Assert.Equal(pdf.BackPresetIds!.IndexOf("compress-pdf") + 1, pdf.BackPresetIds.IndexOf(Xlsx)); + Assert.Equal(ToolbarProfile.MaxSlices, pdf.BackPresetIds.Count); + Assert.False(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); // once only + } + + [Fact] + public void A_face_the_user_changed_stays_as_it_is() + { + var presets = BuiltInData.CreatePresets(); + var profiles = BuiltInData.ProfilesSchema58(); + var pdf = Pdf(profiles); + pdf.BackPresetIds!.Remove("to-cbz"); + var back = pdf.BackPresetIds.ToList(); + + Assert.False(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); + Assert.Equal(back, pdf.BackPresetIds); + + profiles = BuiltInData.CreateProfiles(); + pdf = Pdf(profiles); + pdf.PresetIds.Remove(Xlsx); + pdf.PresetIds.Remove("to-hwp"); + var front = pdf.PresetIds.ToList(); + + Assert.False(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); + Assert.Equal(front, pdf.PresetIds); + } + + [Fact] + public void A_donut_that_already_has_it_or_a_library_without_the_preset_is_left_alone() + { + var presets = BuiltInData.CreatePresets(); + var profiles = BuiltInData.ProfilesSchema58(); + var pdf = Pdf(profiles); + pdf.PresetIds[^1] = Xlsx; // the user put it on the front in place of "Merge PDF" + var back = pdf.BackPresetIds!.ToList(); + + Assert.False(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); + Assert.Equal(back, pdf.BackPresetIds); + + profiles = BuiltInData.ProfilesSchema58(); + presets.RemoveAll(p => p.Id == Xlsx); + + Assert.False(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); + Assert.DoesNotContain(Xlsx, Pdf(profiles).BackPresetIds!); + } + + [Fact] + public void A_library_without_a_PDF_donut_gets_none() + { + var presets = BuiltInData.CreatePresets(); + var profiles = BuiltInData.ProfilesSchema58(); + profiles.RemoveAll(p => p.Id == "pdf"); + + Assert.False(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); + Assert.DoesNotContain(profiles, p => p.Id == "pdf"); + } +} diff --git a/tests/Filee.Core.Tests/UserDataStoreTests.SlotTable.cs b/tests/Filee.Core.Tests/UserDataStoreTests.SlotTable.cs index 1ff252f17..e090a079e 100644 --- a/tests/Filee.Core.Tests/UserDataStoreTests.SlotTable.cs +++ b/tests/Filee.Core.Tests/UserDataStoreTests.SlotTable.cs @@ -77,6 +77,10 @@ private static void AssertKeptAsBefore(string scenario, bool import) "UserWithoutBack" => UserWithoutBackKept(), _ => Schema58Library(), }; + // Loading runs schema 80, which gives the untouched PDF back face XLSX (#1343); import runs no migration. + if (!import && expected.Profiles.SingleOrDefault(p => p.Id == "pdf") is { } pdf + && pdf.BackPresetIds?.SequenceEqual(PdfXlsxSlotTests.Schema58PdfBack()) == true) + pdf.BackPresetIds = PdfXlsxSlotTests.Schema58PdfBackAt80(); Assert.Equal(JsonSerializer.Serialize(expected.Profiles, FileeJsonContext.Default.ListToolbarProfile), JsonSerializer.Serialize(store.Profiles, FileeJsonContext.Default.ListToolbarProfile)); Assert.Equal(JsonSerializer.Serialize(expected.Presets, FileeJsonContext.Default.ListPreset), diff --git a/tests/Filee.Core.Tests/UserDataStoreTests.cs b/tests/Filee.Core.Tests/UserDataStoreTests.cs index 887570306..d6ee02ff9 100644 --- a/tests/Filee.Core.Tests/UserDataStoreTests.cs +++ b/tests/Filee.Core.Tests/UserDataStoreTests.cs @@ -1092,7 +1092,7 @@ public void Version_21_libraries_learn_fbx_on_the_3d_donut_and_nothing_else() Assert.False(SettingsMigrations.ApplyToLibrary(21, presets, profiles)); // once only // A donut of the user that already opens FBX files keeps them. - profiles = BuiltInData.ProfilesSchema58(); + profiles = PdfXlsxSlotTests.Schema58ProfilesAt80(); profiles.Single(p => p.Id == "models").Extensions.Remove("fbx"); profiles.Insert(0, new ToolbarProfile { Id = "games", Name = "Games", Extensions = ["fbx"] }); Assert.False(SettingsMigrations.ApplyToLibrary(21, presets, profiles)); @@ -1139,7 +1139,7 @@ public void Version_23_libraries_learn_potm_on_the_presentation_donut_and_nothin Assert.False(SettingsMigrations.ApplyToLibrary(23, presets, profiles)); // once only // A donut of the user that already opens .potm files keeps them. - profiles = BuiltInData.ProfilesSchema58(); + profiles = PdfXlsxSlotTests.Schema58ProfilesAt80(); profiles.Single(p => p.Id == "presentations").Extensions.Remove("potm"); profiles.Insert(0, new ToolbarProfile { Id = "templates", Name = "Templates", Extensions = ["potm"] }); Assert.False(SettingsMigrations.ApplyToLibrary(23, presets, profiles)); @@ -1162,7 +1162,7 @@ public void Version_26_libraries_learn_ofd_on_the_office_donut_and_nothing_else( Assert.False(SettingsMigrations.ApplyToLibrary(26, presets, profiles)); // once only // A donut of the user that already opens .ofd files keeps them. - profiles = BuiltInData.ProfilesSchema58(); + profiles = PdfXlsxSlotTests.Schema58ProfilesAt80(); profiles.Single(p => p.Id == "office").Extensions.Remove("ofd"); profiles.Insert(0, new ToolbarProfile { Id = "invoices", Name = "Invoices", Extensions = ["ofd"] }); Assert.False(SettingsMigrations.ApplyToLibrary(26, presets, profiles)); From 5852b27b279bcb67a2247751d9fcb163c6327565 Mon Sep 17 00:00:00 2001 From: KnifeLemon Date: Thu, 12 Nov 2026 04:16:22 +0900 Subject: [PATCH 2/2] fix(presets): keep existing libraries as they are, new installs only Drop the schema 80 step that gave existing PDF donuts the XLSX slot, and the schema bump: new defaults are for new installs (#806). Existing users add XLSX from Settings > Donut toolbar. The test contracts for older libraries are back as on main. Refs #1343, #1187 Co-Authored-By: Claude Opus 5.5 --- src/Filee.Core/Settings/AppSettings.cs | 2 +- src/Filee.Core/Settings/UserDataStore.cs | 29 ----- tests/Filee.Core.Tests/BackFaceTests.cs | 4 +- tests/Filee.Core.Tests/MergeImagesTests.cs | 2 +- tests/Filee.Core.Tests/PdfXlsxSlotTests.cs | 113 ++---------------- .../UserDataStoreTests.SlotTable.cs | 4 - tests/Filee.Core.Tests/UserDataStoreTests.cs | 6 +- 7 files changed, 14 insertions(+), 146 deletions(-) diff --git a/src/Filee.Core/Settings/AppSettings.cs b/src/Filee.Core/Settings/AppSettings.cs index 58bc862fd..1d7e2acd3 100644 --- a/src/Filee.Core/Settings/AppSettings.cs +++ b/src/Filee.Core/Settings/AppSettings.cs @@ -139,7 +139,7 @@ public static bool IsFlipKeyAllowed(string key, IEnumerable gest public sealed class AppSettings { /// Current schema version. Increase when the format changes and add a migration. - public const int CurrentSchemaVersion = 80; + public const int CurrentSchemaVersion = 79; public int SchemaVersion { get; set; } = CurrentSchemaVersion; diff --git a/src/Filee.Core/Settings/UserDataStore.cs b/src/Filee.Core/Settings/UserDataStore.cs index 14283e4b9..1311c1f3d 100644 --- a/src/Filee.Core/Settings/UserDataStore.cs +++ b/src/Filee.Core/Settings/UserDataStore.cs @@ -1097,38 +1097,9 @@ public static bool ApplyToLibrary(int from, List presets, List p.Id != BuiltInData.RingtoneId)) changed |= AddLikeNewLibrary(presets, BuiltInData.RingtoneId); } - // v80: PDF → XLSX (#1343, #1187) was on no PDF donut, so people didn't find it. A PDF donut face that is still - // exactly as Filee made it gets the slot: the front of a library made since the slot cleanup, after - // "DOCX" as in a new library, or else the back of an older one, whose front is full, after "Compress - // PDF". A face the user changed stays as it is (#806). (Schema 80 may be renumbered if another change - // takes it first.) - if (from < 80) - changed |= AddPdfXlsx(presets, profiles); return changed; } - /// The PDF front of a new library from the slot cleanup (2.3.0) until XLSX joined it in schema 80. - private static readonly string[] PdfFrontBefore80 = ["to-png", "to-jpg", "to-docx", "pdf-slides", "to-txt", "to-hwpx", "to-hwp"]; - - private static bool AddPdfXlsx(List presets, List profiles) - { - const string id = "to-xlsx"; - if (presets.All(p => p.Id != id) || profiles.FirstOrDefault(p => p.Id == "pdf") is not { } pdf - || pdf.PresetIds.Contains(id) || pdf.BackPresetIds?.Contains(id) == true) - return false; - if (pdf.PresetIds.SequenceEqual(PdfFrontBefore80)) - { - pdf.PresetIds.Insert(pdf.PresetIds.IndexOf("to-docx") + 1, id); - return true; - } - if (pdf.BackPresetIds is { } back && back.SequenceEqual(BuiltInData.ProfilesSchema58().Single(p => p.Id == "pdf").BackPresetIds!)) - { - back.Insert(back.IndexOf("compress-pdf") + 1, id); - return true; - } - return false; - } - private static bool AddTranslatePreset(List presets) => AddLikeNewLibrary(presets, "translate"); /// Adds the built-in preset after the built-in preset before it in a new library. diff --git a/tests/Filee.Core.Tests/BackFaceTests.cs b/tests/Filee.Core.Tests/BackFaceTests.cs index 8fff925d2..3c2ebc267 100644 --- a/tests/Filee.Core.Tests/BackFaceTests.cs +++ b/tests/Filee.Core.Tests/BackFaceTests.cs @@ -141,9 +141,7 @@ public void Version_29_libraries_get_the_built_in_back_faces_and_keep_their_fron foreach (var profile in profiles.Where(p => p != mine && p.Id != "folders")) { - // Schema 80 then gives the untouched PDF back XLSX (#1343). - var expected = (profile.Id == "pdf" ? PdfXlsxSlotTests.Schema58PdfBackAt80() : Schema58(profile.Id).BackPresetIds!) - .Where(id => id != "to-gif"); + var expected = Schema58(profile.Id).BackPresetIds!.Where(id => id != "to-gif"); Assert.Equal(expected, profile.BackPresetIds); } Assert.Null(mine.BackPresetIds); // the store gives it an empty one (below) diff --git a/tests/Filee.Core.Tests/MergeImagesTests.cs b/tests/Filee.Core.Tests/MergeImagesTests.cs index 46b84d598..e90d9689b 100644 --- a/tests/Filee.Core.Tests/MergeImagesTests.cs +++ b/tests/Filee.Core.Tests/MergeImagesTests.cs @@ -100,7 +100,7 @@ public void Schema_53_takes_a_free_slot_before_merge_pdf_and_leaves_gif() public void Schema_53_leaves_a_donut_where_the_user_put_merge_images_or_has_no_gif_to_give() { var presets = BuiltInData.CreatePresets(); - var profiles = PdfXlsxSlotTests.Schema58ProfilesAt80(); + var profiles = BuiltInData.ProfilesSchema58(); var images = profiles.Single(p => p.Id == "images"); images.PresetIds = ["merge-images", "to-png"]; images.BackPresetIds = [.. BackBefore53]; diff --git a/tests/Filee.Core.Tests/PdfXlsxSlotTests.cs b/tests/Filee.Core.Tests/PdfXlsxSlotTests.cs index b4ce3221b..c2651c0f4 100644 --- a/tests/Filee.Core.Tests/PdfXlsxSlotTests.cs +++ b/tests/Filee.Core.Tests/PdfXlsxSlotTests.cs @@ -1,127 +1,30 @@ // PDF → XLSX (#1343, #1187) works but was on no PDF donut, so people didn't find it. A new library has it on the PDF -// front, after DOCX; settings schema 80 gives it to a PDF donut face that is still exactly as Filee made it. +// front, after DOCX; an existing library keeps its donuts as they are (#806), and the user adds it from the palette. using Filee.Core.Presets; using Filee.Core.Profiles; -using Filee.Core.Settings; namespace Filee.Core.Tests; public class PdfXlsxSlotTests { - private const string Xlsx = "to-xlsx"; - private static ToolbarProfile Pdf(List profiles) => profiles.Single(p => p.Id == "pdf"); - internal static List Schema58PdfBack() => Pdf(BuiltInData.ProfilesSchema58()).BackPresetIds!; - - /// The schema 58 PDF back face as schema 80 leaves it: XLSX after "Compress PDF". - internal static List Schema58PdfBackAt80() - { - var back = Schema58PdfBack(); - back.Insert(back.IndexOf("compress-pdf") + 1, Xlsx); - return back; - } - - /// The schema 58 donuts with nothing left for schema 80 to do, for tests of older steps that expect no other change. - internal static List Schema58ProfilesAt80() - { - var profiles = BuiltInData.ProfilesSchema58(); - Pdf(profiles).BackPresetIds = Schema58PdfBackAt80(); - return profiles; - } - [Fact] public void A_new_library_has_XLSX_on_the_PDF_front_after_DOCX() { - var front = Pdf(BuiltInData.CreateProfiles()).PresetIds; - - Assert.Equal(front.IndexOf("to-docx") + 1, front.IndexOf(Xlsx)); - Assert.DoesNotContain(Xlsx, Pdf(BuiltInData.CreateProfiles()).BackPresetIds!); - } - - [Fact] - public void A_version_79_library_from_the_slot_cleanup_gets_it_on_the_front_like_a_new_one() - { - var presets = BuiltInData.CreatePresets(); - var profiles = BuiltInData.CreateProfiles(); - var pdf = Pdf(profiles); - pdf.PresetIds.Remove(Xlsx); - var back = pdf.BackPresetIds!.ToList(); - - Assert.True(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); - - Assert.Equal(Pdf(BuiltInData.CreateProfiles()).PresetIds, pdf.PresetIds); - Assert.Equal(back, pdf.BackPresetIds); - Assert.False(SettingsMigrations.ApplyToLibrary(AppSettings.CurrentSchemaVersion, presets, profiles)); - } - - [Fact] - public void An_older_library_whose_front_is_full_gets_it_on_the_back_after_Compress_PDF() - { - var presets = BuiltInData.CreatePresets(); - var profiles = BuiltInData.ProfilesSchema58(); - var pdf = Pdf(profiles); - var front = pdf.PresetIds.ToList(); - Assert.Equal(ToolbarProfile.MaxSlices, front.Count); - - Assert.True(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); - - Assert.Equal(front, pdf.PresetIds); - Assert.Equal(pdf.BackPresetIds!.IndexOf("compress-pdf") + 1, pdf.BackPresetIds.IndexOf(Xlsx)); - Assert.Equal(ToolbarProfile.MaxSlices, pdf.BackPresetIds.Count); - Assert.False(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); // once only - } - - [Fact] - public void A_face_the_user_changed_stays_as_it_is() - { - var presets = BuiltInData.CreatePresets(); - var profiles = BuiltInData.ProfilesSchema58(); - var pdf = Pdf(profiles); - pdf.BackPresetIds!.Remove("to-cbz"); - var back = pdf.BackPresetIds.ToList(); - - Assert.False(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); - Assert.Equal(back, pdf.BackPresetIds); - - profiles = BuiltInData.CreateProfiles(); - pdf = Pdf(profiles); - pdf.PresetIds.Remove(Xlsx); - pdf.PresetIds.Remove("to-hwp"); - var front = pdf.PresetIds.ToList(); - - Assert.False(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); - Assert.Equal(front, pdf.PresetIds); - } - - [Fact] - public void A_donut_that_already_has_it_or_a_library_without_the_preset_is_left_alone() - { - var presets = BuiltInData.CreatePresets(); - var profiles = BuiltInData.ProfilesSchema58(); - var pdf = Pdf(profiles); - pdf.PresetIds[^1] = Xlsx; // the user put it on the front in place of "Merge PDF" - var back = pdf.BackPresetIds!.ToList(); - - Assert.False(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); - Assert.Equal(back, pdf.BackPresetIds); - - profiles = BuiltInData.ProfilesSchema58(); - presets.RemoveAll(p => p.Id == Xlsx); + var pdf = Pdf(BuiltInData.CreateProfiles()); - Assert.False(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); - Assert.DoesNotContain(Xlsx, Pdf(profiles).BackPresetIds!); + Assert.Equal(pdf.PresetIds.IndexOf("to-docx") + 1, pdf.PresetIds.IndexOf("to-xlsx")); + Assert.DoesNotContain("to-xlsx", pdf.BackPresetIds!); } [Fact] - public void A_library_without_a_PDF_donut_gets_none() + public void The_schema_58_PDF_donut_stays_without_it() { - var presets = BuiltInData.CreatePresets(); - var profiles = BuiltInData.ProfilesSchema58(); - profiles.RemoveAll(p => p.Id == "pdf"); + var pdf = Pdf(BuiltInData.ProfilesSchema58()); - Assert.False(SettingsMigrations.ApplyToLibrary(79, presets, profiles)); - Assert.DoesNotContain(profiles, p => p.Id == "pdf"); + Assert.DoesNotContain("to-xlsx", pdf.PresetIds); + Assert.DoesNotContain("to-xlsx", pdf.BackPresetIds!); } } diff --git a/tests/Filee.Core.Tests/UserDataStoreTests.SlotTable.cs b/tests/Filee.Core.Tests/UserDataStoreTests.SlotTable.cs index e090a079e..1ff252f17 100644 --- a/tests/Filee.Core.Tests/UserDataStoreTests.SlotTable.cs +++ b/tests/Filee.Core.Tests/UserDataStoreTests.SlotTable.cs @@ -77,10 +77,6 @@ private static void AssertKeptAsBefore(string scenario, bool import) "UserWithoutBack" => UserWithoutBackKept(), _ => Schema58Library(), }; - // Loading runs schema 80, which gives the untouched PDF back face XLSX (#1343); import runs no migration. - if (!import && expected.Profiles.SingleOrDefault(p => p.Id == "pdf") is { } pdf - && pdf.BackPresetIds?.SequenceEqual(PdfXlsxSlotTests.Schema58PdfBack()) == true) - pdf.BackPresetIds = PdfXlsxSlotTests.Schema58PdfBackAt80(); Assert.Equal(JsonSerializer.Serialize(expected.Profiles, FileeJsonContext.Default.ListToolbarProfile), JsonSerializer.Serialize(store.Profiles, FileeJsonContext.Default.ListToolbarProfile)); Assert.Equal(JsonSerializer.Serialize(expected.Presets, FileeJsonContext.Default.ListPreset), diff --git a/tests/Filee.Core.Tests/UserDataStoreTests.cs b/tests/Filee.Core.Tests/UserDataStoreTests.cs index d6ee02ff9..887570306 100644 --- a/tests/Filee.Core.Tests/UserDataStoreTests.cs +++ b/tests/Filee.Core.Tests/UserDataStoreTests.cs @@ -1092,7 +1092,7 @@ public void Version_21_libraries_learn_fbx_on_the_3d_donut_and_nothing_else() Assert.False(SettingsMigrations.ApplyToLibrary(21, presets, profiles)); // once only // A donut of the user that already opens FBX files keeps them. - profiles = PdfXlsxSlotTests.Schema58ProfilesAt80(); + profiles = BuiltInData.ProfilesSchema58(); profiles.Single(p => p.Id == "models").Extensions.Remove("fbx"); profiles.Insert(0, new ToolbarProfile { Id = "games", Name = "Games", Extensions = ["fbx"] }); Assert.False(SettingsMigrations.ApplyToLibrary(21, presets, profiles)); @@ -1139,7 +1139,7 @@ public void Version_23_libraries_learn_potm_on_the_presentation_donut_and_nothin Assert.False(SettingsMigrations.ApplyToLibrary(23, presets, profiles)); // once only // A donut of the user that already opens .potm files keeps them. - profiles = PdfXlsxSlotTests.Schema58ProfilesAt80(); + profiles = BuiltInData.ProfilesSchema58(); profiles.Single(p => p.Id == "presentations").Extensions.Remove("potm"); profiles.Insert(0, new ToolbarProfile { Id = "templates", Name = "Templates", Extensions = ["potm"] }); Assert.False(SettingsMigrations.ApplyToLibrary(23, presets, profiles)); @@ -1162,7 +1162,7 @@ public void Version_26_libraries_learn_ofd_on_the_office_donut_and_nothing_else( Assert.False(SettingsMigrations.ApplyToLibrary(26, presets, profiles)); // once only // A donut of the user that already opens .ofd files keeps them. - profiles = PdfXlsxSlotTests.Schema58ProfilesAt80(); + profiles = BuiltInData.ProfilesSchema58(); profiles.Single(p => p.Id == "office").Extensions.Remove("ofd"); profiles.Insert(0, new ToolbarProfile { Id = "invoices", Name = "Invoices", Extensions = ["ofd"] }); Assert.False(SettingsMigrations.ApplyToLibrary(26, presets, profiles));