From e81d60b86800d77e2e1482ee0e34dff3a3f92813 Mon Sep 17 00:00:00 2001 From: REHAN-503 Date: Fri, 12 Jun 2026 18:34:35 +0530 Subject: [PATCH] test(DescriptionSection): add massive scaling tests for #4350 - Test 280-char limit with counter validation - Test oversized input clamping (500 -> 280 chars) - Test amber warning threshold (40 chars remaining) - Test generateReadme with 1000 calls - Test DOM stability after 500 re-renders Closes #4350 --- ...escriptionSection.massive_scaling.test.tsx | 177 ++++++++++++++++++ 1 file changed, 177 insertions(+) create mode 100644 app/generator/components/sections/DescriptionSection.massive_scaling.test.tsx diff --git a/app/generator/components/sections/DescriptionSection.massive_scaling.test.tsx b/app/generator/components/sections/DescriptionSection.massive_scaling.test.tsx new file mode 100644 index 000000000..41104aa63 --- /dev/null +++ b/app/generator/components/sections/DescriptionSection.massive_scaling.test.tsx @@ -0,0 +1,177 @@ +import '@testing-library/jest-dom/vitest'; +import { render, screen, fireEvent } from '@testing-library/react'; +import React from 'react'; +import { describe, it, expect, vi, beforeEach, type Mock } from 'vitest'; +import { DescriptionSection } from './DescriptionSection'; +import * as readmeGenerator from '../../utils/readmeGenerator'; +import type { GeneratorState } from '../../types'; + +vi.mock('lucide-react', () => ({ + ChevronDown: () => , +})); + +vi.mock('../../utils/readmeGenerator', () => ({ + generateReadme: vi.fn(), +})); + +const CHAR_LIMIT = 280; +const NEAR_LIMIT_THRESHOLD = 40; + +const baseState: GeneratorState = { + name: 'Octocat', + description: '', + selectedTechs: [], + selectedSocials: [], + socialLinks: {}, + githubUsername: 'octocat', + showCommitPulse: false, + commitPulseAccent: '', + showSnakeGraph: false, + showPacmanGraph: false, + graphPlacement: 'bottom', +}; + +describe('DescriptionSection – Massive Data Sets and Extreme High Bounds Scaling (Variation 2)', () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it('Case 1: renders correctly at the exact 280-character limit — counter reads zero and layout stays intact', () => { + const maxValue = 'A'.repeat(CHAR_LIMIT); + + const { container } = render(); + + expect(screen.getByText('0 characters remaining')).toBeInTheDocument(); + + const counter = screen.getByText('0 characters remaining'); + expect(counter.className).toMatch(/amber/); + + const textarea = screen.getByRole('textbox') as HTMLTextAreaElement; + expect(textarea.value).toBe(maxValue); + expect(textarea.value.length).toBe(CHAR_LIMIT); + + expect(container.querySelectorAll('[role="region"]').length).toBe(1); + + const bodyText = document.body.textContent ?? ''; + expect(bodyText.indexOf('Description')).toBeLessThan(bodyText.indexOf('Bio / Tagline')); + }); + + it('Case 2: onChange clamps oversized input to 280 chars and never emits a negative remaining count', () => { + const onChange = vi.fn(); + render(); + + const textarea = screen.getByRole('textbox') as HTMLTextAreaElement; + + const oversizedInput = 'B'.repeat(500); + fireEvent.change(textarea, { target: { value: oversizedInput } }); + + expect(onChange).toHaveBeenCalledTimes(1); + const emittedValue: string = onChange.mock.calls[0][0]; + expect(emittedValue.length).toBe(CHAR_LIMIT); + expect(emittedValue).toBe('B'.repeat(CHAR_LIMIT)); + + const { rerender } = render(); + expect(screen.getByText('0 characters remaining')).toBeInTheDocument(); + + rerender(); + expect(screen.getByText('1 characters remaining')).toBeInTheDocument(); + }); + + it('Case 3: amber warning activates at the near-limit threshold across full range re-renders', () => { + const onChange = vi.fn(); + const { rerender } = render(); + + const greyBoundary = CHAR_LIMIT - NEAR_LIMIT_THRESHOLD; + const amberBoundary = greyBoundary + 1; + + const start = performance.now(); + + for (let len = 0; len <= CHAR_LIMIT; len++) { + rerender(); + } + + const elapsed = performance.now() - start; + expect(elapsed).toBeLessThan(5000); + + const counterAtMax = screen.getByText('0 characters remaining'); + expect(counterAtMax.className).toMatch(/amber/); + + rerender(); + const counterAtGrey = screen.getByText('40 characters remaining'); + expect(counterAtGrey.className).not.toMatch(/amber/); + + rerender(); + const counterAtAmber = screen.getByText('39 characters remaining'); + expect(counterAtAmber.className).toMatch(/amber/); + }); + + it('Case 4: generateReadme embeds full 280-char description and handles 1,000 calls efficiently', () => { + const maxDescription = 'D'.repeat(CHAR_LIMIT); + const mockGenerateReadme = readmeGenerator.generateReadme as Mock; + + mockGenerateReadme.mockReturnValue(`# 👋 Hi, I'm Octocat\n\n

${maxDescription}

`); + + const singleResult = mockGenerateReadme({ ...baseState, description: maxDescription }); + expect(singleResult).toContain(`

${maxDescription}

`); + expect(singleResult).toContain("# 👋 Hi, I'm Octocat"); + + const COUNT = 1000; + const start = performance.now(); + + for (let i = 0; i < COUNT; i++) { + mockGenerateReadme({ + ...baseState, + description: `${'E'.repeat(CHAR_LIMIT - 6)}${i.toString().padStart(6, '0')}`, + name: `Contributor ${i}`, + }); + } + + const elapsed = performance.now() - start; + expect(elapsed).toBeLessThan(1000); + }); + + it('Case 5: DOM structure stays intact after 500 rapid re-renders at extreme bounds', () => { + const onChange = vi.fn(); + + const fixtures = [ + '', + 'M'.repeat(140), + 'N'.repeat(CHAR_LIMIT - 39), + 'O'.repeat(CHAR_LIMIT), + ] as const; + + const { rerender, container } = render( + + ); + + const RERENDER_COUNT = 500; + const start = performance.now(); + + for (let i = 0; i < RERENDER_COUNT; i++) { + rerender(); + } + + const elapsed = performance.now() - start; + expect(elapsed).toBeLessThan(5000); + + expect(container.querySelectorAll('[role="region"]').length).toBe(1); + + expect(screen.getByText('Description')).toBeInTheDocument(); + expect(screen.getByText(/bio \/ tagline/i)).toBeInTheDocument(); + expect(screen.getByText(/characters remaining/i)).toBeInTheDocument(); + + const textarea = screen.getByRole('textbox') as HTMLTextAreaElement; + expect(textarea).toBeInTheDocument(); + + fireEvent.change(textarea, { target: { value: 'P'.repeat(100) } }); + expect(onChange).toHaveBeenLastCalledWith('P'.repeat(100)); + + expect(screen.getAllByRole('textbox').length).toBe(1); + expect(screen.getAllByRole('button').length).toBe(1); + + const toggleBtn = screen.getByRole('button'); + expect(toggleBtn).toHaveAttribute('aria-expanded', 'true'); + fireEvent.click(toggleBtn); + expect(toggleBtn).toHaveAttribute('aria-expanded', 'false'); + }); +});