@@ -30,6 +30,8 @@ const infiniteOptionsMocks = vi.hoisted(() => ({
3030
3131const chartOptions = vi . hoisted ( ( ) => ( { current : undefined as unknown } ) )
3232
33+ const editionMock = vi . hoisted ( ( ) => ( { value : 'COMMUNITY' } ) )
34+
3335const queryData = vi . hoisted ( ( ) => ( {
3436 activity : {
3537 data : [
@@ -190,9 +192,13 @@ vi.mock('@/context/permission-state', () => ({
190192 workspacePermissionKeysAtom : permissionState . workspaceKeysAtom ,
191193} ) )
192194
193- vi . mock ( '@/features/system-features/state' , ( ) => ( {
194- knowledgeFsUploadEnabledAtom : systemFeaturesState . uploadAvailableAtom ,
195- } ) )
195+ vi . mock ( '@/features/system-features/state' , async ( ) => {
196+ const { atom } = await import ( 'jotai' )
197+ return {
198+ deploymentEditionAtom : atom ( ( ) => editionMock . value ) ,
199+ knowledgeFsUploadEnabledAtom : systemFeaturesState . uploadAvailableAtom ,
200+ }
201+ } )
196202
197203vi . mock ( '../../space/context' , ( ) => ( {
198204 useKnowledgeSpacePermission : ( permission : string ) =>
@@ -367,6 +373,7 @@ function renderOverviewWithNuqs(
367373describe ( 'KnowledgeOverviewPage' , ( ) => {
368374 beforeEach ( ( ) => {
369375 vi . clearAllMocks ( )
376+ editionMock . value = 'COMMUNITY'
370377 tasksQueryState . isError = false
371378 tasksQueryState . isPending = false
372379 tasksQueryState . isRefetching = false
@@ -821,6 +828,83 @@ describe('KnowledgeOverviewPage', () => {
821828 )
822829 } )
823830
831+ it ( 'limits cloud activity filters to the most recent 90 calendar days' , async ( ) => {
832+ vi . useFakeTimers ( { toFake : [ 'Date' ] } )
833+ vi . setSystemTime ( new Date ( 2026 , 8 , 8 , 12 ) )
834+ editionMock . value = 'CLOUD'
835+ const user = userEvent . setup ( )
836+ const earliest = dayjs ( ) . subtract ( 89 , 'day' ) . startOf ( 'day' )
837+
838+ renderOverviewWithNuqs ( < KnowledgeOverviewPage knowledgeSpaceId = "space-1" /> )
839+ expect ( queryOptionsMocks . activity . mock . lastCall ?. [ 0 ] ) . toMatchObject ( {
840+ input : { query : { from_at : earliest . toISOString ( ) } } ,
841+ } )
842+ await user . click ( screen . getByRole ( 'button' , { name : 'knowledgeOverview.overview.allActivity' } ) )
843+ await user . click ( screen . getByRole ( 'combobox' , { name : 'knowledgeOverview.overview.timeRange' } ) )
844+ expect (
845+ screen . queryByRole ( 'option' , { name : 'knowledgeOverview.overview.allTime' } ) ,
846+ ) . not . toBeInTheDocument ( )
847+ await user . click (
848+ await screen . findByRole ( 'option' , { name : 'knowledgeOverview.overview.last90Days' } ) ,
849+ )
850+
851+ const options = infiniteOptionsMocks . activity . mock . lastCall ?. [ 0 ] as {
852+ input : ( cursor : string | null ) => { query : Record < string , unknown > }
853+ }
854+ expect ( options . input ( null ) . query . from_at ) . toBe ( earliest . toISOString ( ) )
855+ expect ( options . input ( 'older' ) . query ) . toMatchObject ( {
856+ cursor : 'older' ,
857+ from_at : earliest . toISOString ( ) ,
858+ to_at : dayjs ( ) . endOf ( 'day' ) . toISOString ( ) ,
859+ } )
860+
861+ const calendarLabel = ( date : dayjs . Dayjs ) =>
862+ new Intl . DateTimeFormat ( 'en-US' , { dateStyle : 'full' , timeZone : 'UTC' } ) . format (
863+ new Date ( Date . UTC ( date . year ( ) , date . month ( ) , date . date ( ) ) ) ,
864+ )
865+ await user . click (
866+ screen . getByRole ( 'button' , { name : 'knowledgeOverview.overview.timeRange start' } ) ,
867+ )
868+ expect (
869+ screen . getByRole ( 'button' , { name : calendarLabel ( earliest . subtract ( 1 , 'day' ) ) } ) ,
870+ ) . toBeDisabled ( )
871+ expect ( screen . getByRole ( 'button' , { name : calendarLabel ( earliest ) } ) ) . toBeEnabled ( )
872+ await user . click ( screen . getByRole ( 'button' , { name : calendarLabel ( earliest . add ( 1 , 'day' ) ) } ) )
873+ expect (
874+ screen . getByRole ( 'combobox' , { name : 'knowledgeOverview.overview.timeRange' } ) ,
875+ ) . toHaveTextContent ( 'filter.period.custom' )
876+ expect ( infiniteOptionsMocks . activity . mock . lastCall ?. [ 0 ] . input ( null ) . query . from_at ) . toBe (
877+ earliest . add ( 1 , 'day' ) . toISOString ( ) ,
878+ )
879+ } )
880+
881+ it . each ( [ 'COMMUNITY' , 'ENTERPRISE' ] ) (
882+ 'preserves all-time activity queries for %s' ,
883+ async ( edition ) => {
884+ editionMock . value = edition
885+ const user = userEvent . setup ( )
886+ renderOverviewWithNuqs ( < KnowledgeOverviewPage knowledgeSpaceId = "space-1" /> )
887+ expect ( queryOptionsMocks . activity . mock . lastCall ?. [ 0 ] . input . query ) . not . toHaveProperty (
888+ 'from_at' ,
889+ )
890+ await user . click (
891+ screen . getByRole ( 'button' , { name : 'knowledgeOverview.overview.allActivity' } ) ,
892+ )
893+ await user . click (
894+ screen . getByRole ( 'combobox' , { name : 'knowledgeOverview.overview.timeRange' } ) ,
895+ )
896+ await user . click (
897+ await screen . findByRole ( 'option' , { name : 'knowledgeOverview.overview.allTime' } ) ,
898+ )
899+
900+ const options = infiniteOptionsMocks . activity . mock . lastCall ?. [ 0 ] as {
901+ input : ( cursor : string | null ) => { query : Record < string , unknown > }
902+ }
903+ expect ( options . input ( null ) . query ) . not . toHaveProperty ( 'from_at' )
904+ expect ( options . input ( null ) . query ) . not . toHaveProperty ( 'to_at' )
905+ } ,
906+ )
907+
824908 it ( 'shows safe activity details and relative times for today in the drawer' , async ( ) => {
825909 // At midnight, "two hours ago" is yesterday and deliberately uses an absolute date.
826910 vi . useFakeTimers ( { toFake : [ 'Date' ] } )
0 commit comments