Skip to content

Commit

Permalink
Fix Figma source when project has multiple files (#623)
Browse files Browse the repository at this point in the history
  • Loading branch information
joshwooding authored Jul 8, 2024
1 parent 258eea2 commit 1c5a967
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changeset/sixty-gifts-prove.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@jpmorganchase/mosaic-source-figma': patch
---

Fixed projects with multiple files not working.
84 changes: 73 additions & 11 deletions packages/source-figma/src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,11 @@ const options = {
const getProjectById = (id: number) =>
options.projects.find(item => item.id === id) || { meta: { tags: [] } };

const createProjectsResponse = (fileId: string) => ({
const createProjectsResponse = (fileIds: string[]) => ({
name: 'Figma Test Patterns',
files: [
{
key: fileId
}
]
files: fileIds.map(fileId => ({
key: fileId
}))
});

const createProjectFilesResponse = (patternId: string, nodeId: string) => ({
Expand Down Expand Up @@ -93,7 +91,7 @@ const successHandlers = [
// Projects
rest.get('https://myfigma.com/getproject/:project_id/*', (req, res, ctx) => {
const { project_id } = req.params;
const fileId = project_id === '888' ? 'file888' : 'file999';
const fileId = project_id === '888' ? ['file888'] : ['file999'];
return res(ctx.status(200), ctx.json(createProjectsResponse(fileId)));
}),
// Files
Expand All @@ -116,18 +114,47 @@ const successHandlers = [
);
})
];

const multiHandlers = [
// Projects
rest.get('https://myfigma.com/getproject/:project_id/*', (req, res, ctx) => {
const { project_id } = req.params;
const fileIds = project_id === '888' ? ['file111', 'file222'] : [];
return res(ctx.status(200), ctx.json(createProjectsResponse(fileIds)));
}),
// Files
rest.get('https://myfigma.com/getfile/:file_id', (req, res, ctx) => {
const { file_id } = req.params;
const title = file_id.toString().replace('file', '');
const pattern = `jpmSaltPattern_${title}_pattern1`;
return res(ctx.status(200), ctx.json(createProjectFilesResponse(pattern, '2:0')));
}),
// Thumbnails
rest.get('https://myfigma.com/generatethumb/:project_id', (req, res, ctx) => {
const { project_id } = req.params;
const url = new URL(req.url);
const nodeId = url.searchParams.get('ids') as string;
return res(
ctx.status(200),
ctx.json({
images: { [nodeId]: `/thumbnail/${project_id}/${nodeId}` }
})
);
})
];

describe('GIVEN a Figma Source ', () => {
describe('WHEN a fetch is successful', () => {
const server = setupServer();
beforeAll(() => {
server.use(...successHandlers);
server.listen({ onUnhandledRequest: 'warn' });
});

afterAll(() => {
server.close();
});

it('should return the 2 patterns for the 2 subscribed projects', done => {
server.use(...successHandlers);
server.listen({ onUnhandledRequest: 'warn' });

const source$: Observable<FigmaPage[]> = Source.create(options, { schedule });
source$.pipe(take(1)).subscribe({
next: result => {
Expand Down Expand Up @@ -157,5 +184,40 @@ describe('GIVEN a Figma Source ', () => {
complete: () => done()
});
});

it('should support multiple files', done => {
server.use(...multiHandlers);
server.listen({ onUnhandledRequest: 'warn' });

const source$: Observable<FigmaPage[]> = Source.create(options, { schedule });
source$.pipe(take(1)).subscribe({
next: result => {
const meta0: Record<string, any> = {
...getProjectById(888).meta,
tags: ['some-tag1', 'some-tag2', ...getProjectById(888).meta.tags]
};
meta0.data = {
...meta0.data,
contentUrl: `/thumbnail/file111/2:0`,
fileId: 'file111',
projectId: '888'
};
expect(result[0]).toEqual(createExpectedResult('jpmSaltPattern_111_pattern1', meta0));

const meta1: Record<string, any> = {
...getProjectById(888).meta,
tags: ['some-tag1', 'some-tag2', ...getProjectById(888).meta.tags]
};
meta1.data = {
...meta1.data,
fileId: 'file222',
contentUrl: `/thumbnail/file222/2:0`,
projectId: '888'
};
expect(result[1]).toEqual(createExpectedResult('jpmSaltPattern_222_pattern1', meta1));
},
complete: () => done()
});
});
});
});
24 changes: 15 additions & 9 deletions packages/source-figma/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,15 @@ const FigmaSource: Source<FigmaSourceOptions, FigmaPage> = {
requestHeaders: requestHeadersParam
} = parsedOptions;

const projectEndpoints = projects.reduce<Record<string, string>>((result, project) => {
const projectEndpoints: Record<string, string> = {};
const projectById: Record<string, typeof projects[number]> = {};

projects.forEach(project => {
const projectId = project.id.toString();
return {
...result,
[projectId]: endpoints.getProject.replace(':project_id', projectId)
};
}, {});

projectEndpoints[projectId] = endpoints.getProject.replace(':project_id', projectId);
projectById[projectId] = project;
});

const projectsTransformer: HttpSourceResponseTransformerType<
ProjectsResponse,
Expand Down Expand Up @@ -109,6 +111,9 @@ const FigmaSource: Source<FigmaSourceOptions, FigmaPage> = {
}, []);
};

const getPatternPrefix = (metadata: Record<string, any>) =>
projectById[metadata?.data?.projectId].patternPrefix ?? null;

const projectFilesTransformer = (
response: ProjectFilesResponse,
_prefixDir: string,
Expand All @@ -118,7 +123,8 @@ const FigmaSource: Source<FigmaSourceOptions, FigmaPage> = {
const {
document: { sharedPluginData }
} = response;
const { patternPrefix } = projects[index];
const sourceProvidedMetadata = transformerOptions[index].meta ?? {};
const patternPrefix = getPatternPrefix(sourceProvidedMetadata);
return Object.keys(sharedPluginData).reduce<FigmaPage[]>((figmaPagesResult, patternId) => {
if (patternId.indexOf(patternPrefix) === 0) {
/** Figma provided metadata */
Expand All @@ -131,7 +137,7 @@ const FigmaSource: Source<FigmaSourceOptions, FigmaPage> = {
...patternData
}
};
const sourceProvidedMetadata = transformerOptions[index].meta;

const figmaPageMeta = deepmerge<FigmaPage, Partial<FigmaPage>>(
figmaProvidedMetadata,
sourceProvidedMetadata || {}
Expand Down Expand Up @@ -216,7 +222,7 @@ const FigmaSource: Source<FigmaSourceOptions, FigmaPage> = {
);

const thumbnailRequestUrls = Object.keys(thumbnailNodes).map(fileId => {
let generateThumbnailUrl = endpoints.generateThumbnail.replace(':project_id', fileId);
const generateThumbnailUrl = endpoints.generateThumbnail.replace(':project_id', fileId);
return generateThumbnailUrl.replace(':node_id', thumbnailNodes[fileId].join(','));
});
return createHttpSource<GenerateThumbnailResponse, FigmaPage>({
Expand Down

0 comments on commit 1c5a967

Please sign in to comment.