Remove skeleton swaps and deferred layout estimates, restore reveal state, and use native proximity scrolling for project cards. Also make the Docker build npm registry configurable.
88 lines
3.7 KiB
JavaScript
88 lines
3.7 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { access, readFile } from 'node:fs/promises';
|
|
import test from 'node:test';
|
|
|
|
const removedSkeletonFiles = [
|
|
'src/app/(en)/loading.tsx',
|
|
'src/app/(fa)/fa/loading.tsx',
|
|
'src/components/ImageWithSkeleton.tsx',
|
|
'src/components/ImageWithSkeleton.module.css',
|
|
'src/components/skeletons/PortfolioSkeleton.tsx',
|
|
'src/components/skeletons/PortfolioSkeleton.module.css',
|
|
];
|
|
|
|
test('portfolio rendering no longer uses skeleton loading layers', async () => {
|
|
await Promise.all(
|
|
removedSkeletonFiles.map(async (file) => {
|
|
await assert.rejects(access(file), `${file} should be removed`);
|
|
}),
|
|
);
|
|
|
|
const [page, scene, sceneStyles, sourceFiles] = await Promise.all([
|
|
readFile('src/app/PortfolioPage.tsx', 'utf8'),
|
|
readFile('src/components/scenes/DeferredAboutRiverScene.tsx', 'utf8'),
|
|
readFile('src/components/scenes/Scenes.module.css', 'utf8'),
|
|
Promise.all([
|
|
'src/components/HeroSection.tsx',
|
|
'src/components/ProjectThumbnail.tsx',
|
|
'src/components/ExperienceSection.tsx',
|
|
'src/components/SkillsSection.tsx',
|
|
'src/components/EducationSection.tsx',
|
|
'src/components/MilestonesSection.tsx',
|
|
].map((file) => readFile(file, 'utf8'))).then((files) => files.join('\n')),
|
|
]);
|
|
|
|
assert.doesNotMatch(page, /Suspense|Skeleton/);
|
|
assert.doesNotMatch(sourceFiles, /ImageWithSkeleton|skeletonShape/);
|
|
assert.doesNotMatch(scene, /isReady|onReady|sceneSkeleton|aria-busy/);
|
|
assert.doesNotMatch(sceneStyles, /sceneSkeleton|sceneSkeletonShimmer/);
|
|
});
|
|
|
|
test('deferred section sizing cannot replace real layout while scrolling', async () => {
|
|
const [globals, sections] = await Promise.all([
|
|
readFile('src/styles/globals.css', 'utf8'),
|
|
Promise.all([
|
|
'src/components/ProjectsSection.tsx',
|
|
'src/components/ExperienceSection.tsx',
|
|
'src/components/SkillsSection.tsx',
|
|
'src/components/EducationSection.tsx',
|
|
'src/components/MilestonesSection.tsx',
|
|
'src/components/FooterSection.tsx',
|
|
].map((file) => readFile(file, 'utf8'))).then((files) => files.join('\n')),
|
|
]);
|
|
|
|
assert.doesNotMatch(globals, /content-visibility|contain-intrinsic-size/);
|
|
assert.doesNotMatch(sections, /data-deferred-render/);
|
|
});
|
|
|
|
test('project carousel uses native momentum with soft proximity snapping', async () => {
|
|
const [component, styles] = await Promise.all([
|
|
readFile('src/components/ProjectsSection.tsx', 'utf8'),
|
|
readFile('src/components/ProjectsSection.module.css', 'utf8'),
|
|
]);
|
|
|
|
assert.match(styles, /scroll-snap-type:\s*x proximity/);
|
|
assert.match(styles, /touch-action:\s*pan-x pan-y/);
|
|
assert.doesNotMatch(styles, /scroll-snap-type:\s*x mandatory/);
|
|
assert.doesNotMatch(styles, /scroll-snap-stop:\s*always/);
|
|
assert.match(component, /event\.pointerType !== 'mouse'/);
|
|
assert.match(
|
|
component,
|
|
/cancelAnimationFrame\(scrollFrameRef\.current\);\s*scrollFrameRef\.current = 0;/,
|
|
);
|
|
assert.doesNotMatch(component, /targetIndex|velocity fling|Math\.(?:ceil|floor|round)\(currentScroll \/ step\)/);
|
|
});
|
|
|
|
test('motion state is initialized for dependent section animations', async () => {
|
|
const [controller, footer] = await Promise.all([
|
|
readFile('src/components/MotionController.tsx', 'utf8'),
|
|
readFile('src/components/IsometricFooter/IsometricFooter.tsx', 'utf8'),
|
|
]);
|
|
|
|
assert.match(controller, /document\.documentElement\.dataset\.motionReady = 'true'/);
|
|
assert.match(controller, /element\.dataset\.visible = 'true'/);
|
|
assert.match(footer, /className=\{styles\.headerTitle\} data-reveal="soft"/);
|
|
assert.match(footer, /className=\{styles\.headerSubtitle\} data-reveal="soft"/);
|
|
assert.match(footer, /className=\{styles\.emailWrapper\} data-reveal="scale"/);
|
|
});
|