{"record":{"id":"9cc634a2957689f2","repo":"angular/components","slug":"setcontenteditablevalue-can-only-be-called-on-a-c-9cc634","errorCode":null,"errorMessage":"setContenteditableValue can only be called on a `contenteditable` element.","messagePattern":"setContenteditableValue can only be called on a `contenteditable` element\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cdk/testing/testbed/unit-test-element.ts","lineNumber":204,"sourceCode":"    if (options?.exclude) {\n      return _getTextWithExcludedElements(this.element, options.exclude);\n    }\n    return (this.element.textContent || '').trim();\n  }\n\n  /**\n   * Sets the value of a `contenteditable` element.\n   * @param value Value to be set on the element.\n   */\n  async setContenteditableValue(value: string): Promise<void> {\n    const contenteditableAttr = await this.getAttribute('contenteditable');\n\n    if (\n      contenteditableAttr !== '' &&\n      contenteditableAttr !== 'true' &&\n      contenteditableAttr !== 'plaintext-only'\n    ) {\n      throw new Error('setContenteditableValue can only be called on a `contenteditable` element.');\n    }\n\n    await this._stabilize();\n    this.element.textContent = value;\n  }\n\n  /** Gets the value for the given attribute from the element. */\n  async getAttribute(name: string): Promise<string | null> {\n    await this._stabilize();\n    return this.element.getAttribute(name);\n  }\n\n  /** Checks whether the element has the given class. */\n  async hasClass(name: string): Promise<boolean> {\n    await this._stabilize();\n    return this.element.classList.contains(name);\n  }\n","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/cdk/testing/testbed/unit-test-element.ts#L186-L222","documentation":"UnitTestElement.setContenteditableValue in src/cdk/testing/testbed/unit-test-element.ts is the TestBed (unit-test) implementation of setContenteditableValue. It performs the identical guard — the contenteditable attribute must be '', 'true', or 'plaintext-only' — and throws this Error otherwise. After the guard it stabilizes the fixture and sets element.textContent directly.","triggerScenarios":"In unit tests using TestbedHarnessEnvironment/TestElement, calling setContenteditableValue on an element rendered without a contenteditable attribute (or with contenteditable=\"false\"), such as a plain div, span, or form input.","commonSituations":"Unit tests for custom rich-text/editor components where the editable attribute is bound conditionally ([attr.contenteditable]=\"isEditing\") and the test forgot to enable editing; tests copied from sendKeys examples and adapted to the wrong API.","solutions":["Render the element with contenteditable=\"true\" (or bind [attr.contenteditable] and set isEditing = true in the test) before the call.","Use sendKeys for inputs and textareas; setContenteditableValue is only for contenteditable nodes.","Trigger change detection (fixture.detectChanges()) after toggling the attribute so the DOM reflects editability.","Guard the call with getAttribute('contenteditable') to fail with a clearer test assertion instead of the throw."],"exampleFix":"// before\nit('sets text', () => { el.setContenteditableValue('x'); });\n// after\nit('sets text', () => { fixture.componentInstance.isEditing = true; fixture.detectChanges(); el.setContenteditableValue('x'); });","handlingStrategy":"validation","validationCode":"// In the unit test, before calling:\nel.removeAttribute('contenteditable') === undefined; // ensure present\nfixture.componentInstance.isEditing = true;\nfixture.detectChanges();\nexpect(el.getAttribute('contenteditable')).toBe('true');","typeGuard":"function canSetContenteditable(el: HTMLElement): boolean {\n  const v = el.getAttribute('contenteditable');\n  return v === 'true' || v === 'plaintext-only' || v === '';\n}","tryCatchPattern":"try {\n  await el.setContenteditableValue('new text');\n} catch (e) {\n  if (String(e.message).includes('setContenteditableValue can only be called')) {\n    fail('Element under test must render with contenteditable=\"true\"');\n  } else throw e;\n}","preventionTips":["Toggle [attr.contenteditable] state and run fixture.detectChanges() before editing in tests.","Use sendKeys for input/textarea tests instead of setContenteditableValue.","Add a small test helper that asserts contenteditable before setting values.","Render fixtures in the same mode (editing) the component uses in production."],"tags":["angular","cdk-testing","testbed","contenteditable"],"backgroundTag":"invalid-element-state","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}