Skip to content

Commit 2d6cc9b

Browse files
Enhance tests for asset upload handling
- Added tests to verify directory structure and file presence for uploaded bundles and assets. - Implemented checks for scenarios with empty requests and duplicate bundle hashes, ensuring correct behavior without overwriting existing files. - Improved coverage of the `/upload-assets` endpoint to handle various edge cases effectively.
1 parent a750f61 commit 2d6cc9b

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

react_on_rails_pro/packages/node-renderer/tests/worker.test.ts

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,26 @@ describe('worker', () => {
504504
const bundle2Path = path.join(serverBundleCachePathForTest(), secondaryBundleHash, `${secondaryBundleHash}.js`);
505505
expect(fs.existsSync(bundle1Path)).toBe(true);
506506
expect(fs.existsSync(bundle2Path)).toBe(true);
507+
508+
// Verify the directory structure is correct
509+
const bundle1Dir = path.join(bundlePathForTest(), bundleHash);
510+
const bundle2Dir = path.join(bundlePathForTest(), secondaryBundleHash);
511+
512+
// Each bundle directory should contain: 1 bundle file + 2 assets = 3 files total
513+
const bundle1Files = fs.readdirSync(bundle1Dir);
514+
const bundle2Files = fs.readdirSync(bundle2Dir);
515+
516+
expect(bundle1Files).toHaveLength(3); // bundle file + 2 assets
517+
expect(bundle2Files).toHaveLength(3); // bundle file + 2 assets
518+
519+
// Verify the specific files exist in each directory
520+
expect(bundle1Files).toContain(`${bundleHash}.js`);
521+
expect(bundle1Files).toContain('loadable-stats.json');
522+
expect(bundle1Files).toContain('loadable-stats-other.json');
523+
524+
expect(bundle2Files).toContain(`${secondaryBundleHash}.js`);
525+
expect(bundle2Files).toContain('loadable-stats.json');
526+
expect(bundle2Files).toContain('loadable-stats-other.json');
507527
});
508528

509529
test('post /upload-assets with only bundles (no assets)', async () => {
@@ -528,5 +548,128 @@ describe('worker', () => {
528548
// Verify bundle is placed in the correct directory
529549
const bundleFilePath = path.join(serverBundleCachePathForTest(), bundleHash, `${bundleHash}.js`);
530550
expect(fs.existsSync(bundleFilePath)).toBe(true);
551+
552+
// Verify the directory structure is correct
553+
const bundleDir = path.join(bundlePathForTest(), bundleHash);
554+
const files = fs.readdirSync(bundleDir);
555+
556+
// Should only contain the bundle file, no assets
557+
expect(files).toHaveLength(1);
558+
expect(files[0]).toBe(`${bundleHash}.js`);
559+
560+
// Verify no asset files were accidentally copied
561+
expect(files).not.toContain('loadable-stats.json');
562+
expect(files).not.toContain('loadable-stats-other.json');
563+
});
564+
565+
test('post /upload-assets with no assets and no bundles (empty request)', async () => {
566+
const bundleHash = 'empty-request-hash';
567+
568+
const app = worker({
569+
bundlePath: bundlePathForTest(),
570+
password: 'my_password',
571+
});
572+
573+
const form = formAutoContent({
574+
gemVersion,
575+
protocolVersion,
576+
password: 'my_password',
577+
targetBundles: [bundleHash],
578+
// No assets or bundles uploaded
579+
});
580+
581+
const res = await app.inject().post(`/upload-assets`).payload(form.payload).headers(form.headers).end();
582+
expect(res.statusCode).toBe(200);
583+
584+
// Verify bundle directory is created
585+
const bundleDirectory = path.join(bundlePathForTest(), bundleHash);
586+
expect(fs.existsSync(bundleDirectory)).toBe(true);
587+
588+
// Verify no files were copied (since none were uploaded)
589+
const files = fs.readdirSync(bundleDirectory);
590+
expect(files).toHaveLength(0);
591+
});
592+
593+
test('post /upload-assets with duplicate bundle hash silently skips overwrite and returns 200', async () => {
594+
const bundleHash = 'duplicate-bundle-hash';
595+
596+
const app = worker({
597+
bundlePath: bundlePathForTest(),
598+
password: 'my_password',
599+
});
600+
601+
// First upload with bundle
602+
const form1 = formAutoContent({
603+
gemVersion,
604+
protocolVersion,
605+
password: 'my_password',
606+
targetBundles: [bundleHash],
607+
[`bundle_${bundleHash}`]: createReadStream(getFixtureBundle()),
608+
});
609+
610+
const res1 = await app
611+
.inject()
612+
.post(`/upload-assets`)
613+
.payload(form1.payload)
614+
.headers(form1.headers)
615+
.end();
616+
expect(res1.statusCode).toBe(200);
617+
expect(res1.body).toBe(''); // Empty body on success
618+
619+
// Verify first bundle was created correctly
620+
const bundleDir = path.join(bundlePathForTest(), bundleHash);
621+
expect(fs.existsSync(bundleDir)).toBe(true);
622+
const bundleFilePath = path.join(bundleDir, `${bundleHash}.js`);
623+
expect(fs.existsSync(bundleFilePath)).toBe(true);
624+
625+
// Get file stats to verify it's the first bundle
626+
const firstBundleStats = fs.statSync(bundleFilePath);
627+
const firstBundleSize = firstBundleStats.size;
628+
const firstBundleModTime = firstBundleStats.mtime.getTime();
629+
630+
// Second upload with the same bundle hash but different content
631+
// This logs: "File exists when trying to overwrite bundle... Assuming bundle written by other thread"
632+
// Then silently skips the overwrite operation and returns 200 success
633+
const form2 = formAutoContent({
634+
gemVersion,
635+
protocolVersion,
636+
password: 'my_password',
637+
targetBundles: [bundleHash],
638+
[`bundle_${bundleHash}`]: createReadStream(getFixtureSecondaryBundle()), // Different content
639+
});
640+
641+
const res2 = await app
642+
.inject()
643+
.post(`/upload-assets`)
644+
.payload(form2.payload)
645+
.headers(form2.headers)
646+
.end();
647+
expect(res2.statusCode).toBe(200); // Still returns 200 success (no error)
648+
expect(res2.body).toBe(''); // Empty body, no error message returned to client
649+
650+
// Verify the bundle directory still exists
651+
expect(fs.existsSync(bundleDir)).toBe(true);
652+
653+
// Verify the bundle file still exists
654+
expect(fs.existsSync(bundleFilePath)).toBe(true);
655+
656+
// Verify the file was NOT overwritten (original bundle is preserved)
657+
const secondBundleStats = fs.statSync(bundleFilePath);
658+
const secondBundleSize = secondBundleStats.size;
659+
const secondBundleModTime = secondBundleStats.mtime.getTime();
660+
661+
// The file size should be the same as the first upload (no overwrite occurred)
662+
expect(secondBundleSize).toBe(firstBundleSize);
663+
664+
// The modification time should be the same (file wasn't touched)
665+
expect(secondBundleModTime).toBe(firstBundleModTime);
666+
667+
// Verify the directory only contains one file (the original bundle)
668+
const files = fs.readdirSync(bundleDir);
669+
expect(files).toHaveLength(1);
670+
expect(files[0]).toBe(`${bundleHash}.js`);
671+
672+
// Verify the original content is preserved (62 bytes from bundle.js, not 84 from secondary-bundle.js)
673+
expect(secondBundleSize).toBe(62); // Size of getFixtureBundle(), not getFixtureSecondaryBundle()
531674
});
532675
});

0 commit comments

Comments
 (0)