@@ -10,7 +10,7 @@ import { ReactWrapper } from 'enzyme';
1010import { act } from 'react-dom/test-utils' ;
1111import { App } from './app' ;
1212import { LensAppProps , LensAppServices } from './types' ;
13- import { EditorFrameInstance } from '../types' ;
13+ import { EditorFrameInstance , EditorFrameProps } from '../types' ;
1414import { Document } from '../persistence' ;
1515import { DOC_TYPE } from '../../common' ;
1616import { mount } from 'enzyme' ;
@@ -44,6 +44,8 @@ import {
4444import { LensAttributeService } from '../lens_attribute_service' ;
4545import { KibanaContextProvider } from '../../../../../src/plugins/kibana_react/public' ;
4646import { EmbeddableStateTransfer } from '../../../../../src/plugins/embeddable/public' ;
47+ import { NativeRenderer } from '../native_renderer' ;
48+ import moment from 'moment' ;
4749
4850jest . mock ( '../editor_frame_service/editor_frame/expression_helpers' ) ;
4951jest . mock ( 'src/core/public' ) ;
@@ -144,6 +146,11 @@ function createMockTimefilter() {
144146 return unsubscribe ;
145147 } ,
146148 } ) ,
149+ calculateBounds : jest . fn ( ( ) => ( {
150+ min : moment ( '2021-01-10T04:00:00.000Z' ) ,
151+ max : moment ( '2021-01-10T08:00:00.000Z' ) ,
152+ } ) ) ,
153+ getBounds : jest . fn ( ( ) => timeFilter ) ,
147154 getRefreshInterval : ( ) => { } ,
148155 getRefreshIntervalDefaults : ( ) => { } ,
149156 getAutoRefreshFetch$ : ( ) => ( {
@@ -233,6 +240,9 @@ describe('Lens App', () => {
233240 } ) ,
234241 } ,
235242 search : createMockSearchService ( ) ,
243+ nowProvider : {
244+ get : jest . fn ( ) ,
245+ } ,
236246 } as unknown ) as DataPublicPluginStart ,
237247 storage : {
238248 get : jest . fn ( ) ,
@@ -306,8 +316,8 @@ describe('Lens App', () => {
306316 />,
307317 Object {
308318 "dateRange": Object {
309- "fromDate": "now-7d ",
310- "toDate": "now ",
319+ "fromDate": "2021-01-10T04:00:00.000Z ",
320+ "toDate": "2021-01-10T08:00:00.000Z ",
311321 },
312322 "doc": undefined,
313323 "filters": Array [],
@@ -350,7 +360,7 @@ describe('Lens App', () => {
350360 expect ( frame . mount ) . toHaveBeenCalledWith (
351361 expect . any ( Element ) ,
352362 expect . objectContaining ( {
353- dateRange : { fromDate : 'now-7d ' , toDate : 'now ' } ,
363+ dateRange : { fromDate : '2021-01-10T04:00:00.000Z ' , toDate : '2021-01-10T08:00:00.000Z ' } ,
354364 query : { query : '' , language : 'kuery' } ,
355365 filters : [ pinnedFilter ] ,
356366 } )
@@ -1008,7 +1018,7 @@ describe('Lens App', () => {
10081018 expect ( frame . mount ) . toHaveBeenCalledWith (
10091019 expect . any ( Element ) ,
10101020 expect . objectContaining ( {
1011- dateRange : { fromDate : 'now-7d ' , toDate : 'now ' } ,
1021+ dateRange : { fromDate : '2021-01-10T04:00:00.000Z ' , toDate : '2021-01-10T08:00:00.000Z ' } ,
10121022 query : { query : '' , language : 'kuery' } ,
10131023 } )
10141024 ) ;
@@ -1055,7 +1065,11 @@ describe('Lens App', () => {
10551065 } ) ;
10561066
10571067 it ( 'updates the editor frame when the user changes query or time in the search bar' , ( ) => {
1058- const { component, frame } = mountWith ( { } ) ;
1068+ const { component, frame, services } = mountWith ( { } ) ;
1069+ ( services . data . query . timefilter . timefilter . calculateBounds as jest . Mock ) . mockReturnValue ( {
1070+ min : moment ( '2021-01-09T04:00:00.000Z' ) ,
1071+ max : moment ( '2021-01-09T08:00:00.000Z' ) ,
1072+ } ) ;
10591073 act ( ( ) =>
10601074 component . find ( TopNavMenu ) . prop ( 'onQuerySubmit' ) ! ( {
10611075 dateRange : { from : 'now-14d' , to : 'now-7d' } ,
@@ -1071,10 +1085,14 @@ describe('Lens App', () => {
10711085 } ) ,
10721086 { }
10731087 ) ;
1088+ expect ( services . data . query . timefilter . timefilter . setTime ) . toHaveBeenCalledWith ( {
1089+ from : 'now-14d' ,
1090+ to : 'now-7d' ,
1091+ } ) ;
10741092 expect ( frame . mount ) . toHaveBeenCalledWith (
10751093 expect . any ( Element ) ,
10761094 expect . objectContaining ( {
1077- dateRange : { fromDate : 'now-14d ' , toDate : 'now-7d ' } ,
1095+ dateRange : { fromDate : '2021-01-09T04:00:00.000Z ' , toDate : '2021-01-09T08:00:00.000Z ' } ,
10781096 query : { query : 'new' , language : 'lucene' } ,
10791097 } )
10801098 ) ;
@@ -1237,6 +1255,34 @@ describe('Lens App', () => {
12371255 ) ;
12381256 } ) ;
12391257
1258+ it ( 'clears all existing unpinned filters when the active saved query is cleared' , ( ) => {
1259+ const { component, frame, services } = mountWith ( { } ) ;
1260+ act ( ( ) =>
1261+ component . find ( TopNavMenu ) . prop ( 'onQuerySubmit' ) ! ( {
1262+ dateRange : { from : 'now-14d' , to : 'now-7d' } ,
1263+ query : { query : 'new' , language : 'lucene' } ,
1264+ } )
1265+ ) ;
1266+ const indexPattern = ( { id : 'index1' } as unknown ) as IIndexPattern ;
1267+ const field = ( { name : 'myfield' } as unknown ) as IFieldType ;
1268+ const pinnedField = ( { name : 'pinnedField' } as unknown ) as IFieldType ;
1269+ const unpinned = esFilters . buildExistsFilter ( field , indexPattern ) ;
1270+ const pinned = esFilters . buildExistsFilter ( pinnedField , indexPattern ) ;
1271+ FilterManager . setFiltersStore ( [ pinned ] , esFilters . FilterStateStore . GLOBAL_STATE ) ;
1272+ act ( ( ) => services . data . query . filterManager . setFilters ( [ pinned , unpinned ] ) ) ;
1273+ component . update ( ) ;
1274+ act ( ( ) => component . find ( TopNavMenu ) . prop ( 'onClearSavedQuery' ) ! ( ) ) ;
1275+ component . update ( ) ;
1276+ expect ( frame . mount ) . toHaveBeenLastCalledWith (
1277+ expect . any ( Element ) ,
1278+ expect . objectContaining ( {
1279+ filters : [ pinned ] ,
1280+ } )
1281+ ) ;
1282+ } ) ;
1283+ } ) ;
1284+
1285+ describe ( 'search session id management' , ( ) => {
12401286 it ( 'updates the searchSessionId when the query is updated' , ( ) => {
12411287 const { component, frame } = mountWith ( { } ) ;
12421288 act ( ( ) => {
@@ -1263,12 +1309,12 @@ describe('Lens App', () => {
12631309 expect ( frame . mount ) . toHaveBeenCalledWith (
12641310 expect . any ( Element ) ,
12651311 expect . objectContaining ( {
1266- searchSessionId : `sessionId-1 ` ,
1312+ searchSessionId : `sessionId-2 ` ,
12671313 } )
12681314 ) ;
12691315 } ) ;
12701316
1271- it ( 'clears all existing unpinned filters when the active saved query is cleared' , ( ) => {
1317+ it ( 'updates the searchSessionId when the active saved query is cleared' , ( ) => {
12721318 const { component, frame, services } = mountWith ( { } ) ;
12731319 act ( ( ) =>
12741320 component . find ( TopNavMenu ) . prop ( 'onQuerySubmit' ) ! ( {
@@ -1286,31 +1332,67 @@ describe('Lens App', () => {
12861332 component . update ( ) ;
12871333 act ( ( ) => component . find ( TopNavMenu ) . prop ( 'onClearSavedQuery' ) ! ( ) ) ;
12881334 component . update ( ) ;
1289- expect ( frame . mount ) . toHaveBeenLastCalledWith (
1335+ expect ( frame . mount ) . toHaveBeenCalledWith (
12901336 expect . any ( Element ) ,
12911337 expect . objectContaining ( {
1292- filters : [ pinned ] ,
1338+ searchSessionId : `sessionId-2` ,
12931339 } )
12941340 ) ;
12951341 } ) ;
12961342
1297- it ( 'updates the searchSessionId when the active saved query is cleared' , ( ) => {
1298- const { component, frame, services } = mountWith ( { } ) ;
1299- act ( ( ) =>
1300- component . find ( TopNavMenu ) . prop ( 'onQuerySubmit' ) ! ( {
1301- dateRange : { from : 'now-14d' , to : 'now-7d' } ,
1302- query : { query : 'new' , language : 'lucene' } ,
1343+ const mockUpdate = {
1344+ filterableIndexPatterns : [ ] ,
1345+ doc : {
1346+ title : '' ,
1347+ description : '' ,
1348+ visualizationType : '' ,
1349+ state : {
1350+ datasourceStates : { } ,
1351+ visualization : { } ,
1352+ filters : [ ] ,
1353+ query : { query : '' , language : 'lucene' } ,
1354+ } ,
1355+ references : [ ] ,
1356+ } ,
1357+ isSaveable : true ,
1358+ activeData : undefined ,
1359+ } ;
1360+
1361+ it ( 'does not update the searchSessionId when the state changes' , ( ) => {
1362+ const { component, frame } = mountWith ( { } ) ;
1363+ act ( ( ) => {
1364+ ( component . find ( NativeRenderer ) . prop ( 'nativeProps' ) as EditorFrameProps ) . onChange (
1365+ mockUpdate
1366+ ) ;
1367+ } ) ;
1368+ component . update ( ) ;
1369+ expect ( frame . mount ) . not . toHaveBeenCalledWith (
1370+ expect . any ( Element ) ,
1371+ expect . objectContaining ( {
1372+ searchSessionId : `sessionId-2` ,
13031373 } )
13041374 ) ;
1305- const indexPattern = ( { id : 'index1' } as unknown ) as IIndexPattern ;
1306- const field = ( { name : 'myfield' } as unknown ) as IFieldType ;
1307- const pinnedField = ( { name : 'pinnedField' } as unknown ) as IFieldType ;
1308- const unpinned = esFilters . buildExistsFilter ( field , indexPattern ) ;
1309- const pinned = esFilters . buildExistsFilter ( pinnedField , indexPattern ) ;
1310- FilterManager . setFiltersStore ( [ pinned ] , esFilters . FilterStateStore . GLOBAL_STATE ) ;
1311- act ( ( ) => services . data . query . filterManager . setFilters ( [ pinned , unpinned ] ) ) ;
1312- component . update ( ) ;
1313- act ( ( ) => component . find ( TopNavMenu ) . prop ( 'onClearSavedQuery' ) ! ( ) ) ;
1375+ } ) ;
1376+
1377+ it ( 'does update the searchSessionId when the state changes and too much time passed' , ( ) => {
1378+ const { component, frame, services } = mountWith ( { } ) ;
1379+
1380+ // time range is 100,000ms ago to 30,000ms ago (that's a lag of 30 percent)
1381+ ( services . data . nowProvider . get as jest . Mock ) . mockReturnValue ( new Date ( Date . now ( ) - 30000 ) ) ;
1382+ ( services . data . query . timefilter . timefilter . getTime as jest . Mock ) . mockReturnValue ( {
1383+ from : 'now-2m' ,
1384+ to : 'now' ,
1385+ } ) ;
1386+ ( services . data . query . timefilter . timefilter . getBounds as jest . Mock ) . mockReturnValue ( {
1387+ min : moment ( Date . now ( ) - 100000 ) ,
1388+ max : moment ( Date . now ( ) - 30000 ) ,
1389+ } ) ;
1390+
1391+ act ( ( ) => {
1392+ ( component . find ( NativeRenderer ) . prop ( 'nativeProps' ) as EditorFrameProps ) . onChange (
1393+ mockUpdate
1394+ ) ;
1395+ } ) ;
13141396 component . update ( ) ;
13151397 expect ( frame . mount ) . toHaveBeenCalledWith (
13161398 expect . any ( Element ) ,
@@ -1319,6 +1401,34 @@ describe('Lens App', () => {
13191401 } )
13201402 ) ;
13211403 } ) ;
1404+
1405+ it ( 'does not update the searchSessionId when the state changes and too little time has passed' , ( ) => {
1406+ const { component, frame, services } = mountWith ( { } ) ;
1407+
1408+ // time range is 100,000ms ago to 300ms ago (that's a lag of .3 percent, not enough to trigger a session update)
1409+ ( services . data . nowProvider . get as jest . Mock ) . mockReturnValue ( new Date ( Date . now ( ) - 300 ) ) ;
1410+ ( services . data . query . timefilter . timefilter . getTime as jest . Mock ) . mockReturnValue ( {
1411+ from : 'now-2m' ,
1412+ to : 'now' ,
1413+ } ) ;
1414+ ( services . data . query . timefilter . timefilter . getBounds as jest . Mock ) . mockReturnValue ( {
1415+ min : moment ( Date . now ( ) - 100000 ) ,
1416+ max : moment ( Date . now ( ) - 300 ) ,
1417+ } ) ;
1418+
1419+ act ( ( ) => {
1420+ ( component . find ( NativeRenderer ) . prop ( 'nativeProps' ) as EditorFrameProps ) . onChange (
1421+ mockUpdate
1422+ ) ;
1423+ } ) ;
1424+ component . update ( ) ;
1425+ expect ( frame . mount ) . not . toHaveBeenCalledWith (
1426+ expect . any ( Element ) ,
1427+ expect . objectContaining ( {
1428+ searchSessionId : `sessionId-2` ,
1429+ } )
1430+ ) ;
1431+ } ) ;
13221432 } ) ;
13231433
13241434 describe ( 'showing a confirm message when leaving' , ( ) => {
0 commit comments