-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Explore: Fix graph not updating when changing config (#62473)
* Explore: Fix graph not updating when changing config * move useStructureRev to a seprate hook and add specific tests
- Loading branch information
Showing
3 changed files
with
153 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
117 changes: 117 additions & 0 deletions
117
public/app/features/explore/Graph/useStructureRev.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import { renderHook } from '@testing-library/react-hooks'; | ||
|
||
import { DataFrame, FieldType, toDataFrame } from '@grafana/data'; | ||
|
||
import { useStructureRev } from './useStructureRev'; | ||
|
||
let lastResult: number = Number.MIN_SAFE_INTEGER; | ||
|
||
const resetCounters = () => { | ||
lastResult = Number.MIN_SAFE_INTEGER; | ||
}; | ||
|
||
const startCounters = (start: number | Error) => { | ||
// The if is only to make TypeScript happy | ||
if (start instanceof Error) { | ||
expect(start).not.toBeInstanceOf(Error); | ||
return; | ||
} | ||
|
||
lastResult = start; | ||
}; | ||
|
||
beforeAll(() => { | ||
expect.extend({ | ||
toHaveIncremented(received: number[]) { | ||
if (received.length < 2) { | ||
return { | ||
message: () => `expected at least 2 elements, got ${received.length}`, | ||
pass: false, | ||
}; | ||
} | ||
|
||
const pass = received[received.length - 1] > lastResult; | ||
const r = lastResult; | ||
|
||
const message = () => | ||
this.isNot | ||
? `expected ${received[received.length - 1]} to be equal or lesser than ${r}` | ||
: `expected ${received[received.length - 1]} to be greater than ${r}`; | ||
|
||
lastResult = received[received.length - 1]; | ||
|
||
return { | ||
message, | ||
pass, | ||
}; | ||
}, | ||
}); | ||
}); | ||
|
||
describe('useStructureRev', () => { | ||
afterEach(() => resetCounters()); | ||
|
||
it('should increment only when relevant fields in frame change', () => { | ||
let frames: DataFrame[] = [toDataFrame({ fields: [{ name: 'time', type: FieldType.time, values: [1, 2, 3] }] })]; | ||
const { result, rerender } = renderHook((frames) => useStructureRev(frames), { initialProps: frames }); | ||
startCounters(result.current); | ||
|
||
// When changing number of frames, the structureRev should increment | ||
frames = [...frames, toDataFrame({ fields: [{ name: 'time', type: FieldType.time, values: [1, 2, 3] }] })]; | ||
rerender(frames); | ||
expect(result.all).toHaveIncremented(); | ||
|
||
// Changing RefId should not increment the structure revision | ||
frames[0] = toDataFrame({ | ||
refId: 'A', | ||
fields: [{ name: 'time', type: FieldType.time, values: [1, 2, 3] }], | ||
}); | ||
rerender([...frames]); | ||
expect(result.all).not.toHaveIncremented(); | ||
|
||
// Changing frame name should increment the structure revision | ||
frames[0] = toDataFrame({ | ||
refId: 'A', | ||
name: 'Some Name', | ||
fields: [{ name: 'time', type: FieldType.time, values: [1, 2, 3] }], | ||
}); | ||
rerender([...frames]); | ||
expect(result.all).toHaveIncremented(); | ||
|
||
// Changing frame's fields number should increment the structure revision | ||
frames[0] = toDataFrame({ | ||
refId: 'A', | ||
name: 'Some Name', | ||
fields: [ | ||
{ name: 'time', type: FieldType.time, values: [1, 2, 3] }, | ||
{ name: 'value', type: FieldType.number, values: [1, 2, 3] }, | ||
], | ||
}); | ||
rerender([...frames]); | ||
expect(result.all).toHaveIncremented(); | ||
|
||
// Changing a frame's field's config should increment the structure revision | ||
frames[0] = toDataFrame({ | ||
refId: 'A', | ||
name: 'Some Name', | ||
fields: [ | ||
{ name: 'time', type: FieldType.time, values: [1, 2, 3] }, | ||
{ name: 'value', type: FieldType.number, values: [1, 2, 3], config: { unit: 'ms' } }, | ||
], | ||
}); | ||
rerender([...frames]); | ||
expect(result.all).toHaveIncremented(); | ||
|
||
// Changing a frame's field's name should increment the structure revision | ||
frames[0] = toDataFrame({ | ||
refId: 'A', | ||
name: 'Some Name', | ||
fields: [ | ||
{ name: 'time', type: FieldType.time, values: [1, 2, 3] }, | ||
{ name: 'value, but with a different name', type: FieldType.number, values: [1, 2, 3], config: { unit: 'ms' } }, | ||
], | ||
}); | ||
rerender([...frames]); | ||
expect(result.all).toHaveIncremented(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { useMemo } from 'react'; | ||
import { useCounter, usePrevious } from 'react-use'; | ||
|
||
import { DataFrame, compareArrayValues, compareDataFrameStructures } from '@grafana/data'; | ||
|
||
export function useStructureRev(frames: DataFrame[]) { | ||
const [structureRev, { inc }] = useCounter(0); | ||
const previousFrames = usePrevious(frames); | ||
|
||
// We need to increment structureRev when the number of series changes. | ||
// the function passed to useMemo runs during rendering, so when we get a different | ||
// amount of data, structureRev is incremented before we render it | ||
useMemo(() => { | ||
if (previousFrames && !compareArrayValues(frames, previousFrames, compareDataFrameStructures)) { | ||
inc(); | ||
} | ||
}, [frames, previousFrames, inc]); | ||
|
||
return structureRev; | ||
} |