Run lint and prettier
CI Pipeline / test (20) (pull_request) Successful in 3m0s
CI Pipeline / test (18) (pull_request) Successful in 3m18s
CI Pipeline / e2e (firefox) (pull_request) Successful in 3m20s
CI Pipeline / e2e (chromium) (pull_request) Successful in 3m54s
CI Pipeline / e2e (webkit) (pull_request) Successful in 3m41s
CI Pipeline / performance (pull_request) Successful in 3m3s
CI Pipeline / visual-regression (pull_request) Successful in 7m12s
CI Pipeline / storybook (pull_request) Successful in 1m29s
CI Pipeline / lint (pull_request) Failing after 1m7s
CI Pipeline / build (pull_request) Successful in 1m20s
CI Pipeline / test (20) (pull_request) Successful in 3m0s
CI Pipeline / test (18) (pull_request) Successful in 3m18s
CI Pipeline / e2e (firefox) (pull_request) Successful in 3m20s
CI Pipeline / e2e (chromium) (pull_request) Successful in 3m54s
CI Pipeline / e2e (webkit) (pull_request) Successful in 3m41s
CI Pipeline / performance (pull_request) Successful in 3m3s
CI Pipeline / visual-regression (pull_request) Successful in 7m12s
CI Pipeline / storybook (pull_request) Successful in 1m29s
CI Pipeline / lint (pull_request) Failing after 1m7s
CI Pipeline / build (pull_request) Successful in 1m20s
This commit is contained in:
@@ -46,7 +46,7 @@ export async function POST(request) {
|
|||||||
|
|
||||||
// Log for monitoring
|
// Log for monitoring
|
||||||
console.log(
|
console.log(
|
||||||
`Web Vital received: ${metric} = ${data.value}ms (${data.rating})`
|
`Web Vital received: ${metric} = ${data.value}ms (${data.rating})`,
|
||||||
);
|
);
|
||||||
|
|
||||||
return NextResponse.json({ success: true });
|
return NextResponse.json({ success: true });
|
||||||
@@ -54,7 +54,7 @@ export async function POST(request) {
|
|||||||
console.error("Error processing web vital:", error);
|
console.error("Error processing web vital:", error);
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: "Internal server error" },
|
{ error: "Internal server error" },
|
||||||
{ status: 500 }
|
{ status: 500 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -70,7 +70,7 @@ export async function GET() {
|
|||||||
if (file.endsWith(".json")) {
|
if (file.endsWith(".json")) {
|
||||||
const metric = file.replace(".json", "");
|
const metric = file.replace(".json", "");
|
||||||
const data = JSON.parse(
|
const data = JSON.parse(
|
||||||
fs.readFileSync(path.join(WEB_VITALS_DIR, file), "utf8")
|
fs.readFileSync(path.join(WEB_VITALS_DIR, file), "utf8"),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (data.length > 0) {
|
if (data.length > 0) {
|
||||||
@@ -86,14 +86,14 @@ export async function GET() {
|
|||||||
average:
|
average:
|
||||||
values.length > 0
|
values.length > 0
|
||||||
? Math.round(
|
? Math.round(
|
||||||
values.reduce((a, b) => a + b, 0) / values.length
|
values.reduce((a, b) => a + b, 0) / values.length,
|
||||||
)
|
)
|
||||||
: 0,
|
: 0,
|
||||||
min: values.length > 0 ? Math.min(...values) : 0,
|
min: values.length > 0 ? Math.min(...values) : 0,
|
||||||
max: values.length > 0 ? Math.max(...values) : 0,
|
max: values.length > 0 ? Math.max(...values) : 0,
|
||||||
goodCount: ratings.filter((r) => r === "good").length,
|
goodCount: ratings.filter((r) => r === "good").length,
|
||||||
needsImprovementCount: ratings.filter(
|
needsImprovementCount: ratings.filter(
|
||||||
(r) => r === "needs-improvement"
|
(r) => r === "needs-improvement",
|
||||||
).length,
|
).length,
|
||||||
poorCount: ratings.filter((r) => r === "poor").length,
|
poorCount: ratings.filter((r) => r === "poor").length,
|
||||||
lastUpdated: data[data.length - 1]?.receivedAt,
|
lastUpdated: data[data.length - 1]?.receivedAt,
|
||||||
@@ -108,7 +108,7 @@ export async function GET() {
|
|||||||
console.error("Error fetching web vitals:", error);
|
console.error("Error fetching web vitals:", error);
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: "Internal server error" },
|
{ error: "Internal server error" },
|
||||||
{ status: 500 }
|
{ status: 500 },
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ const AskOrganizer = memo(
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
AskOrganizer.displayName = "AskOrganizer";
|
AskOrganizer.displayName = "AskOrganizer";
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ const Avatar = memo(
|
|||||||
const baseStyles = `rounded-[var(--radius-measures-radius-full)] object-cover ${sizeStyles[size]} ${className}`;
|
const baseStyles = `rounded-[var(--radius-measures-radius-full)] object-cover ${sizeStyles[size]} ${className}`;
|
||||||
|
|
||||||
return <img src={src} alt={alt} className={baseStyles} {...props} />;
|
return <img src={src} alt={alt} className={baseStyles} {...props} />;
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Avatar.displayName = "Avatar";
|
Avatar.displayName = "Avatar";
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const AvatarContainer = memo(
|
|||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
AvatarContainer.displayName = "AvatarContainer";
|
AvatarContainer.displayName = "AvatarContainer";
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ const Button = memo(
|
|||||||
{children}
|
{children}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Button.displayName = "Button";
|
Button.displayName = "Button";
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ const ContentContainer = memo(
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentContainer.displayName = "ContentContainer";
|
ContentContainer.displayName = "ContentContainer";
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ const ContentLockup = memo(
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentLockup.displayName = "ContentLockup";
|
ContentLockup.displayName = "ContentLockup";
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ const ContentThumbnailTemplate = memo(
|
|||||||
</div>
|
</div>
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
ContentThumbnailTemplate.displayName = "ContentThumbnailTemplate";
|
ContentThumbnailTemplate.displayName = "ContentThumbnailTemplate";
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class ErrorBoundary extends Component {
|
|||||||
Something went wrong
|
Something went wrong
|
||||||
</h2>
|
</h2>
|
||||||
<p className="text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-016)]">
|
<p className="text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-016)]">
|
||||||
We're sorry, but something unexpected happened.
|
We're sorry, but something unexpected happened.
|
||||||
</p>
|
</p>
|
||||||
<button
|
<button
|
||||||
onClick={() => this.setState({ hasError: false, error: null })}
|
onClick={() => this.setState({ hasError: false, error: null })}
|
||||||
@@ -46,4 +46,3 @@ class ErrorBoundary extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default ErrorBoundary;
|
export default ErrorBoundary;
|
||||||
|
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ const FeatureGrid = memo(({ title, subtitle, className = "" }) => {
|
|||||||
href: "#conflict-resolution",
|
href: "#conflict-resolution",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[]
|
[],
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const HeaderTab = memo(
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
HeaderTab.displayName = "HeaderTab";
|
HeaderTab.displayName = "HeaderTab";
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const HeroBanner = memo(
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
HeroBanner.displayName = "HeroBanner";
|
HeroBanner.displayName = "HeroBanner";
|
||||||
|
|||||||
@@ -79,10 +79,10 @@ const HomeHeader = memo(() => {
|
|||||||
? size === "home" || size === "homeMd"
|
? size === "home" || size === "homeMd"
|
||||||
? "homeMd"
|
? "homeMd"
|
||||||
: size === "large"
|
: size === "large"
|
||||||
? "large"
|
? "large"
|
||||||
: size === "homeXlarge"
|
: size === "homeXlarge"
|
||||||
? "homeXlarge"
|
? "homeXlarge"
|
||||||
: "xsmallUseCases"
|
: "xsmallUseCases"
|
||||||
: size
|
: size
|
||||||
}
|
}
|
||||||
variant={
|
variant={
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const ImagePlaceholder = memo(
|
|||||||
{text}
|
{text}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
ImagePlaceholder.displayName = "ImagePlaceholder";
|
ImagePlaceholder.displayName = "ImagePlaceholder";
|
||||||
|
|||||||
+20
-20
@@ -95,26 +95,26 @@ const Logo = memo(({ size = "default", showText = true }) => {
|
|||||||
size === "homeHeaderXsmall"
|
size === "homeHeaderXsmall"
|
||||||
? sizes.homeHeaderXsmall
|
? sizes.homeHeaderXsmall
|
||||||
: size === "homeHeaderSm"
|
: size === "homeHeaderSm"
|
||||||
? sizes.homeHeaderSm
|
? sizes.homeHeaderSm
|
||||||
: size === "homeHeaderMd"
|
: size === "homeHeaderMd"
|
||||||
? sizes.homeHeaderMd
|
? sizes.homeHeaderMd
|
||||||
: size === "homeHeaderLg"
|
: size === "homeHeaderLg"
|
||||||
? sizes.homeHeaderLg
|
? sizes.homeHeaderLg
|
||||||
: size === "homeHeaderXl"
|
: size === "homeHeaderXl"
|
||||||
? sizes.homeHeaderXl
|
? sizes.homeHeaderXl
|
||||||
: size === "header"
|
: size === "header"
|
||||||
? sizes.header
|
? sizes.header
|
||||||
: size === "headerMd"
|
: size === "headerMd"
|
||||||
? sizes.headerMd
|
? sizes.headerMd
|
||||||
: size === "headerLg"
|
: size === "headerLg"
|
||||||
? sizes.headerLg
|
? sizes.headerLg
|
||||||
: size === "headerXl"
|
: size === "headerXl"
|
||||||
? sizes.headerXl
|
? sizes.headerXl
|
||||||
: size === "footer"
|
: size === "footer"
|
||||||
? sizes.footer
|
? sizes.footer
|
||||||
: size === "footerLg"
|
: size === "footerLg"
|
||||||
? sizes.footerLg
|
? sizes.footerLg
|
||||||
: sizes.default;
|
: sizes.default;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link href="/" className="block" aria-label="CommunityRule Logo">
|
<Link href="/" className="block" aria-label="CommunityRule Logo">
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ const MenuBar = memo(
|
|||||||
{children}
|
{children}
|
||||||
</nav>
|
</nav>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
MenuBar.displayName = "MenuBar";
|
MenuBar.displayName = "MenuBar";
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ const MenuBarItem = memo(
|
|||||||
{children}
|
{children}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
MenuBarItem.displayName = "MenuBarItem";
|
MenuBarItem.displayName = "MenuBarItem";
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ const MiniCard = memo(
|
|||||||
{cardContent}
|
{cardContent}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
MiniCard.displayName = "MiniCard";
|
MiniCard.displayName = "MiniCard";
|
||||||
|
|||||||
@@ -1,58 +1,61 @@
|
|||||||
import React, { memo } from "react";
|
import React, { memo } from "react";
|
||||||
|
|
||||||
const NavigationItem = memo(({
|
const NavigationItem = memo(
|
||||||
href = "#",
|
({
|
||||||
children,
|
href = "#",
|
||||||
variant = "default",
|
children,
|
||||||
size = "default",
|
variant = "default",
|
||||||
className = "",
|
size = "default",
|
||||||
disabled = false,
|
className = "",
|
||||||
...props
|
disabled = false,
|
||||||
}) {
|
...props
|
||||||
// Variant styles
|
}) => {
|
||||||
const variantStyles = {
|
// Variant styles
|
||||||
default:
|
const variantStyles = {
|
||||||
"bg-transparent text-[var(--color-content-default-brand-primary)] border border-transparent hover:bg-[var(--color-surface-default-tertiary)] hover:text-[var(--color-content-default-brand-primary)] active:bg-transparent active:text-[var(--color-content-default-brand-primary)] active:border-[var(--color-content-default-brand-primary)] disabled:bg-[var(--color-surface-default-tertiary)] disabled:text-[var(--color-content-default-tertiary)] disabled:border-[var(--color-content-default-tertiary)] disabled:opacity-50 disabled:cursor-not-allowed",
|
default:
|
||||||
};
|
"bg-transparent text-[var(--color-content-default-brand-primary)] border border-transparent hover:bg-[var(--color-surface-default-tertiary)] hover:text-[var(--color-content-default-brand-primary)] active:bg-transparent active:text-[var(--color-content-default-brand-primary)] active:border-[var(--color-content-default-brand-primary)] disabled:bg-[var(--color-surface-default-tertiary)] disabled:text-[var(--color-content-default-tertiary)] disabled:border-[var(--color-content-default-tertiary)] disabled:opacity-50 disabled:cursor-not-allowed",
|
||||||
|
};
|
||||||
|
|
||||||
// Size styles
|
// Size styles
|
||||||
const sizeStyles = {
|
const sizeStyles = {
|
||||||
default:
|
default:
|
||||||
"px-[var(--spacing-scale-016)] py-[var(--spacing-scale-016)] gap-[var(--spacing-scale-004)]",
|
"px-[var(--spacing-scale-016)] py-[var(--spacing-scale-016)] gap-[var(--spacing-scale-004)]",
|
||||||
xsmall:
|
xsmall:
|
||||||
"px-[var(--spacing-scale-004)] py-[var(--spacing-scale-002)] gap-[var(--spacing-scale-004)]",
|
"px-[var(--spacing-scale-004)] py-[var(--spacing-scale-002)] gap-[var(--spacing-scale-004)]",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Text styles based on size
|
// Text styles based on size
|
||||||
const textStyles = {
|
const textStyles = {
|
||||||
default: "font-inter text-[10px] leading-[12px] font-medium tracking-[0%]",
|
default:
|
||||||
xsmall: "font-inter text-[10px] leading-[12px] font-medium tracking-[0%]",
|
"font-inter text-[10px] leading-[12px] font-medium tracking-[0%]",
|
||||||
};
|
xsmall: "font-inter text-[10px] leading-[12px] font-medium tracking-[0%]",
|
||||||
|
};
|
||||||
|
|
||||||
const baseStyles = `inline-flex items-center ${sizeStyles[size]} rounded-[var(--radius-measures-radius-full)] ${textStyles[size]} transition-all duration-200 cursor-pointer`;
|
const baseStyles = `inline-flex items-center ${sizeStyles[size]} rounded-[var(--radius-measures-radius-full)] ${textStyles[size]} transition-all duration-200 cursor-pointer`;
|
||||||
|
|
||||||
// Determine which variant to use
|
// Determine which variant to use
|
||||||
let finalVariant = variant;
|
let finalVariant = variant;
|
||||||
if (disabled) {
|
if (disabled) {
|
||||||
finalVariant = "default"; // The disabled state is handled by disabled: utilities
|
finalVariant = "default"; // The disabled state is handled by disabled: utilities
|
||||||
}
|
}
|
||||||
|
|
||||||
const combinedStyles = `${baseStyles} ${variantStyles[finalVariant]} ${className}`;
|
const combinedStyles = `${baseStyles} ${variantStyles[finalVariant]} ${className}`;
|
||||||
|
|
||||||
|
if (disabled) {
|
||||||
|
return (
|
||||||
|
<span className={combinedStyles} {...props}>
|
||||||
|
{children}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (disabled) {
|
|
||||||
return (
|
return (
|
||||||
<span className={combinedStyles} {...props}>
|
<a href={href} className={combinedStyles} {...props}>
|
||||||
{children}
|
{children}
|
||||||
</span>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
);
|
||||||
return (
|
|
||||||
<a href={href} className={combinedStyles} {...props}>
|
|
||||||
{children}
|
|
||||||
</a>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
NavigationItem.displayName = "NavigationItem";
|
NavigationItem.displayName = "NavigationItem";
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const NumberedCards = memo(({ title, subtitle, cards }) => {
|
|||||||
text: card.text,
|
text: card.text,
|
||||||
})),
|
})),
|
||||||
}),
|
}),
|
||||||
[title, subtitle, cards]
|
[title, subtitle, cards],
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ const QuoteBlock = memo(
|
|||||||
const handleImageError = (error) => {
|
const handleImageError = (error) => {
|
||||||
console.warn(
|
console.warn(
|
||||||
`QuoteBlock: Failed to load avatar image for ${author}:`,
|
`QuoteBlock: Failed to load avatar image for ${author}:`,
|
||||||
error
|
error,
|
||||||
);
|
);
|
||||||
setImageError(true);
|
setImageError(true);
|
||||||
setImageLoading(false);
|
setImageLoading(false);
|
||||||
@@ -244,7 +244,7 @@ const QuoteBlock = memo(
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
QuoteBlock.displayName = "QuoteBlock";
|
QuoteBlock.displayName = "QuoteBlock";
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ const RelatedArticles = memo(
|
|||||||
// Memoize filtered posts to prevent unnecessary re-computations
|
// Memoize filtered posts to prevent unnecessary re-computations
|
||||||
const filteredPosts = useMemo(
|
const filteredPosts = useMemo(
|
||||||
() => relatedPosts.filter((post) => post.slug !== currentPostSlug),
|
() => relatedPosts.filter((post) => post.slug !== currentPostSlug),
|
||||||
[relatedPosts, currentPostSlug]
|
[relatedPosts, currentPostSlug],
|
||||||
);
|
);
|
||||||
|
|
||||||
const [currentIndex, setCurrentIndex] = useState(0);
|
const [currentIndex, setCurrentIndex] = useState(0);
|
||||||
@@ -44,7 +44,7 @@ const RelatedArticles = memo(
|
|||||||
: "none",
|
: "none",
|
||||||
scrollBehavior: !isMobile ? "smooth" : "auto",
|
scrollBehavior: !isMobile ? "smooth" : "auto",
|
||||||
}),
|
}),
|
||||||
[isMobile, currentIndex]
|
[isMobile, currentIndex],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Memoize progress bar style calculation
|
// Memoize progress bar style calculation
|
||||||
@@ -54,10 +54,10 @@ const RelatedArticles = memo(
|
|||||||
index === currentIndex
|
index === currentIndex
|
||||||
? `${progress}%`
|
? `${progress}%`
|
||||||
: index < currentIndex
|
: index < currentIndex
|
||||||
? "100%"
|
? "100%"
|
||||||
: "0%",
|
: "0%",
|
||||||
}),
|
}),
|
||||||
[currentIndex, progress]
|
[currentIndex, progress],
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check if we're on mobile (below lg breakpoint)
|
// Check if we're on mobile (below lg breakpoint)
|
||||||
@@ -155,7 +155,7 @@ const RelatedArticles = memo(
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
RelatedArticles.displayName = "RelatedArticles";
|
RelatedArticles.displayName = "RelatedArticles";
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ const RuleCard = memo(
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
RuleCard.displayName = "RuleCard";
|
RuleCard.displayName = "RuleCard";
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ const SectionHeader = memo(
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
SectionHeader.displayName = "SectionHeader";
|
SectionHeader.displayName = "SectionHeader";
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ const WebVitalsDashboard = memo(() => {
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ const OptimizedComponent = memo(({ data, onAction }) => {
|
|||||||
(id) => {
|
(id) => {
|
||||||
onAction(id);
|
onAction(id);
|
||||||
},
|
},
|
||||||
[onAction]
|
[onAction],
|
||||||
);
|
);
|
||||||
|
|
||||||
return <div onClick={handleClick}>{/* Component content */}</div>;
|
return <div onClick={handleClick}>{/* Component content */}</div>;
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ test("components work together", () => {
|
|||||||
<Header />
|
<Header />
|
||||||
<MainContent />
|
<MainContent />
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test that components complement each other
|
// Test that components complement each other
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1
-1
@@ -70,7 +70,7 @@ const nextConfig = {
|
|||||||
reportFilename: isServer
|
reportFilename: isServer
|
||||||
? "../analyze/server.html"
|
? "../analyze/server.html"
|
||||||
: "../analyze/client.html",
|
: "../analyze/client.html",
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn("Bundle analyzer not available:", error.message);
|
console.warn("Bundle analyzer not available:", error.message);
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ class BundleAnalyzer {
|
|||||||
|
|
||||||
Object.entries(this.results.bundles).forEach(([filename, bundle]) => {
|
Object.entries(this.results.bundles).forEach(([filename, bundle]) => {
|
||||||
const budget = budgets.find(
|
const budget = budgets.find(
|
||||||
(b) => filename.includes(b.name) || b.name === "all"
|
(b) => filename.includes(b.name) || b.name === "all",
|
||||||
);
|
);
|
||||||
|
|
||||||
if (budget) {
|
if (budget) {
|
||||||
@@ -175,7 +175,7 @@ class BundleAnalyzer {
|
|||||||
// General recommendations
|
// General recommendations
|
||||||
const totalSize = Object.values(this.results.bundles).reduce(
|
const totalSize = Object.values(this.results.bundles).reduce(
|
||||||
(sum, bundle) => sum + bundle.sizeKB,
|
(sum, bundle) => sum + bundle.sizeKB,
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (totalSize > 2000) {
|
if (totalSize > 2000) {
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ class PerformanceMonitor {
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(
|
console.warn(
|
||||||
"⚠️ Development server not running, skipping Lighthouse CI..."
|
"⚠️ Development server not running, skipping Lighthouse CI...",
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -99,23 +99,23 @@ class PerformanceMonitor {
|
|||||||
|
|
||||||
if (resultFile) {
|
if (resultFile) {
|
||||||
const results = JSON.parse(
|
const results = JSON.parse(
|
||||||
fs.readFileSync(path.join(lhciResultsPath, resultFile), "utf8")
|
fs.readFileSync(path.join(lhciResultsPath, resultFile), "utf8"),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (results.lhr && results.lhr.audits) {
|
if (results.lhr && results.lhr.audits) {
|
||||||
this.metrics.coreWebVitals = {
|
this.metrics.coreWebVitals = {
|
||||||
lcp: this.getAuditScore(
|
lcp: this.getAuditScore(
|
||||||
results.lhr.audits,
|
results.lhr.audits,
|
||||||
"largest-contentful-paint"
|
"largest-contentful-paint",
|
||||||
),
|
),
|
||||||
fid: this.getAuditScore(results.lhr.audits, "max-potential-fid"),
|
fid: this.getAuditScore(results.lhr.audits, "max-potential-fid"),
|
||||||
cls: this.getAuditScore(
|
cls: this.getAuditScore(
|
||||||
results.lhr.audits,
|
results.lhr.audits,
|
||||||
"cumulative-layout-shift"
|
"cumulative-layout-shift",
|
||||||
),
|
),
|
||||||
fcp: this.getAuditScore(
|
fcp: this.getAuditScore(
|
||||||
results.lhr.audits,
|
results.lhr.audits,
|
||||||
"first-contentful-paint"
|
"first-contentful-paint",
|
||||||
),
|
),
|
||||||
tti: this.getAuditScore(results.lhr.audits, "interactive"),
|
tti: this.getAuditScore(results.lhr.audits, "interactive"),
|
||||||
performance: results.lhr.categories.performance?.score * 100 || 0,
|
performance: results.lhr.categories.performance?.score * 100 || 0,
|
||||||
@@ -150,7 +150,7 @@ class PerformanceMonitor {
|
|||||||
"..",
|
"..",
|
||||||
".next",
|
".next",
|
||||||
"static",
|
"static",
|
||||||
"chunks"
|
"chunks",
|
||||||
);
|
);
|
||||||
|
|
||||||
if (fs.existsSync(bundleStatsPath)) {
|
if (fs.existsSync(bundleStatsPath)) {
|
||||||
|
|||||||
+12
-12
@@ -90,11 +90,11 @@ class PerformanceTester {
|
|||||||
"..",
|
"..",
|
||||||
".next",
|
".next",
|
||||||
"analyze",
|
"analyze",
|
||||||
"bundle-analysis.json"
|
"bundle-analysis.json",
|
||||||
);
|
);
|
||||||
if (fs.existsSync(bundleReportPath)) {
|
if (fs.existsSync(bundleReportPath)) {
|
||||||
const bundleData = JSON.parse(
|
const bundleData = JSON.parse(
|
||||||
fs.readFileSync(bundleReportPath, "utf8")
|
fs.readFileSync(bundleReportPath, "utf8"),
|
||||||
);
|
);
|
||||||
this.results.bundleAnalysis = bundleData;
|
this.results.bundleAnalysis = bundleData;
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ class PerformanceTester {
|
|||||||
) {
|
) {
|
||||||
this.results.summary.failed += bundleData.budgetViolations.length;
|
this.results.summary.failed += bundleData.budgetViolations.length;
|
||||||
console.log(
|
console.log(
|
||||||
`⚠️ Found ${bundleData.budgetViolations.length} budget violations`
|
`⚠️ Found ${bundleData.budgetViolations.length} budget violations`,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.results.summary.passed += 1;
|
this.results.summary.passed += 1;
|
||||||
@@ -134,7 +134,7 @@ class PerformanceTester {
|
|||||||
"..",
|
"..",
|
||||||
".next",
|
".next",
|
||||||
"monitoring",
|
"monitoring",
|
||||||
"performance-report.json"
|
"performance-report.json",
|
||||||
);
|
);
|
||||||
if (fs.existsSync(perfReportPath)) {
|
if (fs.existsSync(perfReportPath)) {
|
||||||
const perfData = JSON.parse(fs.readFileSync(perfReportPath, "utf8"));
|
const perfData = JSON.parse(fs.readFileSync(perfReportPath, "utf8"));
|
||||||
@@ -144,7 +144,7 @@ class PerformanceTester {
|
|||||||
if (perfData.budgetViolations && perfData.budgetViolations.length > 0) {
|
if (perfData.budgetViolations && perfData.budgetViolations.length > 0) {
|
||||||
this.results.summary.failed += perfData.budgetViolations.length;
|
this.results.summary.failed += perfData.budgetViolations.length;
|
||||||
console.log(
|
console.log(
|
||||||
`⚠️ Found ${perfData.budgetViolations.length} performance violations`
|
`⚠️ Found ${perfData.budgetViolations.length} performance violations`,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
this.results.summary.passed += 1;
|
this.results.summary.passed += 1;
|
||||||
@@ -173,11 +173,11 @@ class PerformanceTester {
|
|||||||
"..",
|
"..",
|
||||||
".next",
|
".next",
|
||||||
"web-vitals",
|
"web-vitals",
|
||||||
"report.json"
|
"report.json",
|
||||||
);
|
);
|
||||||
if (fs.existsSync(vitalsReportPath)) {
|
if (fs.existsSync(vitalsReportPath)) {
|
||||||
const vitalsData = JSON.parse(
|
const vitalsData = JSON.parse(
|
||||||
fs.readFileSync(vitalsReportPath, "utf8")
|
fs.readFileSync(vitalsReportPath, "utf8"),
|
||||||
);
|
);
|
||||||
this.results.webVitals = vitalsData;
|
this.results.webVitals = vitalsData;
|
||||||
console.log("✅ Web Vitals tracking setup complete");
|
console.log("✅ Web Vitals tracking setup complete");
|
||||||
@@ -204,7 +204,7 @@ class PerformanceTester {
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(
|
console.warn(
|
||||||
"⚠️ Development server not running, skipping Lighthouse CI..."
|
"⚠️ Development server not running, skipping Lighthouse CI...",
|
||||||
);
|
);
|
||||||
this.results.summary.warnings += 1;
|
this.results.summary.warnings += 1;
|
||||||
this.results.summary.total += 1;
|
this.results.summary.total += 1;
|
||||||
@@ -221,7 +221,7 @@ class PerformanceTester {
|
|||||||
|
|
||||||
if (resultFile) {
|
if (resultFile) {
|
||||||
const lhciData = JSON.parse(
|
const lhciData = JSON.parse(
|
||||||
fs.readFileSync(path.join(lhciResultsPath, resultFile), "utf8")
|
fs.readFileSync(path.join(lhciResultsPath, resultFile), "utf8"),
|
||||||
);
|
);
|
||||||
this.results.lighthouse = lhciData;
|
this.results.lighthouse = lhciData;
|
||||||
console.log("✅ Lighthouse CI completed");
|
console.log("✅ Lighthouse CI completed");
|
||||||
@@ -248,7 +248,7 @@ class PerformanceTester {
|
|||||||
|
|
||||||
const reportPath = path.join(
|
const reportPath = path.join(
|
||||||
TEST_RESULTS_DIR,
|
TEST_RESULTS_DIR,
|
||||||
"performance-test-report.json"
|
"performance-test-report.json",
|
||||||
);
|
);
|
||||||
fs.writeFileSync(reportPath, JSON.stringify(this.results, null, 2));
|
fs.writeFileSync(reportPath, JSON.stringify(this.results, null, 2));
|
||||||
|
|
||||||
@@ -262,7 +262,7 @@ class PerformanceTester {
|
|||||||
generateMarkdownReport() {
|
generateMarkdownReport() {
|
||||||
const reportPath = path.join(
|
const reportPath = path.join(
|
||||||
TEST_RESULTS_DIR,
|
TEST_RESULTS_DIR,
|
||||||
"performance-test-report.md"
|
"performance-test-report.md",
|
||||||
);
|
);
|
||||||
|
|
||||||
let report = `# Performance Test Report\n\n`;
|
let report = `# Performance Test Report\n\n`;
|
||||||
@@ -310,7 +310,7 @@ class PerformanceTester {
|
|||||||
} (exceeds ${
|
} (exceeds ${
|
||||||
violation.budget
|
violation.budget
|
||||||
}) - ${violation.severity.toUpperCase()}\n`;
|
}) - ${violation.severity.toUpperCase()}\n`;
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
report += `✅ No performance budget violations found\n\n`;
|
report += `✅ No performance budget violations found\n\n`;
|
||||||
|
|||||||
@@ -289,7 +289,7 @@ export default WebVitalsDashboard;
|
|||||||
if (file.endsWith(".json")) {
|
if (file.endsWith(".json")) {
|
||||||
const metric = file.replace(".json", "");
|
const metric = file.replace(".json", "");
|
||||||
const data = JSON.parse(
|
const data = JSON.parse(
|
||||||
fs.readFileSync(path.join(WEB_VITALS_DIR, file), "utf8")
|
fs.readFileSync(path.join(WEB_VITALS_DIR, file), "utf8"),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (data.length > 0) {
|
if (data.length > 0) {
|
||||||
@@ -310,7 +310,7 @@ export default WebVitalsDashboard;
|
|||||||
max: values.length > 0 ? Math.max(...values) : 0,
|
max: values.length > 0 ? Math.max(...values) : 0,
|
||||||
goodCount: ratings.filter((r) => r === "good").length,
|
goodCount: ratings.filter((r) => r === "good").length,
|
||||||
needsImprovementCount: ratings.filter(
|
needsImprovementCount: ratings.filter(
|
||||||
(r) => r === "needs-improvement"
|
(r) => r === "needs-improvement",
|
||||||
).length,
|
).length,
|
||||||
poorCount: ratings.filter((r) => r === "poor").length,
|
poorCount: ratings.filter((r) => r === "poor").length,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,5 +19,3 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ErrorBoundary;
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ describe("LogoWall Component", () => {
|
|||||||
render(<LogoWall />);
|
render(<LogoWall />);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
screen.getByText("Trusted by leading cooperators")
|
screen.getByText("Trusted by leading cooperators"),
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ describe("LogoWall Component", () => {
|
|||||||
const section = document.querySelector("section");
|
const section = document.querySelector("section");
|
||||||
expect(section).toHaveClass(
|
expect(section).toHaveClass(
|
||||||
"p-[var(--spacing-scale-032)]",
|
"p-[var(--spacing-scale-032)]",
|
||||||
"md:px-[var(--spacing-scale-024)]"
|
"md:px-[var(--spacing-scale-024)]",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ describe("LogoWall Component", () => {
|
|||||||
render(<LogoWall />);
|
render(<LogoWall />);
|
||||||
|
|
||||||
const grid = document.querySelector(
|
const grid = document.querySelector(
|
||||||
'[class*="grid grid-cols-2 grid-rows-3"]'
|
'[class*="grid grid-cols-2 grid-rows-3"]',
|
||||||
);
|
);
|
||||||
expect(grid).toBeInTheDocument();
|
expect(grid).toBeInTheDocument();
|
||||||
expect(grid).toHaveClass("sm:grid-cols-3", "sm:grid-rows-2", "md:flex");
|
expect(grid).toHaveClass("sm:grid-cols-3", "sm:grid-rows-2", "md:flex");
|
||||||
@@ -84,7 +84,7 @@ describe("LogoWall Component", () => {
|
|||||||
const foodNotBombsLogo = screen.getByAltText("Food Not Bombs");
|
const foodNotBombsLogo = screen.getByAltText("Food Not Bombs");
|
||||||
expect(foodNotBombsLogo).toHaveAttribute(
|
expect(foodNotBombsLogo).toHaveAttribute(
|
||||||
"src",
|
"src",
|
||||||
"/assets/Section/Logo_FoodNotBombs.png"
|
"/assets/Section/Logo_FoodNotBombs.png",
|
||||||
);
|
);
|
||||||
expect(foodNotBombsLogo).toHaveClass("h-11", "lg:h-14", "xl:h-[70px]");
|
expect(foodNotBombsLogo).toHaveClass("h-11", "lg:h-14", "xl:h-[70px]");
|
||||||
});
|
});
|
||||||
@@ -109,7 +109,7 @@ describe("LogoWall Component", () => {
|
|||||||
render(<LogoWall />);
|
render(<LogoWall />);
|
||||||
|
|
||||||
const logoContainers = document.querySelectorAll(
|
const logoContainers = document.querySelectorAll(
|
||||||
'[class*="hover:opacity-100"]'
|
'[class*="hover:opacity-100"]',
|
||||||
);
|
);
|
||||||
expect(logoContainers.length).toBeGreaterThan(0);
|
expect(logoContainers.length).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
@@ -129,7 +129,7 @@ describe("LogoWall Component", () => {
|
|||||||
render(<LogoWall />);
|
render(<LogoWall />);
|
||||||
|
|
||||||
const logoContainers = document.querySelectorAll(
|
const logoContainers = document.querySelectorAll(
|
||||||
'[class*="transition-opacity duration-500"]'
|
'[class*="transition-opacity duration-500"]',
|
||||||
);
|
);
|
||||||
expect(logoContainers.length).toBeGreaterThan(0);
|
expect(logoContainers.length).toBeGreaterThan(0);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user