Skip to content

Commit

Permalink
materialize droppableIDs, add utils and corresponding tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ehconitin committed Dec 14, 2024
1 parent 0f11614 commit a40580b
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const FAVORITE_DROPPABLE_IDS = {
ORPHAN_FAVORITES: 'orphan-favorites',
FOLDER_PREFIX: 'folder-',
FOLDER_HEADER_PREFIX: 'folder-header-',
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import { act } from 'react';
import { useSetRecoilState } from 'recoil';

import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
import { FAVORITE_DROPPABLE_IDS } from '@/favorites/constants/FavoriteDroppableIds';
import { useHandleFavoriteDragAndDrop } from '@/favorites/hooks/useHandleFavoriteDragAndDrop';
import { createFolderDroppableId } from '@/favorites/utils/createFolderDroppableId';
import { createFolderHeaderDroppableId } from '@/favorites/utils/createFolderHeaderDroppableId';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper';
import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems';
Expand Down Expand Up @@ -53,7 +56,7 @@ describe('useHandleFavoriteDragAndDrop', () => {
act(() => {
result.current.hook.handleFavoriteDragAndDrop(
{
source: { index: 0, droppableId: 'folder-1' },
source: { index: 0, droppableId: createFolderDroppableId('1') },
destination: null,
draggableId: '1',
} as DropResult,
Expand All @@ -68,12 +71,13 @@ describe('useHandleFavoriteDragAndDrop', () => {

it('should not update when destination is same as source', () => {
const { result } = setupHook();
const folderOneId = createFolderDroppableId('1');

act(() => {
result.current.hook.handleFavoriteDragAndDrop(
{
source: { index: 0, droppableId: 'folder-1' },
destination: { index: 0, droppableId: 'folder-1' },
source: { index: 0, droppableId: folderOneId },
destination: { index: 0, droppableId: folderOneId },
draggableId: '1',
} as DropResult,
mockResponderProvided,
Expand All @@ -84,15 +88,16 @@ describe('useHandleFavoriteDragAndDrop', () => {
expect(mocks[3].result).not.toHaveBeenCalled();
expect(mocks[4].result).not.toHaveBeenCalled();
});
//fails

it('should reorder within same folder', async () => {
const { result } = setupHook();
const folderOneId = createFolderDroppableId('1');

act(() => {
result.current.hook.handleFavoriteDragAndDrop(
{
source: { index: 0, droppableId: 'folder-1' },
destination: { index: 2, droppableId: 'folder-1' },
source: { index: 0, droppableId: folderOneId },
destination: { index: 2, droppableId: folderOneId },
draggableId: '1',
} as DropResult,
mockResponderProvided,
Expand All @@ -110,8 +115,8 @@ describe('useHandleFavoriteDragAndDrop', () => {
act(() => {
result.current.hook.handleFavoriteDragAndDrop(
{
source: { index: 0, droppableId: 'folder-1' },
destination: { index: 0, droppableId: 'folder-2' },
source: { index: 0, droppableId: createFolderDroppableId('1') },
destination: { index: 0, droppableId: createFolderDroppableId('2') },
draggableId: '1',
} as DropResult,
mockResponderProvided,
Expand All @@ -129,8 +134,11 @@ describe('useHandleFavoriteDragAndDrop', () => {
act(() => {
result.current.hook.handleFavoriteDragAndDrop(
{
source: { index: 0, droppableId: 'folder-1' },
destination: { index: 0, droppableId: 'orphan-favorites' },
source: { index: 0, droppableId: createFolderDroppableId('1') },
destination: {
index: 0,
droppableId: FAVORITE_DROPPABLE_IDS.ORPHAN_FAVORITES,
},
draggableId: '1',
} as DropResult,
mockResponderProvided,
Expand All @@ -141,15 +149,18 @@ describe('useHandleFavoriteDragAndDrop', () => {
expect(mocks[4].result).toHaveBeenCalled();
});
});
//fails

it('should handle dropping into folder header', async () => {
const { result } = setupHook();

act(() => {
result.current.hook.handleFavoriteDragAndDrop(
{
source: { index: 0, droppableId: 'folder-1' },
destination: { index: 0, droppableId: 'folder-header-2' },
source: { index: 0, droppableId: createFolderDroppableId('1') },
destination: {
index: 0,
droppableId: createFolderHeaderDroppableId('2'),
},
draggableId: '1',
} as DropResult,
mockResponderProvided,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { FAVORITE_DROPPABLE_IDS } from '@/favorites/constants/FavoriteDroppableIds';
import { useSortedFavorites } from '@/favorites/hooks/useSortedFavorites';
import { activeFavoriteFolderIdState } from '@/favorites/states/activeFavoriteFolderIdState';
import { calculateNewPosition } from '@/favorites/utils/calculateNewPosition';
import { validateAndExtractFolderId } from '@/favorites/utils/validateAndExtractFolderId';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
import { OnDragEndResponder } from '@hello-pangea/dnd';
Expand Down Expand Up @@ -32,42 +34,43 @@ export const useHandleFavoriteDragAndDrop = () => {
const draggedFavorite = favorites.find((f) => f.id === draggableId);
if (!draggedFavorite) return;

if (destination.droppableId.startsWith('folder-header-')) {
const targetFolderId = destination.droppableId.replace(
'folder-header-',
'',
);
const destinationFolderId = validateAndExtractFolderId(
destination.droppableId,
);
const sourceFolderId = validateAndExtractFolderId(source.droppableId);

if (
destination.droppableId.startsWith(
FAVORITE_DROPPABLE_IDS.FOLDER_HEADER_PREFIX,
)
) {
if (destinationFolderId === null)
throw new Error('Invalid folder header ID');

const folderFavorites = favoritesSorted.filter(
(favorite) => favorite.favoriteFolderId === targetFolderId,
(favorite) => favorite.favoriteFolderId === destinationFolderId,
);

let newPosition;
if (folderFavorites.length === 0) {
newPosition = 0;
} else {
newPosition = folderFavorites[folderFavorites.length - 1].position + 1;
}
const newPosition =
folderFavorites.length === 0
? 0
: folderFavorites[folderFavorites.length - 1].position + 1;

updateOneFavorite({
idToUpdate: draggableId,
updateOneRecordInput: {
favoriteFolderId: targetFolderId,
favoriteFolderId: destinationFolderId,
position: newPosition,
},
});

setActiveFavoriteFolderId(targetFolderId);
setActiveFavoriteFolderId(destinationFolderId);
return;
}

if (destination.droppableId !== source.droppableId) {
const newFolderId =
destination.droppableId === 'orphan-favorites'
? null
: destination.droppableId.replace('folder-', '');

const destinationFavorites = favoritesSorted.filter(
(favorite) => favorite.favoriteFolderId === newFolderId,
(favorite) => favorite.favoriteFolderId === destinationFolderId,
);

let newPosition;
Expand All @@ -89,20 +92,15 @@ export const useHandleFavoriteDragAndDrop = () => {
updateOneFavorite({
idToUpdate: draggableId,
updateOneRecordInput: {
favoriteFolderId: newFolderId,
favoriteFolderId: destinationFolderId,
position: newPosition,
},
});
return;
}

const currentFolderId =
source.droppableId === 'orphan-favorites'
? null
: source.droppableId.replace('folder-', '');

const favoritesInSameList = favoritesSorted.filter(
(favorite) => favorite.favoriteFolderId === currentFolderId,
(favorite) => favorite.favoriteFolderId === sourceFolderId,
);

const newPosition = calculateNewPosition({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { FAVORITE_DROPPABLE_IDS } from '@/favorites/constants/FavoriteDroppableIds';

export type FavoriteDroppableId =
| typeof FAVORITE_DROPPABLE_IDS.ORPHAN_FAVORITES
| `${typeof FAVORITE_DROPPABLE_IDS.FOLDER_PREFIX}${string}`
| `${typeof FAVORITE_DROPPABLE_IDS.FOLDER_HEADER_PREFIX}${string}`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { FAVORITE_DROPPABLE_IDS } from '@/favorites/constants/FavoriteDroppableIds';
import { createFolderDroppableId } from '../createFolderDroppableId';

describe('createFolderDroppableId', () => {
it('should create a valid folder droppable id', () => {
const folderId = '123-456';
const result = createFolderDroppableId(folderId);

expect(result).toBe(`${FAVORITE_DROPPABLE_IDS.FOLDER_PREFIX}${folderId}`);
});

it('should work with empty string', () => {
const result = createFolderDroppableId('');

expect(result).toBe(FAVORITE_DROPPABLE_IDS.FOLDER_PREFIX);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { FAVORITE_DROPPABLE_IDS } from '@/favorites/constants/FavoriteDroppableIds';
import { createFolderHeaderDroppableId } from '../createFolderHeaderDroppableId';

describe('createFolderHeaderDroppableId', () => {
it('should create a valid folder header droppable id', () => {
const folderId = '123-456';
const result = createFolderHeaderDroppableId(folderId);

expect(result).toBe(
`${FAVORITE_DROPPABLE_IDS.FOLDER_HEADER_PREFIX}${folderId}`,
);
});

it('should work with empty string', () => {
const result = createFolderHeaderDroppableId('');

expect(result).toBe(FAVORITE_DROPPABLE_IDS.FOLDER_HEADER_PREFIX);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { FAVORITE_DROPPABLE_IDS } from '@/favorites/constants/FavoriteDroppableIds';
import { validateAndExtractFolderId } from '../validateAndExtractFolderId';

describe('validateAndExtractFolderId', () => {
it('should return null for orphan favorites', () => {
const result = validateAndExtractFolderId(
FAVORITE_DROPPABLE_IDS.ORPHAN_FAVORITES,
);
expect(result).toBeNull();
});

it('should extract folder id from folder droppable id', () => {
const folderId = '123-456';
const droppableId = `${FAVORITE_DROPPABLE_IDS.FOLDER_PREFIX}${folderId}`;

const result = validateAndExtractFolderId(droppableId);
expect(result).toBe(folderId);
});

it('should extract folder id from folder header droppable id', () => {
const folderId = '123-456';
const droppableId = `${FAVORITE_DROPPABLE_IDS.FOLDER_HEADER_PREFIX}${folderId}`;

const result = validateAndExtractFolderId(droppableId);
expect(result).toBe(folderId);
});

it('should throw error for invalid droppable id format', () => {
expect(() => {
validateAndExtractFolderId('invalid-id');
}).toThrow('Invalid droppable ID format: invalid-id');
});

it('should throw error for empty folder id in folder format', () => {
expect(() => {
validateAndExtractFolderId(FAVORITE_DROPPABLE_IDS.FOLDER_PREFIX);
}).toThrow(`Invalid folder ID: ${FAVORITE_DROPPABLE_IDS.FOLDER_PREFIX}`);
});

it('should throw error for empty folder id in folder header format', () => {
expect(() => {
validateAndExtractFolderId(FAVORITE_DROPPABLE_IDS.FOLDER_HEADER_PREFIX);
}).toThrow(
`Invalid folder header ID: ${FAVORITE_DROPPABLE_IDS.FOLDER_HEADER_PREFIX}`,
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { FAVORITE_DROPPABLE_IDS } from '@/favorites/constants/FavoriteDroppableIds';
import { FavoriteDroppableId } from '@/favorites/types/FavoriteDroppableId';

export const createFolderDroppableId = (
folderId: string,
): FavoriteDroppableId => `${FAVORITE_DROPPABLE_IDS.FOLDER_PREFIX}${folderId}`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { FAVORITE_DROPPABLE_IDS } from '@/favorites/constants/FavoriteDroppableIds';
import { FavoriteDroppableId } from '@/favorites/types/FavoriteDroppableId';

export const createFolderHeaderDroppableId = (
folderId: string,
): FavoriteDroppableId =>
`${FAVORITE_DROPPABLE_IDS.FOLDER_HEADER_PREFIX}${folderId}`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { FAVORITE_DROPPABLE_IDS } from '@/favorites/constants/FavoriteDroppableIds';

export const validateAndExtractFolderId = (
droppableId: string,
): string | null => {
if (droppableId === FAVORITE_DROPPABLE_IDS.ORPHAN_FAVORITES) {
return null;
}

if (droppableId.startsWith(FAVORITE_DROPPABLE_IDS.FOLDER_HEADER_PREFIX)) {
const folderId = droppableId.replace(
FAVORITE_DROPPABLE_IDS.FOLDER_HEADER_PREFIX,
'',
);
if (!folderId) throw new Error(`Invalid folder header ID: ${droppableId}`);
return folderId;
}

if (droppableId.startsWith(FAVORITE_DROPPABLE_IDS.FOLDER_PREFIX)) {
const folderId = droppableId.replace(
FAVORITE_DROPPABLE_IDS.FOLDER_PREFIX,
'',
);
if (!folderId) throw new Error(`Invalid folder ID: ${droppableId}`);
return folderId;
}

throw new Error(`Invalid droppable ID format: ${droppableId}`);
};

0 comments on commit a40580b

Please sign in to comment.