From 1110172597ac9d5d5516e1aa9b9b3d1d26652af8 Mon Sep 17 00:00:00 2001 From: Mathias Jakobsen Date: Mon, 20 Apr 2026 14:41:04 +0100 Subject: [PATCH] Merge pull request #32927 from overleaf/mj-themed-project-page-teardown [web] Tear down new-user-system-overall-theme split test and themed-project-dashboard feature flag GitOrigin-RevId: fe947a603266166332b73a5707bb6cbc9e3d03b9 --- .../Project/ProjectListController.mjs | 1 - .../Features/Project/UserSettingsHelper.mjs | 22 +-- .../web/frontend/extracted-translations.json | 9 - .../components/project-list-ds-nav.tsx | 2 +- .../components/project-list-root.tsx | 2 +- .../components/sidebar/sidebar-ds-nav.tsx | 33 +--- .../themed-project-dashboard-notification.tsx | 101 ----------- .../sidebar/use-themed-dashboard-intro.ts | 38 ---- .../components/navbar/account-menu-items.tsx | 3 +- services/web/locales/en.json | 9 - .../src/Project/UserSettingsHelper.test.mjs | 166 ++++-------------- 11 files changed, 39 insertions(+), 347 deletions(-) delete mode 100644 services/web/frontend/js/features/project-list/components/sidebar/themed-project-dashboard-notification.tsx delete mode 100644 services/web/frontend/js/features/project-list/components/sidebar/use-themed-dashboard-intro.ts diff --git a/services/web/app/src/Features/Project/ProjectListController.mjs b/services/web/app/src/Features/Project/ProjectListController.mjs index e00059ff12..70a8fcdecd 100644 --- a/services/web/app/src/Features/Project/ProjectListController.mjs +++ b/services/web/app/src/Features/Project/ProjectListController.mjs @@ -529,7 +529,6 @@ async function projectListPage(req, res, next) { const splitTests = [ // Split tests that will be made available to the frontend - 'themed-project-dashboard', 'import-docx', ].filter(Boolean) diff --git a/services/web/app/src/Features/Project/UserSettingsHelper.mjs b/services/web/app/src/Features/Project/UserSettingsHelper.mjs index 7908670acd..e99c74731a 100644 --- a/services/web/app/src/Features/Project/UserSettingsHelper.mjs +++ b/services/web/app/src/Features/Project/UserSettingsHelper.mjs @@ -1,8 +1,6 @@ -import SplitTestHandler from '../SplitTests/SplitTestHandler.mjs' - const SYSTEM_THEME_USER_CUTOFF_DATE = new Date(Date.UTC(2026, 2, 2, 12, 0, 0)) // 12pm GMT on March 2, 2026 -async function getOverallTheme(req, res, user) { +function getOverallTheme(user) { if (user.ace.overallTheme != null) { return user.ace.overallTheme } @@ -12,22 +10,10 @@ async function getOverallTheme(req, res, user) { return '' } - const systemOverallSplitTestAssignment = - await SplitTestHandler.promises.getAssignment( - req, - res, - 'new-user-system-overall-theme' - ) - - if (systemOverallSplitTestAssignment.variant === 'system') { - return 'system' - } - - // default / dark - return '' + return 'system' } -async function buildUserSettings(req, res, user) { +async function buildUserSettings(_req, _res, user) { return { mode: user.ace.mode, editorTheme: user.ace.theme, @@ -41,7 +27,7 @@ async function buildUserSettings(req, res, user) { previewTabs: user.ace.previewTabs ?? false, fontFamily: user.ace.fontFamily || 'lucida', lineHeight: user.ace.lineHeight || 'normal', - overallTheme: await getOverallTheme(req, res, user), + overallTheme: getOverallTheme(user), mathPreview: user.ace.mathPreview, breadcrumbs: user.ace.breadcrumbs, nonBlinkingCursor: user.ace.nonBlinkingCursor ?? false, diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index a0be14ed4c..c7f9bcf1dd 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -14,7 +14,6 @@ "Pricing": "", "Solutions": "", "a_custom_size_has_been_used_in_the_latex_code": "", - "a_dashboard_that_follows_your_lead": "", "a_file_with_that_name_already_exists_and_will_be_overriden": "", "a_more_comprehensive_list_of_keyboard_shortcuts": "", "a_new_reference_was_added": "", @@ -624,7 +623,6 @@ "failed_to_send_managed_user_invite_to_email": "", "failed_to_send_sso_link_invite_to_email": "", "fair_usage_policy_applies": "", - "fancy_going_dark": "", "fast": "", "fast_draft": "", "feature_enabled_or_disabled": "", @@ -787,7 +785,6 @@ "go_to_writefull": "", "good_news_you_already_purchased_this_add_on": "", "good_news_you_are_already_receiving_this_add_on_via_writefull": "", - "got_it": "", "group_admin": "", "group_audit_logs": "", "group_has_no_licenses_available_error": "", @@ -1129,7 +1126,6 @@ "math_inline": "", "maximum_files_uploaded_together": "", "maybe_later": "", - "meet_the_new_dark_dashboard": "", "member": "", "members_added": "", "members_management": "", @@ -2275,15 +2271,11 @@ "wed_love_you_to_stay": "", "welcome_to_overleaf_opening_workspace": "", "welcome_to_sl": "", - "welcome_to_the_dark_side": "", "well_be_here_when_youre_ready": "", "were_making_some_changes_to_project_sharing_this_means_you_will_be_visible": "", "were_performing_maintenance": "", "weve_converted_your_content_to_latex": "", - "weve_given_your_dashboard_a_sleek_new_dark_theme_for_more_comfortable_late_night_research_prefer_the_light_switch_back_anytime_right_here": "", "weve_hit_a_problem_try_starting_a_new_chat": "", - "weve_matched_your_dashboard_theme_to_your_editor_preferences_but_you_can_change_that_here_anytime": "", - "weve_set_your_dashboard_to_dark_mode_to_help_you_stay_focused_if_youre_a_fan_of_a_lighter_look_you_can_easily_switch_themes_here": "", "what_did_you_find_most_helpful": "", "what_do_you_need_help_with": "", "what_does_this_mean_for_you": "", @@ -2373,7 +2365,6 @@ "your_current_plan_gives_you": "", "your_current_plan_supports_up_to_x_licenses": "", "your_current_project_will_revert_to_the_version_from_time": "", - "your_dashboard_is_set_to_match_your_system_theme_automatically_want_a_different_look_pick_your_favorite_theme_here": "", "your_email_is_confirmed": "", "your_feedback_matters_answer_two_quick_questions": "", "your_git_access_info": "", diff --git a/services/web/frontend/js/features/project-list/components/project-list-ds-nav.tsx b/services/web/frontend/js/features/project-list/components/project-list-ds-nav.tsx index 67eda26490..bab7c25c47 100644 --- a/services/web/frontend/js/features/project-list/components/project-list-ds-nav.tsx +++ b/services/web/frontend/js/features/project-list/components/project-list-ds-nav.tsx @@ -37,7 +37,7 @@ export function ProjectListDsNav() { tags, selectedTagId, } = useProjectListContext() - const activeOverallTheme = useActiveOverallTheme('themed-project-dashboard') + const activeOverallTheme = useActiveOverallTheme() const selectedTag = tags.find(tag => tag._id === selectedTagId) diff --git a/services/web/frontend/js/features/project-list/components/project-list-root.tsx b/services/web/frontend/js/features/project-list/components/project-list-root.tsx index 52e2ba12a4..bc3a895a1a 100644 --- a/services/web/frontend/js/features/project-list/components/project-list-root.tsx +++ b/services/web/frontend/js/features/project-list/components/project-list-root.tsx @@ -77,7 +77,7 @@ function DefaultPageContentWrapper({ children }: { children: ReactNode }) { } function ProjectListPageContent() { - useThemedPage('themed-project-dashboard') + useThemedPage() const { totalProjectsCount, isLoading, loadProgress } = useProjectListContext() diff --git a/services/web/frontend/js/features/project-list/components/sidebar/sidebar-ds-nav.tsx b/services/web/frontend/js/features/project-list/components/sidebar/sidebar-ds-nav.tsx index b5e081603d..10491e2861 100644 --- a/services/web/frontend/js/features/project-list/components/sidebar/sidebar-ds-nav.tsx +++ b/services/web/frontend/js/features/project-list/components/sidebar/sidebar-ds-nav.tsx @@ -4,12 +4,8 @@ import NewProjectButton from '../new-project-button' import SidebarFilters from './sidebar-filters' import AddAffiliation, { useAddAffiliation } from '../add-affiliation' import { usePersistedResize } from '@/shared/hooks/use-resize' -import { UserProvider } from '@/shared/context/user-context' import { useScrolled } from '@/features/project-list/components/sidebar/use-scroll' import { SurveyWidgetDsNav } from '@/features/project-list/components/survey-widget-ds-nav' -import { useFeatureFlag } from '@/shared/context/split-test-context' -import { ThemedProjectDashboardNotification } from './themed-project-dashboard-notification' -import { useThemedDashboardIntro } from './use-themed-dashboard-intro' import { SidebarLowerSection } from '@/shared/components/sidebar/sidebar-lower-section' function SidebarDsNav() { @@ -19,13 +15,6 @@ function SidebarDsNav() { name: 'project-sidebar', }) const { containerRef, scrolledUp, scrolledDown } = useScrolled() - const themedDsNav = useFeatureFlag('themed-project-dashboard') - const { - completeThemedDashboardIntro, - dismissThemedDashboardIntro, - targetRef, - showingThemedDashboardIntro, - } = useThemedDashboardIntro() return (
- { - if (showingThemedDashboardIntro) { - completeThemedDashboardIntro({ - action: 'complete', - event: 'promo-click', - }) - } - }} - > +
- - {themedDsNav && ( - - )} -
void -} -export const ThemedProjectDashboardNotification = ({ - target, - show, - onDismiss, -}: ThemedProjectDashboardNotificationProps) => { - const theme = useActiveOverallTheme('themed-project-dashboard') - const { - userSettings: { overallTheme }, - } = useUserSettingsContext() - const { signUpDate: signUpDateString } = useUserContext() - const signUpDate = signUpDateString ? new Date(signUpDateString) : new Date(0) - const isNewUser = signUpDate >= SYSTEM_THEME_USER_CUTOFF_DATE - const { t } = useTranslation() - - if (!target) { - return null - } - - if (!show) { - return null - } - - let content - switch (true) { - case overallTheme === 'system': - content = { - header: t('a_dashboard_that_follows_your_lead'), - body: t( - 'your_dashboard_is_set_to_match_your_system_theme_automatically_want_a_different_look_pick_your_favorite_theme_here' - ), - } - break - case isNewUser && theme === 'dark': - content = { - header: t('meet_the_new_dark_dashboard'), - body: t( - 'weve_set_your_dashboard_to_dark_mode_to_help_you_stay_focused_if_youre_a_fan_of_a_lighter_look_you_can_easily_switch_themes_here' - ), - } - break - case theme === 'dark': - content = { - header: t('welcome_to_the_dark_side'), - body: t( - 'weve_given_your_dashboard_a_sleek_new_dark_theme_for_more_comfortable_late_night_research_prefer_the_light_switch_back_anytime_right_here' - ), - } - break - case theme === 'light': - content = { - header: t('fancy_going_dark'), - body: t( - 'weve_matched_your_dashboard_theme_to_your_editor_preferences_but_you_can_change_that_here_anytime' - ), - } - break - default: - content = { header: '', body: '' } - } - - if (!content.header || !content.body) { - return null - } - - return ( - - - - {content.header} - - - - {content.body} -
- - {t('got_it')} - -
-
-
-
- ) -} diff --git a/services/web/frontend/js/features/project-list/components/sidebar/use-themed-dashboard-intro.ts b/services/web/frontend/js/features/project-list/components/sidebar/use-themed-dashboard-intro.ts deleted file mode 100644 index 52ebd8ef04..0000000000 --- a/services/web/frontend/js/features/project-list/components/sidebar/use-themed-dashboard-intro.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { useFeatureFlag } from '@/shared/context/split-test-context' -import useTutorial from '@/shared/hooks/promotions/use-tutorial' -import { useCallback, useEffect, useRef } from 'react' - -const THEMED_DASHBOARD_TUTORIAL_KEY = 'themed-dashboard-intro' - -export const useThemedDashboardIntro = () => { - const themedDsNav = useFeatureFlag('themed-project-dashboard') - const targetRef = useRef(null) - const { - tryShowingPopup: tryShowingPopupThemedDashboardIntro, - showPopup: showingThemedDashboardIntro, - completeTutorial: completeThemedDashboardIntro, - dismissTutorial, - checkCompletion: checkThemedDashboardIntroCompletion, - } = useTutorial(THEMED_DASHBOARD_TUTORIAL_KEY, { - name: THEMED_DASHBOARD_TUTORIAL_KEY, - }) - const dismissThemedDashboardIntro = useCallback(() => { - dismissTutorial() - }, [dismissTutorial]) - useEffect(() => { - if (themedDsNav && !checkThemedDashboardIntroCompletion()) { - tryShowingPopupThemedDashboardIntro() - } - }, [ - checkThemedDashboardIntroCompletion, - tryShowingPopupThemedDashboardIntro, - themedDsNav, - ]) - - return { - targetRef, - showingThemedDashboardIntro, - completeThemedDashboardIntro, - dismissThemedDashboardIntro, - } -} diff --git a/services/web/frontend/js/shared/components/navbar/account-menu-items.tsx b/services/web/frontend/js/shared/components/navbar/account-menu-items.tsx index 93a2e89643..9cff9d8dd3 100644 --- a/services/web/frontend/js/shared/components/navbar/account-menu-items.tsx +++ b/services/web/frontend/js/shared/components/navbar/account-menu-items.tsx @@ -21,6 +21,7 @@ export function AccountMenuItems({ const { t } = useTranslation() const logOutFormId = 'logOutForm' const dsNavStyle = useDsNavStyle() + const hasOverallThemes = Boolean(getMeta('ol-overallThemes')) return ( <> @@ -36,7 +37,7 @@ export function AccountMenuItems({ {t('subscription')} ) : null} - {showThemeToggle && ( + {showThemeToggle && hasOverallThemes && ( diff --git a/services/web/locales/en.json b/services/web/locales/en.json index 91608c7b9e..dd7867f13d 100644 --- a/services/web/locales/en.json +++ b/services/web/locales/en.json @@ -16,7 +16,6 @@ "Terms": "Terms", "Universities": "Universities", "a_custom_size_has_been_used_in_the_latex_code": "A custom size has been used in the LaTeX code.", - "a_dashboard_that_follows_your_lead": "A dashboard that follows your lead", "a_file_with_that_name_already_exists_and_will_be_overriden": "A file with that name already exists. That file will be overwritten.", "a_great_way_to_start_writing_research_papers": "A great way to start writing research papers.", "a_more_comprehensive_list_of_keyboard_shortcuts": "A more comprehensive list of keyboard shortcuts can be found in <0>this __appName__ project template", @@ -828,7 +827,6 @@ "failed_to_send_managed_user_invite_to_email": "Failed to send Managed User invite to <0>__email__. Please try again later.", "failed_to_send_sso_link_invite_to_email": "Failed to send SSO invite reminder to <0>__email__. Please try again later.", "fair_usage_policy_applies": "Fair usage policy applies.", - "fancy_going_dark": "Fancy going dark?", "faq_how_does_free_trial_works_answer": "You get full access to your chosen __appName__ plan during your __len__-day free trial. There is no obligation to continue beyond the trial. Your card will be charged at the end of your __len__ day trial unless you cancel before then. You can cancel via your subscription settings.", "fast": "Fast", "fast_draft": "Fast [draft]", @@ -1040,7 +1038,6 @@ "go_to_writefull": "Go to Writefull", "good_news_you_already_purchased_this_add_on": "Good news! You already have this add-on, so no need to pay again.", "good_news_you_are_already_receiving_this_add_on_via_writefull": "Good news! You already have this add-on via your Writefull subscription. No need to pay again.", - "got_it": "Got it", "great_for_getting_started": "Great for getting started", "great_for_small_teams_and_departments": "Great for small teams and departments", "group": "Group", @@ -1502,7 +1499,6 @@ "maximum_files_uploaded_together": "Maximum __max__ files uploaded together", "may": "May", "maybe_later": "Maybe later", - "meet_the_new_dark_dashboard": "Meet the new dark dashboard", "member": "Member", "member_picker": "Select number of users for group plan", "members_added": "Member(s) added.", @@ -2927,15 +2923,11 @@ "wed_love_you_to_stay": "We’d love you to stay", "welcome_to_overleaf_opening_workspace": "Welcome to Overleaf. Opening your workspace.", "welcome_to_sl": "Welcome to __appName__", - "welcome_to_the_dark_side": "Welcome to the dark side", "well_be_here_when_youre_ready": "We’ll be here when you’re ready to dive back in! 🦆", "were_making_some_changes_to_project_sharing_this_means_you_will_be_visible": "We’re making some <0>changes to project sharing. This means, as someone with edit access, your name and email address will be visible to the project owner and other editors.", "were_performing_maintenance": "We’re performing maintenance on Overleaf and you need to wait a moment. Sorry for any inconvenience. The editor will refresh automatically in __seconds__ seconds.", "weve_converted_your_content_to_latex": "We’ve converted your content to LaTeX. You may need to edit styling, particularly for tables, figures and citations. <0>Get help with LaTeX", - "weve_given_your_dashboard_a_sleek_new_dark_theme_for_more_comfortable_late_night_research_prefer_the_light_switch_back_anytime_right_here": "We’ve given your dashboard a sleek new dark theme for more comfortable late-night research. Prefer the light? Switch back anytime right here.", "weve_hit_a_problem_try_starting_a_new_chat": "We’ve hit a problem. Try starting a new chat.", - "weve_matched_your_dashboard_theme_to_your_editor_preferences_but_you_can_change_that_here_anytime": "We’ve matched your dashboard theme to your editor preferences, but you can change that here anytime.", - "weve_set_your_dashboard_to_dark_mode_to_help_you_stay_focused_if_youre_a_fan_of_a_lighter_look_you_can_easily_switch_themes_here": "We’ve set your dashboard to dark mode to help you stay focused. If you’re a fan of a lighter look, you can easily switch themes here.", "what_did_you_find_most_helpful": "What did you find most helpful?", "what_do_you_need": "What do you need?", "what_do_you_need_help_with": "What do you need help with?", @@ -3038,7 +3030,6 @@ "your_current_plan_gives_you": "By pausing your subscription, you’ll be able to access your premium features faster when you need them again.", "your_current_plan_supports_up_to_x_licenses": "Your current plan supports up to __users__ licenses.", "your_current_project_will_revert_to_the_version_from_time": "Your current project will revert to the version from __timestamp__", - "your_dashboard_is_set_to_match_your_system_theme_automatically_want_a_different_look_pick_your_favorite_theme_here": "Your dashboard is set to match your system theme automatically. Want a different look? Pick your favorite theme here.", "your_email_is_confirmed": "Your email is confirmed.", "your_email_is_not_set_up_with_sso": "Your email is not set up with __institutionName__ SSO. Please log in with your existing login method to confirm your identity.", "your_feedback_matters_answer_two_quick_questions": "Your feedback matters! Answer two quick questions.", diff --git a/services/web/test/unit/src/Project/UserSettingsHelper.test.mjs b/services/web/test/unit/src/Project/UserSettingsHelper.test.mjs index fca866cece..02475a7deb 100644 --- a/services/web/test/unit/src/Project/UserSettingsHelper.test.mjs +++ b/services/web/test/unit/src/Project/UserSettingsHelper.test.mjs @@ -1,27 +1,15 @@ -import { vi, expect } from 'vitest' -import sinon from 'sinon' +import { expect } from 'vitest' const modulePath = '../../../../app/src/Features/Project/UserSettingsHelper.mjs' describe('UserSettingsHelper', function () { beforeEach(async function (ctx) { - ctx.SplitTestHandler = { - promises: { getAssignment: sinon.stub() }, - } - - vi.doMock( - '../../../../app/src/Features/SplitTests/SplitTestHandler.mjs', - () => ({ - default: ctx.SplitTestHandler, - }) - ) - ctx.req = { query: {} } ctx.res = {} ctx.UserSettingsHelper = (await import(modulePath)).default }) - describe('for user with overall theme set to value', function () { - beforeEach(async function (ctx) { + describe('overall theme', function () { + it('should return the overall theme if set', async function (ctx) { const user = { ace: { overallTheme: 'light', @@ -29,137 +17,43 @@ describe('UserSettingsHelper', function () { signUpDate: new Date('2022-01-01'), } - ctx.settings = await ctx.UserSettingsHelper.buildUserSettings( + const settings = await ctx.UserSettingsHelper.buildUserSettings( ctx.req, ctx.res, user ) + + expect(settings.overallTheme).toBe('light') }) - it('should return the user settings with the correct overall theme', function (ctx) { - expect(ctx.settings.overallTheme).toBe('light') + it('should return system for new users with no overall theme set', async function (ctx) { + const user = { + ace: {}, + signUpDate: new Date('2026-03-16T00:00:00Z'), + } + + const settings = await ctx.UserSettingsHelper.buildUserSettings( + ctx.req, + ctx.res, + user + ) + + expect(settings.overallTheme).toBe('system') }) - it('should not check split test', function (ctx) { - expect(ctx.SplitTestHandler.promises.getAssignment).not.toHaveBeenCalled - }) - }) + it('should return dark for old users with no overall theme set', async function (ctx) { + const user = { + ace: {}, + signUpDate: new Date('2025-02-15T00:00:00Z'), + } - describe('for user with no overall theme set', function () { - describe('for new users in treatment group', function () { - beforeEach(async function (ctx) { - const user = { - ace: {}, - signUpDate: new Date('2027-02-16T00:00:00Z'), - } + const settings = await ctx.UserSettingsHelper.buildUserSettings( + ctx.req, + ctx.res, + user + ) - ctx.SplitTestHandler.promises.getAssignment - .withArgs(ctx.req, ctx.res, 'new-user-system-overall-theme') - .resolves({ - variant: 'system', - }) - - ctx.settings = await ctx.UserSettingsHelper.buildUserSettings( - ctx.req, - ctx.res, - user - ) - }) - - it('should default to system theme', function (ctx) { - expect(ctx.settings.overallTheme).toBe('system') - }) - - it('should check split test', function (ctx) { - expect(ctx.SplitTestHandler.promises.getAssignment).toHaveBeenCalled - }) - }) - - describe('for new users in control group', function () { - beforeEach(async function (ctx) { - const user = { - ace: {}, - signUpDate: new Date('2027-02-16T00:00:00Z'), - } - - ctx.SplitTestHandler.promises.getAssignment - .withArgs(ctx.req, ctx.res, 'new-user-system-overall-theme') - .resolves({ - variant: 'default', - }) - - ctx.settings = await ctx.UserSettingsHelper.buildUserSettings( - ctx.req, - ctx.res, - user - ) - }) - - it('should default to dark theme', function (ctx) { - expect(ctx.settings.overallTheme).toBe('') - }) - - it('should check split test', function (ctx) { - expect(ctx.SplitTestHandler.promises.getAssignment).toHaveBeenCalled - }) - }) - - describe('for old users in control group', function () { - beforeEach(async function (ctx) { - const user = { - ace: {}, - signUpDate: new Date('2025-02-15T00:00:00Z'), - } - - ctx.SplitTestHandler.promises.getAssignment - .withArgs(ctx.req, ctx.res, 'new-user-system-overall-theme') - .resolves({ - variant: 'default', - }) - - ctx.settings = await ctx.UserSettingsHelper.buildUserSettings( - ctx.req, - ctx.res, - user - ) - }) - - it('should default to dark theme', function (ctx) { - expect(ctx.settings.overallTheme).toBe('') - }) - - it('should not check split test', function (ctx) { - expect(ctx.SplitTestHandler.promises.getAssignment).not.toHaveBeenCalled - }) - }) - - describe('for old users in treatment group', function () { - beforeEach(async function (ctx) { - const user = { - ace: {}, - signUpDate: new Date('2025-02-15T00:00:00Z'), - } - - ctx.SplitTestHandler.promises.getAssignment - .withArgs(ctx.req, ctx.res, 'new-user-system-overall-theme') - .resolves({ - variant: 'system', - }) - - ctx.settings = await ctx.UserSettingsHelper.buildUserSettings( - ctx.req, - ctx.res, - user - ) - }) - - it('should default to dark theme', function (ctx) { - expect(ctx.settings.overallTheme).toBe('') - }) - - it('should not check split test', function (ctx) { - expect(ctx.SplitTestHandler.promises.getAssignment).not.toHaveBeenCalled - }) + expect(settings.overallTheme).toBe('') }) }) })