srleecode / domain

Domain operations Nx generators
MIT License
30 stars 5 forks source link

React support? #20

Closed hogarthww-labs closed 2 years ago

hogarthww-labs commented 3 years ago

What would it take to add support for react? Where are the main places to change the current generators etc?

I've been browsing through the code and see the following potential changes/modifications:

export enum Language {
  Angular = 'ng',
}

Which could obviously be changed to Framework and React added as a value

export enum Framework {
  Angular = 'ng',
  React = 'react'
}

create-app

export const isAppFolderExisting = (framework: string, tree: Tree): boolean => {
  return tree
    .children('libs')
    .some((appGroupingFolder) =>
      appGroupingFolder.startsWith(framework)
    );
};

FE app generator

  const { framework, name, baseFolder } = options;
  if (!isAppFolderExisting(framework, tree)) {
    await initialiseAngularWorkspace(tree);
  }

To initialise FE framework workspace

export const initialiseFrameworkWorkspace = (tree: Tree): GeneratorCallback => {
  addEslintLayerConstraints(tree);
  return addDependencies(tree);
};

create-domain

leave unchanged

move

leave unchanged

remove

leave unchanged

ng-add

leave unchanged

react-add

export async function reactAddGenerator(tree: Tree) {
  return addDependenciesToPackageJson(
    tree,
    {},
    {
      '@nrwl/react': 'latest',
      '@nrwl/cypress': 'latest',
    }
  );
}
export default reactAddGenerator;

export const reactAddSchematic = convertNxGenerator(reactAddGenerator);

shared

leave unchanged

src/generators

component

Change to ng-component

react-component

Copy ng-component folder

create (create new generator)

leave unchanged

libraries

Modify generator.js slightly to adjust for react framework option

const normalizeOptions = (
  options: LibrariesGeneratorSchema
): LibrariesNormalizedSchema => {
  return {
    ...options,
    libraryDefinitions: getDomainLibraryDefinitions(
      options.application,
      options.domain,
      options.libraries,
      options.framework // support diff FE frameworks
    ),
  };
};
import { wrapAngularDevkitSchematic } from '@nrwl/devkit/ngcli-adapter';
import { wrapReactDevkitSchematic } from '@nrwl/devkit/react-adapter';

const devKitSchematicFrameworkMap = {
  angular: wrapAngularDevkitSchematic,
  react: wrapReactDevkitSchematic
}

  const wrapDevkitSchematic = devKitSchematicFrameworkMap[options.framework]
  const libraryGenerator = wrapDevkitSchematic(
    `@nrwl/${options.framework}`,
    'library'
  );

... leave the rest mostly unchanged it seems

srleecode commented 3 years ago

I am rewriting the generators at the moment. packages\domain\src will eventually be removed and the content in packages\domain\generators will be what is exposed. My current plans are described here: https://github.com/srleecode/domain/tree/master/documentation/next if you have any thoughts on it I would be interested in hearing them.

Most generators should be easy to update to allow react support as well. The main one to think about is the component generator. I would need your help to define the best approach in regards to this generator. What is the best way in react for cypress component testing, can you mount storybook stories and is there a react version of component test harnesses. If there is none, then maybe it should use https://github.com/srleecode/component-command-utils

hogarthww-labs commented 3 years ago

Hi @srleecode

Thanks for your swift reply. I will add my thoughts on component generator for React.

- src/components/Task
 + index.js
 + Task.js
 + Task.spec.js
 + Task.stories.js
 + Task.scss (depending on style lib chosen for Nx)

Component file

// src/components/Task/Task.js
import React from 'react';

export default function Task({ title }) {
  return (
    <div className="list-item">
      <input type="text" value={title} readOnly={true} />
    </div>
  );
}
// src/components/Task/index.js
export * from './Task'

Spec file (using enzyme) (when additional option --test-dom-manager is enzyme)

// src/components/Task/Task.spec.js

    import React from 'react';
    import { shallow } from 'enzyme';
    import Task from './Task';

    describe('Task component', () => {
      it('renders', () => {
        const wrapper = shallow(<Task />);
        expect(wrapper).toMatchSnapshot();
      });
    });

Test file (when additional option --test-dom-manager is react-test-renderer)

// src/components/Task/Task.spec.js

import React from 'react';
import renderer from 'react-test-renderer';
import Task from './Task';

test('Task renders', () => {
  const component = renderer.create(
    <Task />
  );
  let tree = component.toJSON();
  expect(tree).toMatchSnapshot();
})

Storybook

// src/components/Task/Task.stories.js
import React from 'react';

import Task from './Task';

export default {
  component: Task,
  title: 'Task',
};

const Template = args => <Task {...args} />;

export const Default = Template.bind({});
Default.args = {title: 'Test Task'};

Storybook config

.storybook/main.js
module.exports = {
  stories: ['../src/components/**/*.stories.js'],
  addons: [
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@storybook/preset-create-react-app',
  ],
};
srleecode commented 3 years ago

A few points:

hogarthww-labs commented 3 years ago

Thanks @srleecode :) I completely agree on all your points. This PR was mainly just a starting point to have something to discuss around. A very rough draft.

Couldn't agree more. 💯% on point 🚀

srleecode commented 3 years ago

I appreciate your input and the PR (#21). I will close it as I think we got what we wanted out of it.

I made the following changes after going through the pr:

Next step with react is to implement the component generator. Is this something you would be willing to look at and contribute?

I am currently thinking it should:

Once that generator is created then we should know what needs to be installed and setup globally for react and a initaliaseReactWorkspace function can be written here https://github.com/srleecode/domain/blob/98932d76df41e521fb7d69a9f2667f2b428a21cf/packages/domain/generators/grouping-folder/create-app/src/lib/shared/initialise-workspace.ts#L6 The other generators should all either not need a specific one for each application type or be easy to create react versions for them.

hogarthww-labs commented 3 years ago

I would be happy to try implementing the component generator using the recipe you've outlined. I think I would have time next week (end of August)

srleecode commented 3 years ago

That would be great. Since there are still a lot of things that need to be investigated. I think it would be a good idea for you to create a new very simple project that has two components and one component that uses the others api from something like a component test harness in its test. Once that simple project is setup we will know what to generate. It should also allow mounting stories

srleecode commented 2 years ago

I am closing this as there has been no response. @hogarthww-labs if you are still interested in this storybook interaction testing is still in alpha, but it will allow interaction testing https://github.com/srleecode/domain/issues/40 . This resolves the uncertainty mentioned in the above comment and the approach for react is now known . If you are interested let me know and we can reopen this or create a new ticket.