-
Notifications
You must be signed in to change notification settings - Fork 21
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
[AN-247] Edit method functionality #5175
Open
salonishah11
wants to merge
39
commits into
dev
Choose a base branch
from
sps_edit_method
base: dev
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 33 commits
Commits
Show all changes
39 commits
Select commit
Hold shift + click to select a range
f068ade
rename to PostMethodProvider
salonishah11 7d2648f
working clone method
salonishah11 3ee8261
clone tests
salonishah11 df47b02
revert unintentional changes
salonishah11 245b33c
merge dev to branch
salonishah11 fff2d1f
fix tests
salonishah11 b0a87bb
cleanup
salonishah11 2f6cc48
use snapshot in modal
salonishah11 bb2920a
additional tests
salonishah11 3218428
remove playground
salonishah11 5b6e01a
reset store
salonishah11 6c01892
add comment
salonishah11 69e231d
Merge branch 'dev' into sps_edit_clone_method
salonishah11 69ef5da
wip
salonishah11 7373ed9
PR feedback
salonishah11 00d34ca
Merge branch 'dev' into sps_edit_clone_method
salonishah11 030e080
Merge branch 'sps_edit_clone_method' into sps_edit_method
salonishah11 98f4bb8
change naming
salonishah11 47afaff
test change
salonishah11 52d1106
add test from PR feedback
salonishah11 694f54b
Merge branch 'dev' into sps_edit_clone_method
salonishah11 4e6de79
merge from other branch
salonishah11 6ab8ab7
wip; before refactor of WorkflowModal
salonishah11 e85f606
merge dev to branch
salonishah11 7b448dc
refactored WorkflowModal
salonishah11 3b293b5
consolidate submit button logic
salonishah11 0e15ee3
broken EditMethodProvider.test.ts
salonishah11 6109d1f
Placate Jest
sam-schu 7a28ed4
tests
salonishah11 3eae21c
PR feedback
salonishah11 cde08b0
tests
salonishah11 b827c49
refactor
salonishah11 5f0db7d
Merge branch 'dev' into sps_edit_method
salonishah11 776fff1
Merge branch 'dev' into sps_edit_method
salonishah11 59aa0bc
Merge branch 'sps_edit_method' of https://github.com/DataBiosphere/te…
salonishah11 4d00d70
PR feedback
salonishah11 5c8e2a4
Merge branch 'dev' into sps_edit_method
salonishah11 dfdd368
remove import
salonishah11 1a06320
Merge branch 'dev' into sps_edit_method
salonishah11 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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
75 changes: 75 additions & 0 deletions
75
src/libs/ajax/methods/providers/EditMethodProvider.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,75 @@ | ||
import { asMockedFn, partial } from '@terra-ui-packages/test-utils'; | ||
import { Methods, MethodsAjaxContract } from 'src/libs/ajax/methods/Methods'; | ||
import { MethodResponse } from 'src/libs/ajax/methods/methods-models'; | ||
import { editMethodProvider } from 'src/libs/ajax/methods/providers/EditMethodProvider'; | ||
import { oidcStore } from 'src/libs/state'; | ||
|
||
jest.mock('src/libs/ajax/methods/Methods'); | ||
|
||
type MethodAjaxContract = MethodsAjaxContract['method']; | ||
|
||
const mockMethodResponse: MethodResponse = { | ||
name: 'groot-method', | ||
createDate: '2024-11-20T14:40:32Z', | ||
documentation: 'documentation', | ||
synopsis: 'synopsis', | ||
entityType: 'Workflow', | ||
snapshotComment: 'snapshot comment', | ||
snapshotId: 4, | ||
namespace: 'groot-namespace', | ||
payload: 'workflow myGreatWorkflow {}', | ||
url: 'http://agora.dsde-dev.broadinstitute.org/api/v1/methods/groot-namespace/groot-method/4', | ||
}; | ||
|
||
jest.spyOn(oidcStore, 'get').mockImplementation( | ||
jest.fn().mockReturnValue({ | ||
userManager: { getUser: jest.fn() }, | ||
}) | ||
); | ||
|
||
const mockAjax = () => { | ||
const mockCreateSnapshot = jest.fn().mockReturnValue(mockMethodResponse); | ||
asMockedFn(Methods).mockReturnValue({ | ||
method: jest.fn(() => { | ||
return partial<ReturnType<MethodAjaxContract>>({ | ||
createSnapshot: mockCreateSnapshot, | ||
}); | ||
}) as MethodAjaxContract, | ||
} as MethodsAjaxContract); | ||
}; | ||
|
||
describe('EditMethodProvider', () => { | ||
it('handles create new snapshot call', async () => { | ||
// Arrange | ||
mockAjax(); | ||
const signal = new window.AbortController().signal; | ||
|
||
// Act | ||
const result = await editMethodProvider.createNewSnapshot( | ||
'groot-namespace', | ||
'groot-method', | ||
3, | ||
true, | ||
'synopsis', | ||
'documentation', | ||
'workflow myGreatWorkflow {}', | ||
'snapshot comment', | ||
{ signal } | ||
); | ||
|
||
// Assert | ||
expect(Methods).toBeCalledTimes(1); | ||
expect(Methods).toBeCalledWith(signal); | ||
expect(Methods().method).toHaveBeenCalledWith('groot-namespace', 'groot-method', 3); | ||
expect(Methods().method('groot-namespace', 'groot-method', 3).createSnapshot).toHaveBeenCalledWith( | ||
{ | ||
payload: 'workflow myGreatWorkflow {}', | ||
documentation: 'documentation', | ||
synopsis: 'synopsis', | ||
snapshotComment: 'snapshot comment', | ||
}, | ||
true | ||
); | ||
expect(result).toEqual(mockMethodResponse); | ||
}); | ||
}); |
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,42 @@ | ||
import { AbortOption } from '@terra-ui-packages/data-client-core'; | ||
import { Methods } from 'src/libs/ajax/methods/Methods'; | ||
import { MethodResponse } from 'src/libs/ajax/methods/methods-models'; | ||
|
||
export interface EditMethodProvider { | ||
createNewSnapshot: ( | ||
namespace: string, | ||
name: string, | ||
snapshotId: number, | ||
redactPreviousSnapshot: boolean, | ||
synopsis: string, | ||
documentation: string, | ||
wdl: string, | ||
snapshotComment: string, | ||
options?: AbortOption | ||
) => Promise<MethodResponse>; | ||
} | ||
|
||
export const editMethodProvider: EditMethodProvider = { | ||
createNewSnapshot: async ( | ||
namespace: string, | ||
name: string, | ||
snapshotId: number, | ||
redactPreviousSnapshot: boolean, | ||
synopsis: string, | ||
documentation: string, | ||
wdl: string, | ||
snapshotComment: string, | ||
options: AbortOption = {} | ||
): Promise<MethodResponse> => { | ||
const { signal } = options; | ||
|
||
const payload = { | ||
synopsis, | ||
snapshotComment, | ||
documentation, | ||
payload: wdl, | ||
}; | ||
|
||
return await Methods(signal).method(namespace, name, snapshotId).createSnapshot(payload, redactPreviousSnapshot); | ||
}, | ||
}; |
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
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 |
---|---|---|
@@ -1,3 +1,4 @@ | ||
import { expect } from '@storybook/test'; | ||
salonishah11 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
import { delay } from '@terra-ui-packages/core-utils'; | ||
import { act, fireEvent, screen, within } from '@testing-library/react'; | ||
import userEvent, { UserEvent } from '@testing-library/user-event'; | ||
|
@@ -7,6 +8,7 @@ import * as breadcrumbs from 'src/components/breadcrumbs'; | |
import { Ajax, AjaxContract } from 'src/libs/ajax'; | ||
import { MethodsAjaxContract } from 'src/libs/ajax/methods/Methods'; | ||
import { MethodResponse, Snapshot } from 'src/libs/ajax/methods/methods-models'; | ||
import { editMethodProvider } from 'src/libs/ajax/methods/providers/EditMethodProvider'; | ||
import { postMethodProvider } from 'src/libs/ajax/methods/providers/PostMethodProvider'; | ||
import * as ExportWorkflowToWorkspaceProvider from 'src/libs/ajax/workspaces/providers/ExportWorkflowToWorkspaceProvider'; | ||
import { errorWatcher } from 'src/libs/error.mock'; | ||
|
@@ -276,6 +278,12 @@ const mockCloneSnapshotResponse: MethodResponse = { | |
url: 'http://agora.dsde-dev.broadinstitute.org/api/v1/methods/groot-new-namespace/testname_copy/1', | ||
}; | ||
|
||
const mockNewSnapshotResponse: MethodResponse = { | ||
...mockSnapshot, | ||
snapshotComment: "groot's new snapshot", | ||
snapshotId: 2, | ||
}; | ||
|
||
describe('workflow wrapper', () => { | ||
it('displays the method not found page if a method does not exist or the user does not have access', async () => { | ||
// Arrange | ||
|
@@ -566,6 +574,132 @@ describe('workflows container', () => { | |
expect(dialog2).not.toBeInTheDocument(); | ||
}); | ||
|
||
it('renders edit method modal when corresponding button is pressed', async () => { | ||
// Arrange | ||
mockAjax(); | ||
|
||
// set the user's email | ||
jest.spyOn(userStore, 'get').mockImplementation(jest.fn().mockReturnValue(mockUserState('[email protected]'))); | ||
|
||
const user: UserEvent = userEvent.setup(); | ||
|
||
// Act | ||
await act(async () => { | ||
render( | ||
<WorkflowsContainer | ||
namespace={mockSnapshot.namespace} | ||
name={mockSnapshot.name} | ||
snapshotId={`${mockSnapshot.snapshotId}`} | ||
tabName='dashboard' | ||
/> | ||
); | ||
}); | ||
|
||
await user.click(screen.getByRole('button', { name: 'Snapshot action menu' })); | ||
await user.click(screen.getByRole('button', { name: 'Edit' })); | ||
|
||
const dialog = screen.getByRole('dialog', { name: /edit/i }); | ||
|
||
// Assert | ||
expect(dialog).toBeInTheDocument(); | ||
expect(within(dialog).getByRole('textbox', { name: 'Namespace' })).toHaveAttribute('placeholder', 'testnamespace'); | ||
expect(within(dialog).getByRole('textbox', { name: 'Namespace' })).toHaveAttribute('disabled'); | ||
expect(within(dialog).getByRole('textbox', { name: 'Name' })).toHaveAttribute('placeholder', 'testname'); | ||
expect(within(dialog).getByRole('textbox', { name: 'Name' })).toHaveAttribute('disabled'); | ||
expect(within(dialog).getByRole('textbox', { name: 'Documentation' })).toHaveDisplayValue('mock documentation'); | ||
expect(within(dialog).getByRole('textbox', { name: 'Synopsis (80 characters max)' })).toHaveDisplayValue(''); | ||
expect(within(dialog).getByRole('textbox', { name: 'Snapshot comment' })).toHaveDisplayValue(''); | ||
expect(within(dialog).getByTestId('wdl editor')).toHaveDisplayValue(mockSnapshot.payload.toString()); | ||
expect(within(dialog).getByRole('checkbox', { name: 'Delete snapshot 1' })).not.toBeChecked(); | ||
}); | ||
|
||
it('calls the right provider with expected arguments when new snapshot is created', async () => { | ||
// Arrange | ||
mockAjax(); | ||
|
||
jest.spyOn(userStore, 'get').mockImplementation(jest.fn().mockReturnValue(mockUserState('[email protected]'))); | ||
jest.spyOn(editMethodProvider, 'createNewSnapshot').mockResolvedValue(mockNewSnapshotResponse); | ||
|
||
const user: UserEvent = userEvent.setup(); | ||
|
||
// Act | ||
await act(async () => { | ||
render( | ||
<WorkflowsContainer | ||
namespace={mockSnapshot.namespace} | ||
name={mockSnapshot.name} | ||
snapshotId={`${mockSnapshot.snapshotId}`} | ||
tabName='dashboard' | ||
/> | ||
); | ||
}); | ||
|
||
await user.click(screen.getByRole('button', { name: 'Snapshot action menu' })); | ||
await user.click(screen.getByRole('button', { name: 'Edit' })); | ||
|
||
fireEvent.change(screen.getByRole('textbox', { name: 'Snapshot comment' }), { | ||
target: { value: "groot's new improved snapshot" }, | ||
}); | ||
fireEvent.click(screen.getByRole('checkbox', { name: 'Delete snapshot 1' })); | ||
salonishah11 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
await user.click(screen.getByRole('button', { name: 'Create new snapshot' })); | ||
|
||
// Assert | ||
expect(editMethodProvider.createNewSnapshot).toHaveBeenCalled(); | ||
expect(editMethodProvider.createNewSnapshot).toHaveBeenCalledWith( | ||
mockSnapshot.namespace, | ||
mockSnapshot.name, | ||
mockSnapshot.snapshotId, | ||
true, | ||
mockSnapshot.synopsis, | ||
mockSnapshot.documentation, | ||
mockSnapshot.payload, | ||
"groot's new improved snapshot" | ||
); | ||
|
||
expect(Nav.goToPath).toHaveBeenCalledWith('workflow-dashboard', { | ||
name: 'testname', | ||
namespace: 'testnamespace', | ||
snapshotId: 2, | ||
}); | ||
}); | ||
|
||
it('hides the edit method modal when it is dismissed', async () => { | ||
// Arrange | ||
mockAjax(); | ||
|
||
// set the user's email | ||
jest.spyOn(userStore, 'get').mockImplementation(jest.fn().mockReturnValue(mockUserState('[email protected]'))); | ||
|
||
const user: UserEvent = userEvent.setup(); | ||
|
||
// Act | ||
await act(async () => { | ||
render( | ||
<WorkflowsContainer | ||
namespace={mockSnapshot.namespace} | ||
name={mockSnapshot.name} | ||
snapshotId={`${mockSnapshot.snapshotId}`} | ||
tabName='dashboard' | ||
/> | ||
); | ||
}); | ||
|
||
await user.click(screen.getByRole('button', { name: 'Snapshot action menu' })); | ||
await user.click(screen.getByRole('button', { name: 'Edit' })); | ||
|
||
// Assert | ||
const dialog1 = screen.queryByRole('dialog', { name: /edit/i }); | ||
expect(dialog1).toBeInTheDocument(); | ||
|
||
// Act | ||
await user.click(screen.getByRole('button', { name: 'Cancel' })); | ||
|
||
// Assert | ||
const dialog2 = screen.queryByRole('dialog', { name: /edit/i }); | ||
expect(dialog2).not.toBeInTheDocument(); | ||
}); | ||
|
||
it('hides the delete snapshot modal and displays a loading spinner when the deletion is confirmed', async () => { | ||
// Arrange | ||
mockAjax({ | ||
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 wasn't used anywhere so I removed it.