-
Notifications
You must be signed in to change notification settings - Fork 2
Open
Labels
bugSomething isn't workingSomething isn't workinghelp wantedExtra attention is neededExtra attention is needed
Description
Prerequisites
- I have read the Contributing Guidelines.
- I agree to follow the Code of Conduct.
- I have searched for existing issues that already report this problem, without success.
Stencil Version
4.38.3
Current Behavior
newSpecPage from jest-stencil-runner does not call @AttrDeserialize methods. The prop retains the raw attribute string instead of the deserialized object.
instance.testequals'{"foo":"bar","num":42}'(string)instance.testshould equal{ foo: 'bar', num: 42 }(object)
Expected Behavior
When a component uses @AttrDeserialize to parse complex attribute strings (e.g., JSON), the newSpecPage function should invoke the deserializer when hydrating the component from HTML. The prop should contain the deserialized value (parsed object), not the raw attribute string.
System Info
System: node 24.11.0
Platform: darwin (24.6.0)
CPU Model: Apple M2 Pro (12 cpus)
Build: 1762374454
Stencil: 4.38.3 😋
TypeScript: 5.9.3
Rollup: 4.34.9
Parse5: 7.2.1
jQuery: 4.0.0-pre
Terser: 5.37.0
jest-stencil-runner: 0.0.9
Jest: 30.2.0Steps to Reproduce
- Create a component with
@PropSerializeand@AttrDeserializedecorators:
import { AttrDeserialize, Component, Prop, PropSerialize, h } from '@stencil/core';
@Component({
tag: 'inner-one',
shadow: true,
})
export class InnerOne {
@Prop() test: Record<string, unknown> = {};
@PropSerialize('test')
userSerialize(newVal: Record<string, unknown>) {
try {
return JSON.stringify(newVal);
} catch (e) {
return null;
}
}
@AttrDeserialize('test')
userDeserialize(newVal: string) {
try {
return JSON.parse(newVal);
} catch (e) {
return null;
}
}
render() {
return <div class="test">{JSON.stringify(this.test)}</div>;
}
}- Write a spec test:
import { newSpecPage } from 'jest-stencil-runner';
import { InnerOne } from './inner-one';
it('should deserialize test prop from JSON attribute string', async () => {
const page = await newSpecPage({
components: [InnerOne],
html: `<inner-one test='{"foo":"bar","num":42}'></inner-one>`,
});
const instance = page.rootInstance as InnerOne;
expect(instance.test).toEqual({ foo: 'bar', num: 42 }); // FAILS
});-
Run the test — it fails because
instance.testis the raw string, not the parsed object. -
Additionally, accessing object properties in render fails:
render() {
return (
<div>
<div class="test">{JSON.stringify(this.test)}</div>
<div class="test-obj">{this.test?.foo}</div>
</div>
);
}it('should render test prop from JSON attribute string', async () => {
const page = await newSpecPage({
components: [InnerOne],
html: `<inner-one test='{"foo":"bar","num":42}'></inner-one>`,
});
const testDiv = page.root?.shadowRoot?.querySelector('div.test-obj');
expect(testDiv).toEqualText('bar'); // FAILS - renders empty because this.test is a string
});Code Reproduction URL
...
Additional Information
No response
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workinghelp wantedExtra attention is neededExtra attention is needed