Skip to content
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

task/WP-708: add unit tests and refactor getting toolbar rules into a method #1457

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
import { getToolbarRules } from './DatafilesToolbar';
import { TFileListing } from '@client/hooks';

export const fileFixtures = {
txtFile: {
system: 'project-9876543210668535791-242ac118-0001-012',
name: 'test.txt',
path: '/test.txt',
format: 'raw',
type: 'file',
mimeType: 'text/plain',
lastModified: '2024-10-03T19:44:11Z',
length: 10000,
permissions: 'READ',
} as TFileListing,

anotherTxtFile: {
system: 'project-9876543210668535791-242ac118-0001-012',
name: 'another_test.txt',
path: '/another_test.txt',
format: 'raw',
type: 'file',
mimeType: 'text/plain',
lastModified: '2024-10-03T19:44:11Z',
length: 10000,
permissions: 'READ',
} as TFileListing,

hazmapperFile: {
system: 'project-9876543210668535791-242ac118-0001-012',
name: 'test.hazmapper',
path: '/test.hazmapper',
format: 'raw',
type: 'file',
mimeType: '',
lastModified: '2024-10-04T00:50:22Z',
length: 100,
permissions: 'READ',
} as TFileListing,

subDirectory: {
system: 'project-9876543210668535791-242ac118-0001-012',
name: 'test',
path: '/test',
format: 'folder',
type: 'dir',
mimeType: '',
lastModified: '2024-10-03T19:44:51Z',
length: 4096,
permissions: 'READ',
} as TFileListing,
};

describe('getToolbarRules', () => {
const USER_WORK_SYSTEM = 'user_work_system';

test('should disable all buttons when no files are selected', () => {
const selectedFiles: TFileListing[] = [];
const isAuthenticated = true;
const isReadOnly = false;
const system = 'other_system';

const rules = getToolbarRules(
selectedFiles,
isReadOnly,
isAuthenticated,
system,
USER_WORK_SYSTEM
);

expect(rules.canPreview).toBe(false);
expect(rules.canRename).toBe(false);
expect(rules.canCopy).toBe(false);
expect(rules.canMove).toBe(false);
expect(rules.canTrash).toBe(false);
expect(rules.canDownload).toBe(false);
});

test('should enable all buttons when single "normal" file selected', () => {
const selectedFiles: TFileListing[] = [fileFixtures.txtFile];

const isAuthenticated = true;
const isReadOnly = false;
const system = 'other_system';

const rules = getToolbarRules(
selectedFiles,
isReadOnly,
isAuthenticated,
system,
USER_WORK_SYSTEM
);

expect(rules.canPreview).toBe(true);
expect(rules.canRename).toBe(true);
expect(rules.canCopy).toBe(true);
expect(rules.canMove).toBe(true);
expect(rules.canTrash).toBe(true);
expect(rules.canDownload).toBe(true);
});

test('should disable all buttons except preview when single hazmapper file selected', () => {
const selectedFiles: TFileListing[] = [fileFixtures.hazmapperFile];

const isAuthenticated = true;
const isReadOnly = false;
const system = 'other_system';

const rules = getToolbarRules(
selectedFiles,
isReadOnly,
isAuthenticated,
system,
USER_WORK_SYSTEM
);

expect(rules.canPreview).toBe(true);
expect(rules.canRename).toBe(false);
expect(rules.canCopy).toBe(false);
expect(rules.canMove).toBe(false);
expect(rules.canTrash).toBe(false);
expect(rules.canDownload).toBe(false);
});

test('should enable all buttons except rename + preview when multiple "normal" files selected', () => {
const selectedFiles: TFileListing[] = [
fileFixtures.txtFile,
fileFixtures.anotherTxtFile,
];

const isAuthenticated = true;
const isReadOnly = false;
const system = 'other_system';

const rules = getToolbarRules(
selectedFiles,
isReadOnly,
isAuthenticated,
system,
USER_WORK_SYSTEM
);

expect(rules.canPreview).toBe(false);
expect(rules.canRename).toBe(false);
expect(rules.canCopy).toBe(true);
expect(rules.canMove).toBe(true);
expect(rules.canTrash).toBe(true);
expect(rules.canDownload).toBe(true);
});

test('should disable all buttons when a .hazmapper file is part of multiple selection', () => {
const selectedFiles: TFileListing[] = [
fileFixtures.txtFile,
fileFixtures.hazmapperFile,
];

const isAuthenticated = true;
const isReadOnly = false;
const system = 'other_system';

const rules = getToolbarRules(
selectedFiles,
isReadOnly,
isAuthenticated,
system,
USER_WORK_SYSTEM
);

expect(rules.canPreview).toBe(false);
expect(rules.canRename).toBe(false);
expect(rules.canCopy).toBe(false);
expect(rules.canMove).toBe(false);
expect(rules.canTrash).toBe(false);
expect(rules.canDownload).toBe(false);
});

test('should disable all buttons except preview/download when single selection but not authenticated', () => {
const selectedFiles: TFileListing[] = [fileFixtures.txtFile];

const isAuthenticated = false;
const isReadOnly = false;
const system = 'other_system';

const rules = getToolbarRules(
selectedFiles,
isReadOnly,
isAuthenticated,
system,
USER_WORK_SYSTEM
);

expect(rules.canPreview).toBe(true);
expect(rules.canRename).toBe(false);
expect(rules.canCopy).toBe(false);
expect(rules.canMove).toBe(false);
expect(rules.canTrash).toBe(false);
expect(rules.canDownload).toBe(true);
});

test('should disable all buttons except download when multiple selection but not authenticated', () => {
const selectedFiles: TFileListing[] = [
fileFixtures.txtFile,
fileFixtures.anotherTxtFile,
];

const isAuthenticated = false;
const isReadOnly = false;
const system = 'other_system';

const rules = getToolbarRules(
selectedFiles,
isReadOnly,
isAuthenticated,
system,
USER_WORK_SYSTEM
);

expect(rules.canPreview).toBe(false);
expect(rules.canRename).toBe(false);
expect(rules.canCopy).toBe(false);
expect(rules.canMove).toBe(false);
expect(rules.canTrash).toBe(false);
expect(rules.canDownload).toBe(true);
});
});
103 changes: 65 additions & 38 deletions client/modules/datafiles/src/DatafilesToolbar/DatafilesToolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,65 @@ import {
USER_WORK_SYSTEM,
useSelectedFiles,
useSelectedFilesForSystem,
TFileListing,
} from '@client/hooks';
import DatafilesModal from '../DatafilesModal/DatafilesModal';
import TrashButton from './TrashButton';
import { Button, ButtonProps, ConfigProvider, ThemeConfig } from 'antd';
import { useMatches, useParams } from 'react-router-dom';

