Skip to content

Commit

Permalink
Use Patternfly dynamic-modules.json where possible (#2030)
Browse files Browse the repository at this point in the history
* Click on toggle element in BulkSelect tests

* Remove caching from old code

* Add caching to new lookup code

* Update Patternfly to latest version with dynamic-modules.json

* Update snapshots from new Patternfly version

* Click on toggle element in BulkSelect tests

* Use default export for guessComponentModule

* Update gitignore

* Use findFirstGlob in getPossibleLocations

* Use findFirstGlob in getModuleExplicitLocation
  • Loading branch information
randomnetcat authored Jul 8, 2024
1 parent 98b0948 commit b1f5bb5
Show file tree
Hide file tree
Showing 9 changed files with 233 additions and 164 deletions.
64 changes: 32 additions & 32 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"@octokit/rest": "^16.43.2",
"@openshift/dynamic-plugin-sdk-webpack": "^4.0.1",
"@patternfly/quickstarts": "^5.0.0",
"@patternfly/react-core": "^5.0.0",
"@patternfly/react-core": "^5.3.3",
"@patternfly/react-icons": "^5.0.0",
"@patternfly/react-table": "^5.0.0",
"@simonsmith/cypress-image-snapshot": "^8.0.2",
Expand Down
8 changes: 4 additions & 4 deletions packages/components/src/BulkSelect/BulkSelect.spec.ct.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ describe('BulkSelect component', () => {
it('renders component with data', () => {
cy.mount(<BulkSelect {...config} />);
cy.get('#toggle-checkbox').should('contain.text', '100');
cy.get('.pf-v5-c-menu-toggle').click();
cy.get('.pf-v5-c-menu-toggle__controls').click();
// PF has one extra hidden button element
cy.get('.pf-v5-c-menu__list').find('>li>button').should('have.length', 3);
});

it('cannot be expanded or checked when disabled', () => {
cy.mount(<BulkSelect {...config} isDisabled={true} />);
cy.get('.pf-v5-c-menu-toggle').click({ force: true });
cy.get('.pf-v5-c-menu-toggle__controls').click({ force: true });
cy.get('.pf-v5-c-menu__list').should('not.exist');
cy.get('input[name="toggle-checkbox"]').check({ force: true });
cy.get('input[name="toggle-checkbox"]').should('not.be.checked');
Expand All @@ -44,9 +44,9 @@ describe('BulkSelect component', () => {
config.items[1].onClick = cy.spy().as('disabledSpy');
config.onClick = cy.spy().as('checkboxSpy');
cy.mount(<BulkSelect {...config} />);
cy.get('.pf-v5-c-menu-toggle').click();
cy.get('.pf-v5-c-menu-toggle__controls').click();
cy.get('.pf-v5-c-menu__list').find('>li>button').eq(1).click();
cy.get('.pf-v5-c-menu-toggle').click();
cy.get('.pf-v5-c-menu-toggle__controls').click();
cy.get('.pf-v5-c-menu__list').find('>li>button').eq(2).click({ force: true });
cy.get('input[name="toggle-checkbox"]').check();
cy.get('@enabledSpy').should('have.been.called');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ exports[`BulkSelect should render correctly - null checked 1`] = `
>
<label
class="pf-v5-c-check pf-m-standalone"
for="toggle-checkbox"
>
<input
aria-invalid="false"
Expand Down Expand Up @@ -84,7 +83,6 @@ exports[`BulkSelect should render correctly 1`] = `
>
<label
class="pf-v5-c-check"
for="some-id-toggle-checkbox"
>
<input
aria-invalid="false"
Expand Down Expand Up @@ -143,7 +141,6 @@ exports[`BulkSelect should render correctly 2`] = `
>
<label
class="pf-v5-c-check pf-m-standalone"
for="toggle-checkbox"
>
<input
aria-invalid="false"
Expand Down Expand Up @@ -195,7 +192,6 @@ exports[`BulkSelect should render custom props 1`] = `
>
<label
class="pf-v5-c-check pf-m-standalone"
for="toggle-checkbox"
>
<input
aria-invalid="false"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ exports[`FilterInput component should render a checkbox input 1`] = `
<Checkbox
aria-label="label"
className="ins-c-filter-input__checkbox"
component="div"
id="id"
isChecked={false}
isDisabled={false}
isLabelWrapped={false}
isRequired={false}
isValid={true}
label="label"
Expand Down
4 changes: 4 additions & 0 deletions packages/tsc-transform-imports/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
index.js
index.d.ts
index.js.map
directories.js
directories.d.ts
guess-module.js
guess-module.d.ts
33 changes: 33 additions & 0 deletions packages/tsc-transform-imports/src/directories.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import path from 'path';
import * as glob from 'glob';

const MODULES_ROOT = process.env.MODULES_ROOT;

const PACKAGES_ROOT = path.resolve(process.cwd(), 'packages');

export const CORE_DIRECTORIES = [
glob.sync(`${process.cwd()}/node_modules/@patternfly/react-core`),
glob.sync(`${PACKAGES_ROOT}/*/node_modules/@patternfly/react-core`),
].flat();

export const ICONS_DIRECTORIES = [
glob.sync(`${process.cwd()}/node_modules/@patternfly/react-icons`),
glob.sync(`${PACKAGES_ROOT}/*/node_modules/@patternfly/react-icons`),
].flat();

if (MODULES_ROOT) {
// comma separated list of roots
MODULES_ROOT.split(',').forEach((root) => {
CORE_DIRECTORIES.push(...glob.sync(`${path.resolve(__dirname, root)}/node_modules/@patternfly/react-core`.replace(/\/\//, '/')));
ICONS_DIRECTORIES.push(...glob.sync(`${path.resolve(__dirname, root)}/node_modules/@patternfly/react-icons`.replace(/\/\//, '/')));
});
}

export function findFirstGlob(roots: string[], suffix: string, filter?: (path: string) => boolean): string | undefined {
const adjustedSuffix = suffix.startsWith('/') ? suffix.substring(1) : suffix;

return roots.flatMap((root) => {
const found = glob.sync(`${root}/${adjustedSuffix}`);
return filter !== undefined ? found.filter(filter) : found;
})[0];
}
99 changes: 99 additions & 0 deletions packages/tsc-transform-imports/src/guess-module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import * as glob from 'glob';
import { CORE_DIRECTORIES, findFirstGlob } from './directories';

const PROPS_MATCH = /Props$/g;
const VARIANT_MATCH = /Variants?$/g;
const POSITION_MATCH = /Position$/g;
const SIZE_MATCH = /Sizes?$/g;

function filterNonStableLocation(location: string) {
return !location.includes('next') && !location.includes('deprecated');
}

function getPossibleLocations(roots: string[], nameBinding: string) {
let moduleLocation = findFirstGlob(roots, `dist/esm/**/${nameBinding}.js`, filterNonStableLocation);

if (!moduleLocation && nameBinding.match(PROPS_MATCH)) {
moduleLocation = findFirstGlob(roots, `dist/esm/**/${nameBinding.replace(PROPS_MATCH, '')}.js`, filterNonStableLocation);
}

if (!moduleLocation && nameBinding.match(VARIANT_MATCH)) {
moduleLocation = findFirstGlob(roots, `dist/esm/**/${nameBinding.replace(VARIANT_MATCH, '')}.js`, filterNonStableLocation);
}

if (!moduleLocation && nameBinding.match(POSITION_MATCH)) {
moduleLocation = findFirstGlob(roots, `dist/esm/**/${nameBinding.replace(POSITION_MATCH, '')}.js`, filterNonStableLocation);
}

if (!moduleLocation && nameBinding.match(SIZE_MATCH)) {
moduleLocation = findFirstGlob(roots, `dist/esm/**/${nameBinding.replace(SIZE_MATCH, '')}.js`, filterNonStableLocation);
}

return moduleLocation;
}

function getModuleExplicitLocation(roots: string[], relativePath: string) {
const defaultLocation = findFirstGlob(roots, `dist/dynamic/**/${relativePath}`, filterNonStableLocation)?.split('/dynamic/').pop();

if (defaultLocation) {
return defaultLocation;
}

throw new Error(`Could not find source file for ${relativePath} in any of ${roots}!`);
}

// Prefilled with modules which name bindings do not match the import specifier
let HARDCODED_COMPONENTS: {
[nameBinding: string]: string;
} = {};

if (CORE_DIRECTORIES.length > 0) {
HARDCODED_COMPONENTS = {
getResizeObserver: getModuleExplicitLocation(CORE_DIRECTORIES, 'helpers/resizeObserver'),
useOUIAProps: getModuleExplicitLocation(CORE_DIRECTORIES, 'helpers/OUIA/ouia'),
OUIAProps: getModuleExplicitLocation(CORE_DIRECTORIES, 'helpers/OUIA/ouia'),
getDefaultOUIAId: getModuleExplicitLocation(CORE_DIRECTORIES, 'helpers/OUIA/ouia'),
useOUIAId: getModuleExplicitLocation(CORE_DIRECTORIES, 'helpers/OUIA/ouia'),
handleArrows: getModuleExplicitLocation(CORE_DIRECTORIES, 'helpers/KeyboardHandler'),
setTabIndex: getModuleExplicitLocation(CORE_DIRECTORIES, 'helpers/KeyboardHandler'),
IconComponentProps: getModuleExplicitLocation(CORE_DIRECTORIES, 'components/Icon'),
TreeViewDataItem: getModuleExplicitLocation(CORE_DIRECTORIES, 'components/TreeView'),
Popper: getModuleExplicitLocation(CORE_DIRECTORIES, 'helpers/Popper/Popper'),
clipboardCopyFunc: getModuleExplicitLocation(CORE_DIRECTORIES, 'components/ClipboardCopy'),
ToolbarChipGroup: getModuleExplicitLocation(CORE_DIRECTORIES, 'components/Toolbar'),
DatePickerRef: getModuleExplicitLocation(CORE_DIRECTORIES, 'components/DatePicker'),
ButtonType: getModuleExplicitLocation(CORE_DIRECTORIES, 'components/Button'),
PaginationTitles: getModuleExplicitLocation(CORE_DIRECTORIES, 'components/Pagination'),
ProgressMeasureLocation: getModuleExplicitLocation(CORE_DIRECTORIES, 'components/Progress'),
isValidDate: getModuleExplicitLocation(CORE_DIRECTORIES, 'helpers/datetimeUtils'),
ValidatedOptions: getModuleExplicitLocation(CORE_DIRECTORIES, 'helpers/constants'),
capitalize: getModuleExplicitLocation(CORE_DIRECTORIES, 'helpers/util'),
WizardFooterWrapper: getModuleExplicitLocation(CORE_DIRECTORIES, 'components/Wizard'),
WizardFooter: getModuleExplicitLocation(CORE_DIRECTORIES, 'components/Wizard'),
WizardContextProvider: getModuleExplicitLocation(CORE_DIRECTORIES, 'components/Wizard'),
useWizardContext: getModuleExplicitLocation(CORE_DIRECTORIES, 'components/Wizard'),
DataListWrapModifier: getModuleExplicitLocation(CORE_DIRECTORIES, 'components/DataList'),
MenuToggleElement: getModuleExplicitLocation(CORE_DIRECTORIES, 'components/MenuToggle'),
};
}

function guessComponentModule(nameBinding: string) {
let modulePath = HARDCODED_COMPONENTS[nameBinding];
if (modulePath) {
return modulePath;
}

const sourceGlob = getPossibleLocations(CORE_DIRECTORIES, nameBinding);
const sourceFile = sourceGlob ? glob.sync(sourceGlob) : [];
if (sourceFile.length < 1) {
throw new Error(
`Unable to find source file for module ${nameBinding}! The module likely does not have unique file as is included within another file. Please add the entry into the COMPONENTS_CACHE in FEC repository`
);
}
const moduleSource: string[] = sourceFile[0].split('esm').pop()?.split('/') || [];
moduleSource?.pop();
modulePath = moduleSource?.join('/').replace(/^\//, '');
return modulePath;
}

export default guessComponentModule;
Loading

0 comments on commit b1f5bb5

Please sign in to comment.