mirror of
https://github.com/unraid/api.git
synced 2025-12-31 13:39:52 -06:00
feat: move fixtures into __test__ folder
This commit is contained in:
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user