Skip to content

Commit 319f50e

Browse files
committed
Add code
1 parent 3b88921 commit 319f50e

File tree

3 files changed

+185
-153
lines changed

3 files changed

+185
-153
lines changed
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
2+
3+
exports[`registerCodegen should register codegen 1`] = `
4+
[
5+
{
6+
"code":
7+
"export function Test() {
8+
return <Box boxSize="100%" />
9+
}"
10+
,
11+
"language": "TYPESCRIPT",
12+
"title": "Test - Components",
13+
},
14+
{
15+
"code":
16+
"echo 'export function Test() {
17+
return <Box boxSize="100%" />
18+
}' > Test.tsx"
19+
,
20+
"language": "BASH",
21+
"title": "Test - Components CLI",
22+
},
23+
]
24+
`;
25+
26+
exports[`registerCodegen should register codegen 2`] = `
27+
[
28+
{
29+
"code": "<Box boxSize="100%" />",
30+
"language": "TYPESCRIPT",
31+
"title": "Main",
32+
},
33+
]
34+
`;
35+
36+
exports[`registerCodegen should register codegen 3`] = `[]`;

src/__tests__/code.test.ts

Lines changed: 142 additions & 150 deletions
Original file line numberDiff line numberDiff line change
@@ -1,175 +1,167 @@
11
import {
2-
afterAll,
2+
afterEach,
3+
beforeAll,
34
beforeEach,
45
describe,
56
expect,
7+
it,
68
mock,
79
spyOn,
8-
test,
910
} from 'bun:test'
10-
import { registerCodegen, runCommand } from '../code'
11-
import { Codegen } from '../codegen/Codegen'
11+
import { registerCodegen, run, runCommand } from '../code'
1212
import * as devupModule from '../commands/devup'
1313
import * as exportAssetsModule from '../commands/exportAssets'
1414
import * as exportComponentsModule from '../commands/exportComponents'
1515

