Repository: uber-web/baseui
Pull request #1034 (2019-03-15 21:53:20)

feat: add data-baseweb attribute
This adds a new `data-baseweb="component"` attribute to all component roots (there are some exceptions). The idea is that we can later use this attribute to easily detect/scrape/test/screenshot our components across projects.



Patch:
diff --git a/src/accordion/accordion.js b/src/accordion/accordion.js
index 1468f05db..4a0726099 100644
--- a/src/accordion/accordion.js
+++ b/src/accordion/accordion.js
@@ -107,7 +107,7 @@ export default class Accordion extends React.Component<
     const {Root: RootOverride} = overrides;
     const [Root, rootProps] = getOverrides(RootOverride, StyledRoot);
     return (
-      <Root {...sharedProps} {...rootProps}>
+      <Root data-baseweb="accordion" {...sharedProps} {...rootProps}>
         {this.getItems()}
       </Root>
     );
diff --git a/src/avatar/avatar.js b/src/avatar/avatar.js
index 366ddca3c..d77cb2d36 100644
--- a/src/avatar/avatar.js
+++ b/src/avatar/avatar.js
@@ -54,6 +54,7 @@ export default class Avatar extends React.Component<PropsT, StateT> {
         role={didImageFailToLoad ? 'img' : null}
         $didImageFailToLoad={didImageFailToLoad}
         $size={size}
+        data-baseweb="avatar"
         {...rootProps}
       >
         {didImageFailToLoad ? (
diff --git a/src/block/block.js b/src/block/block.js
index 23697ea30..76053e6a1 100644
--- a/src/block/block.js
+++ b/src/block/block.js
@@ -135,6 +135,7 @@ function Block({
       $top={top}
       $right={right}
       $bottom={bottom}
+      data-baseweb="block"
       {...other}
       {...baseBlockProps}
     >
diff --git a/src/breadcrumbs/breadcrumbs.js b/src/breadcrumbs/breadcrumbs.js
index dae39b018..1700b955e 100644
--- a/src/breadcrumbs/breadcrumbs.js
+++ b/src/breadcrumbs/breadcrumbs.js
@@ -45,6 +45,7 @@ export function BreadcrumbsRoot(props: {|...BreadcrumbsPropsT, ...LocaleT|}) {
       aria-label={
         props.ariaLabel || (props.locale ? props.locale.ariaLabel : '')
       }
+      data-baseweb="breadcrumbs"
       {...baseRootProps}
     >
       {childrenWithSeparators}
diff --git a/src/button-group/button-group.js b/src/button-group/button-group.js
index a952ca46c..d80804364 100644
--- a/src/button-group/button-group.js
+++ b/src/button-group/button-group.js
@@ -61,6 +61,7 @@ export function ButtonGroupRoot(props: {|...PropsT, ...LocaleT|}) {
       aria-label={
         props.ariaLabel || (props.locale ? props.locale.ariaLabel : '')
       }
+      data-baseweb="button-group"
       {...rootProps}
     >
       {React.Children.map(props.children, (child, index) => {
diff --git a/src/button/button.js b/src/button/button.js
index e12080c0d..97d909217 100644
--- a/src/button/button.js
+++ b/src/button/button.js
@@ -70,6 +70,7 @@ export default class Button extends React.Component<ButtonPropsT> {
     const sharedProps = getSharedProps(this.props);
     return (
       <BaseButton
+        data-baseweb="button"
         {...sharedProps}
         {...restProps}
         {...baseButtonProps}
diff --git a/src/card/card.js b/src/card/card.js
index c6a7785c7..c38c3645d 100644
--- a/src/card/card.js
+++ b/src/card/card.js
@@ -57,7 +57,11 @@ function Card(props: CardsPropsT) {
 
   const $hasThumbnail = hasThumbnail(props);
   return (
-    <Root {...otherProps} {...getOverrideProps(RootOverride)}>
+    <Root
+      data-baseweb="card"
+      {...otherProps}
+      {...getOverrideProps(RootOverride)}
+    >
       {headerImage && (
         <HeaderImage
           src={headerImage}
diff --git a/src/checkbox/checkbox.js b/src/checkbox/checkbox.js
index 8e9163632..e41c4507e 100644
--- a/src/checkbox/checkbox.js
+++ b/src/checkbox/checkbox.js
@@ -152,6 +152,7 @@ class StatelessCheckbox extends React.Component<PropsT, StatelessStateT> {
     );
     return (
       <Root
+        data-baseweb="checkbox"
         $labelPlacement={labelPlacement}
         {...sharedProps}
         {...mouseEvents}
diff --git a/src/datepicker/calendar.js b/src/datepicker/calendar.js
index 84889dfb2..34d55342c 100644
--- a/src/datepicker/calendar.js
+++ b/src/datepicker/calendar.js
@@ -450,6 +450,7 @@ export default class Calendar extends React.Component<
 
     return (
       <Root
+        data-baseweb="calendar"
         $ref={root => {
           this.root = root;
         }}
diff --git a/src/dnd-list/list.js b/src/dnd-list/list.js
index 5b38ab787..35ed525d0 100644
--- a/src/dnd-list/list.js
+++ b/src/dnd-list/list.js
@@ -51,7 +51,7 @@ class StatelessList extends React.Component<ListPropsT> {
     const [Label, labelProps] = getOverrides(LabelOverride, StyledLabel);
     const isRemovable = this.props.removable || false;
     return (
-      <Root $isRemovable={isRemovable} {...rootProps}>
+      <Root $isRemovable={isRemovable} data-baseweb="dnd-list" {...rootProps}>
         <MovableList
           values={items}
           onChange={onChange}
diff --git a/src/file-uploader/file-uploader.js b/src/file-uploader/file-uploader.js
index fbddbb959..3647a7e38 100644
--- a/src/file-uploader/file-uploader.js
+++ b/src/file-uploader/file-uploader.js
@@ -81,7 +81,11 @@ function FileUploader(props: PropsT) {
         return (
           <LocaleContext.Consumer>
             {locale => (
-              <Root {...prefixedStyledProps} {...rootProps}>
+              <Root
+                data-baseweb="file-uploader"
+                {...prefixedStyledProps}
+                {...rootProps}
+              >
                 <FileDragAndDrop
                   {...getRootProps(getRootPropsArgs)}
                   {...prefixedStyledProps}
diff --git a/src/form-control/form-control.js b/src/form-control/form-control.js
index b7afd3563..6f0ec3a17 100644
--- a/src/form-control/form-control.js
+++ b/src/form-control/form-control.js
@@ -59,6 +59,7 @@ export default class FormControl extends React.Component<FormControlPropsT> {
       <React.Fragment>
         {label && (
           <Label
+            data-baseweb="form-control-label"
             htmlFor={onlyChildProps.id}
             {...sharedProps}
             {...getOverrideProps(LabelOverride)}
@@ -67,6 +68,7 @@ export default class FormControl extends React.Component<FormControlPropsT> {
           </Label>
         )}
         <ControlContainer
+          data-baseweb="form-control-container"
           {...sharedProps}
           {...getOverrideProps(ControlContainerOverride)}
         >
diff --git a/src/header-navigation/header-navigation.js b/src/header-navigation/header-navigation.js
index 16063ea2f..49fd94b8f 100644
--- a/src/header-navigation/header-navigation.js
+++ b/src/header-navigation/header-navigation.js
@@ -26,7 +26,14 @@ class HeaderNavigation extends React.Component<PropsT, {}> {
   render() {
     const {overrides, ...restProps} = this.props;
     const [Root, rootProps] = getOverrides(overrides.Root, StyledRoot);
-    return <Root role="navigation" {...restProps} {...rootProps} />;
+    return (
+      <Root
+        data-baseweb="header-navigation"
+        role="navigation"
+        {...restProps}
+        {...rootProps}
+      />
+    );
   }
 }
 
diff --git a/src/icon/icon.js b/src/icon/icon.js
index c9dd1e1e9..e46b0559c 100644
--- a/src/icon/icon.js
+++ b/src/icon/icon.js
@@ -21,7 +21,7 @@ export default function Icon(props: IconPropsT) {
   const [Svg, overrideProps] = getOverrides(overrides.Svg, StyledSvg);
 
   return (
-    <Svg {...restProps} {...sharedProps} {...overrideProps}>
+    <Svg data-baseweb="icon" {...restProps} {...sharedProps} {...overrideProps}>
       {title ? <title>{title}</title> : null}
       {children}
     </Svg>
diff --git a/src/input/base-input.js b/src/input/base-input.js
index 6ac80ac37..cd83fc0e5 100644
--- a/src/input/base-input.js
+++ b/src/input/base-input.js
@@ -132,7 +132,11 @@ class BaseInput<T: EventTarget> extends React.Component<
     const [Before, beforeProps] = getOverrides(BeforeOverride, NullComponent);
     const [After, afterProps] = getOverrides(AfterOverride, NullComponent);
     return (
-      <InputContainer {...sharedProps} {...inputContainerProps}>
+      <InputContainer
+        data-baseweb={this.props['data-baseweb'] || 'base-input'}
+        {...sharedProps}
+        {...inputContainerProps}
+      >
         <Before {...sharedProps} {...beforeProps} />
         <Input {...sharedProps} {...this.getInputProps()} {...inputProps}>
           {type === CUSTOM_INPUT_TYPE.textarea ? value : null}
diff --git a/src/input/input.js b/src/input/input.js
index d40fad9c2..270827ff9 100644
--- a/src/input/input.js
+++ b/src/input/input.js
@@ -71,7 +71,7 @@ class Input extends React.Component<InputPropsT, InternalStateT> {
     const sharedProps = getSharedProps(this.props, this.state);
 
     return (
-      <Root {...sharedProps} {...rootProps}>
+      <Root data-baseweb="input" {...sharedProps} {...rootProps}>
         {startEnhancer && (
           <StartEnhancer
             {...sharedProps}
diff --git a/src/input/types.js b/src/input/types.js
index c82f06297..d1f091276 100644
--- a/src/input/types.js
+++ b/src/input/types.js
@@ -80,6 +80,7 @@ export type BaseInputPropsT<T> = {
   error: boolean,
   /** Id attribute value to be added to the input element and as a label's for attribute value. */
   id: string,
+  'data-baseweb'?: string,
   $ref: {current: ?HTMLInputElement},
   /** A ref to access an input element. */
   inputRef: {current: ?HTMLInputElement},
diff --git a/src/link/index.js b/src/link/index.js
index 6f8225fa5..21c31036f 100644
--- a/src/link/index.js
+++ b/src/link/index.js
@@ -6,4 +6,8 @@ LICENSE file in the root directory of this source tree.
 */
 // @flow
 // Styled elements
-export {Link as StyledLink} from './styled-components.js';
+import * as React from 'react';
+import {Link} from './styled-components.js';
+
+//$FlowFixMe
+export const StyledLink = props => <Link data-baseweb="link" {...props} />;
diff --git a/src/menu/menu.js b/src/menu/menu.js
index e7b2c492f..55d39b495 100644
--- a/src/menu/menu.js
+++ b/src/menu/menu.js
@@ -36,6 +36,7 @@ export default function Menu(props: StatelessMenuPropsT) {
       onFocus={focusMenu}
       onBlur={unfocusMenu}
       tabIndex={0}
+      data-baseweb="menu"
       {...listProps}
     >
       {items.map((item, index) => {
diff --git a/src/modal/modal.js b/src/modal/modal.js
index 18219a542..5c0b9ecdf 100644
--- a/src/modal/modal.js
+++ b/src/modal/modal.js
@@ -279,6 +279,7 @@ class Modal extends React.Component<ModalPropsT, ModalStateT> {
       <LocaleContext.Consumer>
         {locale => (
           <Root
+            data-baseweb="modal"
             $ref={this.getRef('Root')}
             {...sharedProps}
             {...getOverrideProps(RootOverride)}
diff --git a/src/notification/notification.js b/src/notification/notification.js
index 4618d1614..441a328d1 100644
--- a/src/notification/notification.js
+++ b/src/notification/notification.js
@@ -17,6 +17,6 @@ export default class Notification extends React.Component<ToastPropsT> {
   };
 
   render() {
-    return <Toast {...this.props} />;
+    return <Toast data-baseweb="notification" {...this.props} />;
   }
 }
diff --git a/src/pagination/pagination.js b/src/pagination/pagination.js
index 447dea0dc..10d09c59b 100644
--- a/src/pagination/pagination.js
+++ b/src/pagination/pagination.js
@@ -132,7 +132,7 @@ export default class Pagination extends React.PureComponent<
     return (
       <LocaleContext.Consumer>
         {locale => (
-          <Root {...rootProps}>
+          <Root data-baseweb="pagination" {...rootProps}>
             <Button
               onClick={this.onPrevClick}
               startEnhancer={() => <ChevronLeft title={''} size={24} />}
diff --git a/src/popover/popover.js b/src/popover/popover.js
index 7c68551ce..145b91e42 100644
--- a/src/popover/popover.js
+++ b/src/popover/popover.js
@@ -473,6 +473,7 @@ class Popover extends React.Component<PopoverPropsT, PopoverPrivateStateT> {
       <Body
         key="popover-body"
         $ref={this.popperRef}
+        data-baseweb={this.props['data-baseweb'] || 'popover'}
         {...bodyProps}
         {...sharedProps}
         {...getOverrideProps(BodyOverride)}
diff --git a/src/popover/types.js b/src/popover/types.js
index 0d24485bf..be9a60fb1 100644
--- a/src/popover/types.js
+++ b/src/popover/types.js
@@ -56,6 +56,7 @@ export type BasePopoverPropsT = {
    * See the A11Y section at the bottom of this document for more details.
    */
   accessibilityType?: AccessibilityTypeT,
+  'data-baseweb'?: string,
   id?: string,
   /** If true, popover element will not avoid element boundaries. */
   ignoreBoundary?: boolean,
diff --git a/src/progress-bar/progressbar.js b/src/progress-bar/progressbar.js
index 93d10a15b..3a8f60890 100644
--- a/src/progress-bar/progressbar.js
+++ b/src/progress-bar/progressbar.js
@@ -46,7 +46,12 @@ class ProgressBar extends React.Component<ProgressBarPropsT> {
       $successValue: successValue,
     };
     return (
-      <Root role="progressbar" {...sharedProps} {...rootProps}>
+      <Root
+        data-baseweb="progress-bar"
+        role="progressbar"
+        {...sharedProps}
+        {...rootProps}
+      >
         <Bar {...sharedProps} {...barProps}>
           <BarProgress {...sharedProps} {...barProgressProps} />
         </Bar>
diff --git a/src/progress-steps/progress-steps.js b/src/progress-steps/progress-steps.js
index d28fd8aeb..a6aa9b999 100644
--- a/src/progress-steps/progress-steps.js
+++ b/src/progress-steps/progress-steps.js
@@ -33,7 +33,11 @@ function ProgressSteps({
     );
   });
 
-  return <Root {...rootProps}>{modifiedChildren}</Root>;
+  return (
+    <Root data-baseweb="progress-steps" {...rootProps}>
+      {modifiedChildren}
+    </Root>
+  );
 }
 
 ProgressSteps.defaultProps = {
diff --git a/src/radio/radio.js b/src/radio/radio.js
index ce7dded66..9b0908486 100644
--- a/src/radio/radio.js
+++ b/src/radio/radio.js
@@ -129,6 +129,7 @@ class Radio extends React.Component<RadioPropsT, RadioStateT> {
 
     return (
       <Root
+        data-baseweb="radio"
         onMouseEnter={this.onMouseEnter}
         onMouseLeave={this.onMouseLeave}
         onMouseDown={this.onMouseDown}
diff --git a/src/rating/emoticon-rating.js b/src/rating/emoticon-rating.js
index 2d70aec41..37a33a69a 100644
--- a/src/rating/emoticon-rating.js
+++ b/src/rating/emoticon-rating.js
@@ -82,6 +82,7 @@ class EmoticonRating extends React.Component<
 
     return (
       <Root
+        data-baseweb="emoticon-rating"
         tabIndex={0}
         role="radiogroup"
         onBlur={() => this.updatePreview(undefined)}
diff --git a/src/rating/star-rating.js b/src/rating/star-rating.js
index 07e8a4ebb..8a67d7463 100644
--- a/src/rating/star-rating.js
+++ b/src/rating/star-rating.js
@@ -77,6 +77,7 @@ class StarRating extends React.Component<StarRatingPropsT, RatingStateT> {
 
     return (
       <Root
+        data-baseweb="star-rating"
         tabIndex={0}
         role="radiogroup"
         onBlur={() => this.updatePreview(undefined)}
diff --git a/src/select/select.js b/src/select/select.js
index 0ab680e14..de1a30151 100644
--- a/src/select/select.js
+++ b/src/select/select.js
@@ -867,7 +867,7 @@ class Select extends React.Component<PropsT, SelectStateT> {
             }}
             placement={PLACEMENT.bottom}
           >
-            <Root {...sharedProps} {...rootProps}>
+            <Root data-baseweb="select" {...sharedProps} {...rootProps}>
               <ControlContainer
                 onKeyDown={this.handleKeyDown}
                 onClick={this.handleClick}
diff --git a/src/slider/slider.js b/src/slider/slider.js
index 47914ed1a..e5f9d9968 100644
--- a/src/slider/slider.js
+++ b/src/slider/slider.js
@@ -78,7 +78,7 @@ class Slider extends React.Component<PropsT> {
     );
     const sharedProps = this.getSharedProps();
     return (
-      <Root {...sharedProps} {...rootProps}>
+      <Root data-baseweb="slider" {...sharedProps} {...rootProps}>
         <Range
           step={step}
           min={min}
diff --git a/src/spinner/spinner.js b/src/spinner/spinner.js
index 905c4876c..852ee2b3f 100644
--- a/src/spinner/spinner.js
+++ b/src/spinner/spinner.js
@@ -39,6 +39,7 @@ class Spinner extends React.Component<SpinnerPropsT> {
 
     return (
       <Icon
+        data-baseweb="spinner"
         title="Spinner"
         viewBox="3 3 18 18"
         {...this.props}
diff --git a/src/table/index.js b/src/table/index.js
index f0657bcdb..642585d63 100644
--- a/src/table/index.js
+++ b/src/table/index.js
@@ -5,12 +5,21 @@ This source code is licensed under the MIT license found in the
 LICENSE file in the root directory of this source tree.
 */
 // @flow
+import React from 'react';
+
 export {default as SortableHeadCell} from './sortable-head-cell.js';
 export {default as Table} from './table.js';
 export {default as Filter} from './filter.js';
 // Styled elements
+
+import {StyledTable as Table} from './styled-components.js';
+
+//$FlowFixMe
+export const StyledTable = props => (
+  <Table data-baseweb="table-custom" {...props} />
+);
+
 export {
-  StyledTable,
   StyledFilterButton,
   StyledFilterContent,
   StyledFilterHeading,
diff --git a/src/table/table.js b/src/table/table.js
index 966066aba..463d33cd4 100644
--- a/src/table/table.js
+++ b/src/table/table.js
@@ -29,6 +29,7 @@ export default class Table extends React.Component<TablePropsT> {
   render() {
     return (
       <StyledTable
+        data-baseweb="table"
         role="grid"
         aria-colcount={this.props.columns.length}
         aria-rowcount={this.props.data.length}
diff --git a/src/tabs/tabs.js b/src/tabs/tabs.js
index 77843979c..54ae63d2f 100644
--- a/src/tabs/tabs.js
+++ b/src/tabs/tabs.js
@@ -107,7 +107,7 @@ export default class Tabs extends React.Component<TabsPropsT> {
     const [TabBar, tabBarProps] = getOverrides(TabBarOverride, StyledTabBar);
 
     return (
-      <Root {...sharedProps} {...rootProps}>
+      <Root data-baseweb="tabs" {...sharedProps} {...rootProps}>
         <TabBar role="tablist" {...sharedProps} {...tabBarProps}>
           {this.getTabs()}
         </TabBar>
diff --git a/src/tag/tag.js b/src/tag/tag.js
index db68f8e48..eaaf5b901 100644
--- a/src/tag/tag.js
+++ b/src/tag/tag.js
@@ -102,6 +102,7 @@ class Tag extends React.Component<PropsT, {}> {
     };
     return (
       <Root
+        data-baseweb="tag"
         aria-label="button"
         role="button"
         tabIndex={clickable ? '0' : null}
diff --git a/src/template-component/component.js b/src/template-component/component.js
index 2308df02b..9f61bc026 100644
--- a/src/template-component/component.js
+++ b/src/template-component/component.js
@@ -34,6 +34,7 @@ class Component extends React.Component<ComponentPropsT> {
     return (
       //$FlowFixMe
       <Root
+        data-baseweb="component"
         onClick={this.props.onClick}
         {...sharedProps}
         {...getOverrideProps(RootOverride)}
diff --git a/src/textarea/textarea.js b/src/textarea/textarea.js
index 52c082042..f71aa84d0 100644
--- a/src/textarea/textarea.js
+++ b/src/textarea/textarea.js
@@ -45,6 +45,7 @@ class Textarea extends React.Component<TextareaPropsT> {
     );
     return (
       <BaseInput
+        data-baseweb="textarea"
         {...this.props}
         type={CUSTOM_INPUT_TYPE.textarea}
         overrides={overrides}
diff --git a/src/toast/toast.js b/src/toast/toast.js
index 5a3b60b7f..ce2108784 100644
--- a/src/toast/toast.js
+++ b/src/toast/toast.js
@@ -161,6 +161,7 @@ class Toast extends React.Component<ToastPropsT, ToastPrivateStateT> {
           <Body
             tabIndex={0}
             role="alert"
+            data-baseweb={this.props['data-baseweb'] || 'toast'}
             {...sharedProps}
             {...bodyProps}
             // the properties below have to go after overrides
diff --git a/src/toast/toaster.js b/src/toast/toaster.js
index 14e713d1e..03092d38d 100644
--- a/src/toast/toaster.js
+++ b/src/toast/toaster.js
@@ -170,7 +170,7 @@ export class ToasterContainer extends React.Component<
     }
 
     const root = (
-      <Root {...sharedProps} {...rootProps}>
+      <Root data-baseweb="toaster" {...sharedProps} {...rootProps}>
         {toastsToRender}
       </Root>
     );
diff --git a/src/toast/types.js b/src/toast/types.js
index 5c09d213d..3cf7b9190 100644
--- a/src/toast/types.js
+++ b/src/toast/types.js
@@ -74,6 +74,7 @@ export type ToastPropsT = {
   onFocus: (e: Event) => void,
   onMouseEnter: (e: Event) => void,
   onMouseLeave: (e: Event) => void,
+  'data-baseweb'?: string,
   overrides: OverridesT,
   key: React.Key,
 };
diff --git a/src/tooltip/tooltip.js b/src/tooltip/tooltip.js
index 1c478ea54..86da0c594 100644
--- a/src/tooltip/tooltip.js
+++ b/src/tooltip/tooltip.js
@@ -31,7 +31,9 @@ class Tooltip extends React.Component<TooltipPropsT> {
       },
       this.props.overrides,
     );
-    return <Popover {...this.props} overrides={overrides} />;
+    return (
+      <Popover data-baseweb="tooltip" {...this.props} overrides={overrides} />
+    );
   }
 }
 
diff --git a/src/typography/index.js b/src/typography/index.js
index 822a6cc9f..31ef4a60b 100644
--- a/src/typography/index.js
+++ b/src/typography/index.js
@@ -13,6 +13,7 @@ import type {BlockPropsT} from '../block/types.js';
 // Captions - aka Caption, CaptionLabel
 export const Caption1 = (props: BlockPropsT) => (
   <Block
+    data-baseweb="typo-caption1"
     {...props}
     font={props.font || 'font200'}
     color={props.color || 'colorSecondary'}
@@ -21,6 +22,7 @@ export const Caption1 = (props: BlockPropsT) => (
 
 export const Caption2 = (props: BlockPropsT) => (
   <Block
+    data-baseweb="typo-caption2"
     {...props}
     font={props.font || 'font250'}
     color={props.color || 'colorSecondary'}
@@ -30,6 +32,7 @@ export const Caption2 = (props: BlockPropsT) => (
 // Display
 export const Display = (props: BlockPropsT) => (
   <Block
+    data-baseweb="typo-display"
     {...props}
     font={props.font || 'font1100'}
     color={props.color || 'colorPrimary'}
@@ -41,6 +44,7 @@ export function H1(props: BlockPropsT) {
   const as = props.as || 'h1';
   return (
     <Block
+      data-baseweb="typo-h1"
       as={as}
       {...props}
       font={props.font || 'font1000'}
@@ -53,6 +57,7 @@ export function H2(props: BlockPropsT) {
   const as = props.as || 'h2';
   return (
     <Block
+      data-baseweb="typo-h2"
       as={as}
       {...props}
       font={props.font || 'font900'}
@@ -65,6 +70,7 @@ export function H3(props: BlockPropsT) {
   const as = props.as || 'h3';
   return (
     <Block
+      data-baseweb="typo-h3"
       as={as}
       {...props}
       font={props.font || 'font800'}
@@ -77,6 +83,7 @@ export function H4(props: BlockPropsT) {
   const as = props.as || 'h4';
   return (
     <Block
+      data-baseweb="typo-h4"
       as={as}
       {...props}
       font={props.font || 'font700'}
@@ -89,6 +96,7 @@ export function H5(props: BlockPropsT) {
   const as = props.as || 'h5';
   return (
     <Block
+      data-baseweb="typo-h5"
       as={as}
       {...props}
       font={props.font || 'font600'}
@@ -101,6 +109,7 @@ export function H6(props: BlockPropsT) {
   const as = props.as || 'h6';
   return (
     <Block
+      data-baseweb="typo-h6"
       as={as}
       {...props}
       font={props.font || 'font500'}
@@ -112,6 +121,7 @@ export function H6(props: BlockPropsT) {
 // Labels - aka Label1, Label2
 export const Label1 = (props: BlockPropsT) => (
   <Block
+    data-baseweb="typo-label1"
     {...props}
     font={props.font || 'font350'}
     color={props.color || 'colorPrimary'}
@@ -120,6 +130,7 @@ export const Label1 = (props: BlockPropsT) => (
 
 export const Label2 = (props: BlockPropsT) => (
   <Block
+    data-baseweb="typo-label2"
     {...props}
     font={props.font || 'font450'}
     color={props.color || 'colorPrimary'}
@@ -131,6 +142,7 @@ export function Paragraph1(props: BlockPropsT) {
   const as = props.as || 'p';
   return (
     <Block
+      data-baseweb="typo-p1"
       as={as}
       {...props}
       font={props.font || 'font300'}
@@ -143,6 +155,7 @@ export function Paragraph2(props: BlockPropsT) {
   const as = props.as || 'p';
   return (
     <Block
+      data-baseweb="typo-p2"
       as={as}
       {...props}
       font={props.font || 'font400'}


Test patch:
diff --git a/src/breadcrumbs/__tests__/__snapshots__/breadcrumbs.test.js.snap b/src/breadcrumbs/__tests__/__snapshots__/breadcrumbs.test.js.snap
index b9fd08ad2..831330c16 100644
--- a/src/breadcrumbs/__tests__/__snapshots__/breadcrumbs.test.js.snap
+++ b/src/breadcrumbs/__tests__/__snapshots__/breadcrumbs.test.js.snap
@@ -3,22 +3,23 @@
 exports[`Breadcrumbs displays separators in correct positions 1`] = `
 <MockStyledComponent
   aria-label=""
+  data-baseweb="breadcrumbs"
 >
-  <MockStyledComponent
+  <StyledLink
     href="#"
   >
     Parent Page
-  </MockStyledComponent>
+  </StyledLink>
   <MockStyledComponent
     key="separator-0"
   >
     <MockStyledComponent />
   </MockStyledComponent>
-  <MockStyledComponent
+  <StyledLink
     href="#"
   >
     Sub-Parent Page
-  </MockStyledComponent>
+  </StyledLink>
   <MockStyledComponent
     key="separator-1"
   >
diff --git a/src/header-navigation/__tests__/__snapshots__/header-navigation.test.js.snap b/src/header-navigation/__tests__/__snapshots__/header-navigation.test.js.snap
index 28bb9dba2..c486e287d 100644
--- a/src/header-navigation/__tests__/__snapshots__/header-navigation.test.js.snap
+++ b/src/header-navigation/__tests__/__snapshots__/header-navigation.test.js.snap
@@ -5,9 +5,11 @@ exports[`Stateless header navigation should render component: Component has corr
   overrides={Object {}}
 >
   <MockStyledComponent
+    data-baseweb="header-navigation"
     role="navigation"
   >
     <nav
+      data-baseweb="header-navigation"
       role="navigation"
       styled-component="true"
     >
diff --git a/src/icon/__tests__/__snapshots__/icon.test.js.snap b/src/icon/__tests__/__snapshots__/icon.test.js.snap
index 4df1e7752..8b3b1df0b 100644
--- a/src/icon/__tests__/__snapshots__/icon.test.js.snap
+++ b/src/icon/__tests__/__snapshots__/icon.test.js.snap
@@ -2,6 +2,7 @@
 
 exports[`Icon renders an icon with viewbox and title: Icon basic render 1`] = `
 <MockStyledComponent
+  data-baseweb="icon"
   viewBox="0 0 23px 23px"
 >
   <title>
diff --git a/src/input/__tests__/__snapshots__/input.test.js.snap b/src/input/__tests__/__snapshots__/input.test.js.snap
index 2f0ddba48..ebb3d4a28 100644
--- a/src/input/__tests__/__snapshots__/input.test.js.snap
+++ b/src/input/__tests__/__snapshots__/input.test.js.snap
@@ -78,6 +78,7 @@ Object {
       $size="default"
     />,
   ],
+  "data-baseweb": "base-input",
 }
 `;
 
@@ -135,6 +136,7 @@ Object {
       $size="default"
     />,
   ],
+  "data-baseweb": "base-input",
 }
 `;
 
@@ -192,5 +194,6 @@ Object {
       $size="default"
     />,
   ],
+  "data-baseweb": "base-input",
 }
 `;
diff --git a/src/modal/__tests__/__snapshots__/modal.test.js.snap b/src/modal/__tests__/__snapshots__/modal.test.js.snap
index ca6daa467..5201be555 100644
--- a/src/modal/__tests__/__snapshots__/modal.test.js.snap
+++ b/src/modal/__tests__/__snapshots__/modal.test.js.snap
@@ -25,6 +25,7 @@ exports[`Modal renders portal when open: Rendered Modal 1`] = `
       }
       $role="dialog"
       $size="default"
+      data-baseweb="modal"
     >
       <Portal>
         <MockStyledComponent
diff --git a/src/popover/__tests__/__snapshots__/popover.test.js.snap b/src/popover/__tests__/__snapshots__/popover.test.js.snap
index 225bbba29..996725647 100644
--- a/src/popover/__tests__/__snapshots__/popover.test.js.snap
+++ b/src/popover/__tests__/__snapshots__/popover.test.js.snap
@@ -37,6 +37,7 @@ Object {
     "current": null,
   },
   "$showArrow": true,
+  "data-baseweb": "popover",
   "id": "bui-mock-id",
   "onMouseEnter": [Function],
   "onMouseLeave": [Function],
diff --git a/src/popover/__tests__/popover.test.js b/src/popover/__tests__/popover.test.js
index 8178dc38c..00f794b0e 100644
--- a/src/popover/__tests__/popover.test.js
+++ b/src/popover/__tests__/popover.test.js
@@ -86,7 +86,7 @@ describe('Popover', () => {
 
     // Portal should have the popover body and content
     let popoverBody = portal.childAt(0);
-    expect(popoverBody).toMatchSelector('MockStyledComponent');
+    expect(popoverBody).toMatchSelector('[data-baseweb="popover"]');
     expect(popoverBody).toHaveProp({
       $showArrow: false,
       $placement: 'auto',
diff --git a/src/progress-bar/__tests__/__snapshots__/progressbar.test.js.snap b/src/progress-bar/__tests__/__snapshots__/progressbar.test.js.snap
index c539c4014..8ecdcc18c 100644
--- a/src/progress-bar/__tests__/__snapshots__/progressbar.test.js.snap
+++ b/src/progress-bar/__tests__/__snapshots__/progressbar.test.js.snap
@@ -11,9 +11,11 @@ exports[`Stateless progress bar should render component: Component has correct r
   <MockStyledComponent
     $successValue={100}
     $value={75}
+    data-baseweb="progress-bar"
     role="progressbar"
   >
     <div
+      data-baseweb="progress-bar"
       role="progressbar"
       styled-component="true"
     >
diff --git a/src/select/__tests__/__snapshots__/select.test.js.snap b/src/select/__tests__/__snapshots__/select.test.js.snap
index bcbfa682b..d98f8dcda 100644
--- a/src/select/__tests__/__snapshots__/select.test.js.snap
+++ b/src/select/__tests__/__snapshots__/select.test.js.snap
@@ -89,6 +89,7 @@ exports[`Select component renders component in search mode and false for multipl
       aria-controls={null}
       aria-expanded="false"
       aria-haspopup="true"
+      data-baseweb="select"
       key="popover-anchor"
       onClick={[Function]}
     >
@@ -96,6 +97,7 @@ exports[`Select component renders component in search mode and false for multipl
         aria-controls={null}
         aria-expanded="false"
         aria-haspopup="true"
+        data-baseweb="select"
         onClick={[Function]}
         styled-component="true"
       >
@@ -182,9 +184,11 @@ exports[`Select component renders component in search mode and false for multipl
                   $searchable={true}
                   $size={16}
                   $type="search"
+                  data-baseweb="icon"
                   viewBox="0 0 24 24"
                 >
                   <svg
+                    data-baseweb="icon"
                     styled-component="true"
                     viewBox="0 0 24 24"
                   >
@@ -466,6 +470,7 @@ exports[`Select component renders component in search mode and true for multiple
       aria-controls={null}
       aria-expanded="false"
       aria-haspopup="true"
+      data-baseweb="select"
       key="popover-anchor"
       onClick={[Function]}
     >
@@ -473,6 +478,7 @@ exports[`Select component renders component in search mode and true for multiple
         aria-controls={null}
         aria-expanded="false"
         aria-haspopup="true"
+        data-baseweb="select"
         onClick={[Function]}
         styled-component="true"
       >
@@ -559,9 +565,11 @@ exports[`Select component renders component in search mode and true for multiple
                   $searchable={true}
                   $size={16}
                   $type="search"
+                  data-baseweb="icon"
                   viewBox="0 0 24 24"
                 >
                   <svg
+                    data-baseweb="icon"
                     styled-component="true"
                     viewBox="0 0 24 24"
                   >
@@ -843,6 +851,7 @@ exports[`Select component renders component in select mode and false for multipl
       aria-controls={null}
       aria-expanded="false"
       aria-haspopup="true"
+      data-baseweb="select"
       key="popover-anchor"
       onClick={[Function]}
     >
@@ -850,6 +859,7 @@ exports[`Select component renders component in select mode and false for multipl
         aria-controls={null}
         aria-expanded="false"
         aria-haspopup="true"
+        data-baseweb="select"
         onClick={[Function]}
         styled-component="true"
       >
@@ -1104,9 +1114,11 @@ exports[`Select component renders component in select mode and false for multipl
                       $searchable={true}
                       $size={16}
                       $type="select"
+                      data-baseweb="icon"
                       viewBox="0 0 24 24"
                     >
                       <svg
+                        data-baseweb="icon"
                         styled-component="true"
                         viewBox="0 0 24 24"
                       >
@@ -1219,6 +1231,7 @@ exports[`Select component renders component in select mode and true for multiple
       aria-controls={null}
       aria-expanded="false"
       aria-haspopup="true"
+      data-baseweb="select"
       key="popover-anchor"
       onClick={[Function]}
     >
@@ -1226,6 +1239,7 @@ exports[`Select component renders component in select mode and true for multiple
         aria-controls={null}
         aria-expanded="false"
         aria-haspopup="true"
+        data-baseweb="select"
         onClick={[Function]}
         styled-component="true"
       >
@@ -1480,9 +1494,11 @@ exports[`Select component renders component in select mode and true for multiple
                       $searchable={true}
                       $size={16}
                       $type="select"
+                      data-baseweb="icon"
                       viewBox="0 0 24 24"
                     >
                       <svg
+                        data-baseweb="icon"
                         styled-component="true"
                         viewBox="0 0 24 24"
                       >
diff --git a/src/table/__tests__/table.test.js b/src/table/__tests__/table.test.js
index 20a2e6fa4..95a769d75 100644
--- a/src/table/__tests__/table.test.js
+++ b/src/table/__tests__/table.test.js
@@ -11,7 +11,6 @@ import {mount, shallow} from 'enzyme';
 
 import {
   Table,
-  StyledTable,
   StyledHead,
   StyledHeadCell,
   StyledBody,
@@ -46,13 +45,11 @@ describe('Table', () => {
 
   it('applies correct aria attributes to table container', () => {
     const wrapper = mount(<Table columns={COLUMNS} data={DATA} />);
-    const container = wrapper.find(StyledTable);
-
-    expect(container.getDOMNode().getAttribute('role')).toBe('grid');
-    expect(container.getDOMNode().getAttribute('aria-colcount')).toBe(
+    expect(wrapper.getDOMNode().getAttribute('role')).toBe('grid');
+    expect(wrapper.getDOMNode().getAttribute('aria-colcount')).toBe(
       COLUMNS.length.toString(),
     );
-    expect(container.getDOMNode().getAttribute('aria-rowcount')).toBe(
+    expect(wrapper.getDOMNode().getAttribute('aria-rowcount')).toBe(
       DATA.length.toString(),
     );
   });
diff --git a/src/tabs/__tests__/__snapshots__/stateful-tabs.test.js.snap b/src/tabs/__tests__/__snapshots__/stateful-tabs.test.js.snap
index 6dcb41ac4..8414ac57a 100644
--- a/src/tabs/__tests__/__snapshots__/stateful-tabs.test.js.snap
+++ b/src/tabs/__tests__/__snapshots__/stateful-tabs.test.js.snap
@@ -29,8 +29,10 @@ exports[`StatefulTabs basic render with initial state: Stateful tabs render corr
       <MockStyledComponent
         $disabled={false}
         $orientation="horizontal"
+        data-baseweb="tabs"
       >
         <div
+          data-baseweb="tabs"
           styled-component="true"
         >
           <MockStyledComponent
@@ -227,8 +229,10 @@ exports[`StatefulTabs basic render: Stateful tabs render correctly 1`] = `
       <MockStyledComponent
         $disabled={false}
         $orientation="horizontal"
+        data-baseweb="tabs"
       >
         <div
+          data-baseweb="tabs"
           styled-component="true"
         >
           <MockStyledComponent
diff --git a/src/tag/__tests__/__snapshots__/tag.test.js.snap b/src/tag/__tests__/__snapshots__/tag.test.js.snap
index f2cece184..f8f2ee910 100644
--- a/src/tag/__tests__/__snapshots__/tag.test.js.snap
+++ b/src/tag/__tests__/__snapshots__/tag.test.js.snap
@@ -23,6 +23,7 @@ exports[`Stateless tag should render component: Component has correct render 1`]
     $kind="primary"
     $variant="light"
     aria-label="button"
+    data-baseweb="tag"
     onClick={null}
     onKeyDown={[Function]}
     role="button"
@@ -30,6 +31,7 @@ exports[`Stateless tag should render component: Component has correct render 1`]
   >
     <span
       aria-label="button"
+      data-baseweb="tag"
       onClick={null}
       onKeyDown={[Function]}
       role="button"
diff --git a/src/textarea/__tests__/__snapshots__/textarea.test.js.snap b/src/textarea/__tests__/__snapshots__/textarea.test.js.snap
index 54856d196..a048b95f6 100644
--- a/src/textarea/__tests__/__snapshots__/textarea.test.js.snap
+++ b/src/textarea/__tests__/__snapshots__/textarea.test.js.snap
@@ -32,6 +32,7 @@ Object {
   "aria-label": null,
   "aria-labelledby": null,
   "autoFocus": false,
+  "data-baseweb": "textarea",
   "disabled": false,
   "error": false,
   "inputRef": Object {
@@ -68,6 +69,7 @@ Object {
   "aria-label": null,
   "aria-labelledby": null,
   "autoFocus": false,
+  "data-baseweb": "textarea",
   "disabled": false,
   "error": false,
   "inputRef": Object {
diff --git a/src/tooltip/__tests__/tooltip.test.js b/src/tooltip/__tests__/tooltip.test.js
index 53b35bab9..8454efd78 100644
--- a/src/tooltip/__tests__/tooltip.test.js
+++ b/src/tooltip/__tests__/tooltip.test.js
@@ -53,6 +53,7 @@ describe('Tooltip', () => {
     expect(component.props()).toEqual({
       ...baseDefaultProps,
       ...props,
+      'data-baseweb': 'tooltip',
       children: button,
       ignoreBoundary: false,
       overrides: {