diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/mail/components/unifiedtoolbar/test/unit | |
parent | Initial commit. (diff) | |
download | thunderbird-upstream.tar.xz thunderbird-upstream.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/mail/components/unifiedtoolbar/test/unit')
6 files changed, 769 insertions, 0 deletions
diff --git a/comm/mail/components/unifiedtoolbar/test/unit/test_buttonStyle.js b/comm/mail/components/unifiedtoolbar/test/unit/test_buttonStyle.js new file mode 100644 index 0000000000..0ffeefa00b --- /dev/null +++ b/comm/mail/components/unifiedtoolbar/test/unit/test_buttonStyle.js @@ -0,0 +1,40 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { BUTTON_STYLE_MAP, BUTTON_STYLE_PREF } = ChromeUtils.importESModule( + "resource:///modules/ButtonStyle.mjs" +); + +add_task(function test_buttonStyleMap() { + Assert.ok(Array.isArray(BUTTON_STYLE_MAP), "BUTTON_STYLE_MAP is an array"); + Assert.ok( + BUTTON_STYLE_MAP.every(style => typeof style === "string"), + "All entries in the style map should be strings" + ); + for (const style of BUTTON_STYLE_MAP) { + Assert.stringMatches( + style, + /[a-z-]/, + "Button style class should be formatted in kebab case" + ); + } +}); + +add_task(function test_buttonStylePref() { + Assert.equal( + typeof BUTTON_STYLE_PREF, + "string", + "BUTTON_STYLE_PREF is a string" + ); + const prefValue = Services.prefs.getIntPref(BUTTON_STYLE_PREF, 0); + Assert.ok( + Number.isInteger(prefValue), + "BUTTON_STYLE_PREF pref should hold an integer" + ); + Assert.less( + prefValue, + BUTTON_STYLE_MAP.length, + "Value of BUTTON_STYLE_PREF should be within map" + ); +}); diff --git a/comm/mail/components/unifiedtoolbar/test/unit/test_customizableItems.js b/comm/mail/components/unifiedtoolbar/test/unit/test_customizableItems.js new file mode 100644 index 0000000000..55d4f5ba91 --- /dev/null +++ b/comm/mail/components/unifiedtoolbar/test/unit/test_customizableItems.js @@ -0,0 +1,123 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { + getAvailableItemIdsForSpace, + getDefaultItemIdsForSpace, + MULTIPLE_ALLOWED_ITEM_IDS, + SKIP_FOCUS_ITEM_IDS, +} = ChromeUtils.importESModule("resource:///modules/CustomizableItems.sys.mjs"); + +const { default: CUSTOMIZABLE_ITEMS } = ChromeUtils.importESModule( + "resource:///modules/CustomizableItemsDetails.mjs" +); + +add_task(function test_getAvailableItemIdsForSpace_anySpace() { + const itemsForAnySpace = getAvailableItemIdsForSpace(); + Assert.ok(Array.isArray(itemsForAnySpace), "returns an array"); + for (const itemId of itemsForAnySpace) { + Assert.equal(typeof itemId, "string", `item ID "${itemId}" is string`); + Assert.greater(itemId.length, 0, `item ID is not empty`); + } +}); + +add_task(function test_getAvailableItemIdsForSpace_emptySpace() { + const itemsForEmptySpace = getAvailableItemIdsForSpace("test"); + Assert.deepEqual(itemsForEmptySpace, [], "Empty array for empty space"); +}); + +add_task(function test_getAvailableItemIdsForSpace_includingAgnostic() { + const items = getAvailableItemIdsForSpace("mail", true); + const itemsForAnySpace = getAvailableItemIdsForSpace(); + const itemsForMailSpace = getAvailableItemIdsForSpace("mail"); + + Assert.ok( + itemsForAnySpace.every(itemId => items.includes(itemId)), + "All space agnostic items are included" + ); + + Assert.ok( + itemsForMailSpace.every(itemId => items.includes(itemId)), + "All mail space items are included" + ); +}); + +add_task(function test_getDefaultItemIdsForSpace_default() { + const items = getDefaultItemIdsForSpace("default"); + + Assert.ok(Array.isArray(items), "Should return an array"); + Assert.deepEqual( + items, + ["spacer", "search-bar", "spacer"], + "Default space should contain the default item set" + ); +}); + +add_task(function test_getDefaultItemIdsForSpace_cloningArray() { + const items1 = getDefaultItemIdsForSpace("default"); + const items2 = getDefaultItemIdsForSpace("default"); + const items3 = getDefaultItemIdsForSpace("mail"); + + Assert.notStrictEqual( + items1, + items2, + "The default sets should be different array instances" + ); + Assert.notStrictEqual( + items2, + items3, + "The second default set an mail space should be different array instances" + ); + Assert.notStrictEqual( + items3, + items1, + "The mail space and first default set should be different array instances" + ); + + Assert.deepEqual( + items1, + items2, + "The two default pseudospace sets should contain the same items" + ); +}); + +add_task(function test_multipleAllowedItemIds() { + Assert.equal( + typeof MULTIPLE_ALLOWED_ITEM_IDS.has, + "function", + "Multiple allowed item IDs should be set-like" + ); + Assert.ok( + Array.from(MULTIPLE_ALLOWED_ITEM_IDS).every( + itemId => typeof itemId === "string" + ), + "Every item in the set should be a string" + ); + for (const item of CUSTOMIZABLE_ITEMS) { + Assert.equal( + MULTIPLE_ALLOWED_ITEM_IDS.has(item.id), + Boolean(item.allowMultiple), + `Set's state should matche the allowMultiple value of ${item.allowMultiple} for ${item.id}` + ); + } +}); + +add_task(function test_skipFocusItemIds() { + Assert.equal( + typeof SKIP_FOCUS_ITEM_IDS.has, + "function", + "Skip focus item IDs should be set-like" + ); + Assert.ok( + Array.from(SKIP_FOCUS_ITEM_IDS).every(itemId => typeof itemId === "string"), + "Every item in the set should be a string" + ); + for (const item of CUSTOMIZABLE_ITEMS) { + Assert.equal( + SKIP_FOCUS_ITEM_IDS.has(item.id), + Boolean(item.skipFocus), + `Set's state should match the skipFocus value of ${item.skipFocus} for ${item.id}` + ); + } +}); diff --git a/comm/mail/components/unifiedtoolbar/test/unit/test_customizableItemsDetails.js b/comm/mail/components/unifiedtoolbar/test/unit/test_customizableItemsDetails.js new file mode 100644 index 0000000000..474e5483ce --- /dev/null +++ b/comm/mail/components/unifiedtoolbar/test/unit/test_customizableItemsDetails.js @@ -0,0 +1,103 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { default: CUSTOMIZABLE_ITEMS } = ChromeUtils.importESModule( + "resource:///modules/CustomizableItemsDetails.mjs" +); + +add_task(function test_format() { + for (const item of CUSTOMIZABLE_ITEMS) { + Assert.equal(typeof item, "object", "Customizable item is an object"); + Assert.equal(typeof item.id, "string", `id "${item.id}" is a string`); + Assert.ok(!item.id.includes(","), `id "${item.id}" may not contain commas`); + Assert.greater(item.id.length, 0, `id "${item.id}" is not empty`); + Assert.equal( + typeof item.labelId, + "string", + `labelId is a string for ${item.id}` + ); + Assert.greater( + item.labelId.length, + 0, + `labelId is not empty for ${item.id}` + ); + Assert.ok( + !item.allowMultiple || item.allowMultiple === true, + `allowMultiple is falsy or boolean for ${item.id}` + ); + Assert.ok( + item.spaces === undefined || Array.isArray(item.spaces), + `spaces is undefined or an array for ${item.id}` + ); + if (item.spaces) { + for (const space of item.spaces) { + Assert.equal( + typeof space, + "string", + `space "${space}" expected to be string for ${item.id}` + ); + Assert.greater( + space.length, + 0, + `space is not empty in ${item.id} spaces` + ); + } + } + Assert.ok( + item.templateId === undefined || typeof item.templateId === "string", + `templateId must be undefined or a string for ${item.id}` + ); + if (item.templateId !== undefined) { + Assert.greater( + item.templateId.length, + 0, + `templateId is not empty for ${item.id}` + ); + Assert.ok( + item.requiredModules === undefined || + Array.isArray(item.requiredModules), + `requiredModules is undefined or an array for ${item.id}` + ); + if (item.requiredModules) { + for (const module of item.requiredModules) { + Assert.equal( + typeof module, + "string", + `module "${module}" expected to be string for ${item.id}` + ); + Assert.greater( + module.length, + 0, + `module is not empty in ${item.id} requiredModules` + ); + } + } + } else { + Assert.strictEqual( + item.requiredModules, + undefined, + `requiredModules must not be set because there is no template for item ${item.id}` + ); + } + Assert.ok( + item.hasContextMenu === undefined || + typeof item.hasContextMenu === "boolean", + `hasContextMenu must be undefined or a boolean for ${item.id}` + ); + Assert.ok( + item.skipFocus === undefined || typeof item.skipFocus === "boolean", + `skipFocus must be undefined or a boolean for ${item.id}` + ); + } +}); + +add_task(function test_idsUnique() { + const allIds = CUSTOMIZABLE_ITEMS.map(item => item.id); + const idCounts = allIds.reduce((counts, id) => { + counts[id] = counts[id] ? counts[id] + 1 : 1; + return counts; + }, {}); + const duplicateIds = Object.keys(idCounts).filter(id => idCounts[id] > 1); + Assert.deepEqual(duplicateIds, [], "All IDs should only be used once"); +}); diff --git a/comm/mail/components/unifiedtoolbar/test/unit/test_customizationState.js b/comm/mail/components/unifiedtoolbar/test/unit/test_customizationState.js new file mode 100644 index 0000000000..048b5c5cde --- /dev/null +++ b/comm/mail/components/unifiedtoolbar/test/unit/test_customizationState.js @@ -0,0 +1,64 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +const { TestUtils } = ChromeUtils.importESModule( + "resource://testing-common/TestUtils.sys.mjs" +); +const { storeState, getState } = ChromeUtils.importESModule( + "resource:///modules/CustomizationState.mjs" +); + +add_setup(function () { + // Ensure xulStore has a profile to refer to. + do_get_profile(); +}); + +add_task(function test_getState_empty() { + const state = getState(); + Assert.equal(typeof state, "object", "State should be an object"); + Assert.deepEqual(state, {}, "Empty state should be an empty object"); +}); + +add_task(async function test_storeState_observer() { + const stateChangeObserved = TestUtils.topicObserved( + "unified-toolbar-state-change" + ); + storeState({ + mail: ["write-message", "spacer", "search-bar", "spacer"], + }); + await stateChangeObserved; +}); + +add_task(function test_storeState_getState() { + const state = { + mail: ["write-message", "spacer", "search-bar", "spacer"], + calendar: [], + }; + const previousState = getState(); + Assert.notDeepEqual( + previousState, + state, + "Current state should be different from the state to write" + ); + storeState(state); + const newState = getState(); + Assert.deepEqual( + newState, + state, + "State loaded should matche the stored state" + ); + Assert.notStrictEqual( + newState, + state, + "State loaded should not be the same object as what was saved" + ); +}); + +registerCleanupFunction(() => { + Services.xulStore.removeValue( + "chrome://messenger/content/messenger.xhtml", + "unifiedToolbar", + "state" + ); +}); diff --git a/comm/mail/components/unifiedtoolbar/test/unit/test_toolbarMigration.js b/comm/mail/components/unifiedtoolbar/test/unit/test_toolbarMigration.js new file mode 100644 index 0000000000..637d40e066 --- /dev/null +++ b/comm/mail/components/unifiedtoolbar/test/unit/test_toolbarMigration.js @@ -0,0 +1,431 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; + +const { migrateToolbarForSpace, clearXULToolbarState } = + ChromeUtils.importESModule("resource:///modules/ToolbarMigration.sys.mjs"); +const { getState, storeState } = ChromeUtils.importESModule( + "resource:///modules/CustomizationState.mjs" +); +const { AppConstants } = ChromeUtils.importESModule( + "resource://gre/modules/AppConstants.sys.mjs" +); + +const MESSENGER_WINDOW = "chrome://messenger/content/messenger.xhtml"; + +function setXULToolbarState( + currentSet = "", + defaultSet = "", + toolbarId = "mail-bar3" +) { + Services.xulStore.setValue( + MESSENGER_WINDOW, + toolbarId, + "currentset", + currentSet + ); + Services.xulStore.setValue( + MESSENGER_WINDOW, + toolbarId, + "defaultset", + defaultSet + ); +} + +add_setup(() => { + do_get_profile(); + storeState({}); +}); + +add_task(function test_migration_customized() { + setXULToolbarState( + "button-getmsg,button-newmsg,button-reply,spacer,qfb-show-filter-bar,button-file,folder-location-container,spring,gloda-search,button-appmenu" + ); + setXULToolbarState( + "menubar-items,spring,button-addons", + "", + "toolbar-menubar" + ); + setXULToolbarState("button-delete", "", "tabbar-toolbar"); + + migrateToolbarForSpace("mail"); + + const newState = getState(); + + Assert.deepEqual( + newState.mail, + [ + "get-messages", + "write-message", + "reply", + "spacer", + "quick-filter-bar", + "move-to", + "folder-location", + "spacer", + "search-bar", + "spacer", + "add-ons-and-themes", + "delete", + ], + "Items were combined and migrated" + ); + Assert.ok( + !Services.xulStore.hasValue(MESSENGER_WINDOW, "mail-bar3", "currentset"), + "Old toolbar state is cleared" + ); + Assert.ok( + !Services.xulStore.hasValue(MESSENGER_WINDOW, "mail-bar3", "defaultset"), + "Old toolbar default state is cleared" + ); + + storeState({}); +}); + +add_task(function test_migration_defaults() { + setXULToolbarState(); + setXULToolbarState("", "", "toolbar-menubar"); + setXULToolbarState("", "", "tabbar-toolbar"); + + migrateToolbarForSpace("mail"); + + const newState = getState(); + + Assert.ok(!newState.mail, "New default state was preserved"); + Assert.ok( + !Services.xulStore.hasValue(MESSENGER_WINDOW, "mail-bar3", "currentset"), + "Old toolbar state is cleared" + ); + Assert.ok( + !Services.xulStore.hasValue(MESSENGER_WINDOW, "mail-bar3", "defaultset"), + "Old toolbar default state is cleared" + ); + + storeState({}); +}); + +add_task(function test_migration_empty() { + setXULToolbarState("__empty"); + setXULToolbarState("__empty", "menubar-items,spring", "toolbar-menubar"); + setXULToolbarState("__empty", "", "tabbar-toolbar"); + + migrateToolbarForSpace("mail"); + + const newState = getState(); + + Assert.deepEqual(newState.mail, [], "The toolbar contents were emptied"); + Assert.ok( + !Services.xulStore.hasValue(MESSENGER_WINDOW, "mail-bar3", "currentset"), + "Old toolbar state is cleared" + ); + Assert.ok( + !Services.xulStore.hasValue(MESSENGER_WINDOW, "mail-bar3", "defaultset"), + "Old toolbar default state is cleared" + ); + + storeState({}); +}); + +add_task(function test_migration_noop() { + const state = { mail: ["spacer", "search-bar", "spacer"] }; + storeState(state); + + migrateToolbarForSpace("mail"); + + const newState = getState(); + + Assert.deepEqual(newState, state, "Customization state is not modified"); + Assert.ok( + !Services.xulStore.hasValue(MESSENGER_WINDOW, "mail-bar3", "currentset"), + "Old toolbar state is cleared" + ); + Assert.ok( + !Services.xulStore.hasValue(MESSENGER_WINDOW, "mail-bar3", "defaultset"), + "Old toolbar default state is cleared" + ); + + storeState({}); +}); + +add_task(function test_calendar_migration() { + setXULToolbarState( + "calendar-synchronize-button,calendar-newevent-button,separator,calendar-edit-button,calendar-delete-button,spring,calendar-unifinder-button,calendar-appmenu-button", + "", + "calendar-toolbar2" + ); + setXULToolbarState( + "menubar-items,spring,button-addons", + "", + "toolbar-menubar" + ); + setXULToolbarState("button-delete", "", "tabbar-toolbar"); + + migrateToolbarForSpace("calendar"); + + const newState = getState(); + + Assert.deepEqual( + newState.calendar, + [ + "synchronize", + "new-event", + "edit-event", + "delete-event", + "spacer", + "unifinder", + "spacer", + "add-ons-and-themes", + ], + "Items were combined and migrated" + ); + Assert.ok( + !Services.xulStore.hasValue( + MESSENGER_WINDOW, + "calendar-toolbar2", + "currentset" + ), + "Old toolbar state is cleared" + ); + Assert.ok( + !Services.xulStore.hasValue( + MESSENGER_WINDOW, + "calendar-toolbar2", + "defaultset" + ), + "Old toolbar default state is cleared" + ); + + storeState({}); +}); + +add_task(function test_calendar_migration_defaults() { + setXULToolbarState("", "", "calendar-toolbar2"); + setXULToolbarState("", "", "toolbar-menubar"); + setXULToolbarState("", "", "tabbar-toolbar"); + + migrateToolbarForSpace("calendar"); + + const newState = getState(); + + Assert.deepEqual( + newState.calendar, + [ + "synchronize", + "new-event", + "new-task", + "edit-event", + "delete-event", + "spacer", + ], + "Default states were combined and migrated" + ); + Assert.ok( + !Services.xulStore.hasValue( + MESSENGER_WINDOW, + "calendar-toolbar2", + "currentset" + ), + "Old toolbar state is cleared" + ); + Assert.ok( + !Services.xulStore.hasValue( + MESSENGER_WINDOW, + "calendar-toolbar2", + "defaultset" + ), + "Old toolbar default state is cleared" + ); + + storeState({}); +}); + +add_task(function test_tasks_migration() { + setXULToolbarState( + "task-synchronize-button,task-newtask-button,task-edit-button,task-delete-button,task-print-button,spring,task-appmenu-button", + "", + "task-toolbar2" + ); + setXULToolbarState( + "menubar-items,spring,button-addons", + "", + "toolbar-menubar" + ); + setXULToolbarState("button-delete", "", "tabbar-toolbar"); + + migrateToolbarForSpace("tasks"); + + const newState = getState(); + + Assert.deepEqual( + newState.tasks, + [ + "synchronize", + "new-task", + "edit-event", + "delete-event", + "print-event", + "spacer", + "add-ons-and-themes", + ], + "Items were combined and migrated" + ); + Assert.ok( + !Services.xulStore.hasValue( + MESSENGER_WINDOW, + "task-toolbar2", + "currentset" + ), + "Old toolbar state is cleared" + ); + Assert.ok( + !Services.xulStore.hasValue( + MESSENGER_WINDOW, + "task-toolbar2", + "defaultset" + ), + "Old toolbar default state is cleared" + ); + + storeState({}); +}); + +add_task(function test_tasks_migration_defaults() { + setXULToolbarState("", "", "task-toolbar2"); + setXULToolbarState("", "", "toolbar-menubar"); + setXULToolbarState("", "", "tabbar-toolbar"); + + migrateToolbarForSpace("tasks"); + + const newState = getState(); + + Assert.deepEqual( + newState.tasks, + [ + "synchronize", + "new-event", + "new-task", + "edit-event", + "delete-event", + "spacer", + ], + "Default states were combined and migrated" + ); + Assert.ok( + !Services.xulStore.hasValue( + MESSENGER_WINDOW, + "task-toolbar2", + "currentset" + ), + "Old toolbar state is cleared" + ); + Assert.ok( + !Services.xulStore.hasValue( + MESSENGER_WINDOW, + "task-toolbar2", + "defaultset" + ), + "Old toolbar default state is cleared" + ); + + storeState({}); +}); + +add_task(function test_global_items_migration() { + setXULToolbarState( + "menubar-items,spring,button-addons", + "", + "toolbar-menubar" + ); + setXULToolbarState("button-delete", "", "tabbar-toolbar"); + + migrateToolbarForSpace("settings"); + + const newState = getState(); + + Assert.deepEqual(newState.settings, [ + "spacer", + "search-bar", + "spacer", + "add-ons-and-themes", + ]); + + storeState({}); +}); + +add_task(function test_global_items_migration_defaults() { + setXULToolbarState("", "", "toolbar-menubar"); + setXULToolbarState("", "", "tabbar-toolbar"); + + migrateToolbarForSpace("settings"); + + const newState = getState(); + + Assert.deepEqual(newState.settings, ["spacer", "search-bar", "spacer"]); + + storeState({}); +}); + +add_task(function test_clear_xul_toolbar_state() { + setXULToolbarState( + "menubar-items,spring,button-addons", + "menubar-items,spring", + "toolbar-menubar" + ); + + clearXULToolbarState("toolbar-menubar"); + + Assert.ok( + !Services.xulStore.hasValue( + MESSENGER_WINDOW, + "toolbar-menubar", + "currentset" + ), + "Old toolbar state is cleared" + ); + Assert.ok( + !Services.xulStore.hasValue( + MESSENGER_WINDOW, + "toolbar-menubar", + "defaultset" + ), + "Old toolbar default state is cleared" + ); +}); + +add_task(function test_migration_defaults_with_extension() { + setXULToolbarState( + AppConstants.platform == "macosx" + ? "button-getmsg,button-newmsg,button-tag,qfb-show-filter-bar,spring,gloda-search,extension1,extension2,button-appmenu" + : "button-getmsg,button-newmsg,separator,button-tag,qfb-show-filter-bar,spring,gloda-search,extension1,extension2,button-appmenu" + ); + setXULToolbarState("", "", "toolbar-menubar"); + setXULToolbarState("", "", "tabbar-toolbar"); + Services.xulStore.setValue( + MESSENGER_WINDOW, + "mail-bar3", + "extensionset", + "extension1,extension2" + ); + + migrateToolbarForSpace("mail"); + + const newState = getState(); + + Assert.ok(!newState.mail, "New default state was preserved"); + Assert.ok( + !Services.xulStore.hasValue(MESSENGER_WINDOW, "mail-bar3", "currentset"), + "Old toolbar state is cleared" + ); + Assert.ok( + !Services.xulStore.hasValue(MESSENGER_WINDOW, "mail-bar3", "defaultset"), + "Old toolbar default state is cleared" + ); + Assert.ok( + !Services.xulStore.hasValue(MESSENGER_WINDOW, "mail-bar3", "extensionset"), + "Old toolbar extension state is cleared" + ); + + storeState({}); +}); diff --git a/comm/mail/components/unifiedtoolbar/test/unit/xpcshell.ini b/comm/mail/components/unifiedtoolbar/test/unit/xpcshell.ini new file mode 100644 index 0000000000..ec9807b399 --- /dev/null +++ b/comm/mail/components/unifiedtoolbar/test/unit/xpcshell.ini @@ -0,0 +1,8 @@ +[DEFAULT] +head = + +[test_buttonStyle.js] +[test_customizableItems.js] +[test_customizableItemsDetails.js] +[test_customizationState.js] +[test_toolbarMigration.js] |