Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/core/src/__tests__/__snapshots__/qwik.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -10145,7 +10145,7 @@ exports[`qwik > page-with-symbol 1`] = `
});
};
",
"low.js": "import { Symbol1 } from \\"./med.js\\";
"low.js": "import { SymbolHeaderSymbol } from \\"./med.js\\";

import {
Fragment,
Expand Down Expand Up @@ -10178,7 +10178,7 @@ export const MyComponentOnMount = (p) => {
return h(
Fragment,
null,
h(Symbol1, {
h(SymbolHeaderSymbol, {
class: \\"c713ty2\\",
symbol: {
model: \\"page\\",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4925,3 +4925,117 @@ function MyComponent(props) {
export default MyComponent;
"
`;

exports[`Symbol Serialization > Multiple symbols with different names 1`] = `
"import {
SymbolPrimaryButton,
SymbolSecondaryButton,
SymbolFooterSection,
} from \\"@components\\";

export default function MyComponent(props) {
return (
<>
<SymbolPrimaryButton
symbol={{
entry: \\"2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e\\",
model: \\"symbol\\",
ownerId: \\"99d964b716f94737a50de4d76134d098\\",
}}
text={\\"Get Started\\"}
variant={\\"primary\\"}
/>
<SymbolSecondaryButton
symbol={{
entry: \\"3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f\\",
model: \\"symbol\\",
ownerId: \\"99d964b716f94737a50de4d76134d098\\",
}}
text={\\"Learn More\\"}
variant={\\"secondary\\"}
/>
<SymbolFooterSection
symbol={{
entry: \\"4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a\\",
model: \\"symbol\\",
ownerId: \\"99d964b716f94737a50de4d76134d098\\",
}}
copyrightText={\\"© 2024 Company Name\\"}
showSocialLinks={true}
/>
</>
);
}
"
`;

exports[`Symbol Serialization > Symbol with basic metadata 1`] = `
"import { SymbolBasicSymbol } from \\"@components\\";

export default function MyComponent(props) {
return (
<SymbolBasicSymbol
symbol={{
entry: \\"5a009380a7274b1388f8f1e500d2e28a\\",
model: \\"symbol\\",
ownerId: \\"99d964b716f94737a50de4d76134d098\\",
}}
/>
);
}
"
`;

exports[`Symbol Serialization > Symbol with entry name 1`] = `
"import { SymbolHeaderNavigation } from \\"@components\\";

export default function MyComponent(props) {
return (
<SymbolHeaderNavigation
symbol={{
entry: \\"1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d\\",
model: \\"symbol\\",
ownerId: \\"99d964b716f94737a50de4d76134d098\\",
}}
logoUrl={\\"/logo.png\\"}
showSearch={true}
menuItems={[
{
label: \\"Home\\",
url: \\"/\\",
},
{
label: \\"About\\",
url: \\"/about\\",
},
]}
/>
);
}
"
`;

exports[`Symbol Serialization > Symbol with inputs as top-level props 1`] = `
"import { SymbolButtonComponent } from \\"@components\\";

export default function MyComponent(props) {
return (
<SymbolButtonComponent
symbol={{
entry: \\"7b8c9d0e1a2b3c4d5e6f7a8b9c0d1e2f\\",
model: \\"symbol\\",
ownerId: \\"99d964b716f94737a50de4d76134d098\\",
}}
buttonText={\\"Click me!\\"}
variant={\\"primary\\"}
isDisabled={false}
count={42}
config={{
showIcon: true,
iconPosition: \\"left\\",
}}
/>
);
}
"
`;
82 changes: 82 additions & 0 deletions packages/core/src/__tests__/builder/builder.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ import lazyLoadSection from '../data/builder/lazy-load-section.json?raw';
import localization from '../data/builder/localization.json?raw';
import slotsContent from '../data/builder/slots.json?raw';
import slots2Content from '../data/builder/slots2.json?raw';
import symbolBasic from '../data/builder/symbol-basic.json?raw';
import symbolMultiple from '../data/builder/symbol-multiple.json?raw';
import symbolWithInputs from '../data/builder/symbol-with-inputs.json?raw';
import symbolWithNamedEntry from '../data/builder/symbol-with-named-entry.json?raw';
import tagNameContent from '../data/builder/tag-name.json?raw';
import textBindings from '../data/builder/text-bindings.json?raw';
import advancedFor from '../data/for/advanced-for.raw.tsx?raw';
Expand Down Expand Up @@ -2094,3 +2098,81 @@ const bindingJson = {
],
},
};