16-
const exportDevupMock = mock(() => Promise.resolve())
17-
const importDevupMock = mock(() => Promise.resolve())
18-
const exportAssetsMock = mock(() => Promise.resolve())
19-
const exportComponentsMock = mock(() => Promise.resolve())
20-
const codegenRunMock = mock(() => Promise.resolve())
21-
const codegenGetCodeMock = mock(() => 'main-code')
22-
const codegenGetComponentsCodesMock = mock(
23-
() => [['Comp', '<Comp />']] as [string, string][],
24-
)
25-
26-
describe('code.ts', () => {
27-
beforeEach(() => {
28-
exportDevupMock.mockReset()
29-
importDevupMock.mockReset()
30-
exportAssetsMock.mockReset()
31-
exportComponentsMock.mockReset()
32-
codegenRunMock.mockReset()
33-
codegenGetCodeMock.mockReset()
34-
codegenGetComponentsCodesMock.mockReset()
35-
exportDevupMock.mockImplementation(() => Promise.resolve())
36-
importDevupMock.mockImplementation(() => Promise.resolve())
37-
exportAssetsMock.mockImplementation(() => Promise.resolve())
38-
exportComponentsMock.mockImplementation(() => Promise.resolve())
39-
codegenRunMock.mockImplementation(() => Promise.resolve())
40-
codegenGetCodeMock.mockImplementation(() => 'main-code')
41-
codegenGetComponentsCodesMock.mockImplementation(() => [
42-
['Comp', '<Comp />'],
43-
])
44-
45-
spyOn(devupModule, 'exportDevup').mockImplementation(exportDevupMock)
46-
spyOn(devupModule, 'importDevup').mockImplementation(importDevupMock)
47-
spyOn(exportAssetsModule, 'exportAssets').mockImplementation(
48-
exportAssetsMock,
49-
)
50-
spyOn(exportComponentsModule, 'exportComponents').mockImplementation(
51-
exportComponentsMock,
52-
)
53-
54-
spyOn(Codegen.prototype, 'run').mockImplementation(
55-
codegenRunMock as unknown as (
56-
node?: SceneNode,
57-
dep?: number,
58-
) => Promise<string>,
59-
)
60-
spyOn(Codegen.prototype, 'getCode').mockImplementation(codegenGetCodeMock)
61-
spyOn(Codegen.prototype, 'getComponentsCodes').mockImplementation(
62-
codegenGetComponentsCodesMock,
63-
)
64-
})
65-
66-
afterAll(() => {
67-
mock.restore()
68-
})
69-
70-
describe('runCommand', () => {
71-
test('dispatches devup export/import and asset/component commands', async () => {
72-
const closePlugin = mock(() => {})
73-
const figmaBase = {
74-
editorType: 'figma',
75-
closePlugin,
76-
} as unknown as typeof figma
77-
78-
runCommand({ ...figmaBase, command: 'export-devup' })
79-
await Promise.resolve()
80-
expect(exportDevupMock).toHaveBeenCalledWith('json')
81-
82-
runCommand({ ...figmaBase, command: 'export-devup-without-treeshaking' })
83-
await Promise.resolve()
84-
expect(exportDevupMock).toHaveBeenCalledWith('json', false)
85-
86-
runCommand({ ...figmaBase, command: 'export-devup-excel' })
87-
await Promise.resolve()
88-
expect(exportDevupMock).toHaveBeenCalledWith('excel')
89-
90-
runCommand({
91-
...figmaBase,
92-
command: 'export-devup-excel-without-treeshaking',
93-
})
94-
await Promise.resolve()
95-
expect(exportDevupMock).toHaveBeenCalledWith('excel', false)
96-
97-
runCommand({ ...figmaBase, command: 'import-devup' })
98-
await Promise.resolve()
99-
expect(importDevupMock).toHaveBeenCalledWith('json')
100-
101-
runCommand({ ...figmaBase, command: 'import-devup-excel' })
102-
await Promise.resolve()
103-
expect(importDevupMock).toHaveBeenCalledWith('excel')
16+
beforeAll(() => {
17+
;(globalThis as { figma?: unknown }).figma = {
18+
editorType: 'dev',
19+
mode: 'codegen',
20+
command: 'noop',
21+
codegen: { on: mock(() => {}) },
22+
closePlugin: mock(() => {}),
23+
} as unknown as typeof figma
24+
})
10425

105-
runCommand({ ...figmaBase, command: 'export-assets' })
106-
await Promise.resolve()
107-
expect(exportAssetsMock).toHaveBeenCalled()
26+
beforeEach(() => {
27+
spyOn(devupModule, 'exportDevup').mockImplementation(
28+
mock(() => Promise.resolve()),
29+
)
30+
spyOn(devupModule, 'importDevup').mockImplementation(
31+
mock(() => Promise.resolve()),
32+
)
33+
spyOn(exportAssetsModule, 'exportAssets').mockImplementation(
34+
mock(() => Promise.resolve()),
35+
)
36+
spyOn(exportComponentsModule, 'exportComponents').mockImplementation(
37+
mock(() => Promise.resolve()),
38+
)
39+
})
10840

109-
runCommand({ ...figmaBase, command: 'export-components' })
110-
await Promise.resolve()
111-
expect(exportComponentsMock).toHaveBeenCalled()
41+
afterEach(() => {
42+
;(globalThis as { figma?: unknown }).figma = undefined
43+
mock.restore()
44+
})
11245

113-
expect(closePlugin).toHaveBeenCalledTimes(8)
114-
})
46+
describe('runCommand', () => {
47+
it.each([
48+
['export-devup', ['json'], 'exportDevup'],
49+
['export-devup-without-treeshaking', ['json', false], 'exportDevup'],
50+
['export-devup-excel', ['excel'], 'exportDevup'],
51+
['export-devup-excel-without-treeshaking', ['excel', false], 'exportDevup'],
52+
['import-devup', ['json'], 'importDevup'],
53+
['import-devup-excel', ['excel'], 'importDevup'],
54+
['export-assets', [], 'exportAssets'],
55+
['export-components', [], 'exportComponents'],
56+
] as const)('dispatches %s', async (command, args, fn) => {
57+
const closePlugin = mock(() => {})
58+
const figmaMock = {
59+
editorType: 'figma',
60+
command,
61+
closePlugin,
62+
} as unknown as typeof figma
63+
64+
await runCommand(figmaMock as typeof figma)
65+
66+
switch (fn) {
67+
case 'exportDevup':
68+
expect(devupModule.exportDevup).toHaveBeenCalledWith(...args)
69+
break
70+
case 'importDevup':
71+
expect(devupModule.importDevup).toHaveBeenCalledWith(...args)
72+
break
73+
case 'exportAssets':
74+
expect(exportAssetsModule.exportAssets).toHaveBeenCalled()
75+
break
76+
case 'exportComponents':
77+
expect(exportComponentsModule.exportComponents).toHaveBeenCalled()
78+
break
79+
}
80+
expect(closePlugin).toHaveBeenCalled()
11581
})
82+
})
11683

117-
describe('registerCodegen', () => {
118-
test('wires generate handler and returns codes for devup-ui', async () => {
119-
const on = mock(() => {})
120-
const figmaMock = {
84+
describe('registerCodegen', () => {
85+
it.each([
86+
[
87+
{
12188
editorType: 'dev',
12289
mode: 'codegen',
123-
codegen: { on },
124-
} as unknown as typeof figma
125-
126-
registerCodegen(figmaMock)
127-
expect(on).toHaveBeenCalledWith('generate', expect.any(Function))
128-
129-
const callback = (on.mock.calls[0] as unknown[])[1] as unknown as ({
130-
node,
131-
language,
132-
}: {
133-
node: SceneNode
134-
language: string
135-
}) => Promise<unknown[]>
136-
137-
const res = (await callback({
138-
node: { type: 'FRAME', name: 'Frame1' } as unknown as SceneNode,
90+
command: 'noop',
91+
},
92+
{
93+
node: {
94+
type: 'COMPONENT',
95+
name: 'Test',
96+
},
13997
language: 'devup-ui',
140-
})) as { title: string; language: string }[]
141-
142-
expect(codegenRunMock).toHaveBeenCalled()
143-
expect(res.find((r) => r.title === 'Frame1')).toBeTruthy()
144-
expect(
145-
res.find((r) => r.title === 'Frame1 - Components CLI'),
146-
).toBeTruthy()
147-
})
148-
149-
test('returns empty array for other languages', async () => {
150-
const on = mock(() => {})
151-
const figmaMock = {
98+
},
99+
],
100+
[
101+
{
152102
editorType: 'dev',
153103
mode: 'codegen',
154-
codegen: { on },
155-
} as unknown as typeof figma
156-
157-
registerCodegen(figmaMock)
158-
const callback = (on.mock.calls[0] as unknown[])[1] as unknown as ({
159-
node,
160-
language,
161-
}: {
162-
node: SceneNode
163-
language: string
164-
}) => Promise<unknown[]>
165-
166-
const res = await callback({
167-
node: { type: 'FRAME', name: 'Frame1' } as unknown as SceneNode,
104+
command: 'noop',
105+
},
106+
{
107+
node: {
108+
type: 'FRAME',
109+
name: 'Main',
110+
},
111+
language: 'devup-ui',
112+
},
113+
],
114+
[
115+
{
116+
editorType: 'dev',
117+
mode: 'codegen',
118+
command: 'noop',
119+
},
120+
{
121+
node: {
122+
type: 'FRAME',
123+
name: 'Other',
124+
},
168125
language: 'other',
169-
})
126+
},
127+
],
128+
] as const)('should register codegen', async (figmaInfo, event) => {
129+
const figmaMock = {
130+
...figmaInfo,
131+
codegen: { on: mock(() => {}) },
132+
closePlugin: mock(() => {}),
133+
} as unknown as typeof figma
134+
registerCodegen(figmaMock)
135+
expect(figmaMock.codegen.on).toHaveBeenCalledWith(
136+
'generate',
137+
expect.any(Function),
138+
)
170139

171-
expect(Array.isArray(res)).toBe(true)
172-
expect((res as unknown[]).length).toBe(0)
173-
})
140+
expect(
141+
await (figmaMock.codegen.on as ReturnType<typeof mock>).mock.calls[0][1](
142+
event,
143+
),
144+
).toMatchSnapshot()
174145
})
175146
})
147+
148+
it('should not register codegen if figma is not defined', () => {
149+
run(undefined as unknown as typeof figma)
150+
expect(devupModule.exportDevup).not.toHaveBeenCalled()
151+
expect(devupModule.importDevup).not.toHaveBeenCalled()
152+
expect(exportAssetsModule.exportAssets).not.toHaveBeenCalled()
153+
expect(exportComponentsModule.exportComponents).not.toHaveBeenCalled()
154+
})
155+
156+
it('should run command', () => {
157+
const figmaMock = {
158+
editorType: 'figma',
159+
command: 'export-devup',
160+
closePlugin: mock(() => {}),
161+
} as unknown as typeof figma
162+
run(figmaMock as typeof figma)
163+
expect(devupModule.exportDevup).toHaveBeenCalledWith('json')
164+
expect(devupModule.importDevup).not.toHaveBeenCalled()
165+
expect(exportAssetsModule.exportAssets).not.toHaveBeenCalled()
166+
expect(exportComponentsModule.exportComponents).not.toHaveBeenCalled()
167+
})

src/code.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,11 @@ export function runCommand(ctx: typeof figma = figma) {
8181
}
8282
}
8383

84-
if (typeof figma !== 'undefined') {
85-
registerCodegen()
86-
runCommand()
84+
export function run(ctx: typeof figma) {
85+
if (typeof ctx !== 'undefined') {
86+
registerCodegen(ctx)
87+
runCommand(ctx)
88+
}
8789
}
90+
91+
run((globalThis as { figma?: unknown }).figma as typeof figma)

0 commit comments

Comments
 (0)