Contributing to TDS - developer guide
- Set up your environment
- Write some code
- Using lerna
- Writing unit tests with Jest
- Running end-to-end (e2e) tests with Nightwatch
- Make a commit
- Make a pull request
Set up your environment
To get started, clone the repository and create your branch from master. If you are not part of the TELUS digital organization, you may fork the repository instead.
Before getting started, you should also install Docker. This facilitates our e2e tests to ensure they are tested in a reproducible environment, and having all tests pass is essential to a successful TDS contribution. If Docker is not installed, the following steps will not complete successfully.
After setting up TDS locally, the following steps will get you started:
# Bootstrap your dev environment # This will install node and Gitbook dependencies, set up symlinks for lerna, build components for tests, and build docker containers npm run bootstrap # If pulling in changes on an outdated repository, or after rebasing, we recommend bootstrapping again # This will install node dependencies, set up symlinks for lerna, and build components for tests npm run bootstrap:quick
We use Prettier, an opinionated code formatter that integrates with your text editor. Configure your IDE or text editor to format your code automatically on save, and Prettier will adjust your syntax in accordance with the TDS conventions.
Set up your dev environment
When developing components, we recommend using our documentation as a testing sandbox.
# Start the styleguidist dev server, check output for the location of the docs npm run dev # Open a new terminal window # Start the test watcher, it will rerun tests based on the files you modify npm run test:watch
After this, you can open up a browser to view the documentation site (usually http://localhost:6060). The browser will automatically refresh when there are changes to any of the source files.
Write some code
Read the codebase overview to understand the structure of the codebase and the conventions being followed.
If you need to create a new component, run the scaffolding script to generate the basic folder structure, React component, documentation, and base unit tests for a new component.
npm run scaffold MyComponent
TDS uses lerna to build and publish component packages, and manage dependencies throughout the project. It's important to have an understanding of lerna's essential features in order to write code for components for tds-core or tds-community.
How lerna works within TDS
When you clone tds-core or tds-community and run
npm run bootstrap, it runs an important command:
npx lerna bootstrap --hoist that scans all the packages in the repository
and sets up symbolic links to them within
node_modules, treating the repository as a local registry for all linked packages.
npm run bootstrap includes a build step for
Rollup to build all packages into their respective
dist directories. Building is important in order for tests to pass, for example,
core-text must be built locally in order for
core-expand-collapse to consume it.
It is normal to have multiple packages in tds-core reuse dependencies, such as
@tds/core-text being a dependency of
@tds/core-radio. On publish, lerna assures all dependents of
@tds/core-text are using
its latest version since it is part of the same monorepo.
Helpful lerna commands
Adding dependencies to component packages
- Use lerna to add dependencies by specifying a scope for the target component package
- Using the command regularly will add packages as
- Using the command with
--devwill add packages as
- Note: if adding a private module in this monorepo, add it as a devDependency, otherwise consumers of the component won't be able to download unpublished dependencies
npx lerna add package-to-add --scope @tds/core-component-name [--dev]
Seeing which packages will get published
- To preview which components will get published:
npx lerna updated
- To preview what the next version bump for changed components will be:
npm run prepr
- Note: this command will be run automatically in pull requests, and TDS Bot will add a comment to the pull request showing what version bumps will occur on publish
Components are published via our continuous integration pipeline. Do not try publishing components yourself. TDS Core components are the responsibility of the TDS Core team, and TDS Community components are the responsibility of the Digital Platform Ambassadors.
npx lerna publish --conventional-commits
Troubleshooting build issues
If you see several errors related to components not building, it could be that lerna had set up
node_modules directories within each package during
Try clearing those directories and build again.
npx lerna clean --yes npm run build
If this does not resolve your issue, there could be an issue with duplicate dependencies throughout the repository with mismatched versions.
To solve this, we use lerna-update-wizard using the command
npx lernaupdate --dedupe to
assure duplicate packages are on the same version.
Running and updating tests
All TDS components use a combination of Jest tests and Nightwatch visual regression tests. As part of our Git hooks, these tests are run automatically on commit and on push. However, there are cases where you may want to run these tests manually, or require the ability to update test snapshots that are no longer up to date with the component you're working on.
Writing unit tests with Jest
Jest unit tests are integrated into all TDS React components. These are run to ensure that a component's functionality has not been compromised by a change. These unit tests will check the component's different states by providing different sets of prop values, and compare them to a set of pre-defined criteria. It is important to create new unit tests whenever a feature is added or significantly modified to ensure the stability of the component.
If a component's structure has significantly changed, it may require a snapshot update with the update command listed below. However, it is important to use discretion here, as a failing snapshot may be the symptom of a larger problem with the component. (Such as unexpected extra/missing classes or unintended shuffling of the component's DOM structure) Always review the log of a snapshot failure before running the update command. When in doubt, reach out to our support avenues.
# Manually run unit tests on modified components npm run test -- [opts] # Options: # -a: Run tests on all components regardless of if they were recently modified. # -u: Update test snapshots. (Useful if the component's structure has changed)
Running end-to-end (e2e) tests with Nightwatch
Nightwatch e2e tests are run to ensure that no unexpected visual regressions were made to a component. These tests are run automatically on all components with no test writing required on the developer's part.
# Manually run visual regression tests on modified components npm run test:e2e -- [opts] # Options: # -a: Run tests on all components regardless of if they were recently modified. # -u: Update test screenshots. (Useful if the component was purposefully changed visually)
Make a commit
husky is used to run precommit tasks on staged files, which includes code formatting, linting, and tests. You will not be able to make a commit until the precommit tasks pass. We also have a prepush hook to run a full build before pushing your code.
Automated component versioning is facilitated by the Conventional Commits specification, so you must be deliberate when choosing the type of commit.
Given the commit format:
type(scope): subject body footer
type field to inform lerna what Conventional Commit you intend to use:
- For breaking changes, use the feat commit type with body text that begins with the phrase "BREAKING CHANGE:"
- For minor changes, use the feat commit type
- For patches, use the fix commit type
Follow these guidelines to determine the type of your commit:
- Breaking changes are removals of features such as props, changes that affect the box model, or dramatic changes in branding or appearance
- Minor changes are new features, animations, props, or visual options
- Patches are defect fixes that do not remove features, alter pixel dimensions related to the box model, nor add new features. If an intended feature was not working in a previous release, changing that feature to match the original design counts as a patch even if it affects the box model
scope field when referring to an area in the codebase, such as a package name (e.g.
a directory (e.g.
subject field to write a succinct description of the change. The first word is often a verb using present
imperative tense such as 'change' or 'remove'.
body field can include more detailed notes regarding the change. If there is a breaking change, it must begin with
the phrase 'BREAKING CHANGE:'.
footer field can be used to reference a commit hash or issue number on GitHub.
|feat||Indicates a minor, public-facing change. A change is considered minor if it adds new functionality in a backwards-compatible manner. It must also be perceivable by consumers of TDS Core, and not just a change that only impacts developers of TDS Core. Additionally, it may be used if functionality is being deprecated. If a commit of this type contains a public-facing breaking change, add the text
|fix||Indicates a patch level, public-facing change. Generally, this is used for backwards-compatible bug fixes. There should be no consumer-facing API changes at all in patches. It must also be perceivable by consumers of TDS, and not just a change that only impacts developers of TDS Core.|
|test||Used for commits that only modify/add unit tests or anything test related, such as snapshots, screenshots, or test scripts.|
|refactor||Used if code has been refactored without any modifications to functionality or behaviour. If your refactor also fixes a bug, please use the
|docs||Indicates a modification to documentation. Changes to the .md files of components, or changes to the documentation site use this type.|
|chore||A type for miscellaneous changes. Anything not covered here is considered a chore. Additionally, this is useful when iterating on changes due to PR reviews or other factors. Only one commit may be labeled as a
The TDS codebase includes a script to run commitizen for a streamline commit-making experience:
# Stage your files and make a commit using commitizen npm run cz ## At the `type` and `scope` prompts, you can press TAB to view options
Example commit messages
feat(core-flex-grid): remove center prop BREAKING CHANGE: deprecated `center` prop is removed fix(core-button-link): adjust hover animation speed
Make a Pull Request
Before making your Pull Request, please be sure the following items were addressed:
- New component code has corresponding unit tests
- Any changes to component functionality has corresponding documentation
Paste the full output of the pre-pr task into the body of your PR so that a maintainer/publisher can verify when publishing.
npm run prepr
The pre-pr task will show you the version change that will result from your changeset. If the output is unexpected, you may need to adjust your commit messages before making your PR. See the Conventional Commits spec FAQ for more info on correcting mistakes.