feat: move fixtures into __test__ folder

This commit is contained in:
Eli Bosley
2025-02-04 10:33:35 -05:00
parent 445f3b50b1
commit dfb006e696
12 changed files with 34 additions and 10 deletions

View File

@@ -17,17 +17,28 @@ export abstract class FileModification {
public constructor(protected readonly logger: Logger) {} public constructor(protected readonly logger: Logger) {}
// This is the main method that child classes need to implement /**
* Generate the patch for the target filePath
* @param overridePath - The path displayed in the patch file
*/
protected abstract generatePatch(overridePath?: string): Promise<string>; protected abstract generatePatch(overridePath?: string): Promise<string>;
private getPatchFilePath(targetFile: string): string { /**
* Get the path to the applied patch file for the target filePath, saved after applying the patch
* @param targetFile - The path to the file that was patched
*/
private getPathToAppliedPatch(targetFile: string): string {
const dir = dirname(targetFile); const dir = dirname(targetFile);
const filename = `${basename(targetFile)}.patch`; const filename = `${basename(targetFile)}.patch`;
return join(dir, filename); return join(dir, filename);
} }
/**
* Save the patch to disk, next to the changed file
* @param patchResult - The patch to save to filePath.patch
*/
private async savePatch(patchResult: string): Promise<void> { private async savePatch(patchResult: string): Promise<void> {
const patchFilePath = this.getPatchFilePath(this.filePath); const patchFilePath = this.getPathToAppliedPatch(this.filePath);
await writeFile(patchFilePath, patchResult, 'utf8'); await writeFile(patchFilePath, patchResult, 'utf8');
} }
@@ -37,7 +48,7 @@ export abstract class FileModification {
* @returns The patch contents if it exists (targetFile.patch), null otherwise * @returns The patch contents if it exists (targetFile.patch), null otherwise
*/ */
private async loadPatchedFilePatch(targetFile: string): Promise<string | null> { private async loadPatchedFilePatch(targetFile: string): Promise<string | null> {
const patchFile = this.getPatchFilePath(targetFile); const patchFile = this.getPathToAppliedPatch(targetFile);
try { try {
await access(patchFile, constants.R_OK); await access(patchFile, constants.R_OK);
return await readFile(patchFile, 'utf8'); return await readFile(patchFile, 'utf8');
@@ -46,6 +57,10 @@ export abstract class FileModification {
} }
} }
/**
* Load the pregenerated patch for the target file
* @returns The patch contents if it exists (targetFile.patch), null otherwise
*/
private async getPregeneratedPatch(): Promise<string | null> { private async getPregeneratedPatch(): Promise<string | null> {
const patchResults = await import.meta.glob('./modifications/patches/*.patch', { const patchResults = await import.meta.glob('./modifications/patches/*.patch', {
query: '?raw', query: '?raw',
@@ -68,6 +83,11 @@ export abstract class FileModification {
} }
} }
/**
* Apply the patch to the target file
* @param patchContents - The patch to apply
* @returns The result of the patch
*/
private async applyPatch(patchContents: string): Promise<string> { private async applyPatch(patchContents: string): Promise<string> {
if (!patchContents.trim()) { if (!patchContents.trim()) {
throw new Error('Patch contents are empty'); throw new Error('Patch contents are empty');
@@ -87,7 +107,9 @@ export abstract class FileModification {
/** /**
* Apply the patch for the target file * Apply the patch for the target file
* @returns * Attempts to apply the pregenerated patch first, then the dynamically generated patch
* Will roll back the already applied patch before running if the .patch file exists next to the target file
* @returns The result of the patch
*/ */
async apply(): Promise<string> { async apply(): Promise<string> {
try { try {
@@ -160,7 +182,7 @@ export abstract class FileModification {
// Clean up the patch file after successful rollback // Clean up the patch file after successful rollback
try { try {
const patchFile = this.getPatchFilePath(this.filePath); const patchFile = this.getPathToAppliedPatch(this.filePath);
await access(patchFile, constants.W_OK); await access(patchFile, constants.W_OK);
await unlink(patchFile); await unlink(patchFile);
} catch { } catch {

View File

@@ -1,5 +1,6 @@
import { Logger } from '@nestjs/common'; import { Logger } from '@nestjs/common';
import { readFile, writeFile } from 'fs/promises'; import { readFile, writeFile } from 'fs/promises';
import { afterEach } from 'node:test';
import { basename, resolve } from 'path'; import { basename, resolve } from 'path';
import { describe, expect, test, vi } from 'vitest'; import { describe, expect, test, vi } from 'vitest';
@@ -10,7 +11,6 @@ import DefaultPageLayoutModification from '@app/unraid-api/unraid-file-modifier/
import { LogRotateModification } from '@app/unraid-api/unraid-file-modifier/modifications/log-rotate.modification'; import { LogRotateModification } from '@app/unraid-api/unraid-file-modifier/modifications/log-rotate.modification';
import NotificationsPageModification from '@app/unraid-api/unraid-file-modifier/modifications/notifications-page.modification'; import NotificationsPageModification from '@app/unraid-api/unraid-file-modifier/modifications/notifications-page.modification';
import SSOFileModification from '@app/unraid-api/unraid-file-modifier/modifications/sso.modification'; import SSOFileModification from '@app/unraid-api/unraid-file-modifier/modifications/sso.modification';
import { afterEach } from 'node:test';
interface ModificationTestCase { interface ModificationTestCase {
ModificationClass: new (...args: ConstructorParameters<typeof FileModification>) => FileModification; ModificationClass: new (...args: ConstructorParameters<typeof FileModification>) => FileModification;
@@ -18,6 +18,8 @@ interface ModificationTestCase {
fileName: string; fileName: string;
} }
let patcher: FileModification; let patcher: FileModification;
const getPathToFixture = (fileName: string) => resolve(__dirname, `__fixtures__/downloaded/${fileName}`);
const testCases: ModificationTestCase[] = [ const testCases: ModificationTestCase[] = [
{ {
ModificationClass: DefaultPageLayoutModification, ModificationClass: DefaultPageLayoutModification,
@@ -78,7 +80,7 @@ const downloadOrRetrieveOriginalFile = async (filePath: string, fileUrl: string)
async function testModification(testCase: ModificationTestCase) { async function testModification(testCase: ModificationTestCase) {
const fileName = basename(testCase.fileUrl); const fileName = basename(testCase.fileUrl);
const filePath = resolve(__dirname, `../__fixtures__/downloaded/${fileName}`); const filePath = getPathToFixture(fileName);
const originalContent = await downloadOrRetrieveOriginalFile(filePath, testCase.fileUrl); const originalContent = await downloadOrRetrieveOriginalFile(filePath, testCase.fileUrl);
const logger = new Logger(); const logger = new Logger();
patcher = await new testCase.ModificationClass(logger); patcher = await new testCase.ModificationClass(logger);
@@ -119,7 +121,7 @@ async function testInvalidModification(testCase: ModificationTestCase) {
patcher.getPregeneratedPatch = vi.fn().mockResolvedValue('I AM NOT A VALID PATCH'); patcher.getPregeneratedPatch = vi.fn().mockResolvedValue('I AM NOT A VALID PATCH');
const path = patcher.filePath; const path = patcher.filePath;
const filePath = resolve(__dirname, `../__fixtures__/downloaded/${testCase.fileName}`); const filePath = getPathToFixture(testCase.fileName);
// @ts-expect-error - Testing invalid pregenerated patches // @ts-expect-error - Testing invalid pregenerated patches
patcher.filePath = filePath; patcher.filePath = filePath;

View File

@@ -12,7 +12,7 @@ import {
} from '@app/unraid-api/unraid-file-modifier/file-modification'; } from '@app/unraid-api/unraid-file-modifier/file-modification';
import { UnraidFileModificationService } from '@app/unraid-api/unraid-file-modifier/unraid-file-modifier.service'; import { UnraidFileModificationService } from '@app/unraid-api/unraid-file-modifier/unraid-file-modifier.service';
const FIXTURE_PATH = join(__dirname, 'modifications', '__fixtures__', 'text-patch-file.txt'); const FIXTURE_PATH = join(__dirname, 'modifications', '__test__', '__fixtures__', 'text-patch-file.txt');
const ORIGINAL_CONTENT = 'original'; const ORIGINAL_CONTENT = 'original';
class TestFileModification extends FileModification { class TestFileModification extends FileModification {