From 6ec51d89cf1f26c6aa37b16adcb3ae4df212eadb Mon Sep 17 00:00:00 2001 From: Christian Milocanovich Date: Wed, 24 Sep 2025 17:48:43 -0300 Subject: [PATCH 1/6] Create character counter component --- src/components/ch-counter/ch-counter.css | 3 + src/components/ch-counter/ch-counter.tsx | 63 +++++++++++++++++++ .../ch-counter/test/ch-counter.e2e.ts | 11 ++++ .../ch-counter/test/ch-counter.spec.tsx | 18 ++++++ .../components/counter/counter.showcase.tsx | 36 +++++++++++ src/showcase/assets/components/pages.ts | 5 ++ .../assets/components/showcase-stories.ts | 2 + src/showcase/assets/components/types.ts | 1 + 8 files changed, 139 insertions(+) create mode 100644 src/components/ch-counter/ch-counter.css create mode 100644 src/components/ch-counter/ch-counter.tsx create mode 100644 src/components/ch-counter/test/ch-counter.e2e.ts create mode 100644 src/components/ch-counter/test/ch-counter.spec.tsx create mode 100644 src/showcase/assets/components/counter/counter.showcase.tsx diff --git a/src/components/ch-counter/ch-counter.css b/src/components/ch-counter/ch-counter.css new file mode 100644 index 00000000..5d4e87f3 --- /dev/null +++ b/src/components/ch-counter/ch-counter.css @@ -0,0 +1,3 @@ +:host { + display: block; +} diff --git a/src/components/ch-counter/ch-counter.tsx b/src/components/ch-counter/ch-counter.tsx new file mode 100644 index 00000000..5bc5e4b0 --- /dev/null +++ b/src/components/ch-counter/ch-counter.tsx @@ -0,0 +1,63 @@ +import { Component, Element, Host, Prop, State, Watch, h } from "@stencil/core"; + +@Component({ + tag: "ch-counter", + styleUrl: "ch-counter.css", + shadow: true +}) +export class ChCounter { + @Element() hostElement!: HTMLChCounterElement; + /** + * Represents the value of the input field. + */ + @State() currentLength: number = 0; + + /** + * Represents the maximum length of the input field. + */ + @State() maxLength: number = 0; + + /** + * Represents the initial value of the input field. + * Note: This is required when component is updated by a parent component. + */ + @Prop() readonly initialValue: string = ""; + @Watch("initialValue") + initialValueChanged(newValue: string) { + this.currentLength = newValue.length; + } + + componentWillLoad() { + const chEdit = this.hostElement.querySelector("ch-edit"); + + chEdit?.addEventListener("input", (ev: Event) => { + this.currentLength = (ev.target as HTMLInputElement).value.length; + }); + + this.currentLength = (chEdit?.value ?? this.initialValue).length; + this.maxLength = chEdit?.maxLength ?? 0; + } + + render() { + const remainingChars = this.maxLength - this.currentLength; + const isNearLimit = remainingChars <= 20; + const isAtLimit = remainingChars <= 0; + return ( + + + + {this.maxLength > 0 && ( +
+ {`${this.currentLength} / ${this.maxLength}`} +
+ )} +
+ ); + } +} diff --git a/src/components/ch-counter/test/ch-counter.e2e.ts b/src/components/ch-counter/test/ch-counter.e2e.ts new file mode 100644 index 00000000..220bb024 --- /dev/null +++ b/src/components/ch-counter/test/ch-counter.e2e.ts @@ -0,0 +1,11 @@ +import { newE2EPage } from '@stencil/core/testing'; + +describe('ch-counter', () => { + it('renders', async () => { + const page = await newE2EPage(); + await page.setContent(''); + + const element = await page.find('ch-counter'); + expect(element).toHaveClass('hydrated'); + }); +}); diff --git a/src/components/ch-counter/test/ch-counter.spec.tsx b/src/components/ch-counter/test/ch-counter.spec.tsx new file mode 100644 index 00000000..3b4de919 --- /dev/null +++ b/src/components/ch-counter/test/ch-counter.spec.tsx @@ -0,0 +1,18 @@ +import { newSpecPage } from '@stencil/core/testing'; +import { ChCounter } from '../ch-counter'; + +describe('ch-counter', () => { + it('renders', async () => { + const page = await newSpecPage({ + components: [ChCounter], + html: ``, + }); + expect(page.root).toEqualHtml(` + + + + + + `); + }); +}); diff --git a/src/showcase/assets/components/counter/counter.showcase.tsx b/src/showcase/assets/components/counter/counter.showcase.tsx new file mode 100644 index 00000000..bdcb3f23 --- /dev/null +++ b/src/showcase/assets/components/counter/counter.showcase.tsx @@ -0,0 +1,36 @@ +import { h } from "@stencil/core"; + +import { ShowcaseRenderProperties, ShowcaseStory } from "../types"; +import { showcaseTemplateClassProperty } from "../utils"; + +const state: Partial = {}; + +const showcaseRenderProperties: ShowcaseRenderProperties = + []; + +const render = () => ( + + + +); + +export const counterShowcaseStory: ShowcaseStory = { + properties: showcaseRenderProperties, + markupWithoutUIModel: { + react: () => ``, + + stencil: () => `` + }, + render: render, + state: state +}; diff --git a/src/showcase/assets/components/pages.ts b/src/showcase/assets/components/pages.ts index 079cb481..c99ee70b 100644 --- a/src/showcase/assets/components/pages.ts +++ b/src/showcase/assets/components/pages.ts @@ -105,6 +105,11 @@ export const showcasePages: NavigationListModel = [ link: { url: "#switch" }, caption: "Switch", metadata: EXPERIMENTAL + }, + { + link: { url: "#counter" }, + caption: "Counter", + metadata: EXPERIMENTAL } ] }, diff --git a/src/showcase/assets/components/showcase-stories.ts b/src/showcase/assets/components/showcase-stories.ts index 1f91d141..d879f7e2 100644 --- a/src/showcase/assets/components/showcase-stories.ts +++ b/src/showcase/assets/components/showcase-stories.ts @@ -9,6 +9,7 @@ import { codeDiffEditorShowcaseStory } from "./code-diff-editor/code-diff-editor import { codeEditorShowcaseStory } from "./code-editor/code-editor.showcase"; import { codeShowcaseStory } from "./code/code.showcase"; import { comboBoxShowcaseStory } from "./combo-box/combo-box.showcase"; +import { counterShowcaseStory } from "./counter/counter.showcase"; import { dialogShowcaseStory } from "./dialog/dialog.showcase"; import { editShowcaseStory } from "./edit/edit.showcase"; import { flexibleLayoutShowcaseStory } from "./flexible-layout/flexible-layout.showcase"; @@ -48,6 +49,7 @@ export const showcaseStories = { chat: chatShowcaseStory, code: codeShowcaseStory, "combo-box": comboBoxShowcaseStory, + counter: counterShowcaseStory, dialog: dialogShowcaseStory, edit: editShowcaseStory, image: imageShowcaseStory, diff --git a/src/showcase/assets/components/types.ts b/src/showcase/assets/components/types.ts index 7f03cc7c..fdafe2ee 100644 --- a/src/showcase/assets/components/types.ts +++ b/src/showcase/assets/components/types.ts @@ -167,6 +167,7 @@ export type ChameleonStories = { chat: ShowcaseStory; code: ShowcaseStory; "combo-box": ShowcaseStory; + counter: ShowcaseStory; dialog: ShowcaseStory; edit: ShowcaseStory; image: ShowcaseStory; From 3ca3c2203bdfad47f847e08eb468eba0931e1bd1 Mon Sep 17 00:00:00 2001 From: Christian Milocanovich Date: Fri, 26 Sep 2025 18:11:38 -0300 Subject: [PATCH 2/6] Update counter --- src/components/ch-counter/ch-counter.css | 3 - src/components/counter/ch-counter.scss | 22 +++++++ .../{ch-counter => counter}/ch-counter.tsx | 5 +- .../test/ch-counter.e2e.ts | 0 .../test/ch-counter.spec.tsx | 0 .../components/counter/counter.showcase.tsx | 58 +++++++++++++++++-- .../assets/components/edit/edit.showcase.tsx | 2 +- 7 files changed, 80 insertions(+), 10 deletions(-) delete mode 100644 src/components/ch-counter/ch-counter.css create mode 100644 src/components/counter/ch-counter.scss rename src/components/{ch-counter => counter}/ch-counter.tsx (93%) rename src/components/{ch-counter => counter}/test/ch-counter.e2e.ts (100%) rename src/components/{ch-counter => counter}/test/ch-counter.spec.tsx (100%) diff --git a/src/components/ch-counter/ch-counter.css b/src/components/ch-counter/ch-counter.css deleted file mode 100644 index 5d4e87f3..00000000 --- a/src/components/ch-counter/ch-counter.css +++ /dev/null @@ -1,3 +0,0 @@ -:host { - display: block; -} diff --git a/src/components/counter/ch-counter.scss b/src/components/counter/ch-counter.scss new file mode 100644 index 00000000..946c41d7 --- /dev/null +++ b/src/components/counter/ch-counter.scss @@ -0,0 +1,22 @@ +:host { + /** + * @prop --ch-counter-status__warning-color: + * Specifies the color when is near to limit + * @default currentColor + */ + --ch-counter-status__warning-color: currentColor; + + /** + * @prop --ch-counter-status__error-color: + * Specifies the color when limit was reached + * @default currentColor + */ + --ch-counter-status__error-color: currentColor; +} + +.counter-warning { + color: var(--ch-counter-status__warning-color); +} +.counter-error { + color: var(--ch-counter-status__warning-color); +} diff --git a/src/components/ch-counter/ch-counter.tsx b/src/components/counter/ch-counter.tsx similarity index 93% rename from src/components/ch-counter/ch-counter.tsx rename to src/components/counter/ch-counter.tsx index 5bc5e4b0..a6db2424 100644 --- a/src/components/ch-counter/ch-counter.tsx +++ b/src/components/counter/ch-counter.tsx @@ -2,7 +2,7 @@ import { Component, Element, Host, Prop, State, Watch, h } from "@stencil/core"; @Component({ tag: "ch-counter", - styleUrl: "ch-counter.css", + styleUrl: "ch-counter.scss", shadow: true }) export class ChCounter { @@ -47,13 +47,14 @@ export class ChCounter { {this.maxLength > 0 && ( -
+
{`${this.currentLength} / ${this.maxLength}`}
)} diff --git a/src/components/ch-counter/test/ch-counter.e2e.ts b/src/components/counter/test/ch-counter.e2e.ts similarity index 100% rename from src/components/ch-counter/test/ch-counter.e2e.ts rename to src/components/counter/test/ch-counter.e2e.ts diff --git a/src/components/ch-counter/test/ch-counter.spec.tsx b/src/components/counter/test/ch-counter.spec.tsx similarity index 100% rename from src/components/ch-counter/test/ch-counter.spec.tsx rename to src/components/counter/test/ch-counter.spec.tsx diff --git a/src/showcase/assets/components/counter/counter.showcase.tsx b/src/showcase/assets/components/counter/counter.showcase.tsx index bdcb3f23..4f7fd0fb 100644 --- a/src/showcase/assets/components/counter/counter.showcase.tsx +++ b/src/showcase/assets/components/counter/counter.showcase.tsx @@ -6,12 +6,62 @@ import { showcaseTemplateClassProperty } from "../utils"; const state: Partial = {}; const showcaseRenderProperties: ShowcaseRenderProperties = - []; + [ + { + caption: "Styles", + properties: [ + { + id: "customVars", + type: "style", + properties: [ + { + id: "--ch-counter-status__warning-color", + caption: "--ch-counter-status__warning-color", + value: "yelow", + render: "input", + type: "string" + } + ] + }, + { + id: "customVars", + type: "style", + properties: [ + { + id: "--ch-counter-status__error-color", + caption: "--ch-counter-status__error-color", + value: "red", + render: "input", + type: "string" + } + ] + } + ] + } + ]; const render = () => ( - - - +
+
+

Textarea

+ + + +
+ +
+

input

+ + + +
+
); export const counterShowcaseStory: ShowcaseStory = { diff --git a/src/showcase/assets/components/edit/edit.showcase.tsx b/src/showcase/assets/components/edit/edit.showcase.tsx index d275a10c..88e9c480 100644 --- a/src/showcase/assets/components/edit/edit.showcase.tsx +++ b/src/showcase/assets/components/edit/edit.showcase.tsx @@ -181,7 +181,7 @@ const render = () => ( autocapitalize={state.autocapitalize} autocomplete={state.autocomplete} autoGrow={state.autoGrow} - class="input" + class="input input-error" debounce={state.debounce} disabled={state.disabled} maxLength={state.maxLength} From 35b786275a82080ac9bd1755d816296610e0bb6b Mon Sep 17 00:00:00 2001 From: Christian Milocanovich Date: Fri, 26 Sep 2025 18:47:37 -0300 Subject: [PATCH 3/6] create counter e2e tests --- src/components/counter/test/ch-counter.e2e.ts | 199 +++++++++++++++++- .../counter/test/ch-counter.spec.tsx | 18 -- .../components/counter/counter.showcase.tsx | 44 ++-- 3 files changed, 222 insertions(+), 39 deletions(-) delete mode 100644 src/components/counter/test/ch-counter.spec.tsx diff --git a/src/components/counter/test/ch-counter.e2e.ts b/src/components/counter/test/ch-counter.e2e.ts index 220bb024..52b36863 100644 --- a/src/components/counter/test/ch-counter.e2e.ts +++ b/src/components/counter/test/ch-counter.e2e.ts @@ -1,11 +1,196 @@ -import { newE2EPage } from '@stencil/core/testing'; +import { E2EElement, E2EPage, newE2EPage } from "@stencil/core/testing"; +import { testDefaultProperties } from "../../../testing/utils.e2e"; -describe('ch-counter', () => { - it('renders', async () => { - const page = await newE2EPage(); - await page.setContent(''); +testDefaultProperties("ch-counter", { + initialValue: "" +}); + +describe("[ch-counter][basic]", () => { + let page: E2EPage; + let counterRef: E2EElement; + + beforeEach(async () => { + page = await newE2EPage({ + html: ``, + failOnConsoleError: true + }); + + counterRef = await page.find("ch-counter"); + }); + + it("should have Shadow DOM", () => + expect(counterRef.shadowRoot).toBeTruthy()); + + it("should render without counter display when no ch-edit is present", async () => { + const counterContainer = await page.find( + "ch-counter >>> [part='counter-container']" + ); + expect(counterContainer).toBeNull(); + }); + + it("should render without counter display when ch-edit has no maxLength", async () => { + await page.setContent(` + + + + `); + await page.waitForChanges(); + + const counterContainer = await page.find( + "ch-counter >>> [part='counter-container']" + ); + expect(counterContainer).toBeNull(); + }); +}); + +describe("[ch-counter][functionality]", () => { + let page: E2EPage; + let counterRef: E2EElement; + let editRef: E2EElement; + + beforeEach(async () => { + page = await newE2EPage({ + html: ` + + + + `, + failOnConsoleError: true + }); + + counterRef = await page.find("ch-counter"); + editRef = await page.find("ch-edit"); + }); + + it("should display counter when ch-edit has maxLength", async () => { + const counterContainer = await page.find( + "ch-counter >>> [part='counter-container']" + ); + const counterText = await page.find("ch-counter >>> [part='counter-text']"); + + expect(counterContainer).toBeTruthy(); + expect(counterText).toBeTruthy(); + expect(await counterText.textContent).toBe("0 / 100"); + }); + + it("should update counter when typing in ch-edit", async () => { + const input = await page.find("ch-edit >>> input"); + const counterText = await page.find("ch-counter >>> [part='counter-text']"); + + await input.type("Hello World"); + await page.waitForChanges(); + + expect(await counterText.textContent).toBe("11 / 100"); + }); + + it("should show warning state when approaching limit", async () => { + const input = await page.find("ch-edit >>> input"); + const counterText = await page.find("ch-counter >>> [part='counter-text']"); + + // Type 81 characters (100 - 19 = 81, which is <= 20 remaining) + const longText = "a".repeat(81); + await input.type(longText); + await page.waitForChanges(); + + expect(await counterText.textContent).toBe("81 / 100"); + expect(await counterText.getAttribute("class")).toContain( + "counter-warning" + ); + }); + + it("should show error state when at limit", async () => { + const input = await page.find("ch-edit >>> input"); + const counterText = await page.find("ch-counter >>> [part='counter-text']"); + + // Type exactly 100 characters + const longText = "a".repeat(100); + await input.type(longText); + await page.waitForChanges(); + + expect(await counterText.textContent).toBe("100 / 100"); + expect(await counterText.getAttribute("class")).toContain("counter-error"); + }); + + it("should show error state when exceeding limit", async () => { + const input = await page.find("ch-edit >>> input"); + const counterText = await page.find("ch-counter >>> [part='counter-text']"); + + // Type more than 100 characters + const longText = "a".repeat(105); + await input.type(longText); + await page.waitForChanges(); + + expect(await counterText.textContent).toBe("100 / 100"); + expect(await counterText.getAttribute("class")).toContain("counter-error"); + }); + + it("should handle initial value correctly", async () => { + await page.setContent(` + + + + `); + await page.waitForChanges(); + + const counterText = await page.find("ch-counter >>> [part='counter-text']"); + expect(await counterText.textContent).toBe("12 / 100"); + }); + + it("should update counter when initial value changes", async () => { + const counterText = await page.find("ch-counter >>> [part='counter-text']"); + + await counterRef.setProperty("initialValue", "Updated text"); + await page.waitForChanges(); + + expect(await counterText.textContent).toBe("12 / 100"); + }); + + it("should work with multiline ch-edit", async () => { + await page.setContent(` + + + + `); + await page.waitForChanges(); + + const textarea = await page.find("ch-edit >>> textarea"); + const counterText = await page.find("ch-counter >>> [part='counter-text']"); + + expect(counterText).toBeTruthy(); + expect(await counterText.textContent).toBe("0 / 50"); + + await textarea.type("Multiline text\nwith newlines"); + await page.waitForChanges(); + + expect(await counterText.textContent).toBe("25 / 50"); + }); + + it("should handle dynamic maxLength changes", async () => { + const counterText = await page.find("ch-counter >>> [part='counter-text']"); + + // Change maxLength to 50 + await editRef.setProperty("maxLength", 50); + await page.waitForChanges(); + + expect(await counterText.textContent).toBe("0 / 50"); + + // Type some text + const input = await page.find("ch-edit >>> input"); + await input.type("Hello"); + await page.waitForChanges(); + + expect(await counterText.textContent).toBe("5 / 50"); + }); + + it("should hide counter when maxLength is removed", async () => { + const counterContainer = await page.find( + "ch-counter >>> [part='counter-container']" + ); + + // Remove maxLength + await editRef.setProperty("maxLength", undefined); + await page.waitForChanges(); - const element = await page.find('ch-counter'); - expect(element).toHaveClass('hydrated'); + expect(counterContainer).toBeNull(); }); }); diff --git a/src/components/counter/test/ch-counter.spec.tsx b/src/components/counter/test/ch-counter.spec.tsx deleted file mode 100644 index 3b4de919..00000000 --- a/src/components/counter/test/ch-counter.spec.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { newSpecPage } from '@stencil/core/testing'; -import { ChCounter } from '../ch-counter'; - -describe('ch-counter', () => { - it('renders', async () => { - const page = await newSpecPage({ - components: [ChCounter], - html: ``, - }); - expect(page.root).toEqualHtml(` - - - - - - `); - }); -}); diff --git a/src/showcase/assets/components/counter/counter.showcase.tsx b/src/showcase/assets/components/counter/counter.showcase.tsx index 4f7fd0fb..e566dda1 100644 --- a/src/showcase/assets/components/counter/counter.showcase.tsx +++ b/src/showcase/assets/components/counter/counter.showcase.tsx @@ -1,7 +1,11 @@ import { h } from "@stencil/core"; -import { ShowcaseRenderProperties, ShowcaseStory } from "../types"; -import { showcaseTemplateClassProperty } from "../utils"; +import { + ShowcaseRenderProperties, + ShowcaseStory, + ShowcaseTemplatePropertyInfo +} from "../types"; +import { renderShowcaseProperties } from "../utils"; const state: Partial = {}; @@ -17,7 +21,7 @@ const showcaseRenderProperties: ShowcaseRenderProperties = { id: "--ch-counter-status__warning-color", caption: "--ch-counter-status__warning-color", - value: "yelow", + value: "#ffff00", render: "input", type: "string" } @@ -30,7 +34,7 @@ const showcaseRenderProperties: ShowcaseRenderProperties = { id: "--ch-counter-status__error-color", caption: "--ch-counter-status__error-color", - value: "red", + value: "#ff0000", render: "input", type: "string" } @@ -64,22 +68,34 @@ const render = () => (
); +const showcaseCounterPropertiesInfo: ShowcaseTemplatePropertyInfo[] = + [ + { + name: "class", + fixed: true, + value: "navigation-list navigation-list-secondary", + type: "string" + } + ]; + export const counterShowcaseStory: ShowcaseStory = { properties: showcaseRenderProperties, markupWithoutUIModel: { - react: () => ``, + showcaseCounterPropertiesInfo + )}> + + `, - stencil: () => `` + showcaseCounterPropertiesInfo + )}> + + ` }, render: render, state: state From eeca2eec2b109ede0097a248d11893eaa31959d4 Mon Sep 17 00:00:00 2001 From: Christian Milocanovich Date: Mon, 29 Sep 2025 16:39:19 -0300 Subject: [PATCH 4/6] Update ch-counter tests --- .../counter/{test => tests}/ch-counter.e2e.ts | 76 ++++++------------- 1 file changed, 25 insertions(+), 51 deletions(-) rename src/components/counter/{test => tests}/ch-counter.e2e.ts (76%) diff --git a/src/components/counter/test/ch-counter.e2e.ts b/src/components/counter/tests/ch-counter.e2e.ts similarity index 76% rename from src/components/counter/test/ch-counter.e2e.ts rename to src/components/counter/tests/ch-counter.e2e.ts index 52b36863..9b9ea851 100644 --- a/src/components/counter/test/ch-counter.e2e.ts +++ b/src/components/counter/tests/ch-counter.e2e.ts @@ -46,19 +46,21 @@ describe("[ch-counter][basic]", () => { describe("[ch-counter][functionality]", () => { let page: E2EPage; let counterRef: E2EElement; + let inputRef: E2EElement; let editRef: E2EElement; beforeEach(async () => { page = await newE2EPage({ html: ` - + `, failOnConsoleError: true }); counterRef = await page.find("ch-counter"); + inputRef = await page.find("ch-edit >>> input"); editRef = await page.find("ch-edit"); }); @@ -74,24 +76,29 @@ describe("[ch-counter][functionality]", () => { }); it("should update counter when typing in ch-edit", async () => { - const input = await page.find("ch-edit >>> input"); - const counterText = await page.find("ch-counter >>> [part='counter-text']"); - - await input.type("Hello World"); + inputRef.press("H"); + inputRef.press("e"); + inputRef.press("l"); + inputRef.press("l"); + inputRef.press("o"); + inputRef.press(" "); + inputRef.press("W"); + inputRef.press("o"); + inputRef.press("r"); + inputRef.press("l"); + inputRef.press("d"); await page.waitForChanges(); + const counterText = await page.find("ch-counter >>> [part='counter-text']"); expect(await counterText.textContent).toBe("11 / 100"); }); it("should show warning state when approaching limit", async () => { - const input = await page.find("ch-edit >>> input"); - const counterText = await page.find("ch-counter >>> [part='counter-text']"); - - // Type 81 characters (100 - 19 = 81, which is <= 20 remaining) const longText = "a".repeat(81); - await input.type(longText); + await inputRef.type(longText); await page.waitForChanges(); + const counterText = await page.find("ch-counter >>> [part='counter-text']"); expect(await counterText.textContent).toBe("81 / 100"); expect(await counterText.getAttribute("class")).toContain( "counter-warning" @@ -99,27 +106,21 @@ describe("[ch-counter][functionality]", () => { }); it("should show error state when at limit", async () => { - const input = await page.find("ch-edit >>> input"); - const counterText = await page.find("ch-counter >>> [part='counter-text']"); - - // Type exactly 100 characters const longText = "a".repeat(100); - await input.type(longText); + await inputRef.type(longText); await page.waitForChanges(); + const counterText = await page.find("ch-counter >>> [part='counter-text']"); expect(await counterText.textContent).toBe("100 / 100"); expect(await counterText.getAttribute("class")).toContain("counter-error"); }); it("should show error state when exceeding limit", async () => { - const input = await page.find("ch-edit >>> input"); - const counterText = await page.find("ch-counter >>> [part='counter-text']"); - - // Type more than 100 characters const longText = "a".repeat(105); - await input.type(longText); + await inputRef.type(longText); await page.waitForChanges(); + const counterText = await page.find("ch-counter >>> [part='counter-text']"); expect(await counterText.textContent).toBe("100 / 100"); expect(await counterText.getAttribute("class")).toContain("counter-error"); }); @@ -137,11 +138,10 @@ describe("[ch-counter][functionality]", () => { }); it("should update counter when initial value changes", async () => { - const counterText = await page.find("ch-counter >>> [part='counter-text']"); - await counterRef.setProperty("initialValue", "Updated text"); await page.waitForChanges(); + const counterText = await page.find("ch-counter >>> [part='counter-text']"); expect(await counterText.textContent).toBe("12 / 100"); }); @@ -162,35 +162,9 @@ describe("[ch-counter][functionality]", () => { await textarea.type("Multiline text\nwith newlines"); await page.waitForChanges(); - expect(await counterText.textContent).toBe("25 / 50"); - }); - - it("should handle dynamic maxLength changes", async () => { - const counterText = await page.find("ch-counter >>> [part='counter-text']"); - - // Change maxLength to 50 - await editRef.setProperty("maxLength", 50); - await page.waitForChanges(); - - expect(await counterText.textContent).toBe("0 / 50"); - - // Type some text - const input = await page.find("ch-edit >>> input"); - await input.type("Hello"); - await page.waitForChanges(); - - expect(await counterText.textContent).toBe("5 / 50"); - }); - - it("should hide counter when maxLength is removed", async () => { - const counterContainer = await page.find( - "ch-counter >>> [part='counter-container']" + const counterTextUpdated = await page.find( + "ch-counter >>> [part='counter-text']" ); - - // Remove maxLength - await editRef.setProperty("maxLength", undefined); - await page.waitForChanges(); - - expect(counterContainer).toBeNull(); + expect(await counterTextUpdated.textContent).toBe("28 / 50"); }); }); From b9304f7ec340d73cde2f364da2428ccddeb94ccb Mon Sep 17 00:00:00 2001 From: Christian Milocanovich Date: Mon, 29 Sep 2025 16:47:50 -0300 Subject: [PATCH 5/6] update ch-counter tests --- src/components/counter/tests/ch-counter.e2e.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/components/counter/tests/ch-counter.e2e.ts b/src/components/counter/tests/ch-counter.e2e.ts index 9b9ea851..ef3cdd08 100644 --- a/src/components/counter/tests/ch-counter.e2e.ts +++ b/src/components/counter/tests/ch-counter.e2e.ts @@ -47,7 +47,6 @@ describe("[ch-counter][functionality]", () => { let page: E2EPage; let counterRef: E2EElement; let inputRef: E2EElement; - let editRef: E2EElement; beforeEach(async () => { page = await newE2EPage({ @@ -61,7 +60,6 @@ describe("[ch-counter][functionality]", () => { counterRef = await page.find("ch-counter"); inputRef = await page.find("ch-edit >>> input"); - editRef = await page.find("ch-edit"); }); it("should display counter when ch-edit has maxLength", async () => { From 836501d497cf42330af3df01425a7add7e717b10 Mon Sep 17 00:00:00 2001 From: Christian Milocanovich Date: Mon, 29 Sep 2025 17:04:38 -0300 Subject: [PATCH 6/6] fix ch-counter tests --- src/components/counter/tests/ch-counter.e2e.ts | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/components/counter/tests/ch-counter.e2e.ts b/src/components/counter/tests/ch-counter.e2e.ts index ef3cdd08..74fc6da2 100644 --- a/src/components/counter/tests/ch-counter.e2e.ts +++ b/src/components/counter/tests/ch-counter.e2e.ts @@ -74,17 +74,7 @@ describe("[ch-counter][functionality]", () => { }); it("should update counter when typing in ch-edit", async () => { - inputRef.press("H"); - inputRef.press("e"); - inputRef.press("l"); - inputRef.press("l"); - inputRef.press("o"); - inputRef.press(" "); - inputRef.press("W"); - inputRef.press("o"); - inputRef.press("r"); - inputRef.press("l"); - inputRef.press("d"); + await inputRef.type("Hello world"); await page.waitForChanges(); const counterText = await page.find("ch-counter >>> [part='counter-text']");