Skip to content

Commit

Permalink
feat(tests): add tests for file-util.ts (#100)
Browse files Browse the repository at this point in the history
  • Loading branch information
virgofx authored Oct 28, 2024
1 parent f1db197 commit 036733a
Show file tree
Hide file tree
Showing 7 changed files with 358 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ on:
# a pull request.
push:
branches:
- master
- main
pull_request:
types: [opened, synchronize, reopened]

Expand Down
2 changes: 1 addition & 1 deletion __tests__/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type InputMap = {
[key: string]: string;
};

describe('config', () => {
describe('config.ts', () => {
const defaultInputs: InputMap = {
'major-keywords': 'BREAKING CHANGE,!',
'minor-keywords': 'feat,feature',
Expand Down
318 changes: 318 additions & 0 deletions __tests__/file-util.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,318 @@
import * as fs from 'node:fs';
import * as os from 'node:os';
import * as path from 'node:path';
import { copyModuleContents, removeDirectoryContents, shouldExcludeFile } from '../src/file-util';

describe('file-util.ts', () => {
let tempDir: string;

beforeEach(() => {
// Create a temporary directory before each test
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-dir-'));
});

afterEach(() => {
// Remove temporary directory
fs.rmSync(tempDir, { recursive: true });
});

describe('shouldExcludeFile', () => {
it('should exclude file when pattern matches', () => {
const baseDirectory = tempDir;
const filePath = path.join(tempDir, 'file.txt');
const excludePatterns = ['*.txt'];

expect(shouldExcludeFile(baseDirectory, filePath, excludePatterns)).toBe(true);
});

it('should not exclude file when pattern does not match', () => {
const baseDirectory = tempDir;
const filePath = path.join(tempDir, 'file.txt');
const excludePatterns = ['*.js'];

expect(shouldExcludeFile(baseDirectory, filePath, excludePatterns)).toBe(false);
});

it('should handle relative paths correctly', () => {
const baseDirectory = tempDir;
const filePath = path.join(tempDir, 'subdir', 'file.txt');
const excludePatterns = ['subdir/*.txt'];

expect(shouldExcludeFile(baseDirectory, filePath, excludePatterns)).toBe(true);
});

it('should handle exclusion pattern: *.md', () => {
const baseDirectory = tempDir;
const filePath1 = path.join(tempDir, 'README.md');
const filePath2 = path.join(tempDir, 'nested', 'README.md');
const excludePatterns = ['*.md'];

expect(shouldExcludeFile(baseDirectory, filePath1, excludePatterns)).toBe(true);
expect(shouldExcludeFile(baseDirectory, filePath2, excludePatterns)).toBe(true);
});

it('should handle exclusion pattern: **/*.md', () => {
const baseDirectory = tempDir;
const filePath1 = path.join(tempDir, 'README.md');
const filePath2 = path.join(tempDir, 'nested', 'README.md');
const excludePatterns = ['**/*.md'];

expect(shouldExcludeFile(baseDirectory, filePath1, excludePatterns)).toBe(true);
expect(shouldExcludeFile(baseDirectory, filePath2, excludePatterns)).toBe(true);
});

it('should handle exclusion pattern: tests/**', () => {
const baseDirectory = tempDir;
const filePath1 = path.join(tempDir, 'tests/config.test.ts');
const filePath2 = path.join(tempDir, 'tests2/config.test.ts');
const filePath3 = path.join(tempDir, 'tests2/tests/config.test.ts');
const excludePatterns = ['tests/**'];

expect(shouldExcludeFile(baseDirectory, filePath1, excludePatterns)).toBe(true);
expect(shouldExcludeFile(baseDirectory, filePath2, excludePatterns)).toBe(false);
expect(shouldExcludeFile(baseDirectory, filePath3, excludePatterns)).toBe(false);
});

it('should handle exclusion pattern: **/tests/**', () => {
const baseDirectory = tempDir;
const filePath1 = path.join(tempDir, 'tests/config.test.ts');
const filePath2 = path.join(tempDir, 'tests2/config.test.ts');
const filePath3 = path.join(tempDir, 'tests2/tests/config.test.ts');
const excludePatterns = ['**/tests/**'];

expect(shouldExcludeFile(baseDirectory, filePath1, excludePatterns)).toBe(true);
expect(shouldExcludeFile(baseDirectory, filePath2, excludePatterns)).toBe(false);
expect(shouldExcludeFile(baseDirectory, filePath3, excludePatterns)).toBe(true);
});
});

describe('copyModuleContents', () => {
beforeEach(() => {
// Create src and dest directories for every test in this suite
fs.mkdirSync(path.join(tempDir, 'src'), { recursive: true });
fs.mkdirSync(path.join(tempDir, 'dest'), { recursive: true });
});

it('should copy directory contents excluding files that match patterns', () => {
const srcDirectory = path.join(tempDir, 'src');
const destDirectory = path.join(tempDir, 'dest');
const excludePatterns = ['*.txt'];

// Create files in src directory
fs.writeFileSync(path.join(srcDirectory, 'file.txt'), 'Hello World!');
fs.writeFileSync(path.join(srcDirectory, 'file.js'), 'console.log("Hello World!");');

// Now perform the copy operation
copyModuleContents(srcDirectory, destDirectory, excludePatterns);

// Check that the file was copied
expect(fs.existsSync(path.join(destDirectory, 'file.txt'))).toBe(false);
expect(fs.existsSync(path.join(destDirectory, 'file.js'))).toBe(true);
});

it('should handle recursive directory copying', () => {
const srcDirectory = path.join(tempDir, 'src');
const destDirectory = path.join(tempDir, 'dest');
const excludePatterns: string[] = [];

// Create source structure
fs.mkdirSync(path.join(srcDirectory, 'subdir'), { recursive: true });
fs.writeFileSync(path.join(srcDirectory, 'file.txt'), 'Hello World!');
fs.writeFileSync(path.join(srcDirectory, 'subdir', 'file.js'), 'console.log("Hello World!");');

// Perform the copy operation
copyModuleContents(srcDirectory, destDirectory, excludePatterns);

// Validate the destination contents
expect(fs.existsSync(path.join(destDirectory, 'file.txt'))).toBe(true);
expect(fs.existsSync(path.join(destDirectory, 'subdir', 'file.js'))).toBe(true);
});

it('should copy files excluding multiple patterns', () => {
const srcDirectory = path.join(tempDir, 'src');
const destDirectory = path.join(tempDir, 'dest');
const excludePatterns = ['*.txt', '*.js'];

fs.writeFileSync(path.join(srcDirectory, 'file.txt'), 'Hello World!');
fs.writeFileSync(path.join(srcDirectory, 'file.js'), 'console.log("Hello World!");');
fs.writeFileSync(path.join(srcDirectory, 'file.md'), 'This is a markdown file.');

copyModuleContents(srcDirectory, destDirectory, excludePatterns);

expect(fs.existsSync(path.join(destDirectory, 'file.txt'))).toBe(false);
expect(fs.existsSync(path.join(destDirectory, 'file.js'))).toBe(false);
expect(fs.existsSync(path.join(destDirectory, 'file.md'))).toBe(true);
});

it('should handle copying from an empty directory', () => {
const srcDirectory = path.join(tempDir, 'src');
const destDirectory = path.join(tempDir, 'dest');
const excludePatterns = ['*.txt'];

copyModuleContents(srcDirectory, destDirectory, excludePatterns);

// Validate that the destination directory is still empty
expect(fs.readdirSync(destDirectory).length).toBe(0);
});

it('should throw an error if the source directory does not exist', () => {
const nonExistentSrcDirectory = path.join(tempDir, 'non-existent-src');
const destDirectory = path.join(tempDir, 'dest');
const excludePatterns = ['*.txt'];

expect(() => {
copyModuleContents(nonExistentSrcDirectory, destDirectory, excludePatterns);
}).toThrow(); // Assuming your implementation throws an error for non-existent directories
});

it('should copy files that do not match any exclusion patterns', () => {
const srcDirectory = path.join(tempDir, 'src');
const destDirectory = path.join(tempDir, 'dest');
const excludePatterns = ['*.js'];

fs.writeFileSync(path.join(srcDirectory, 'file.txt'), 'Hello World!');
fs.writeFileSync(path.join(srcDirectory, 'file.js'), 'console.log("Hello World!");');

copyModuleContents(srcDirectory, destDirectory, excludePatterns);

expect(fs.existsSync(path.join(destDirectory, 'file.txt'))).toBe(true);
expect(fs.existsSync(path.join(destDirectory, 'file.js'))).toBe(false);
});

it('should overwrite files in the destination if they have the same name and do not match exclusion patterns', () => {
const srcDirectory = path.join(tempDir, 'src');
const destDirectory = path.join(tempDir, 'dest');
const excludePatterns: string[] = [];

fs.writeFileSync(path.join(srcDirectory, 'file.txt'), 'Hello World from source!');
fs.writeFileSync(path.join(destDirectory, 'file.txt'), 'Hello World from destination!');

copyModuleContents(srcDirectory, destDirectory, excludePatterns);

const destContent = fs.readFileSync(path.join(destDirectory, 'file.txt'), 'utf-8');
expect(destContent).toBe('Hello World from source!');
});
});

describe('removeDirectoryContents', () => {
it('should remove directory contents except for specified exceptions', () => {
const directory = path.join(tempDir, 'dir');
const exceptions = ['file.txt'];

fs.mkdirSync(directory);
fs.writeFileSync(path.join(directory, 'file.txt'), 'Hello World!');
fs.writeFileSync(path.join(directory, 'file.js'), 'console.log("Hello World!");');

removeDirectoryContents(directory, exceptions);

expect(fs.existsSync(path.join(directory, 'file.txt'))).toBe(true);
expect(fs.existsSync(path.join(directory, 'file.js'))).toBe(false);
});

it('should handle recursive directory removal', () => {
const directory = path.join(tempDir, 'dir');
const exceptions: string[] = [];

fs.mkdirSync(directory);
fs.mkdirSync(path.join(directory, 'subdir'));
fs.writeFileSync(path.join(directory, 'file.txt'), 'Hello World!');
fs.writeFileSync(path.join(directory, 'subdir', 'file.js'), 'console.log("Hello World!");');

removeDirectoryContents(directory, exceptions);

expect(fs.existsSync(path.join(directory, 'file.txt'))).toBe(false);
expect(fs.existsSync(path.join(directory, 'subdir', 'file.js'))).toBe(false);
});

it('should handle exceptions correctly', () => {
const directory = path.join(tempDir, 'dir');
const exceptions = ['file.txt', 'subdir'];

fs.mkdirSync(directory);
fs.mkdirSync(path.join(directory, 'subdir'));
fs.writeFileSync(path.join(directory, 'file.txt'), 'Hello World!');
fs.writeFileSync(path.join(directory, 'file.js'), 'console.log("Hello World!");');
fs.writeFileSync(path.join(directory, 'subdir', 'file.js'), 'console.log("Hello World!");');

removeDirectoryContents(directory, exceptions);

expect(fs.existsSync(path.join(directory, 'file.txt'))).toBe(true);
expect(fs.existsSync(path.join(directory, 'file.js'))).toBe(false);
expect(fs.existsSync(path.join(directory, 'subdir', 'file.js'))).toBe(true);
});

it('should handle an empty directory', () => {
const directory = path.join(tempDir, 'dir');
const exceptions: string[] = [];

fs.mkdirSync(directory); // Create an empty directory
removeDirectoryContents(directory, exceptions);

// Validate that the directory is still empty
expect(fs.readdirSync(directory).length).toBe(0);
});

it('should not remove if only exceptions are present', () => {
const directory = path.join(tempDir, 'dir');
const exceptions = ['file.txt'];

fs.mkdirSync(directory);
fs.writeFileSync(path.join(directory, 'file.txt'), 'Hello World!');

removeDirectoryContents(directory, exceptions);

expect(fs.existsSync(path.join(directory, 'file.txt'))).toBe(true);
expect(fs.readdirSync(directory).length).toBe(1); // Only the exception should exist
});

it('should handle nested exceptions correctly', () => {
const directory = path.join(tempDir, 'dir');
const exceptions = ['subdir'];

fs.mkdirSync(directory);
fs.mkdirSync(path.join(directory, 'subdir'));
fs.writeFileSync(path.join(directory, 'file.txt'), 'Hello World!');
fs.writeFileSync(path.join(directory, 'subdir', 'file.js'), 'console.log("Hello World!");');

removeDirectoryContents(directory, exceptions);

expect(fs.existsSync(path.join(directory, 'subdir'))).toBe(true);
expect(fs.existsSync(path.join(directory, 'file.txt'))).toBe(false);
expect(fs.existsSync(path.join(directory, 'subdir', 'file.js'))).toBe(true);
});

it('should not throw an error if the directory does not exist', () => {
const nonExistentDirectory = path.join(tempDir, 'non-existent-dir');
const exceptions = ['file.txt'];

expect(() => {
removeDirectoryContents(nonExistentDirectory, exceptions);
}).not.toThrow(); // Ensure no error is thrown
});

it('should handle exceptions that do not exist in the directory', () => {
const directory = path.join(tempDir, 'dir');
const exceptions = ['file.txt'];

fs.mkdirSync(directory);
fs.writeFileSync(path.join(directory, 'file.js'), 'console.log("Hello World!");');

removeDirectoryContents(directory, exceptions);

expect(fs.existsSync(path.join(directory, 'file.js'))).toBe(false);
});

it('should remove directory contents when no exceptions specified', () => {
const directory = path.join(tempDir, 'dir');

fs.mkdirSync(directory);
fs.writeFileSync(path.join(directory, 'file.txt'), 'Hello World!');
fs.writeFileSync(path.join(directory, 'file.js'), 'console.log("Hello World!");');

removeDirectoryContents(directory);

expect(fs.existsSync(path.join(directory, 'file.txt'))).toBe(false);
expect(fs.existsSync(path.join(directory, 'file.js'))).toBe(false);
});
});
});
2 changes: 1 addition & 1 deletion assets/coverage-badge.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
sonar.organization=techpivot
sonar.projectKey=terraform-module-releaser
sonar.projectName=Terraform Mmodule Releaser
sonar.projectName=Terraform Module Releaser

sonar.sourceEncoding=UTF-8

Expand Down
Loading

0 comments on commit 036733a

Please sign in to comment.