From 9541c7519e7002eef82aa7c261e3049986357e3e Mon Sep 17 00:00:00 2001 From: Anurag Yadav Date: Wed, 28 Oct 2026 20:37:00 +0530 Subject: [PATCH 1/2] Added template github maintainers Signed-off-by: Anurag Yadav --- package-lock.json | 18 - src/templates/github/index.ts | 1 + src/templates/github/maintainers-wanted.ts | 488 +++++++++++++++++++++ src/templates/registry.ts | 2 + tests/templates/maintainers-wanted.test.ts | 204 +++++++++ 5 files changed, 695 insertions(+), 18 deletions(-) create mode 100644 src/templates/github/maintainers-wanted.ts create mode 100644 tests/templates/maintainers-wanted.test.ts diff --git a/package-lock.json b/package-lock.json index 679a9e2..efaff88 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2324,9 +2324,6 @@ "cpu": [ "arm64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2343,9 +2340,6 @@ "cpu": [ "arm64" ], - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -2362,9 +2356,6 @@ "cpu": [ "ppc64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2381,9 +2372,6 @@ "cpu": [ "s390x" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2400,9 +2388,6 @@ "cpu": [ "x64" ], - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -2419,9 +2404,6 @@ "cpu": [ "x64" ], - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ diff --git a/src/templates/github/index.ts b/src/templates/github/index.ts index a88a197..0456b7c 100644 --- a/src/templates/github/index.ts +++ b/src/templates/github/index.ts @@ -15,3 +15,4 @@ export { default as githubGoodFirstIssues } from './good-first-issues'; export { default as githubMilestone } from './milestone'; export { default as githubSponsorsGoal } from './sponsors-goal'; export { default as githubSecurityAdvisory } from './security-advisory'; +export { default as githubMaintainersWanted } from './maintainers-wanted'; diff --git a/src/templates/github/maintainers-wanted.ts b/src/templates/github/maintainers-wanted.ts new file mode 100644 index 0000000..d364218 --- /dev/null +++ b/src/templates/github/maintainers-wanted.ts @@ -0,0 +1,488 @@ +import type { SatoriElement, TemplateDefinition } from '../types'; +import { autoFontSize, commonFields, isLightColor, mixColors, starIcon, truncate } from '../utils'; + +function issueIcon(size: number, color: string) { + return { + type: 'svg', + props: { + width: size, + height: size, + viewBox: '0 0 16 16', + children: [ + { + type: 'path', + props: { + d: 'M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z', + fill: color, + }, + }, + { + type: 'path', + props: { + d: 'M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0zM1.5 8a6.5 6.5 0 1 1 13 0 6.5 6.5 0 0 1-13 0z', + fill: color, + }, + }, + ], + }, + }; +} + +function checkIcon(size: number, color: string) { + return { + type: 'svg', + props: { + width: size, + height: size, + viewBox: '0 0 16 16', + fill: 'none', + stroke: color, + strokeWidth: '2.5', + strokeLinecap: 'round', + strokeLinejoin: 'round', + children: { + type: 'path', + props: { + d: 'M3.5 8.5l3 3 6-6', + }, + }, + }, + }; +} + +const template: TemplateDefinition = { + id: 'github-maintainers-wanted', + name: 'Maintainers Wanted', + category: 'github', + description: 'Call for open source maintainers with repository stats, pitch, help checklist and site branding', + tags: ['github', 'maintainers', 'open-source', 'contributors', 'community'], + fields: [ + { + ...commonFields.title, + defaultValue: 'acme/csv-stream', + placeholder: 'owner/repo', + }, + { + ...commonFields.description, + defaultValue: 'A streaming CSV parser for Node', + placeholder: 'A streaming CSV parser for Node', + required: false, + }, + { + key: 'stars', + label: 'Stars', + type: 'text', + defaultValue: '4.2k stars', + placeholder: '4.2k stars', + required: false, + group: 'Content', + }, + { + key: 'openIssues', + label: 'Open Issues', + type: 'text', + defaultValue: '38 open issues', + placeholder: '38 open issues', + required: false, + group: 'Content', + }, + { + key: 'help1', + label: 'Help Item 1', + type: 'text', + defaultValue: 'Review pull requests', + placeholder: 'Review pull requests', + required: false, + group: 'Content', + }, + { + key: 'help2', + label: 'Help Item 2', + type: 'text', + defaultValue: 'Triage new issues', + placeholder: 'Triage new issues', + required: false, + group: 'Content', + }, + { + key: 'help3', + label: 'Help Item 3', + type: 'text', + defaultValue: 'Cut releases', + placeholder: 'Cut releases', + required: false, + group: 'Content', + }, + { + ...commonFields.siteName, + defaultValue: 'github.com/acme/csv-stream', + placeholder: 'github.com/acme/csv-stream', + }, + { + ...commonFields.bgColor, + defaultValue: '#0d1117', + }, + { + ...commonFields.accentColor, + defaultValue: '#58a6ff', + }, + { + ...commonFields.textColor, + defaultValue: '#e6edf3', + }, + ], + defaults: { + title: 'acme/csv-stream', + description: 'A streaming CSV parser for Node', + stars: '4.2k stars', + openIssues: '38 open issues', + help1: 'Review pull requests', + help2: 'Triage new issues', + help3: 'Cut releases', + siteName: 'github.com/acme/csv-stream', + bgColor: '#0d1117', + accentColor: '#58a6ff', + textColor: '#e6edf3', + }, + render: (params) => { + const rawTitle = String(params.title ?? '').trim() || 'acme/csv-stream'; + const titleSize = autoFontSize(rawTitle, [ + { maxLen: 18, size: 54 }, + { maxLen: 28, size: 46 }, + { maxLen: 40, size: 38 }, + { maxLen: 55, size: 32 }, + ]); + const title = truncate(rawTitle, 60); + + const rawDescription = params.description !== undefined && params.description !== null + ? String(params.description).trim() + : 'A streaming CSV parser for Node'; + const descriptionSize = autoFontSize(rawDescription, [ + { maxLen: 40, size: 24 }, + { maxLen: 70, size: 21 }, + { maxLen: 100, size: 19 }, + { maxLen: 140, size: 17 }, + ]); + const description = rawDescription ? truncate(rawDescription, 140) : ''; + + const rawStars = params.stars !== undefined && params.stars !== null + ? String(params.stars).trim() + : '4.2k stars'; + const stars = rawStars ? truncate(rawStars, 30) : ''; + + const rawOpenIssues = params.openIssues !== undefined && params.openIssues !== null + ? String(params.openIssues).trim() + : '38 open issues'; + const openIssues = rawOpenIssues ? truncate(rawOpenIssues, 30) : ''; + + const defaultHelps = ['Review pull requests', 'Triage new issues', 'Cut releases']; + const helpKeys = ['help1', 'help2', 'help3'] as const; + const helpItems = helpKeys + .map((key, i) => { + const val = params[key]; + const text = val !== undefined && val !== null ? String(val).trim() : defaultHelps[i]; + return text ? truncate(text, 60) : ''; + }) + .filter(Boolean); + + const rawSiteName = params.siteName !== undefined && params.siteName !== null + ? String(params.siteName).trim() + : 'github.com/acme/csv-stream'; + const siteName = rawSiteName ? truncate(rawSiteName, 50) : ''; + + const bgColor = String(params.bgColor || '#0d1117'); + const accentColor = String(params.accentColor || '#58a6ff'); + const textColor = String(params.textColor || '#e6edf3'); + + const lightBg = isLightColor(bgColor); + const accentInk = lightBg ? mixColors(accentColor, '#000000', 0.45) : accentColor; + const cardBg = mixColors(bgColor, textColor, lightBg ? 0.04 : 0.06); + const cardBorder = mixColors(bgColor, textColor, lightBg ? 0.12 : 0.16); + const checkCircleBg = mixColors(bgColor, accentInk, lightBg ? 0.12 : 0.2); + const checkCircleBorder = mixColors(bgColor, accentInk, lightBg ? 0.25 : 0.35); + + const statsItems = [ + ...(stars + ? [ + { + type: 'div', + props: { + style: { + display: 'flex', + alignItems: 'center', + gap: '8px', + padding: '8px 18px', + borderRadius: '10px', + backgroundColor: cardBg, + border: `1px solid ${cardBorder}`, + }, + children: [ + starIcon(18, accentInk), + { + type: 'span', + props: { + style: { + fontSize: '17px', + fontWeight: 600, + color: textColor, + fontFamily: 'JetBrains Mono, monospace', + }, + children: stars, + }, + }, + ], + }, + }, + ] + : []), + ...(openIssues + ? [ + { + type: 'div', + props: { + style: { + display: 'flex', + alignItems: 'center', + gap: '8px', + padding: '8px 18px', + borderRadius: '10px', + backgroundColor: cardBg, + border: `1px solid ${cardBorder}`, + }, + children: [ + issueIcon(18, accentInk), + { + type: 'span', + props: { + style: { + fontSize: '17px', + fontWeight: 600, + color: textColor, + fontFamily: 'JetBrains Mono, monospace', + }, + children: openIssues, + }, + }, + ], + }, + }, + ] + : []), + ]; + + const helpRows: SatoriElement[] = helpItems.map((item) => ({ + type: 'div', + props: { + style: { + display: 'flex', + alignItems: 'center', + padding: '14px 22px', + borderRadius: '12px', + backgroundColor: cardBg, + border: `1px solid ${cardBorder}`, + width: '100%', + }, + children: [ + { + type: 'div', + props: { + style: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + width: '30px', + height: '30px', + borderRadius: '50%', + backgroundColor: checkCircleBg, + border: `1px solid ${checkCircleBorder}`, + marginRight: '16px', + flexShrink: 0, + }, + children: checkIcon(14, accentInk), + }, + }, + { + type: 'span', + props: { + style: { + fontSize: '19px', + fontWeight: 500, + color: textColor, + lineHeight: 1.4, + }, + children: item, + }, + }, + ], + }, + })); + + return { + type: 'div', + props: { + style: { + display: 'flex', + flexDirection: 'column', + width: '1200px', + height: '630px', + boxSizing: 'border-box', + backgroundColor: bgColor, + fontFamily: 'Inter, sans-serif', + padding: '48px 64px', + }, + children: [ + // Header block: Label badge, Title, Pitch + { + type: 'div', + props: { + style: { + display: 'flex', + flexDirection: 'column', + }, + children: [ + { + type: 'div', + props: { + style: { + display: 'flex', + alignItems: 'center', + padding: '5px 14px', + borderRadius: '999px', + backgroundColor: mixColors(bgColor, accentInk, lightBg ? 0.08 : 0.16), + border: `1px solid ${accentInk}55`, + marginBottom: '14px', + alignSelf: 'flex-start', + }, + children: { + type: 'span', + props: { + style: { + fontSize: '13px', + fontWeight: 700, + color: accentInk, + letterSpacing: '0.08em', + textTransform: 'uppercase', + }, + children: 'Maintainers wanted', + }, + }, + }, + }, + { + type: 'h1', + props: { + style: { + fontSize: `${titleSize}px`, + fontWeight: 800, + color: textColor, + lineHeight: 1.15, + margin: 0, + letterSpacing: '-0.02em', + }, + children: title, + }, + }, + ...(description + ? [ + { + type: 'p', + props: { + style: { + fontSize: `${descriptionSize}px`, + color: lightBg ? mixColors(bgColor, textColor, 0.7) : `${textColor}aa`, + lineHeight: 1.4, + margin: 0, + marginTop: '10px', + maxWidth: '960px', + }, + children: description, + }, + }, + ] + : []), + ], + }, + }, + // Stats row + ...(statsItems.length > 0 + ? [ + { + type: 'div', + props: { + style: { + display: 'flex', + alignItems: 'center', + gap: '14px', + marginTop: '20px', + marginBottom: '20px', + }, + children: statsItems, + }, + }, + ] + : []), + // Help items list + ...(helpRows.length > 0 + ? [ + { + type: 'div', + props: { + style: { + display: 'flex', + flexDirection: 'column', + gap: '10px', + width: '100%', + }, + children: helpRows, + }, + }, + ] + : []), + // Spacer + { + type: 'div', + props: { + style: { + display: 'flex', + flex: 1, + }, + children: [], + }, + }, + // Bottom branding + ...(siteName + ? [ + { + type: 'div', + props: { + style: { + display: 'flex', + alignItems: 'center', + paddingTop: '16px', + borderTop: `1px solid ${lightBg ? mixColors(bgColor, textColor, 0.12) : `${textColor}15`}`, + }, + children: [ + { + type: 'span', + props: { + style: { + fontSize: '17px', + fontWeight: 500, + color: lightBg ? mixColors(bgColor, textColor, 0.6) : `${textColor}88`, + fontFamily: 'Inter, sans-serif', + }, + children: siteName, + }, + }, + ], + }, + }, + ] + : []), + ], + }, + }; + }, +}; + +export default template; diff --git a/src/templates/registry.ts b/src/templates/registry.ts index 4e60e3c..59430a5 100644 --- a/src/templates/registry.ts +++ b/src/templates/registry.ts @@ -147,6 +147,7 @@ import githubGoodFirstIssues from './github/good-first-issues'; import githubMilestone from './github/milestone'; import githubSponsorsGoal from './github/sponsors-goal'; import githubSecurityAdvisory from './github/security-advisory'; +import githubMaintainersWanted from './github/maintainers-wanted'; [ githubRepoCard, githubContributionGraph, githubReadmeHero, githubReleaseNotes, @@ -158,6 +159,7 @@ import githubSecurityAdvisory from './github/security-advisory'; githubMilestone, githubSponsorsGoal, githubSecurityAdvisory, + githubMaintainersWanted, ].forEach(registerTemplate); // Event diff --git a/tests/templates/maintainers-wanted.test.ts b/tests/templates/maintainers-wanted.test.ts new file mode 100644 index 0000000..f9dc1ec --- /dev/null +++ b/tests/templates/maintainers-wanted.test.ts @@ -0,0 +1,204 @@ +import { describe, expect, it } from 'vitest'; +import maintainersWanted from '@/templates/github/maintainers-wanted'; +import { getTemplate } from '@/templates/registry'; +import { isLightColor, mixColors } from '@/templates/utils'; +import type { SatoriElement } from '@/templates/types'; + +function elements(node: unknown): SatoriElement[] { + if (Array.isArray(node)) return node.flatMap(elements); + if (!node || typeof node !== 'object' || !('type' in node)) return []; + + const element = node as SatoriElement; + return [element, ...elements(element.props.children)]; +} + +function texts(node: unknown): string[] { + if (typeof node === 'string') return [node]; + if (Array.isArray(node)) return node.flatMap(texts); + if (node && typeof node === 'object' && 'props' in node) { + return texts((node as SatoriElement).props.children); + } + return []; +} + +function styleOf(node: unknown, text: string): Record | undefined { + if (Array.isArray(node)) { + for (const child of node) { + const found = styleOf(child, text); + if (found) return found; + } + return undefined; + } + if (node && typeof node === 'object' && 'props' in node) { + const { style, children } = (node as SatoriElement).props; + if (children === text) return style; + return styleOf(children, text); + } + return undefined; +} + +const tree = (overrides: Record = {}) => + maintainersWanted.render({ ...maintainersWanted.defaults, ...overrides }); + +const render = (overrides: Record = {}) => texts(tree(overrides)); + +describe('github-maintainers-wanted', () => { + it('is registered in the github category and re-exported', async () => { + expect(getTemplate('github-maintainers-wanted')?.category).toBe('github'); + const exports = await import('@/templates/github'); + expect(exports.githubMaintainersWanted.id).toBe('github-maintainers-wanted'); + }); + + it('has the fields the issue asks for, with the defaults it names', () => { + expect(maintainersWanted.fields.map((field) => field.key)).toEqual([ + 'title', + 'description', + 'stars', + 'openIssues', + 'help1', + 'help2', + 'help3', + 'siteName', + 'bgColor', + 'accentColor', + 'textColor', + ]); + expect(maintainersWanted.defaults).toMatchObject({ + title: 'acme/csv-stream', + description: 'A streaming CSV parser for Node', + stars: '4.2k stars', + openIssues: '38 open issues', + help1: 'Review pull requests', + help2: 'Triage new issues', + help3: 'Cut releases', + siteName: 'github.com/acme/csv-stream', + bgColor: '#0d1117', + accentColor: '#58a6ff', + textColor: '#e6edf3', + }); + }); + + it('renders a 1200x630 card and every div is flex', () => { + const root = tree(); + expect(root.props.style).toMatchObject({ width: '1200px', height: '630px' }); + for (const el of elements(root).filter((e) => e.type === 'div')) { + expect(el.props.style?.display).toBe('flex'); + } + }); + + it('renders with its defaults in order', () => { + expect(render()).toEqual([ + 'Maintainers wanted', + 'acme/csv-stream', + 'A streaming CSV parser for Node', + '4.2k stars', + '38 open issues', + 'Review pull requests', + 'Triage new issues', + 'Cut releases', + 'github.com/acme/csv-stream', + ]); + }); + + it('shrinks long repository name with autoFontSize and truncates', () => { + const normalTitle = 'acme/csv-stream'; + const longTitle = 'acme-corporation/ultra-fast-streaming-csv-parser-and-serializer-for-nodejs'; + + const normalStyle = styleOf(tree({ title: normalTitle }), normalTitle); + const longTree = tree({ title: longTitle }); + const renderedTexts = texts(longTree); + const truncatedTitle = renderedTexts.find((t) => t.startsWith('acme-corporation/')); + expect(truncatedTitle).toBeDefined(); + expect(truncatedTitle?.length).toBeLessThanOrEqual(60); + + const longStyle = styleOf(longTree, truncatedTitle!); + const normalSize = parseInt(String(normalStyle?.fontSize), 10); + const longSize = parseInt(String(longStyle?.fontSize), 10); + expect(longSize).toBeLessThan(normalSize); + }); + + it('shrinks long pitch with autoFontSize and truncates', () => { + const normalPitch = 'A streaming CSV parser for Node'; + const longPitch = + 'A high-performance streaming CSV parser and serializer designed specifically for enterprise Node.js environments with custom delimiters, asynchronous pipelines, and schema validation.'; + + const normalStyle = styleOf(tree({ description: normalPitch }), normalPitch); + const longTree = tree({ description: longPitch }); + const renderedTexts = texts(longTree); + const truncatedPitch = renderedTexts.find((t) => t.startsWith('A high-performance')); + expect(truncatedPitch).toBeDefined(); + expect(truncatedPitch?.length).toBeLessThanOrEqual(140); + + const longStyle = styleOf(longTree, truncatedPitch!); + const normalSize = parseInt(String(normalStyle?.fontSize), 10); + const longSize = parseInt(String(longStyle?.fontSize), 10); + expect(longSize).toBeLessThan(normalSize); + }); + + it('skips blank help lines with no gaps', () => { + const withBlankMiddle = render({ + help1: 'Review pull requests', + help2: ' ', + help3: 'Cut releases', + }); + expect(withBlankMiddle).toEqual([ + 'Maintainers wanted', + 'acme/csv-stream', + 'A streaming CSV parser for Node', + '4.2k stars', + '38 open issues', + 'Review pull requests', + 'Cut releases', + 'github.com/acme/csv-stream', + ]); + + const withOnlyOneHelp = render({ + help1: ' ', + help2: 'Triage new issues', + help3: '', + }); + expect(withOnlyOneHelp).toEqual([ + 'Maintainers wanted', + 'acme/csv-stream', + 'A streaming CSV parser for Node', + '4.2k stars', + '38 open issues', + 'Triage new issues', + 'github.com/acme/csv-stream', + ]); + }); + + it('hides an empty pitch, stars, openIssues or site name (or only spaces) cleanly', () => { + expect(render({ description: '' })).not.toContain('A streaming CSV parser for Node'); + expect(render({ description: ' ' })).not.toContain('A streaming CSV parser for Node'); + + expect(render({ stars: '' })).not.toContain('4.2k stars'); + expect(render({ stars: ' ' })).not.toContain('4.2k stars'); + + expect(render({ openIssues: '' })).not.toContain('38 open issues'); + expect(render({ openIssues: ' ' })).not.toContain('38 open issues'); + + expect(render({ siteName: '' })).not.toContain('github.com/acme/csv-stream'); + expect(render({ siteName: ' ' })).not.toContain('github.com/acme/csv-stream'); + + const allOptionalCleared = render({ + description: '', + stars: ' ', + openIssues: '', + help1: '', + help2: ' ', + help3: '', + siteName: '', + }); + expect(allOptionalCleared).toEqual(['Maintainers wanted', 'acme/csv-stream']); + }); + + it('keeps the label and accent text readable on a light background', () => { + const lightTree = tree({ bgColor: '#ffffff', accentColor: '#58a6ff' }); + const labelStyle = styleOf(lightTree, 'Maintainers wanted'); + const labelColor = String(labelStyle?.color); + + expect(labelColor).toBe(mixColors('#58a6ff', '#000000', 0.45)); + expect(isLightColor(labelColor)).toBe(false); + }); +}); From 5d08b24bae84884b73777060d564fd0867907f07 Mon Sep 17 00:00:00 2001 From: Anurag Yadav Date: Wed, 28 Oct 2026 21:07:40 +0530 Subject: [PATCH 2/2] revert file and fixed margin Signed-off-by: Anurag Yadav --- package-lock.json | 18 ++++++++++++++++++ src/templates/github/maintainers-wanted.ts | 1 + tests/templates/maintainers-wanted.test.ts | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/package-lock.json b/package-lock.json index efaff88..679a9e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2324,6 +2324,9 @@ "cpu": [ "arm64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2340,6 +2343,9 @@ "cpu": [ "arm64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -2356,6 +2362,9 @@ "cpu": [ "ppc64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2372,6 +2381,9 @@ "cpu": [ "s390x" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2388,6 +2400,9 @@ "cpu": [ "x64" ], + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -2404,6 +2419,9 @@ "cpu": [ "x64" ], + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ diff --git a/src/templates/github/maintainers-wanted.ts b/src/templates/github/maintainers-wanted.ts index d364218..40a04e1 100644 --- a/src/templates/github/maintainers-wanted.ts +++ b/src/templates/github/maintainers-wanted.ts @@ -432,6 +432,7 @@ const template: TemplateDefinition = { flexDirection: 'column', gap: '10px', width: '100%', + marginTop: statsItems.length > 0 ? '0px' : '24px', }, children: helpRows, }, diff --git a/tests/templates/maintainers-wanted.test.ts b/tests/templates/maintainers-wanted.test.ts index f9dc1ec..abaa8ce 100644 --- a/tests/templates/maintainers-wanted.test.ts +++ b/tests/templates/maintainers-wanted.test.ts @@ -201,4 +201,22 @@ describe('github-maintainers-wanted', () => { expect(labelColor).toBe(mixColors('#58a6ff', '#000000', 0.45)); expect(isLightColor(labelColor)).toBe(false); }); + + it('gives the help list a top margin when the stats row is hidden', () => { + const defaultElements = elements(tree()); + const helpContainerWithStats = defaultElements.find((el) => + Array.isArray(el.props.children) && + el.props.children.length === 3 && + el.props.style?.gap === '10px' + ); + expect(helpContainerWithStats?.props.style?.marginTop).toBe('0px'); + + const noStatsElements = elements(tree({ stars: '', openIssues: '' })); + const helpContainerWithoutStats = noStatsElements.find((el) => + Array.isArray(el.props.children) && + el.props.children.length === 3 && + el.props.style?.gap === '10px' + ); + expect(helpContainerWithoutStats?.props.style?.marginTop).toBe('24px'); + }); });