Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

create release 2.1.6 #32

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "find-duplicate-strings",
"version": "2.1.5",
"version": "2.1.6",
"description": "Easy to use CLI that finds duplicate strings in a directory and stores them in a external file for easy reference",
"author": "Erwin Heitzman",
"homepage": "https://github.com/erwinheitzman/find-duplicate-strings/blob/master/README.md",
Expand Down
6 changes: 5 additions & 1 deletion src/cli/questions/question.mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { Question } from './question';
import { QuestionMap } from 'inquirer';

export class QuestionMock extends Question {
constructor(name: string, message: string, type: keyof QuestionMap = 'input', defaultAnswer?: string) {
public constructor(name: string, message: string, type?: keyof QuestionMap, defaultAnswer?: string) {
super(name, message, type, defaultAnswer);
}

public async getAnswer(): Promise<string> {
return super.getAnswer();
}
}
26 changes: 25 additions & 1 deletion src/cli/questions/question.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { prompt } from 'inquirer';
import { QuestionMock } from './question.mocks';

jest.mock('inquirer');

const promptMock = prompt as unknown as jest.Mock;

describe('Question', () => {
it('should have default type "input"', () => {
const question = new QuestionMock('foo', 'bar');

expect(question['type']).toEqual('input');
});

Expand All @@ -21,4 +23,26 @@ describe('Question', () => {

expect(question['type']).toEqual('password');
});

it('should set the defaultAnswer', () => {
const question = new QuestionMock('foo', 'bar', 'password', 'foobar');

expect(question['defaultAnswer']).toEqual('foobar');
});

it('should return the answer when it exists', async () => {
const answerData = { cookies: 'yes' };
promptMock.mockResolvedValue(answerData);
const question = new QuestionMock('cookies', 'do you want cookies?');
const answer = await question.getAnswer();
expect(answer).toEqual('yes');
});

it('should return undefined when it does not exist', async () => {
const answerData = {};
promptMock.mockResolvedValue(answerData);
const question = new QuestionMock('cookies', 'do you want cookies?');
const answer = await question.getAnswer();
expect(answer).toEqual(undefined);
});
});
2 changes: 2 additions & 0 deletions src/cli/questions/question.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ export abstract class Question {
default: this.defaultAnswer,
});

console.log('answer: ', answer);

return answer[this.name];
}
}
24 changes: 22 additions & 2 deletions src/scanner.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,28 +83,48 @@ describe('Scanner', () => {
expect(scanner['exclusions']).toEqual(['one', 'two', 'three']);
});

it('should ask a question when exclusions are not provided', async () => {
it('should ask a question when exclusions are not provided and the path does not point to a file', async () => {
statSyncMock.mockReturnValue({ isFile: () => false, isDirectory: () => true });
const scanner = new Scanner({}, bottomBar, interval);

await scanner.scan();

expect(ExclusionsQuestion.prototype.getAnswer).toBeCalledTimes(1);
});

it('should not ask a question when exclusions are not provided and the path points to a file', async () => {
statSyncMock.mockReturnValue({ isFile: () => true, isDirectory: () => false });
const scanner = new Scanner({}, bottomBar, interval);

await scanner.scan();

expect(ExclusionsQuestion.prototype.getAnswer).toBeCalledTimes(0);
});

it('should set extensions', async () => {
const scanner = new Scanner({ extensions: 'one,two,three' }, bottomBar, interval);

expect(scanner['extensions']).toEqual(['one', 'two', 'three']);
});

it('should ask a question when extensions are not provided', async () => {
it('should ask a question when extensions are not provided and the path does not point to a file', async () => {
statSyncMock.mockReturnValue({ isFile: () => false, isDirectory: () => true });
const scanner = new Scanner({}, bottomBar, interval);

await scanner.scan();

expect(ExtensionsQuestion.prototype.getAnswer).toBeCalledTimes(1);
});

it('should not ask a question when extensions are not provided and the path points to a file', async () => {
statSyncMock.mockReturnValue({ isFile: () => true, isDirectory: () => false });
const scanner = new Scanner({}, bottomBar, interval);

await scanner.scan();

expect(ExtensionsQuestion.prototype.getAnswer).toBeCalledTimes(0);
});

it('should set a threshold when passing threshold as a number', async () => {
getAllMock.mockReturnValue([{ count: 5 }]);
const scanner = new Scanner({ threshold: 3 }, bottomBar, interval);
Expand Down
49 changes: 18 additions & 31 deletions src/scanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,20 @@ export class Scanner {
public async scan(): Promise<void> {
const path = this.path.length ? this.path : await new PathQuestion().getAnswer();

if (!this.exclusions) {
const fullPath = normalize(resolve(process.cwd(), path));

if (!existsSync(fullPath)) {
throw new Error('Invalid path: No such directory or file.');
}

const lstat = statSync(fullPath);

if (!this.exclusions && lstat.isDirectory()) {
const answer = await new ExclusionsQuestion().getAnswer();
this.exclusions = Exclusions.process(answer);
}

if (!this.extensions) {
if (!this.extensions && lstat.isDirectory()) {
const answer = await new ExtensionsQuestion().getAnswer();
this.extensions = Extensions.process(answer);
}
Expand Down Expand Up @@ -96,30 +104,6 @@ export class Scanner {
await new Output(duplicates as Finding[], this.silent).output();
}

private async startScan(path: string) {
const fullPath = normalize(resolve(process.cwd(), path));

const noSuchDirectoryOrFileError = new Error('Invalid path: No such directory or file.');

if (!existsSync(fullPath)) {
throw noSuchDirectoryOrFileError;
}

const lstat = statSync(fullPath);

if (lstat.isFile()) {
await this.scanFile(fullPath);
return;
}

if (lstat.isDirectory()) {
await this.scanDir(fullPath);
return;
}

throw noSuchDirectoryOrFileError;
}

private async scanDir(path: string): Promise<void> {
const directory = new Directory(path, this.exclusions, this.extensions);
const files = directory.getFiles();
Expand Down Expand Up @@ -156,11 +140,14 @@ export class Scanner {
clearInterval(loader);
});

try {
await this.startScan(path);
} catch (error: any) {
clearLoader();
throw error;
const lstat = statSync(path);

if (lstat.isFile()) {
await this.scanFile(path);
}

if (lstat.isDirectory()) {
await this.scanDir(path);
}

clearLoader();
Expand Down