Skip to content

Commit

Permalink
task/WP-273-CategoryIcon-v4
Browse files Browse the repository at this point in the history
  • Loading branch information
Taylor Grafft authored and Taylor Grafft committed Oct 6, 2023
1 parent fe13f81 commit d924916
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 26 deletions.
32 changes: 27 additions & 5 deletions client/src/components/_common/AppIcon/AppIcon.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,32 @@ import PropTypes from 'prop-types';
import Icon from '_common/Icon';
import './AppIcon.scss';

const doesClassExist = (className) => {
// Check if the CSS class exists in the stylesheets
for (let sheet of document.styleSheets) {
try {
for (let rule of sheet.cssRules) {
if (
rule.selectorText &&
rule.selectorText.includes(`.${className}::before`)
) {
return true;
}
}
} catch (e) {
// Handle cross-origin stylesheet errors
continue;
}
}
return false;
};

const AppIcon = ({ appId, category }) => {
const appIcons = useSelector((state) => state.apps.appIcons);
const findAppIcon = (id) => {
if (!category) {
console.error('Category is undefined for appId:', id);
return 'applications';
}
let appIcon = category.replace(' ', '-').toLowerCase();
let appIcon = category
? category.replace(' ', '-').toLowerCase()
: 'applications';
Object.keys(appIcons).forEach((appName) => {
if (id.includes(appName)) {
appIcon = appIcons[appName].toLowerCase();
Expand All @@ -23,6 +41,10 @@ const AppIcon = ({ appId, category }) => {
} else if (id.includes('extract')) {
appIcon = 'extract';
}
// Check if the CSS class exists, if not default to 'icon-applications'
if (!doesClassExist(`icon-${appIcon}`)) {
appIcon = 'applications';
}
return appIcon;
};
const iconName = findAppIcon(appId);
Expand Down
52 changes: 35 additions & 17 deletions client/src/components/_common/AppIcon/AppIcon.test.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import React from 'react';
import { render } from '@testing-library/react';
import {
toHaveAttribute,
toHaveTextContent,
} from '@testing-library/jest-dom/dist/matchers';
import '@testing-library/jest-dom/extend-expect';
import { Provider } from 'react-redux';
import configureStore from 'redux-mock-store';
import AppIcon from './AppIcon';
Expand All @@ -16,46 +13,67 @@ const store = mockStore({
},
},
categories: {
'test-apps': ['vasp'],
visualization: ['vasp'],
'data-processing': ['jupyter'],
},
});

expect.extend({ toHaveAttribute });
// Mock document.styleSheets to simulate the existence of the CSS classes we're testing for
Object.defineProperty(document, 'styleSheets', {
value: [
{
cssRules: [
{ selectorText: '.icon-jupyter::before' },
{ selectorText: '.icon-visualization::before' },
{ selectorText: '.icon-compress::before' },
{ selectorText: '.icon-extract::before' },
],
},
],
writable: true,
});

function renderAppIcon(appId, category = 'default') {
return render(
<Provider store={store}>
<AppIcon appId={appId} category={category} />
<AppIcon
appId={appId}
category={category}
appIcons={store.getState().apps.appIcons}
/>
</Provider>
);
}

describe('AppIcon', () => {
it('should render icons for known app IDs', () => {
const { getByRole } = renderAppIcon('jupyter', 'data-processing');
expect(getByRole('img')).toHaveAttribute('class', 'icon icon-jupyter');
const { container } = renderAppIcon('jupyter', 'data-processing');
expect(container.firstChild).toHaveClass('icon-jupyter');
});

it('should show category icons for apps with no appIcon', () => {
const { getByRole } = renderAppIcon('vasp', 'test-apps');
expect(getByRole('img')).toHaveAttribute('class', 'icon icon-test-apps');
const { container } = renderAppIcon('vasp', 'visualization');
expect(container.firstChild).toHaveClass('icon-visualization');
});

it('should render icons for prtl.clone apps', () => {
const { getByRole } = renderAppIcon(
const { container } = renderAppIcon(
'prtl.clone.username.allocation.jupyter'
);
expect(getByRole('img')).toHaveAttribute('class', 'icon icon-jupyter');
expect(container.firstChild).toHaveClass('icon-jupyter');
});

it('should render icon for zippy toolbar app', () => {
const { getByRole } = renderAppIcon(
const { container } = renderAppIcon(
'prtl.clone.username.FORK.zippy-0.2u2-2.0'
);
expect(getByRole('img')).toHaveAttribute('class', 'icon icon-compress');
expect(container.firstChild).toHaveClass('icon-compress');
});

it('should render icon for extract toolbar app', () => {
const { getByRole } = renderAppIcon(
const { container } = renderAppIcon(
'prtl.clone.username.FORK.extract-0.1u7-7.0'
);
expect(getByRole('img')).toHaveAttribute('class', 'icon icon-extract');
expect(container.firstChild).toHaveClass('icon-extract');
});
});
4 changes: 0 additions & 4 deletions client/src/styles/trumps/icon.fonts.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit d924916

Please sign in to comment.