diff --git a/static/app/components/sidebar/index.spec.tsx b/static/app/components/sidebar/index.spec.tsx
index bcd81f848faceb..1a47c6e80f80d5 100644
--- a/static/app/components/sidebar/index.spec.tsx
+++ b/static/app/components/sidebar/index.spec.tsx
@@ -78,6 +78,28 @@ describe('Sidebar', function () {
await userEvent.click(screen.getByTestId('sidebar-dropdown'));
});
+ it('renders for self-hosted errors only', async function () {
+ act(() => void ConfigStore.set('isSelfHostedErrorsOnly', true));
+ const {container} = renderSidebar({organization});
+ expect(await screen.findByTestId('sidebar-dropdown')).toBeInTheDocument();
+ const sidebarItems = container.querySelectorAll('[id^="sidebar-item"]');
+ const sidebarItemIds = Array.from(sidebarItems).map(sidebarItem => sidebarItem.id);
+ expect(sidebarItems.length).toEqual(10);
+ expect(sidebarItemIds).toEqual([
+ 'sidebar-item-issues',
+ 'sidebar-item-projects',
+ 'sidebar-item-alerts',
+ 'sidebar-item-releases',
+ 'sidebar-item-stats',
+ 'sidebar-item-settings',
+ 'sidebar-item-help',
+ 'sidebar-item-broadcasts',
+ 'sidebar-item-statusupdate',
+ 'sidebar-item-collapse',
+ ]);
+ act(() => void ConfigStore.set('isSelfHostedErrorsOnly', false));
+ });
+
it('has can logout', async function () {
const mock = MockApiClient.addMockResponse({
url: '/auth/',
@@ -274,15 +296,93 @@ describe('Sidebar', function () {
});
describe('when the accordion is used', () => {
- const renderSidebarWithFeatures = () => {
- renderSidebar({
+ const renderSidebarWithFeatures = (features: string[] = []) => {
+ return renderSidebar({
organization: {
...organization,
- features: [...organization.features, ...sidebarAccordionFeatures],
+ features: [...organization.features, ...sidebarAccordionFeatures, ...features],
},
});
};
+ it('renders sidebar with features', async function () {
+ const {container} = renderSidebarWithFeatures();
+ expect(await screen.findByTestId('sidebar-dropdown')).toBeInTheDocument();
+ const sidebarItems = container.querySelectorAll('[id^="sidebar-item"]');
+ const sidebarItemIds = Array.from(sidebarItems).map(sidebarItem => sidebarItem.id);
+ expect(sidebarItems.length).toEqual(12);
+ expect(sidebarItemIds).toEqual([
+ 'sidebar-item-issues',
+ 'sidebar-item-projects',
+ 'sidebar-item-sidebar-accordion-performance-item',
+ 'sidebar-item-crons',
+ 'sidebar-item-alerts',
+ 'sidebar-item-releases',
+ 'sidebar-item-stats',
+ 'sidebar-item-settings',
+ 'sidebar-item-help',
+ 'sidebar-item-broadcasts',
+ 'sidebar-item-statusupdate',
+ 'sidebar-item-collapse',
+ ]);
+ });
+
+ it('renders new sidebar hierarchy', async function () {
+ const {container} = renderSidebarWithFeatures([
+ 'performance-insights',
+ 'insights-entry-points',
+ ]);
+ expect(await screen.findByTestId('sidebar-dropdown')).toBeInTheDocument();
+ const sidebarItems = container.querySelectorAll('[id^="sidebar-item"]');
+ const sidebarItemIds = Array.from(sidebarItems).map(sidebarItem => sidebarItem.id);
+ expect(sidebarItems.length).toEqual(21);
+ expect(sidebarItemIds).toEqual([
+ 'sidebar-item-issues',
+ 'sidebar-item-projects',
+ 'sidebar-item-sidebar-accordion-explore-item',
+ 'sidebar-item-sidebar-accordion-insights-item',
+ 'sidebar-item-performance-http',
+ 'sidebar-item-performance-database',
+ 'sidebar-item-performance-browser-resources',
+ 'sidebar-item-performance-mobile-app-startup',
+ 'sidebar-item-performance-mobile-screens',
+ 'sidebar-item-performance-webvitals',
+ 'sidebar-item-performance-cache',
+ 'sidebar-item-performance',
+ 'sidebar-item-crons',
+ 'sidebar-item-alerts',
+ 'sidebar-item-releases',
+ 'sidebar-item-stats',
+ 'sidebar-item-settings',
+ 'sidebar-item-help',
+ 'sidebar-item-broadcasts',
+ 'sidebar-item-statusupdate',
+ 'sidebar-item-collapse',
+ ]);
+ });
+
+ it('renders sidebar items for self-hosted errors only', async function () {
+ act(() => void ConfigStore.set('isSelfHostedErrorsOnly', true));
+ const {container} = renderSidebarWithFeatures();
+ expect(await screen.findByTestId('sidebar-dropdown')).toBeInTheDocument();
+ const sidebarItems = container.querySelectorAll('[id^="sidebar-item"]');
+ const sidebarItemIds = Array.from(sidebarItems).map(sidebarItem => sidebarItem.id);
+ expect(sidebarItems.length).toEqual(10);
+ expect(sidebarItemIds).toEqual([
+ 'sidebar-item-issues',
+ 'sidebar-item-projects',
+ 'sidebar-item-alerts',
+ 'sidebar-item-releases',
+ 'sidebar-item-stats',
+ 'sidebar-item-settings',
+ 'sidebar-item-help',
+ 'sidebar-item-broadcasts',
+ 'sidebar-item-statusupdate',
+ 'sidebar-item-collapse',
+ ]);
+ act(() => void ConfigStore.set('isSelfHostedErrorsOnly', false));
+ });
+
it('should not render floating accordion when expanded', async () => {
renderSidebarWithFeatures();
await userEvent.click(screen.getByTestId('sidebar-accordion-performance-item'));
diff --git a/static/app/components/sidebar/index.tsx b/static/app/components/sidebar/index.tsx
index 47aada29c2c3bb..a3ff2401eee04b 100644
--- a/static/app/components/sidebar/index.tsx
+++ b/static/app/components/sidebar/index.tsx
@@ -130,6 +130,7 @@ function Sidebar() {
const organization = useOrganization({allowNull: true});
const {shouldAccordionFloat} = useContext(ExpandedContext);
const resourceModuleTitle = useModuleTitle(ModuleName.RESOURCE);
+ const isSelfHostedErrorsOnly = ConfigStore.get('isSelfHostedErrorsOnly');
const collapsed = !!preferences.collapsed;
const horizontal = useMedia(`(max-width: ${theme.breakpoints.medium})`);
@@ -671,7 +672,7 @@ function Sidebar() {
{projects}
- {hasNewSidebarHierarchy && (
+ {hasNewSidebarHierarchy && !isSelfHostedErrorsOnly && (
{explore}
@@ -689,7 +690,7 @@ function Sidebar() {
)}
- {!hasNewSidebarHierarchy && (
+ {!hasNewSidebarHierarchy && !isSelfHostedErrorsOnly && (
{performance}
@@ -711,6 +712,18 @@ function Sidebar() {
)}
+ {isSelfHostedErrorsOnly && (
+
+
+ {alerts}
+ {discover2}
+ {dashboards}
+ {releases}
+ {userFeedback}
+
+
+ )}
+
{stats}
{settings}
diff --git a/static/app/types/system.tsx b/static/app/types/system.tsx
index ab0cb73d7519ca..aa0aa80600941a 100644
--- a/static/app/types/system.tsx
+++ b/static/app/types/system.tsx
@@ -150,6 +150,7 @@ export interface Config {
// Maintain isOnPremise key for backcompat (plugins?).
isOnPremise: boolean;
isSelfHosted: boolean;
+ isSelfHostedErrorsOnly: boolean;
languageCode: string;
lastOrganization: string | null;
links: {
diff --git a/tests/js/fixtures/config.ts b/tests/js/fixtures/config.ts
index 41de61b2085fb4..4526150dcab492 100644
--- a/tests/js/fixtures/config.ts
+++ b/tests/js/fixtures/config.ts
@@ -25,6 +25,7 @@ export function ConfigFixture(params: Partial = {}): Config {
// Maintain isOnPremise key for backcompat (plugins?).
isOnPremise: false,
isSelfHosted: false,
+ isSelfHostedErrorsOnly: false,
lastOrganization: null,
gravatarBaseUrl: 'https://gravatar.com',
initialTrace: {