The following documentation is only for the maintainers of this repository.
- Monorepo setup
- Installation
- Develop a component
- Update docs
- Release the packages
- Release docs
- Available commands
- Testing
- CI
- Add a new package to the monorepo
- Gotchas to remember
This repository is managed as a monorepo that is composed of many npm packages.
For more information on monorepo:
This monorepo is using Pnpm workspace feature to handle the installation of the npm dependencies and manage the packages inter-dependencies.
This project use Pnpm as a package manager. Therefore, you must install Pnpm:
npm install -g pnpm
For more options to install Pnpm, view https://pnpm.io/installation.
To install the project, open a terminal at the root of the workspace and execute the following command:
pnpm i
The installation should take up to 5 minutes.
During the installation you will encoutered several missing peerDependencies warnings. Ignore those warnings, this is happening because the devDependencies of this monorepo are defined at the root of the workspace.
The following documentation is a brief overview of the tools and processes involved in the development of a component. For more information, please read the React components documentation.
Orbiter is using hopper-ui icon components, please refer to the Hopper documentation.
Every components must be developed and documented in Storybook.
Storybook is a convenient sandbox that help the developpers write organized and isolated stories that match the specifications of the component. Storybook also facilitate functionnal testing and integrate very well with automated visual testing technologies.
The resulting Storybook playbook will represent a catalog of all the Sharegate design system components and will be available online for the design team.
For more informations about automated visual tests, read the Testings section.
To start developing, open a terminal in VSCode and execute the following command at the root of the workspace:
pnpm start
Any updates to the packages or Storybook's stories will automatically re-compile the packages and refresh the Storybook app accordingly.
To start developing in docs mode, open a terminal in VSCode and execute the following command at the root of the workspace:
pnpm start-sb-docs
Basically the only difference is that the process will be start with the --docs
arguments.
Any updates to the packages or Storybook's stories will automatically re-compile the packages and refresh the Storybook app accordingly.
When you are ready to release the packages, you must follow the following steps:
- Run
pnpm new-version
to bump the version of the packages that have been updated since the previous release. You will be prompted to select the type of release (major, minor or patch) for each package and to enter release notes. If you prefer writing the release notes in a text editor, enter a placeholder line in the command line, and the you can modify the file generated before committing it. - Commit the newly generated file in your branch and submit a new Pull Request(PR). Changesets will automatically detect the changes and post a message in your pull request telling you that once the PR closes, the versions will be released.
- Merge the Pull request into master. A Github action will automatically trigger and update the version of the packages and publish them to npm.
- Create a new Github release associated to the tag created previously
- Optionally deploy Storybook and the document Website
Sometimes it's useful to publish an alpha version to test the packages installation or share a preview.
Before you release, make sure you are in the master
branch or a branch with a name matching the feature/*
pattern, have write access to every selected npm packages and that you are logged in to npm.
To release an alpha version, open a terminal at the root of the workspace and execute the following commands:
pnpm release-alpha
When Pnpm version prompt pop, you should pick a version number matching your future main version. E.g. if you plan on publishing your changes as version 19.0.0
once they are done, your alpha version should be 19.0.0-alpha.1
.
If you need to publish a subsequent alpha package for the same version, do not select any Pnpm suggestion. Instead, select "Custom Prelease" and then enter "alpha". By doing so, the new alpha package version will be 19.0.0-alpha.2
.
Make sure you're Git is clean (No pending changes).
Make sure you have write access to the selected npm packages.
If you are using 2FA, make sure you specified a valid OTP.
If the packages failed to compile, it's easier to debug without executing the full release flow everytime. To do so, instead, execute the following command:
pnpm build
By default, packages compilation output will be in their respective dist directory. For more details, read the packages README file.
Orbiter documentation is host on Netlify. 2 sites are available, a currated site for the official documentation (https://wl-orbiter-website.netlify.app/) and a raw site containing every Storybook stories (https://sg-storybook.netlify.com).
Login to Netlify and make sure you have access to the sg-orbiter and sg-storybook sites of the GSoft team.
Netlify is configured to automatically deploy (unpublished) both sites everytime a new commit is done in an opened PR or a PR is merged back into master.
To publish a site:
- Login to Netlify
- Find the latest deploy of your site
- Click on the deploy link to access it's overview
- Click on the "Publish deploy" button
If you encounter any errors when building or publishing a site, login to Netlify and go to the deploy settings of the site. Make sure the Build command
and the Publish directory
properties are valid.
The Build command
property should match a script of the root package.json
file and the Publish directory
property should be a relative path matching a folder of the solution containing the static site to deploy after build.
A Netlify deploy can be started locally with a CLI command. This is useful if you are working in a branch and want to share a preview of your work with someone else.
To deploy a draft to the sg-storybook site, open a terminal at the root of the workspace and execute the following commands:
pnpm deploy-netlify-sb-preview
The draft link will be available in the terminal (ex. https://616dab5c22680800ccd47d6f--sg-storybook.netlify.app).
If you encountered any problem with the CLI command, make sure the site App ID
of sg-storybook site match the --site
parameter of the script deploy-netlify-sb-preview
in the package.json file.
All commands are available in the package.json file. Here's a list of the commands you might need to use frequently. The following commands must be executed in a terminal opened at the root of the workspace.
Compile all the packages & start Storybook.
pnpm start
Compile all the packages & start Storybook in docs mode.
pnpm start-sb-docs
Build all the packages and Storybook for production.
pnpm build
Reset the monorepo installation. The following will be deleted:
- All the node_modules directories
- All the pnpm-lock.yaml files
- All the compiled & cache folders
pnpm reset
If you encounter the following error:
C:\Dev\20_gsoft\sg-orbiter\node_modules\rimraf\bin.js:47
throw er
^
[Error: EPERM: operation not permitted, unlink 'XXX\sg-orbiter\node_modules\@types'] {
Close & re-open VSCode and delete manually the node_modules folder at the root of the workspace.
Execute all the linters & validate the TypeScript types.
pnpm lint
Validate the TypeScript types.
pnpm lint:typecheck
Execute all the Jest tests.
pnpm jest
Manually deploy Storybook to Netlify from any branch.
pnpm deploy-sb-preview
Deploy an alpha version of the packages.
pnpm release-alpha
For testing the components we currently rely only on visual testing & interaction testing.
Visual testing assert on what visually appears on the screen instead of asserting on specifics CSS selectors or DOM elements.
This is a more black box and robust testing approach since it shouldn't requires to modify the tests if the code refactor haven't change anything visually.
This approach is usually strictly use to assert that the visual of a component do not regress. Since it's easy and very efficient to write a robust test with this approach, we also use it to test the specifications of a component that are related to the behaviors and states.
Therefore, prefer this approach to interactions and api testing when possible.
Setting all the tools to perform automated visual tests involve a lot of time and knowledge. Therefore, we bought a license of Chromatic QA. This is the perfect tool for us since it perfectly integrate with Storybook.
For access to our Chromatic QA environment, ask to join the gsoft-inc organization on Github.
For more information about automated visual testing:
- https://storybook.js.org/tutorials/visual-testing-handbook/react/en/introduction
- https://storybook.js.org/docs/testing/automated-visual-testing
- https://www.youtube.com/watch?v=QE-xQxN9Sps
UI is all about interacting with the user. We need to test if a component work properly when those interactions occurs.
This approach is used to cover the interaction behaviors of a component.
Examples:
- Ensure that a given element X is visible when the user click on the element Y.
- Ensure that an handler of the component interface is called when the user on the element Y.
To facilite those tests, we use a combination of Jest and React testing library.
For more information about interaction testing:
API testing is useful to tests the properties of a component that can hardly be tested with visual testing.
Visual testing can easily assert that the disabled
property of a component visually work as expected. Asserting that the onChange
handler has been only called once when the user type a value in a textbox is harder.
This is where API testing shine.
To facilite those tests, we use a combination of Jest and React testing library.
Circle CI is the continuous integration platform for this repository. To have access to the CI environment, ask to join the gsoft-inc on Github.
2 builds are currently configured:
On every commits the CI will execute the linters.
Once per night, the CI will execute the automated visual tests. Those tests can't be executed on every commits since visual test snapshots are pricy and limited.
For more information on the automated visual tests, read the Testing section.
To investigate general problems with Circle CI you can debug with SSH.
If Chromatic can't reach the Storybook server, the Storybook potentially can't compile.
Sadly the Chromatic CLI doesn't properly relay Storybook compilation errors. To see the errors, build the Storybook app locally.
There is a few steps to add a new packages to the monorepo.
Before you add a new package, please read the GSoft Github guidelines.
First, create a new folder matching the package name in the packages directory.
Open a terminal, navigate to the newly created directory and execute the following command:
pnpm init
Answer the CLI questions.
Once the package.json is generated, please read again the GSoft Github guidelines and make sure the package name, author and license are valid.
Don't forget to add the npm scope "@orbit-ui" before the package name. For example if the project name is "foo", your package name should be "@orbit-ui/foo".
Make sure the package publish access is public by adding the following to the package.json file:
"publishConfig": {
"access": "public"
}
npm dependencies and peerDependencies must be added to the package own package.json file.
However, the devDependencies must be added to the package.json file at the root of the workspace.
Why?
Because packages hoisting is dangerous! When multiple packages of the monorepo requires the same dependencies but with a different version there is no garantee on which version will be hoisted to the node_modules directory at the root of the workspace and which version will be installed locally. To prevent all kinds of problems, always install the devDependencies at the root of the workspace. This ensure that every packages use the same version of the dependencies.
If you are uncertain wether or not you should add a peerDependencies, please read the post dependencies-done-right on the Yarn website.
If you're package is a new component, please read the React components documentation
When adding a new script, there is a few rules to follow.
A script should only do one thing. This practice promote better readability and reusability.
Then you can write top level script that compose all those atomic scripts to provide a functionnality.
Instead of doing:
"scripts": {
"build": "rimraf dist && babel src -d dist"
}
Do:
"scripts": {
"build": "pnpm delete & pnpm transpile",
"delete": "rimraf dist",
"transpile": "babel src -d dist"
}
Make sure you add a script entry in the package.json file at the root of the workspace even if your script is already define in a package or the website.
If a script can be called in batch, separate the discriminant by ":"
Example:
"scripts": {
"clean": "run-p clean:*",
"clean:pkg": "...",
"clean:sb": "..."
}
Otherwise, separare words with "-"
Example:
"scripts": {
"deploy-sb": "..."
}
The Storybook configuration doesn't load the Interphases custom font if the app is started by the chromatic CLI because visual tests offer inconsistent results when a custom font is loaded. Not sure why.
The following will not work:
"prepublishOnly": "cross-env NODE_ENV=production && pnpm build"
But the following work:
"prepublishOnly": "cross-env NODE_ENV=production pnpm build"
For other variables that need to be pass accross tasks, please read the following issue: kentcdodds/cross-env#176
Some side effects happens in the browsers following a user actions.
For example, if a user click on a textbox, the textbox will then have focus and be the "active element".
The focus side effect doesn't happen with react-testing-library. For more information view issues https://github.com/testing-library/jest-dom/issues/53 and https://github.com/testing-library/jest-dom/issues/59.
The solution to this problem have been to create an higher level abstraction library called https://github.com/testing-library/user-event that will take care of triggering the event AND the side effects.
For more information on the topic view the issue https://github.com/testing-library/dom-testing-library/issues/107.
To enable deploy previews on PR, Netlify sg-orbiter and sg-storybook sites have been linked to the sg-orbiter Github repository. Netlify will deploy a preview on every commits for any branches, even for master (which is Netlify production). This beging said, since the sites have been configured with "Auto Publish" disabled, even if a deploy is compiled for production IT IS NOT DEPLOY, it's only available for preview and must be deployed manually.
Having disabled "Auto Publish" is also the reason why our script that publish our sites to production "doesn't work anymore". It still works, the reason why the site doesn't update is because the script will create a new production build but WILL NOT PUBLISH IT, since it's auto publishing is disabled. It must be published manually throught Netlify web interface.
The Storybook props tables somewhow doesn't play well if our types comes from an external packages (even if it's a package in our own mono-repo). Props from the external packages might not be list in the props tables.
It's straightforward to spot when a snapshot test fails after a bug has been introduced. When that happens, go ahead and fix the issue and make sure your snapshot tests are passing again.
You can run the command
pnpm jest --updateSnapshot -u FILENAME
So if you want to update the useStyledSystem.test.tsx file
pnpm jest --updateSnapshot -u useStyledSystem.test.tsx