type ToolbarRules = {
canPreview: boolean;
canRename: boolean;
canCopy: boolean;
canMove: boolean;
canTrash: boolean;
canDownload: boolean;
};

/**
* Get the rules for enabling or disabling toolbar buttons based on the selected files, user permissions,
* system, and read-only mode.
*/
export function getToolbarRules(
selectedFiles: TFileListing[],
isReadOnly: boolean,
isAuthenticated: boolean,
system: string,
USER_WORK_SYSTEM: string
): ToolbarRules {
const notContainingHazmapperFile = selectedFiles.every(
(file) => !file.path.endsWith('.hazmapper')
);

return {
canPreview: selectedFiles.length === 1 && selectedFiles[0].type === 'file',
canRename:
isAuthenticated &&
selectedFiles.length === 1 &&
!isReadOnly &&
notContainingHazmapperFile,
canCopy:
isAuthenticated &&
selectedFiles.length >= 1 &&
notContainingHazmapperFile,
canMove:
isAuthenticated &&
selectedFiles.length >= 1 &&
!isReadOnly &&
notContainingHazmapperFile,
canTrash:
isAuthenticated &&
selectedFiles.length >= 1 &&
!isReadOnly &&
notContainingHazmapperFile,
canDownload:
selectedFiles.length >= 1 &&
system !== USER_WORK_SYSTEM &&
notContainingHazmapperFile,
};
}

const toolbarTheme: ThemeConfig = {
components: {
Button: {
Expand Down Expand Up @@ -41,10 +94,10 @@ export const DatafilesToolbar: React.FC<{ searchInput?: React.ReactNode }> = ({
const { user } = useAuthenticatedUser();

const matches = useMatches();
const isProjects = matches.find((m) => m.id === 'project');
const isPublished = matches.find((m) => m.id === 'published');
const isEntityListing = matches.find((m) => m.id === 'entity-listing');
const isNees = matches.find((m) => m.id === 'nees');
const isProjects = !!matches.find((m) => m.id === 'project');
const isPublished = !!matches.find((m) => m.id === 'published');
const isEntityListing = !!matches.find((m) => m.id === 'entity-listing');
const isNees = !!matches.find((m) => m.id === 'nees');

const isReadOnly =
isPublished || isNees || system === 'designsafe.storage.community';
Expand Down Expand Up @@ -82,40 +135,14 @@ export const DatafilesToolbar: React.FC<{ searchInput?: React.ReactNode }> = ({
: listingSelectedFiles;

const rules = useMemo(
function () {
// Check if none of the selected files end with `.hazmapper`.
const notContainingHazmapperFile = selectedFiles.every(
(file) => !file.path.endsWith('.hazmapper')
);

// Rules for which toolbar buttons are active for a given selection.
return {
canPreview:
selectedFiles.length === 1 && selectedFiles[0].type === 'file',
canRename:
user &&
selectedFiles.length === 1 &&
!isReadOnly &&
notContainingHazmapperFile,
canCopy:
user && selectedFiles.length >= 1 && notContainingHazmapperFile,
canMove:
user &&
selectedFiles.length >= 1 &&
!isReadOnly &&
notContainingHazmapperFile,
canTrash:
user &&
selectedFiles.length >= 1 &&
!isReadOnly &&
notContainingHazmapperFile,
// Disable downloads from frontera.work until we have a non-flaky mount on ds-download.
canDownload:
selectedFiles.length >= 1 &&
system !== USER_WORK_SYSTEM &&
notContainingHazmapperFile,
};
},
() =>
getToolbarRules(
selectedFiles,
isReadOnly,
!!user,
system,
USER_WORK_SYSTEM
),
[selectedFiles, isReadOnly, user, system]
);

Expand Down
Loading