-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
refactor onLoadedProject() creator to handle success==false consistently; add tests of project state action creators #5362
refactor onLoadedProject() creator to handle success==false consistently; add tests of project state action creators #5362
Conversation
src/reducers/project-state.js
Outdated
@@ -435,10 +435,21 @@ const onLoadedProject = (loadingState, canSave, success) => { | |||
default: | |||
return; | |||
} | |||
} else { |
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 code seems to be getting more confusing because of the combination of if
and switch
. I realize that's the way the code was already written, but for example, I think this else
is not needed since there's a default: return
above. However, that fact is not immediately obvious/easy to reason about.
Do you have any thoughts on how we could simplify 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.
Thanks for pointing this out. I tried using one switch statement instead, and I think it's better:
switch (loadingState) {
case LoadingState.LOADING_VM_WITH_ID:
if (success) {
return {type: DONE_LOADING_VM_WITH_ID};
}
// failed to load project; just keep showing current project
return {type: RETURN_TO_SHOWING};
case LoadingState.LOADING_VM_FILE_UPLOAD:
if (success) {
if (canSave) {
return {type: DONE_LOADING_VM_TO_SAVE};
}
return {type: DONE_LOADING_VM_WITHOUT_ID};
}
// failed to load project; just keep showing current project
return {type: RETURN_TO_SHOWING};
case LoadingState.LOADING_VM_NEW_DEFAULT:
if (success) {
return {type: DONE_LOADING_VM_WITHOUT_ID};
}
// failed to load default project; show error
return {type: START_ERROR};
default:
return;
}
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 feels much better/easier to reason about!
src/reducers/project-state.js
Outdated
case LoadingState.LOADING_VM_WITH_ID: | ||
case LoadingState.LOADING_VM_FILE_UPLOAD: | ||
return { | ||
type: RETURN_TO_SHOWING |
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.
What is the difference between RETURN_TO_SHOWING and START_ERROR? Since I am not familiar w/the project state machine, I think it would be helpful to have comments describing the state changes that are happening (this does not necessarily need to be added to this PR but would be useful to have in the future).
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.
Thanks -- I'll put in a bit of commenting here, and I have done some experiments on how to add documentation to this file that I'd like to show you
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITHOUT_ID); | ||
}); | ||
|
||
test('onLoadedProject (LOADING_VM_FILE_UPLOAD, false, false), with project id, shows with id', () => { |
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 sure I understand what's going on in this test...
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.
the test names are not exactly very clear! Let me try revising them.
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 the revised name more helpful?
Please take a look -- I revised a few things, and I think made it a bit clearer! |
return {type: DONE_LOADING_VM_WITHOUT_ID}; | ||
} | ||
// failed to load default project; show error | ||
return {type: START_ERROR}; |
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.
Just to be clear, this is the piece of logic that is new to this PR, right?
The rest of this is chunk of code is a refactor?
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.
Yes.
const initialState = { | ||
loadingState: LoadingState.LOADING_VM_WITH_ID | ||
}; | ||
const action = onLoadedProject(initialState.loadingState, true, true); |
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 this one supposed to be false, true
? It looks like this test is exactly the same as the one above...
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.
Will fix!
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.
Done
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITH_ID); | ||
}); | ||
|
||
test('onLoadedProject(LOADING_VM_WITH_ID, false, false), with no project id, ' + |
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.
What should happen here? State is LOADING_VM_WITH_ID, but projectId is null -- is that even possible?
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.
Would be good to add a comment here explaining that this is for the case where we started viewing a project that doesn't have an ID (e.g. in standalone mode where we go from viewing a project w/o an ID and then add an id using the #....
method in the URL)
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.
Done
test('onLoadedProject(LOADING_VM_WITH_ID, false, false), with project id, ' + | ||
'results in state SHOWING_WITH_ID', () => { |
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.
Could you add a comment here that explains why it results in state "SHOWING_WITH_ID"? That we're showing the original project w/ID (not the one that failed to load)
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.
Done
loadingState: LoadingState.LOADING_VM_FILE_UPLOAD, | ||
projectId: '12345' | ||
}; | ||
const action = onLoadedProject(initialState.loadingState, false, false); | ||
const resultState = projectStateReducer(initialState, action); | ||
expect(resultState.loadingState).toBe(LoadingState.SHOWING_WITH_ID); |
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.
We should be also checking that the projectid is what we expect -- in each expect line
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.
Done
41f6427
to
2e11787
Compare
@kchadha Made the changes we discussed! |
test('onLoadedProject(LOADING_VM_WITH_ID, false, false), with no project id, ' + | ||
'results in state SHOWING_WITHOUT_ID', () => { | ||
const initialState = { | ||
projectId: '0', |
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.
Hmmm did the nature of this test change here by adding the projectId field? E.g. is it the same test as the one above or does the '0' here have special meaning that exercises a different code path?
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.
That's a good question. '0' is the specific projectId value of the default project. It's defined at the top of the project-state reducer file.
So this test's expecting to reach the state SHOWING_WITHOUT_ID, whereas the test above is expecting to reach the state SHOWING_WITH_ID.
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.
Had one last question about one of the tests, but otherwise LGTM
@kchadha I'm realizing I named this PR poorly at the start; this was intended as a change in project state reducer to support further changes in vm-manager-hoc. So this change only changes the project state reducer's onLoadedProject() action creator to be more consistent about how it will handle the cases when the The change it was saying it made -- switching to an error state if loading the default project fails -- is actually satisfied by gui's current functionality! It's other cases that don't work as intended: if loading fails for a different fetched project, currently gui will enter an error state without even calling onLoadedProject(). After this change, we would/will be able to change vm-manager-hoc to call onLoadedProject() with the |
Also, I replied to your outstanding question on that test! |
Here's a patch that you can apply locally, which will make vm loading fail 50% of the time, and call
When I run gui locally with this, what I see is
...which is what's desired. |
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.
LGTM! Thanks for all the conversation on this.
Resolves
Resolves #5361
Proposed Changes
Adds unit tests for many project state reducer action creator functions.
Also refactors the project state reducer's
onLoadedProject()
function to be clearer, and to specifically handle failures to load the default project by switching to an error state.(This relates to the project state reducer's handling of success and failure in loading the default project. Since we get that project data locally, and not from the server, loading it into the VM should always succeed. If it fails, we should switch to an error state.)
This change doesn't make a change to actual behavior, only to the project state reducer's API for clarity and consistency.