-
Notifications
You must be signed in to change notification settings - Fork 99
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add: Extract a useEntityClone hook from EntityComponent
EntityComponent is a render prop component and can be replaced by several hooks.
- Loading branch information
1 parent
75b9024
commit 434e357
Showing
3 changed files
with
115 additions
and
24 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
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,64 @@ | ||
/* SPDX-FileCopyrightText: 2025 Greenbone AG | ||
* | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
|
||
import {describe, test, expect, testing} from '@gsa/testing'; | ||
import useEntityClone from 'web/entity/hooks/useEntityClone'; | ||
import {rendererWith, wait} from 'web/utils/Testing'; | ||
|
||
describe('useEntityClone', () => { | ||
test('should allow to clone an entity', async () => { | ||
const entity = {id: '123'}; | ||
const cloneEntity = testing.fn().mockResolvedValue(entity); | ||
const gmp = { | ||
foo: {clone: cloneEntity}, | ||
}; | ||
const onCloned = testing.fn(); | ||
const onCloneError = testing.fn(); | ||
const onInteraction = testing.fn(); | ||
const {renderHook} = rendererWith({gmp, store: true}); | ||
|
||
const {result} = renderHook(() => | ||
useEntityClone('foo', { | ||
onCloned, | ||
onCloneError, | ||
onInteraction, | ||
}), | ||
); | ||
expect(result.current).toBeDefined; | ||
result.current(entity); | ||
await wait(); | ||
expect(cloneEntity).toHaveBeenCalledWith(entity); | ||
expect(onCloned).toHaveBeenCalledWith(entity); | ||
expect(onCloneError).not.toHaveBeenCalled(); | ||
expect(onInteraction).toHaveBeenCalledOnce(); | ||
}); | ||
|
||
test('should call onCloneError when cloning an entity fails', async () => { | ||
const cloneEntity = testing.fn().mockRejectedValue(new Error('error')); | ||
const entity = {id: '123'}; | ||
const gmp = { | ||
foo: {clone: cloneEntity}, | ||
}; | ||
const onCloned = testing.fn(); | ||
const onCloneError = testing.fn(); | ||
const onInteraction = testing.fn(); | ||
const {renderHook} = rendererWith({gmp, store: true}); | ||
|
||
const {result} = renderHook(() => | ||
useEntityClone('foo', { | ||
onCloned, | ||
onCloneError, | ||
onInteraction, | ||
}), | ||
); | ||
expect(result.current).toBeDefined; | ||
result.current(entity); | ||
await wait(); | ||
expect(cloneEntity).toHaveBeenCalledWith(entity); | ||
expect(onCloned).not.toHaveBeenCalled(); | ||
expect(onCloneError).toHaveBeenCalledWith(new Error('error')); | ||
expect(onInteraction).toHaveBeenCalledOnce(); | ||
}); | ||
}); |
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,45 @@ | ||
/* SPDX-FileCopyrightText: 2025 Greenbone AG | ||
* | ||
* SPDX-License-Identifier: AGPL-3.0-or-later | ||
*/ | ||
|
||
import {isDefined} from 'gmp/utils/identity'; | ||
import {actionFunction} from 'web/entity/hooks/utils'; | ||
import useGmp from 'web/hooks/useGmp'; | ||
import useTranslation from 'web/hooks/useTranslation'; | ||
|
||
/** | ||
* Custom hook to handle the cloning of an entity. | ||
* | ||
* @param {string} name - The name of the entity to be cloned. | ||
* @param {Object} [callbacks] - Optional callbacks for handling clone events. | ||
* @param {Function} [callbacks.onCloneError] - Callback function to be called when cloning fails. | ||
* @param {Function} [callbacks.onCloned] - Callback function to be called when cloning is successful. | ||
* @param {Function} [callbacks.onInteraction] - Callback function to be called on interaction. | ||
* @returns {Function} - A function that takes an entity and handles its cloning. | ||
*/ | ||
const useEntityClone = (name, {onCloneError, onCloned, onInteraction} = {}) => { | ||
const gmp = useGmp(); | ||
const cmd = gmp[name]; | ||
const [_] = useTranslation(); | ||
|
||
const handleInteraction = () => { | ||
if (isDefined(onInteraction)) { | ||
onInteraction(); | ||
} | ||
}; | ||
|
||
const handleEntityClone = async entity => { | ||
handleInteraction(); | ||
|
||
return actionFunction( | ||
cmd.clone(entity), | ||
onCloned, | ||
onCloneError, | ||
_('{{name}} cloned successfully.', {name: entity.name}), | ||
); | ||
}; | ||
return handleEntityClone; | ||
}; | ||
|
||
export default useEntityClone; |