-
+
+
-
+
\ No newline at end of file
diff --git a/src/lib/badge/badge.scss b/src/lib/badge/badge.scss
index 04e54f646..9d5aaf8dd 100644
--- a/src/lib/badge/badge.scss
+++ b/src/lib/badge/badge.scss
@@ -1,35 +1,121 @@
-@use '../theme';
-@use './mixins';
+@use './core' as *;
+@use '../core/styles/theme';
-@include mixins.core-styles;
+//
+// Host
+//
:host {
- @include mixins.host;
+ @include host;
}
:host([hidden]) {
display: none;
}
-:host([positioned]) {
- @include mixins.host-positioned;
+//
+// Base
+//
+
+.forge-badge {
+ @include tokens;
+}
+
+.forge-badge {
+ @include base;
+}
+
+//
+// Start/End slots
+//
+
+::slotted(:is([slot=start],[slot=end])) {
+ font-size: inherit;
}
+//
+// Hide
+//
+
+:host([hide]) {
+ .forge-badge {
+ @include hide;
+ }
+}
+
+//
+// Dot
+//
+
:host([dot]) {
- top: 0.5rem;
+ .forge-badge {
+ @include dot;
+ }
.forge-badge > slot {
display: none;
}
}
-:host([static]) {
- @include mixins.static;
+//
+// Themes
+//
+
+// General theme overrides
+@each $theme in [primary secondary tertiary success warning] {
+ :host([theme=#{$theme}]) {
+ .forge-badge {
+ @include override(background, theme.variable(#{$theme}-container), value);
+ @include override(color, theme.variable(on-#{$theme}-container), value);
+ }
+ }
+
+ :host([strong][theme=#{$theme}]) {
+ .forge-badge {
+ @include override(background, theme.variable($theme), value);
+ @include override(color, theme.variable(on-#{$theme}), value);
+ }
+ }
+}
+
+// Map both "error" and "danger" for backwards compatibility with legacy "danger" theme
+:host(:not([strong]):is([theme=error],[theme=danger])) {
+ .forge-badge {
+ @include override(background, theme.variable(error-container), value);
+ @include override(color, theme.variable(error), value);
+ }
+}
+:host([strong]:is([theme=error],[theme=danger])) {
+ .forge-badge {
+ @include override(background, theme.variable(error), value);
+ @include override(color, theme.variable(on-error), value);
+ }
}
-@include mixins.default-theme();
-@include mixins.theme('danger');
-@include mixins.theme('warning');
-@include mixins.theme('success');
-@include mixins.theme('info-primary');
-@include mixins.theme('info-secondary');
+// Map both "info" and "info-primary" for backwards compatibility with "info" theme
+:host(:not([strong]):is([theme=info],[theme=info-primary])) {
+ .forge-badge {
+ @include override(background, theme.variable(info-container), value);
+ @include override(color, theme.variable(on-info-container), value);
+ }
+}
+:host([strong]:is([theme=info],[theme=info-primary])) {
+ .forge-badge {
+ @include override(background, theme.variable(info), value);
+ @include override(color, theme.variable(on-info), value);
+ }
+}
+
+// Support "info-secondary" separately since it is not a core theme
+:host(:not([strong])[theme=info-secondary]) {
+ .forge-badge {
+ @include override(background, theme.variable(surface-container-low), value);
+ @include override(color, theme.variable(on-surface-container-low), value);
+ }
+}
+:host([strong][theme=info-secondary]) {
+ .forge-badge {
+ @include override(background, theme.variable(surface-inverse), value);
+ @include override(color, theme.variable(on-surface-inverse), value);
+ }
+}
diff --git a/src/lib/badge/badge.test.ts b/src/lib/badge/badge.test.ts
new file mode 100644
index 000000000..a451e7307
--- /dev/null
+++ b/src/lib/badge/badge.test.ts
@@ -0,0 +1,85 @@
+import { expect } from '@esm-bundle/chai';
+import { elementUpdated, fixture, html } from '@open-wc/testing';
+import { IBadgeComponent } from './badge';
+import { BadgeTheme, BADGE_CONSTANTS } from './badge-constants';
+
+import './badge';
+
+describe('Inline Message', () => {
+ it('should contain shadow root', async () => {
+ const el = await fixture(html`
Test`);
+ expect(el.shadowRoot).not.to.be.null;
+ });
+
+ it('should be accessible', async () => {
+ const el = await fixture(html`
Test`);
+ await expect(el).to.be.accessible();
+ });
+
+ it('should be accessible in all theme colors', async () => {
+ const el = await fixture
(html`Test`);
+
+ const themes: BadgeTheme[] = ['primary', 'secondary', 'tertiary', 'success', 'error', 'warning', 'info', 'info-secondary'];
+ for (const theme of themes) {
+ el.theme = theme;
+ await elementUpdated(el);
+ await expect(el).to.be.accessible();
+ }
+ });
+
+ it('should set theme attribute when theme property is set', async () => {
+ const el = await fixture(html``);
+ el.theme = 'error';
+ expect(el.getAttribute(BADGE_CONSTANTS.attributes.THEME)).to.equal('error');
+ });
+
+ it('should set theme property when theme attribute is set', async () => {
+ const el = await fixture(html``);
+ expect(el.theme).to.equal('error');
+ });
+
+ it('should get default theme when no theme attribute is set', async () => {
+ const el = await fixture(html``);
+ expect(el.theme).to.equal(BADGE_CONSTANTS.defaults.THEME);
+ });
+
+ it('should set dot attribute when dot property is set', async () => {
+ const el = await fixture(html``);
+ el.dot = true;
+ expect(el.hasAttribute(BADGE_CONSTANTS.attributes.DOT)).to.be.true;
+ });
+
+ it('should set dot property when dot attribute is set', async () => {
+ const el = await fixture(html``);
+ expect(el.dot).to.be.true;
+ });
+
+ it('should set strong attribute when strong property is set', async () => {
+ const el = await fixture(html``);
+ el.strong = true;
+ expect(el.hasAttribute(BADGE_CONSTANTS.attributes.STRONG)).to.be.true;
+ });
+
+ it('should set strong property when strong attribute is set', async () => {
+ const el = await fixture(html``);
+ expect(el.strong).to.be.true;
+ });
+
+ it('should set hide attribute when hide property is set', async () => {
+ const el = await fixture(html``);
+ el.hide = true;
+ expect(el.hasAttribute(BADGE_CONSTANTS.attributes.HIDE)).to.be.true;
+ });
+
+ it('should set hide property when hide attribute is set', async () => {
+ const el = await fixture(html``);
+ expect(el.hide).to.be.true;
+ });
+
+ it('should set transform when hide attribute is set', async () => {
+ const el = await fixture(html``);
+ const rootEl = el.shadowRoot?.querySelector(BADGE_CONSTANTS.selectors.ROOT) as HTMLElement;
+
+ expect(getComputedStyle(rootEl).transform).to.equal('matrix(0, 0, 0, 0, 0, 0)');
+ });
+});
diff --git a/src/lib/badge/badge.ts b/src/lib/badge/badge.ts
index 1534252e2..5e43108d9 100644
--- a/src/lib/badge/badge.ts
+++ b/src/lib/badge/badge.ts
@@ -1,15 +1,15 @@
-import { attachShadowTemplate, coerceBoolean, CustomElement, FoundationProperty } from '@tylertech/forge-core';
+import { attachShadowTemplate, coerceBoolean, CustomElement } from '@tylertech/forge-core';
import { BaseComponent, IBaseComponent } from '../core/base/base-component';
-import { BadgeAdapter } from './badge-adapter';
-import { BADGE_CONSTANTS } from './badge-constants';
-import { BadgeFoundation } from './badge-foundation';
+import { BadgeTheme, BADGE_CONSTANTS } from './badge-constants';
import template from './badge.html';
import styles from './badge.scss';
export interface IBadgeComponent extends IBaseComponent {
dot: boolean;
- open: boolean;
+ theme: BadgeTheme;
+ strong: boolean;
+ hide: boolean;
}
declare global {
@@ -19,49 +19,70 @@ declare global {
}
/**
- * The web component class behind the `` custom element.
- *
* @tag forge-badge
+ *
+ * @summary Badges are non-interactive components used to inform status, counts, or as a descriptive label.
+ *
+ * @property {boolean} dot - Controls whether the badge will be a small dot without any content visible.
+ * @property {BadgeTheme} theme - The theme of the badge.
+ * @property {boolean} strong - Controls whether the badge will have a stronger visual appearance.
+ * @property {boolean} hide - Controls whether the badge is visible.
+ *
+ * @attribute {boolean} dot - When present, the badge will be a small dot without any content visible.
+ * @attribute {BadgeTheme} theme - The theme of the badge.
+ * @attribute {boolean} strong - Controls whether the badge will have a stronger visual appearance.
+ * @attribute {boolean} hide - Controls whether the badge is visible.
+ *
+ * @cssproperty --forge-badge-background - The background color.
+ * @cssproperty --forge-badge-color - The text color.
+ * @cssproperty --forge-badge-shape - The shape radius.
+ * @cssproperty --forge-badge-padding-inline - The inline padding.
+ * @cssproperty --forge-badge-padding-block - The block padding.
+ * @cssproperty --forge-badge-border-width - The border width.
+ * @cssproperty --forge-badge-border-color - The border color.
+ * @cssproperty --forge-badge-border-style - The border style.
+ * @cssproperty --forge-badge-gap - The spacing between the content within the badge.
+ *
+ * @slot - Default content placed inside the badge.
+ * @slot start - Content placed before the default content.
+ * @slot end - Content placed after the default content.
*/
@CustomElement({
name: BADGE_CONSTANTS.elementName
})
export class BadgeComponent extends BaseComponent implements IBadgeComponent {
- public static get observedAttributes(): string[] {
- return [
- BADGE_CONSTANTS.attributes.DOT,
- BADGE_CONSTANTS.attributes.OPEN
- ];
- }
-
- private _foundation: BadgeFoundation;
-
constructor() {
super();
attachShadowTemplate(this, template, styles);
- this._foundation = new BadgeFoundation(new BadgeAdapter(this));
}
- public connectedCallback(): void {
- this._foundation.initialize();
+ public get dot(): boolean {
+ return this.hasAttribute(BADGE_CONSTANTS.attributes.DOT);
+ }
+ public set dot(value: boolean) {
+ this.toggleAttribute(BADGE_CONSTANTS.attributes.DOT, value);
}
- public attributeChangedCallback(name: string, oldValue: string, newValue: string): void {
- switch (name) {
- case BADGE_CONSTANTS.attributes.DOT:
- this.dot = coerceBoolean(newValue);
- break;
- case BADGE_CONSTANTS.attributes.OPEN:
- this.open = coerceBoolean(newValue);
- break;
- }
+ public get theme(): BadgeTheme {
+ return this.getAttribute(BADGE_CONSTANTS.attributes.THEME) as BadgeTheme ?? BADGE_CONSTANTS.defaults.THEME;
+ }
+ public set theme(value: BadgeTheme) {
+ this.setAttribute(BADGE_CONSTANTS.attributes.THEME, value);
}
- /** Controls whether the component renders a simple dot/circle, or allows for content. */
- @FoundationProperty()
- public declare dot: boolean;
+ public get strong(): boolean {
+ return this.hasAttribute(BADGE_CONSTANTS.attributes.STRONG);
+ }
+ public set strong(value: boolean) {
+ this.toggleAttribute(BADGE_CONSTANTS.attributes.STRONG, value);
+ }
- /** Controls the visibility state. */
- @FoundationProperty()
- public declare open: boolean;
+ public get hide(): boolean {
+ return this.hasAttribute(BADGE_CONSTANTS.attributes.HIDE);
+ }
+ public set hide(value: boolean) {
+ if (this.hasAttribute(BADGE_CONSTANTS.attributes.HIDE) !== value) {
+ this.toggleAttribute(BADGE_CONSTANTS.attributes.HIDE, value);
+ }
+ }
}
diff --git a/src/lib/badge/build.json b/src/lib/badge/build.json
deleted file mode 100644
index 07c79a465..000000000
--- a/src/lib/badge/build.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "$schema": "../../../node_modules/@tylertech/forge-cli/config/build-schema.json",
- "extends": "../build.json"
-}
\ No newline at end of file
diff --git a/src/lib/badge/index.scss b/src/lib/badge/index.scss
new file mode 100644
index 000000000..98a38c0d9
--- /dev/null
+++ b/src/lib/badge/index.scss
@@ -0,0 +1 @@
+@forward './core';
diff --git a/src/lib/badge/index.ts b/src/lib/badge/index.ts
index bb7498fa0..859998ee8 100644
--- a/src/lib/badge/index.ts
+++ b/src/lib/badge/index.ts
@@ -2,11 +2,8 @@ import { defineCustomElement } from '@tylertech/forge-core';
import { BadgeComponent } from './badge';
-export * from './badge-adapter';
export * from './badge-constants';
-export * from './badge-foundation';
export * from './badge';
-export * from './badge-component-delegate';
export function defineBadgeComponent(): void {
defineCustomElement(BadgeComponent);
diff --git a/src/lib/circular-progress/circular-progress-foundation.ts b/src/lib/circular-progress/circular-progress-foundation.ts
index 903f46d00..32b35b109 100644
--- a/src/lib/circular-progress/circular-progress-foundation.ts
+++ b/src/lib/circular-progress/circular-progress-foundation.ts
@@ -47,6 +47,9 @@ export class CircularProgressFoundation implements ICircularProgressFoundation {
return this._progress;
}
public set progress(value: number) {
+ if (isNaN(value)) {
+ value = 0;
+ }
if (this._progress !== value) {
this._progress = value;
if (this._determinate) {
diff --git a/src/lib/core/styles/tokens/badge/_tokens.scss b/src/lib/core/styles/tokens/badge/_tokens.scss
new file mode 100644
index 000000000..7e38f25f9
--- /dev/null
+++ b/src/lib/core/styles/tokens/badge/_tokens.scss
@@ -0,0 +1,37 @@
+@use 'sass:map';
+@use '../../theme';
+@use '../../shape';
+@use '../../spacing';
+@use '../../border';
+@use '../../animation';
+@use '../../utils';
+
+$tokens: (
+ background: utils.module-val(badge, background, theme.variable(secondary)),
+ color: utils.module-val(badge, color, theme.variable(on-secondary)),
+ shape: utils.module-val(badge, shape, shape.variable(full)),
+ height: utils.module-val(badge, height, 20px),
+ min-width: utils.module-val(badge, min-width, 0),
+ max-width: utils.module-val(badge, max-width, auto),
+ padding-inline: utils.module-val(badge, padding-inline, spacing.variable(xsmall)),
+ padding-block: utils.module-val(badge, padding-block, 0),
+ border-width: utils.module-val(badge, border-width, border.variable(thin)),
+ border-style: utils.module-val(badge, border-style, none),
+ border-color: utils.module-ref(badge, border-color, color),
+ gap: utils.module-val(badge, gap, spacing.variable(xsmall)),
+ font-weight: utils.module-val(badge, font-weight, bold),
+
+ // Dot
+ dot-size: utils.module-val(badge, dot-size, 8px),
+ dot-height: utils.module-ref(badge, dot-height, dot-size),
+ dot-width: utils.module-ref(badge, dot-width, dot-size),
+ dot-padding: utils.module-val(badge, dot-padding, 0),
+
+ // Transition
+ transition-duration: utils.module-val(badge, transition-duration, animation.variable(duration-short4)),
+ transition-easing: utils.module-val(badge, transition-easing, animation.variable(easing-decelerate)),
+) !default;
+
+@function get($key) {
+ @return map.get($tokens, $key);
+}
diff --git a/src/stories/src/components/badge/badge-arg-types.ts b/src/stories/src/components/badge/badge-arg-types.ts
index e6f6814bd..e4b650630 100644
--- a/src/stories/src/components/badge/badge-arg-types.ts
+++ b/src/stories/src/components/badge/badge-arg-types.ts
@@ -1,12 +1,11 @@
export interface IBadgeProps {
dot: boolean;
- open: boolean;
+ hide: boolean;
theme: string;
- positioned: boolean;
strong: boolean;
text: string;
- hasLeadingIcon: boolean;
- hasTrailingIcon: boolean;
+ hasStartIcon: boolean;
+ hasEndIcon: boolean;
}
export const argTypes = {
@@ -17,9 +16,9 @@ export const argTypes = {
category: 'Properties'
},
},
- open: {
+ hide: {
control: 'boolean',
- description: 'Use open to show or hide the badge',
+ description: 'Use the visibility of the badge',
table: {
category: 'Properties'
},
@@ -42,13 +41,6 @@ export const argTypes = {
category: 'Attributes'
},
},
- positioned: {
- control: 'boolean',
- description: 'Use positioned to place the badge relative to an icon such as a notification icon',
- table: {
- category: 'Attributes'
- },
- },
strong: {
control: 'boolean',
description: 'Use muted badges by default. In cases where more visual emphasis is needed, use strong badges instead. In general, only pages where just a few badges are used should use the strong style.',
@@ -63,14 +55,14 @@ export const argTypes = {
category: 'Slots'
},
},
- hasLeadingIcon: {
+ hasStartIcon: {
control: 'boolean',
description: 'Use an icon to visually reinforce a badge\'s meaning.',
table: {
category: 'Slots'
},
},
- hasTrailingIcon: {
+ hasEndIcon: {
control: 'boolean',
description: 'Use an icon to visually reinforce a badge\'s meaning.',
table: {
diff --git a/src/stories/src/components/badge/badge.stories.tsx b/src/stories/src/components/badge/badge.stories.tsx
index 859f905ce..a0b91b1dd 100644
--- a/src/stories/src/components/badge/badge.stories.tsx
+++ b/src/stories/src/components/badge/badge.stories.tsx
@@ -21,75 +21,67 @@ export default {
export const Default: Story = ({
text = '',
- open = true,
+ hide = false,
strong = false,
dot = false,
- positioned = false,
theme = 'default',
- hasLeadingIcon = false,
- hasTrailingIcon = false
+ hasStartIcon = false,
+ hasEndIcon = false
}) => {
useEffect(() => {
IconRegistry.define([tylIconFace, tylIconStar]);
}, []);
return (
-
- {hasLeadingIcon && }
+
+ {hasStartIcon && }
{text}
- {hasTrailingIcon && }
+ {hasEndIcon && }
)
};
Default.args = {
dot: false,
- open: true,
+ hide: false,
theme: 'default',
- positioned: false,
strong: false,
- text: 'Default',
- hasLeadingIcon: false,
- hasTrailingIcon: false
+ text: 'Status',
+ hasStartIcon: false,
+ hasEndIcon: false
} as IBadgeProps;
export const WithIconButton: Story = ({
text = '',
- open = true,
+ hide = false,
strong = false,
dot = false,
- positioned = false,
theme = 'default',
- hasLeadingIcon = false,
- hasTrailingIcon = false
+ hasStartIcon = false,
+ hasEndIcon = false
}) => {
useEffect(() => {
IconRegistry.define([tylIconFace, tylIconNotifications, tylIconStar]);
}, []);
- const demoIconButtonStyles = {
- color: 'var(--mdc-theme-on-surface, #000000)',
- };
-
return (
-
+
-
- {hasLeadingIcon && }
+
+ {hasStartIcon && }
{text}
- {hasTrailingIcon && }
+ {hasEndIcon && }
)
};
WithIconButton.args = {
dot: false,
- open: true,
+ hide: false,
theme: 'default',
- positioned: true,
strong: false,
text: '3',
- hasLeadingIcon: false,
- hasTrailingIcon: false
+ hasStartIcon: false,
+ hasEndIcon: false
} as IBadgeProps;
diff --git a/src/test/spec/badge/badge.spec.ts b/src/test/spec/badge/badge.spec.ts
deleted file mode 100644
index f8bd45f9e..000000000
--- a/src/test/spec/badge/badge.spec.ts
+++ /dev/null
@@ -1,199 +0,0 @@
-import { defineBadgeComponent, BADGE_CONSTANTS, IBadgeComponent, BadgeComponent } from '@tylertech/forge/badge';
-import { removeElement, getShadowElement } from '@tylertech/forge-core';
-
-interface ITestContext {
- context: ITestBadgeContext;
-}
-
-interface ITestBadgeContext {
- component: IBadgeComponent;
- appendToBody(): void;
- appendToFixture(): void;
- destroy(): void;
-}
-
-describe('BadgeComponent', function(this: ITestContext) {
- const bogusAttribute = 'BOGUS_ATTRIBUTE';
-
- beforeAll(function(this: ITestContext) {
- defineBadgeComponent();
- });
-
- afterEach(function(this: ITestContext) {
- this.context.destroy();
- });
-
- it('should instantiate component instance', function(this: ITestContext) {
- this.context = setupTestContext();
- expect(this.context.component.shadowRoot).not.toBeNull();
- });
-
- describe('with default values', function(this: ITestContext) {
- it('should instantiate dot to false', function(this: ITestContext) {
- this.context = setupTestContext();
- expect(this.context.component.dot).toBeFalse();
- });
- it('should instantiate open to true', function(this: ITestContext) {
- this.context = setupTestContext();
- expect(this.context.component.open).toBeTrue();
- });
- });
-
- describe('with dot set to true', function(this: ITestContext) {
- it('should add the dot class to the root element', function(this: ITestContext) {
- this.context = setupTestContext();
- this.context.component.dot = true;
- const rootElement = getShadowElement(this.context.component, BADGE_CONSTANTS.selectors.ROOT);
-
- const thatTheElementContainmentOfTheDotClass = rootElement.classList.contains(
- BADGE_CONSTANTS.classes.DOT
- );
-
- expect(thatTheElementContainmentOfTheDotClass).toBe(true);
- });
-
- it('should add the dot attriute to the component', function(this: ITestContext) {
- this.context = setupTestContext();
- this.context.component.dot = true;
-
- const thatTheDotAttributeDefinition = this.context.component.getAttribute(
- BADGE_CONSTANTS.attributes.DOT
- );
- expect(thatTheDotAttributeDefinition).not.toBeNull();
- });
- });
-
- describe('with dot set to false', function(this: ITestContext) {
- it('should not add the dot class to the root element', function(this: ITestContext) {
- this.context = setupTestContext();
- this.context.component.dot = false;
- const rootElement = getShadowElement(this.context.component, BADGE_CONSTANTS.selectors.ROOT);
-
- const theClassContainsTheDotClass = rootElement.classList.contains(
- BADGE_CONSTANTS.classes.DOT
- );
-
- expect(theClassContainsTheDotClass).toBe(false);
- });
-
- it('should not add the dot attribute to the component', function(this: ITestContext) {
- this.context = setupTestContext();
- this.context.component.dot = false;
-
- const theDotAttributeIsDefined = this.context.component.getAttribute(
- BADGE_CONSTANTS.attributes.DOT
- );
- expect(theDotAttributeIsDefined).toBeNull();
- });
- });
-
- describe('with open set to true', function(this: ITestContext) {
- it('should add the open class to the root element', function(this: ITestContext) {
- this.context = setupTestContext(false, false);
- this.context.component.open = true;
- this.context.appendToFixture();
- const rootElement = getShadowElement(this.context.component, BADGE_CONSTANTS.selectors.ROOT);
-
- const theClassContainsTheOpenClass = rootElement.classList.contains(
- BADGE_CONSTANTS.classes.OPEN
- );
-
- expect(theClassContainsTheOpenClass).toBe(true);
- });
-
- it('should add the open attribute to the component', function(this: ITestContext) {
- this.context = setupTestContext(true);
- this.context.component.open = true;
-
- const theOpenAttributeIsDefined = this.context.component.getAttribute(
- BADGE_CONSTANTS.attributes.OPEN
- );
-
- expect(theOpenAttributeIsDefined).not.toBeNull();
- });
- });
-
- describe('with open set to false', function(this: ITestContext) {
- it('should not add the open class to the root element', function(this: ITestContext) {
- this.context = setupTestContext(false, false);
- this.context.component.open = false;
- this.context.appendToFixture();
- const rootElement = getShadowElement(this.context.component, BADGE_CONSTANTS.selectors.ROOT);
-
- const theClassContainsTheOpenClass = rootElement.classList.contains(
- BADGE_CONSTANTS.classes.OPEN
- );
-
- expect(theClassContainsTheOpenClass).toBe(false);
- });
-
- it('should not add the open attribute to the component', function(this: ITestContext) {
- this.context = setupTestContext();
- this.context.component.open = false;
- this.context.appendToFixture();
-
- const theOpenAttributeIsDefined = this.context.component.getAttribute(
- BADGE_CONSTANTS.attributes.OPEN
- );
-
- expect(theOpenAttributeIsDefined).toBeNull();
- });
- });
-
- it('should observe the dot attribute', function(this: ITestContext) {
- this.context = setupTestContext();
- const componentDefinedAttributes = BadgeComponent.observedAttributes;
- const dotAttributeName = componentDefinedAttributes.find(
- (a) => a === BADGE_CONSTANTS.attributes.DOT
- );
-
- expect(dotAttributeName).toEqual(BADGE_CONSTANTS.attributes.DOT);
- });
-
- it('should observe the open attribute', function(this: ITestContext) {
- this.context = setupTestContext();
- const componentDefinedAttributes = BadgeComponent.observedAttributes;
-
- const openAttributeName = componentDefinedAttributes.find(
- (a) => a === BADGE_CONSTANTS.attributes.OPEN
- );
-
- expect(openAttributeName).toEqual(BADGE_CONSTANTS.attributes.OPEN);
- });
-
- describe('with non-observed attribute set', function(this: ITestContext) {
- it('should have no change to the open property', function(this: ITestContext) {
- this.context = setupTestContext();
- const open = this.context.component.open;
- this.context.component.setAttribute(bogusAttribute, bogusAttribute);
-
- expect(open).toEqual(this.context.component.open);
- });
-
- it('should have no change to dot property', function(this: ITestContext) {
- this.context = setupTestContext();
- const dot = this.context.component.dot;
- this.context.component.setAttribute(bogusAttribute, bogusAttribute);
-
- expect(dot).toEqual(this.context.component.dot);
- });
- });
-
- function setupTestContext(appendToBody = false, appendToFixture = true): ITestBadgeContext {
- const fixture = document.createElement('div');
- fixture.id = 'badge-test-fixture';
- const component = document.createElement(BADGE_CONSTANTS.elementName) as IBadgeComponent;
- if (appendToFixture) {
- fixture.appendChild(component);
- }
- if (appendToBody) {
- document.body.appendChild(fixture);
- }
- return {
- component,
- appendToFixture: () => document.body.appendChild(fixture),
- appendToBody: () => fixture.appendChild(component),
- destroy: () => removeElement(fixture)
- };
- }
-});