describe('Symbol Serialization', () => {
test('Symbol with basic metadata', () => {
const builderContent = JSON.parse(symbolBasic) as BuilderContent;
const component = builderContentToMitosisComponent(builderContent);
const mitosis = componentToMitosis(mitosisOptions)({ component });

// Verify symbol name is sanitized and prefixed
expect(component.children[0].name).toBe('SymbolBasicSymbol');
expect(mitosis).toMatchSnapshot();
});

test('Symbol with entry name', () => {
const builderContent = JSON.parse(symbolWithNamedEntry) as BuilderContent;
const component = builderContentToMitosisComponent(builderContent);
const mitosis = componentToMitosis(mitosisOptions)({ component });

// Verify symbol name is sanitized and prefixed
expect(component.children[0].name).toBe('SymbolHeaderNavigation');
expect(mitosis).toMatchSnapshot();
});

test('Symbol with inputs as top-level props', () => {
const builderContent = JSON.parse(symbolWithInputs) as BuilderContent;
const component = builderContentToMitosisComponent(builderContent);
const mitosis = componentToMitosis(mitosisOptions)({ component });

// Verify inputs are top-level bindings
const symbolNode = component.children[0];
expect(symbolNode.name).toBe('SymbolButtonComponent');
expect(symbolNode.bindings).toHaveProperty('buttonText');
expect(symbolNode.bindings).toHaveProperty('variant');
expect(symbolNode.bindings).toHaveProperty('isDisabled');
expect(symbolNode.bindings).toHaveProperty('count');
expect(symbolNode.bindings).toHaveProperty('config');
expect(symbolNode.bindings.symbol).toBeDefined();

// Verify symbol binding doesn't contain data anymore
const symbolBinding = JSON.parse(symbolNode.bindings.symbol.code);
expect(symbolBinding.data).toBeUndefined();

expect(mitosis).toMatchSnapshot();
});

test('Multiple symbols with different names', () => {
const builderContent = JSON.parse(symbolMultiple) as BuilderContent;
const component = builderContentToMitosisComponent(builderContent);
const mitosis = componentToMitosis(mitosisOptions)({ component });

// Verify each symbol has unique name
expect(component.children[0].name).toBe('SymbolPrimaryButton');
expect(component.children[1].name).toBe('SymbolSecondaryButton');
expect(component.children[2].name).toBe('SymbolFooterSection');

// Verify inputs are extracted for each
expect(component.children[0].bindings).toHaveProperty('text');
expect(component.children[0].bindings).toHaveProperty('variant');
expect(component.children[1].bindings).toHaveProperty('text');
expect(component.children[1].bindings).toHaveProperty('variant');
expect(component.children[2].bindings).toHaveProperty('copyrightText');
expect(component.children[2].bindings).toHaveProperty('showSocialLinks');
Comment on lines +2150 to +2161
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd make this a snapshot check that way we can validate property names and values. (same feedback for other instances of this)


expect(mitosis).toMatchSnapshot();
});

test('Symbol roundtrip: Builder -> Mitosis -> Builder', () => {
const original = JSON.parse(symbolWithInputs) as BuilderContent;
const mitosisComponent = builderContentToMitosisComponent(original);
const backToBuilder = componentToBuilder()({ component: mitosisComponent });

// Verify the symbol structure is preserved
const originalSymbol = original.data?.blocks?.[0];
const roundtripSymbol = backToBuilder.data?.blocks?.[0];

expect(roundtripSymbol?.component?.name).toBeDefined();
expect(roundtripSymbol?.component?.options?.symbol).toBeDefined();
});
});
24 changes: 24 additions & 0 deletions packages/core/src/__tests__/data/builder/symbol-basic.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"data": {
"blocks": [
{
"@type": "@builder.io/sdk:Element",
"@version": 2,
"id": "builder-abc123",
"component": {
"name": "Symbol",
"options": {
"symbol": {
"entry": "5a009380a7274b1388f8f1e500d2e28a",
"model": "symbol",
"ownerId": "99d964b716f94737a50de4d76134d098",
"content": {
"name": "Basic Symbol"
}
}
}
}
}
]
}
}
72 changes: 72 additions & 0 deletions packages/core/src/__tests__/data/builder/symbol-multiple.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"data": {
"blocks": [
{
"@type": "@builder.io/sdk:Element",
"@version": 2,
"id": "builder-jkl012",
"component": {
"name": "Symbol",
"options": {
"symbol": {
"entry": "2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e",
"model": "symbol",
"ownerId": "99d964b716f94737a50de4d76134d098",
"content": {
"name": "Primary Button"
},
"data": {
"text": "Get Started",
"variant": "primary"
}
}
}
}
},
{
"@type": "@builder.io/sdk:Element",
"@version": 2,
"id": "builder-mno345",
"component": {
"name": "Symbol",
"options": {
"symbol": {
"entry": "3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f",
"model": "symbol",
"ownerId": "99d964b716f94737a50de4d76134d098",
"content": {
"name": "Secondary Button"
},
"data": {
"text": "Learn More",
"variant": "secondary"
}
}
}
}
},
{
"@type": "@builder.io/sdk:Element",
"@version": 2,
"id": "builder-pqr678",
"component": {
"name": "Symbol",
"options": {
"symbol": {
"entry": "4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a",
"model": "symbol",
"ownerId": "99d964b716f94737a50de4d76134d098",
"content": {
"name": "Footer Section"
},
"data": {
"copyrightText": "© 2024 Company Name",
"showSocialLinks": true
}
}
}
}
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"data": {
"blocks": [
{
"@type": "@builder.io/sdk:Element",
"@version": 2,
"id": "builder-def456",
"component": {
"name": "Symbol",
"options": {
"symbol": {
"entry": "7b8c9d0e1a2b3c4d5e6f7a8b9c0d1e2f",
"model": "symbol",
"ownerId": "99d964b716f94737a50de4d76134d098",
"content": {
"name": "Button Component"
},
"data": {
"buttonText": "Click me!",
"variant": "primary",
"isDisabled": false,
"count": 42,
"config": {
"showIcon": true,
"iconPosition": "left"
}
}
}
}
}
}
]
}
}
Loading