Skip to content

Commit

Permalink
docs(testing): document stable selector support (#13868)
Browse files Browse the repository at this point in the history
* docs(testing): document stable selector support

* docs(testing): cleanup

* docs(testing): cleanup

* docs(testing): cleanup

* Update docs/developer-handbook.md

Co-authored-by: TJ Egan <[email protected]>

* Update docs/developer-handbook.md

Co-authored-by: TJ Egan <[email protected]>

* Update docs/developer-handbook.md

Co-authored-by: TJ Egan <[email protected]>

* Update docs/developer-handbook.md

Co-authored-by: TJ Egan <[email protected]>

* Update docs/developer-handbook.md

Co-authored-by: TJ Egan <[email protected]>

* Update docs/developer-handbook.md

Co-authored-by: TJ Egan <[email protected]>

* Update docs/developer-handbook.md

Co-authored-by: TJ Egan <[email protected]>

* Update docs/guides/versioning.md

Co-authored-by: TJ Egan <[email protected]>

* Update docs/style.md

Co-authored-by: TJ Egan <[email protected]>

* chore: formatting

---------

Co-authored-by: TJ Egan <[email protected]>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored May 25, 2023
1 parent fdb5c79 commit b8701c9
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 99 deletions.
124 changes: 25 additions & 99 deletions docs/developer-handbook.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@

- [Getting started](#getting-started)
- [Common tasks](#common-tasks)
- [`carbon-components`](#carbon-components)
- [Dependency management](#dependency-management)
- [Continuous Integration](#continuous-integration)
- [Package architecture and layout](#package-architecture-and-layout)
Expand All @@ -26,12 +25,9 @@
- [Start a new `block` or `element`?](#start-a-new-block-or-element)
- [Red flags](#red-flags)
- [Files and folders](#files-and-folders)
- [Defining markups for components and their variants](#defining-markups-for-components-and-their-variants)
- [Defining markup with no conditional or data interpolations](#defining-markup-with-no-conditional-or-data-interpolations)
- [Defining markup with conditionals or data interpolations](#defining-markup-with-conditionals-or-data-interpolations)
- [Working on JavaScript-framework-specific styles](#working-on-javascript-framework-specific-styles)
- [Using `npm link`/`yarn link`](#using-npm-linkyarn-link)
- [Pointing NPM dependency of `carbon-components` right to the source code](#pointing-npm-dependency-of-carbon-components-right-to-the-source-code)
- [Pointing NPM dependency of `@carbon/styles` right to the source code](#pointing-npm-dependency-of-carbonstyles-right-to-the-source-code)
- [Maintainers](#maintainers)
- [Working with icons and pictograms](#working-with-icons-and-pictograms)
- [Code Patterns](#code-patterns)
Expand All @@ -40,7 +36,7 @@
- [Publishing older library versions](#publishing-older-library-versions)
- [FAQ](#faq)
- [How do I install a dependency?](#how-do-i-install-a-dependency)
- [CircleCI is failing saying that it cannot find a dependency in offline mode](#circleci-is-failing-saying-that-it-cannot-find-a-dependency-in-offline-mode)
- [CI is failing saying that it cannot find a dependency in offline mode](#ci-is-failing-saying-that-it-cannot-find-a-dependency-in-offline-mode)
- [How do I fix the repo state if I cancel during a publish?](#how-do-i-fix-the-repo-state-if-i-cancel-during-a-publish)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->
Expand Down Expand Up @@ -447,81 +443,11 @@ Avoid names with multiple `__element` names:

### Files and folders

All components belong in `src/components` in their own folder.
All react components belong in `packages/react/src/components` in their own
folder.

Name files and folders using **singular** form; not plural.

```
button
- button.hbs
- _button.scss
- button.js
- button.config.js
```

Also note that all variants of a component can live in a single HBS, SCSS and JS
file respectively. For example, while there are many button variants (primary,
secondary, etc.), they're all contained in those single source files in the
button folder.

### Defining markups for components and their variants

There are two ways to define markups for components and their variants:

1. Defining markup with no conditional or data interpolations
2. Defining markup with conditionals or data interpolations

### Defining markup with no conditional or data interpolations

To define markup with no conditional or data interpolation you will need to add
a `.hbs` file to the component directory. No `.config.js` file in the component
directory is required in this case. One thing to note is that If there is a
`.hbs` file whose basename is exactly the same as the component name, other
`.hbs` files has to be in `componentname--variantname.hbs` format.

### Defining markup with conditionals or data interpolations

Defining markup with conditionals or data interpolations requires creating
`.config.js` file, which is a
[JavaScript module format of Fractal configuration](https://fractal.build/guide/core-concepts/configuration-files.html#configuration-file-formats),
in component directory. `.hbs` files are rendered with the data given via
`context` property in `variants[n]` (below).

Supported
[properties in `.config.js`](https://fractal.build/guide/components/configuration-reference.html#component-properties)
are the following:

- [`default`](https://fractal.build/guide/components/configuration#default): The
default variant name
- [`variants`](https://fractal.build/guide/components/configuration#variant-properties) -
An array of objects, supporting the following properties:
- `name`: The variant name
- `label`: The variant name shown in dev env UI
- `notes`: A short explainer the variant shown in dev env UI
- `context`: The data used for rendering `.hbs`
- `view`: The basename of the `.hbs` file for variant markup (Unlike
[default Fractal environment](https://fractal.build/guide/components/configuration#view),
this property should point to the basename of a `.hbs` file under `demo`
directory or `src` directory, _without_ its path)
- `preview`: The basename of the `.hbs` file for the markup that lays out the
variant markup, in "full render" mode (Unlike
[default Fractal environment](https://fractal.build/guide/components/configuration#preview),
this property should point to the basename of a `.hbs` file under `demo`
directory or `src` directory, _without_ `@` symbol)
- `meta`: Some metadata. Carbon vanilla development environment reads the
following ones specifically:
- `linkOnly`: Only full-page demo is allowed
- `useIframe`: Use of `<iframe>` for non full-page demo
- `xVersionOnly`: Supports "experimental" theme only
- `xVersionNotSupported`: "Experimental" theme is not supported

What `.hbs` file is used for rendering a variant is determined by searching for
`.hbs` files in `demo` or `src` directory and find one whose basename matches
one of the following (the priority is the following order):

1. `view` property in `variants[n]`
2. Variant handle, which takes a format of `componentname--variantname` format
3. Component handle, which is `componentname`
All Component styles belong in `packages/styles/scss/components` in their own
folder.

### Working on JavaScript-framework-specific styles

Expand All @@ -535,7 +461,7 @@ There are a couple ways to work on framework-specific style.
### Using `npm link`/`yarn link`

This is the most straightforward way. When in the directory of your
`carbon-components` folder, run the following command:
`@carbon/styles` folder, run the following command:

```bash
yarn link
Expand All @@ -544,30 +470,30 @@ yarn link
You should see a success message similar to:

```bash
success Registered "carbon-components".
info You can now run `yarn link "carbon-components"` in the projects where you want to use this package and it will be used instead.
success Registered "@carbon/styles".
info You can now run `yarn link "@carbon/styles"` in the projects where you want to use this package and it will be used instead.
```

Now, go to the folder where `carbon-components-angular` is located and run:

```bash
yarn link carbon-components
yarn link @carbon/styles
```

You should see a success message similar to:

```bash
success Using linked package for "carbon-components".
success Using linked package for "@carbon/styles".
```

The `yarn link` command will allow us to point the `carbon-components` package
The `yarn link` command will allow us to point the `@carbon/styles` package
under `node_modules` to the folder on our filesystem. So, if we make a change in
`carbon-components` and re-compile the project it will update in the Storybook
`@carbon/styles` and re-compile the project it will update in the Storybook
environment for `carbon-components-angular`.

In addition, if you would like to have your changes to styles automatically
compile and update Storybook you can run the following command in the
`carbon-components` folder on your machine:
`@carbon/styles` folder on your machine:

```bash
yarn gulp watch -s
Expand All @@ -577,26 +503,26 @@ This will run the `watch` command in `gulpfile.js`. As a result, whenever you
make a change to the project styles it will automatically copy over into the
`scss` folder which Storybook uses in `carbon-components-angular`.

### Pointing NPM dependency of `carbon-components` right to the source code
### Pointing NPM dependency of `@carbon/styles` right to the source code

Though above approach is the most straightforward, it involves an overhead of
having to run build process at `carbon-components`, in addition to one at
framework variant repo, upon every Sass code change.
Though the above approach is the most straightforward, it involves the overhead
of having to run the build process at `@carbon/styles`, in addition to one at
the framework variant repo, upon every Sass code change.

To avoid such overhead, you can point NPM dependency of `carbon-components`
right to the source code, though there is a caveat that our future change to
To avoid such overhead, you can point NPM dependency of `@carbon/styles` right
to the source code, though there is a caveat that our future change to the
directory structure, etc. may make such steps no longer work. Here are the
steps:

```sh
> cd /path/to/carbon-components-angular/node_modules/carbon-components
> cd /path/to/carbon-components-angular/node_modules/@carbon/styles
> mv scss scss.orig
> ln -s /path/to/carbon-components/src scss
> ln -s /path/to/@carbon/styles/scss scss
```

Then edits of `.scss` files in `/path/to/carbon-components/src` will be
reflected to the development environment of your framework variant repository.
You don't need to do anything in `carbon-components` side.
Then edits of `.scss` files in `/path/to/@carbon/styles/scss` will be reflected
to the development environment of your framework variant repository. You don't
need to do anything in `@carbon/styles` side.

## Maintainers

Expand Down
22 changes: 22 additions & 0 deletions docs/guides/versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,3 +267,25 @@ values are passed along to a given element in the DOM. While the label should
stay consistent over time, you should not rely on either prop pointing to the
same element over time. In other words, the node that `aria-label` or
`aria-labelledby` is supplied to may change over time.

#### The DOM node that a `data-testid` corresponds to is changed

semver bump: **minor**, but ideally **major**

We support the placement of `data-testid` attributes on components as a "stable
selector" for locating elements for testing when
[all other options](https://testing-library.com/docs/queries/about#priority) are
exhausted.

We are aware that consumers relying on these in their tests will be impacted
from any modifications to their placement. For this reason we'll always aim to
contain any of these changes behind a feature flag or major version bump, but
under some circumstances the node that this is applied to may change across
minor versions. In these cases we will make a strong effort to loudly
communicate the change to notify teams as well as provide automated tooling
where possible to minimize the impact of the change.

**We highly encourage consuming applications to _avoid using `data-testid`
unless absolutely necessary_ and instead use more stable
[relative queries focused on accessible roles](https://testing-library.com/docs/queries/about#priority)
or HTML5 and ARIA semantics for selecting elements for testing.**
65 changes: 65 additions & 0 deletions docs/style.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ row before the </tbody></table> line.
- [Guidelines](#guidelines)
- [Writing a component](#writing-a-component)
- [When to use `React.ForwardRef`](#when-to-use-reactforwardref)
- [Class names, `data-testid` attributes, and `...rest`](#class-names-data-testid-attributes-and-rest)
- [Authoring dynamic/inline styles](#authoring-dynamicinline-styles)
- [Translating a component](#translating-a-component)
- [Working with messages that depend on state](#working-with-messages-that-depend-on-state)
- [Using `useCallback` and `useMemo`](#using-usecallback-and-usememo)
Expand All @@ -76,6 +78,7 @@ row before the </tbody></table> line.
- [Testing](#testing)
- [Strategy](#strategy)
- [Organization](#organization)
- [Stable selectors](#stable-selectors)
- [Recipes](#recipes)
- [`ComponentName-test.js`](#componentname-testjs)
- [`ComponentName-test.a11y.js`](#componentname-testa11yjs)
Expand Down Expand Up @@ -255,6 +258,68 @@ change. When creating a new component, even if you do not anticipate an explicit
need to provide a forwarded ref, it's likely still worthwhile to include one to
avoid unecessary breaking changes in the future.

#### `className`, `data-testid`, and `...rest`

Where possible, the following should be placed on the outermost, parent, or root
element within a component:

- The `className` prop
- Additional props spread via `...rest`
- `data-testid` attributes

```jsx
function MyComponent({ className, ...rest }) {
return (
<div className={className} {...rest}>
<div>
<div></div>
</div>
</div>
);
}
```

The location and placement of what elements these props are placed on should be
stable across major, minor, and patch versions. This may not always be possible,
but movement of any of these to different elements should ideally only happen
within a major version change. In some rare cases to fix critical bugs we can
consider moving placement in a minor version, but we'll need to be highly
communicative of the change on all of our support channels. Consumers rely on
the placement of these within the DOM and any changes can cause tests,
functionality, and custom styling to break within consuming applications.

##### Stable selectors

We also support the placement of `data-testid` attributes on components as a
"stable selector" for locating elements for testing when
[all other options](https://testing-library.com/docs/queries/about#priority) are
exhausted. The location and placement of these in the DOM should remain stable
between versions. This can be accomplished by explicitly placing this prop on
the outermost element, or it can be accomplished by having `...rest` spread on
the outermost element.

In some cases `...rest` can not be spread on the outermost element and needs to
be spread on other key interior elements, such as inputs. For these cases we
cannot rely on `data-testid` being included in `...rest` and it must explicitly
be applied to the outermost element.

```jsx
function MyComponent({ className, ...rest }) {
return (
<div className={className} data-testid={rest['data-testid']}>
<div>
<input {...rest} />
</div>
</div>
);
}
```

**We highly encourage consuming applications to _avoid using `data-testid`
unless absolutely necessary_ and instead use more stable
[relative queries focused on accessible roles](https://testing-library.com/docs/queries/about#priority)
or HTML5 and ARIA semantics for selecting elements for testing.**

#### Authoring dynamic/inline styles

It's increasingly common for applications to use a Content Security Policy (CSP)
Expand Down

0 comments on commit b8701c9

Please sign in to comment.