-
Notifications
You must be signed in to change notification settings - Fork 3.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(ui): ignore false change events in VariableForm #15317
Conversation
closes #15059 if a user re-selects the same variable type when adding a variable, no action takes place
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
waiting on clarification of acceptance criteria before merging |
the original intent of the issue was to persist user data across type selection interfaces, not only guard against double clicks. this commit pushes all of the variable editor information down to redux to allow persistance outside of the view state until the user clicks "cancel" or "create" in the interface. more tests forthcoming
made more sense than all of the copy pasta that was being slung around in the previous commit. Tests should still live on the form.
@drdelambre it's pretty common that people rebase and squash things into a single commit, but there's no hard requirements on that at the moment. Feel free to merge at your discretion. |
i'm all about it! game plan is to use the big green "squash and merge" button and rewrite the commit log, unless otherwise instructed. |
works for me 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks awesome. Some nits but 👍
values: KeyValueMap | ||
interface Argument<T> { | ||
type: VariableArgumentType | ||
values: T |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love this use of generics.
case 'query': | ||
return ( | ||
<Form.Element label="Script"> | ||
<Grid.Column> | ||
<div className="overlay-flux-editor"> | ||
<FluxEditor | ||
script={args.values.query} | ||
script={(args as QueryArguments).values.query} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Generally a smell when I have to cast a type using as
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
felt the same way, seemed to come along with the use of the generics and the vartype = type1 | type2 | type3
definitions. typescript seems to be only able to resolve in one direction. any tips on mitigating this kind of polymorphism?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a solution, but it's in a whole branch. let's look at it together tomorrow?
@@ -0,0 +1,84 @@ | |||
// Libraries | |||
import React from 'react' | |||
import {shallow} from 'enzyme' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use react-testing-library
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
....cause i forgot.
WILL DO!
import VariableForm from 'src/variables/components/VariableForm' | ||
|
||
// Constants | ||
import {variables} from 'mocks/dummyData' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's decide on a convention on where to put dummy test data.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i need a rough overview of this tomorrow. running into weird conditions when trying to run the code in different environments.
}) | ||
|
||
describe('type selector', () => { | ||
it('should not tell the the parrent if the type was not changed', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it('should not tell the the parrent if the type was not changed', () => { | |
it('should not tell the the parent if the type was not changed', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lol thanks for the catch
@@ -0,0 +1,45 @@ | |||
// Libraries | |||
import React from 'react' | |||
import {shallow} from 'enzyme' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought you liked react-testing-library
} | ||
|
||
const mstp = (state: AppState): StateProps => { | ||
const variables = extractVariablesList(state), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love all the selectors.
Silly nit but is the prefix extract
adding value to these function names?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not at all! i was trying to follow the convention, but extractions/segmentation/whatever is a function of their include path, so it's a bit redundant.
// Libraries | ||
import React from 'react' | ||
import {shallow} from 'enzyme' | ||
|
||
// Components | ||
import VariableForm from 'src/variables/components/VariableForm' | ||
|
||
// Constants | ||
import {variables} from 'mocks/dummyData' | ||
|
||
const setup = (override?) => { | ||
const props = { | ||
variables, | ||
initialScript: 'Hello There!', | ||
onCreateVariable: jest.fn(), | ||
onHideOverlay: jest.fn(), | ||
...override, | ||
} | ||
|
||
const wrapper = shallow<VariableForm>(<VariableForm {...props} />) | ||
|
||
return {wrapper} | ||
} | ||
|
||
describe('VariableForm', () => { | ||
describe('rendering', () => { | ||
it('renders', () => { | ||
const {wrapper} = setup() | ||
expect(wrapper.exists()).toBe(true) | ||
expect(wrapper).toMatchSnapshot() | ||
}) | ||
}) | ||
|
||
describe('type selector', () => { | ||
it('should not update state if the type was not changed', () => { | ||
const {wrapper} = setup() | ||
|
||
const defaultType = wrapper.state().args.type | ||
const stateStub = jest.fn() | ||
|
||
wrapper.instance().setState = stateStub | ||
|
||
// this way of accessing the instance function | ||
// bypasses typescript's private function check | ||
wrapper.instance()['handleChangeType'](defaultType) | ||
expect(stateStub.mock.calls.length).toBe(0) | ||
}) | ||
|
||
it('should update state if the type was changed', () => { | ||
const {wrapper} = setup() | ||
|
||
const stateStub = jest.fn() | ||
|
||
wrapper.instance().setState = stateStub | ||
|
||
// this way of accessing the instance function | ||
// bypasses typescript's private function check | ||
wrapper.instance()['handleChangeType']('map') | ||
expect(stateStub.mock.calls.length).toBe(1) | ||
}) | ||
}) | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
😍😍😍
mstp, | ||
mdtp | ||
() => {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm getting a mapDispatchToProps() in Connect(withRouter(SaveAsVariable)) must return a plain object. Instead received undefined
error in the console from this line. I think we have used this previously:
export default connect<StateProps, {}, OwnProps>(
mstp,
null
)(Component)
case 'query': | ||
return ( | ||
<Form.Element label="Script"> | ||
<Grid.Column> | ||
<div className="overlay-flux-editor"> | ||
<FluxEditor | ||
script={args.values.query} | ||
script={(args as QueryArguments).values.query} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a solution, but it's in a whole branch. let's look at it together tomorrow?
export const updateConstant = (arg: VariableArguments): SetConstant => ({ | ||
type: 'UPDATE_VARIABLE_EDITOR_CONSTANT', | ||
payload: arg, | ||
}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(nit) One pattern that makes these just a little bit easier to read since you don't have to separately define types..
export type Actions =
| ReturnType<typeof createAction>
| ReturnType<typeof createOtherAction>
const createAction = (status: RemoteDataState) => ({
type: 'CREATE_THIS_ACTION' as 'CREATE_THIS_ACTION'
payload: {status},
})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there some more examples in the code so that i can wrap my head around this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ui/src/alerting/actions/checks.ts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated the file to reflect the new pattern!
ui/src/variables/reducers/index.ts
Outdated
export const initialEditorState = (): VariableEditorState => ({ | ||
name: '', | ||
selected: 'query', | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
runaway newline! :)
closes #15059 the issue is to persist user data across variable type selection interfaces within the variable editor. this commit pushes all of the variable editor information down to redux to allow persistence outside of the view state until the user clicks "cancel" or "create" in the interface.
add test for hydrateVars dashboard variable dropdown test: inspect values, not just array length add RTL test for variable dropdown changes lint fix: Disable saving threshold check if no threshold selected (#15348) * Prevent check saving if no thresholds * Add tests * Add changes to changelog * make optional props optional * use false instead of null for boolean changelog fix(ui): ignore false change events in VariableForm (#15317) closes #15059 the issue is to persist user data across variable type selection interfaces within the variable editor. this commit pushes all of the variable editor information down to redux to allow persistence outside of the view state until the user clicks "cancel" or "create" in the interface.
Closes #15059
If a user re-selects the same variable type when adding a variable, no action takes place