Skip to content

Commit

Permalink
chore(testing): add unit tests for checkout
Browse files Browse the repository at this point in the history
  • Loading branch information
aorinevo committed Feb 11, 2024
1 parent 64233f6 commit 36fb8e5
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 1 deletion.
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@
"test": "jest --coverage src/"
},
"jest": {
"coveragePathIgnorePatterns": [
"\\.mock\\.ts$"
],
"moduleFileExtensions": [
"ts",
"tsx",
Expand Down
26 changes: 26 additions & 0 deletions src/adapters/adapter.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import IRepoAdapter, { IEnvironmentVariables, IRepo } from './base';

const mockAdapter: IRepoAdapter = {
getCandidateRepos: jest.fn() as unknown as (onRetry: jest.Mock) => Promise<IRepo[]>,
parseRepo: jest.fn() as unknown as (repo: string) => IRepo,
reposEqual: jest.fn() as unknown as (repo1: IRepo, repo2: IRepo) => boolean,
stringifyRepo: jest.fn() as unknown as (repo: IRepo) => string,
mapRepoAfterCheckout: jest.fn() as unknown as (repo: Readonly<IRepo>) => Promise<IRepo>,
checkoutRepo: jest.fn() as unknown as (repo: IRepo) => Promise<void>,
resetChangedFiles: jest.fn() as unknown as (repo: IRepo) => Promise<void>,
resetRepoBeforeApply: jest.fn() as unknown as (repo: IRepo, force: boolean) => Promise<void>,
commitRepo: jest.fn() as unknown as (repo: IRepo) => Promise<void>,
pushRepo: jest.fn() as unknown as (repo: IRepo, force: boolean) => Promise<void>,
createPullRequest: jest.fn() as unknown as (
repo: IRepo,
message: string,
upstreamOwner: string
) => Promise<void>,
getPullRequestStatus: jest.fn() as unknown as (repo: IRepo) => Promise<string[]>,
getRepoDir: jest.fn() as unknown as (repo: IRepo) => string,
getDataDir: jest.fn() as unknown as (repo: IRepo) => string,
getBaseBranch: jest.fn() as unknown as (repo: IRepo) => string,
getEnvironmentVariables: jest.fn() as unknown as (repo: IRepo) => Promise<IEnvironmentVariables>,
};

export default mockAdapter;
70 changes: 70 additions & 0 deletions src/commands/checkout.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { IMigrationContext } from '../migration-context';
import checkout from './checkout';
import mockAdapter from '../adapters/adapter.mock';
import mockLogger from '../logger/logger.mock';
import mockSpinner from '../logger/spinner.mock';

jest.mock('fs-extra', () => {
return {
// Mock other methods as needed
mkdirs: jest.fn().mockResolvedValue(undefined),
pathExists: jest.fn().mockResolvedValue(true),
readFile: jest.fn().mockResolvedValue('{"name": "test"}'),
outputFile: jest.fn().mockResolvedValue(undefined),
remove: jest.fn().mockResolvedValue(undefined),
};
});

describe('checkout command', () => {
const mockContext: IMigrationContext = {
shepherd: {
workingDirectory: 'workingDirectory',
},
migration: {
migrationDirectory: 'migrationDirectory',
spec: {
id: 'id',
title: 'title',
adapter: {
type: 'adapter',
},
hooks: {},
},
workingDirectory: 'workingDirectory',
selectedRepos: [{ name: 'selectedRepos' }],
repos: [{ name: 'selectedRepos' }],
upstreamOwner: 'upstreamOwner',
},
adapter: mockAdapter,
logger: mockLogger,
};

beforeEach(() => {
jest.clearAllMocks();
});

it('clones repos given a specific list of repos', async () => {
await checkout(mockContext);
expect(mockLogger.info).toHaveBeenCalledWith('Using 1 selected repos');
expect(mockAdapter.checkoutRepo).toHaveBeenCalledWith({ name: 'selectedRepos' });
expect(mockSpinner.succeed).toHaveBeenCalledWith('Checked out repo');
});

it('gets candidate repos when list of repos is not provided', async () => {
mockContext.migration.selectedRepos = undefined;
await checkout(mockContext);
expect(mockAdapter.getCandidateRepos).toHaveBeenCalled();
expect(mockSpinner.succeed).toHaveBeenCalledWith('Loaded 0 repos');
});

it('handles errors when checking out repos', async () => {
mockContext.migration.selectedRepos = [{ name: 'selectedRepos' }];
mockContext.migration.repos = [{ name: 'selectedRepos' }];
mockAdapter.checkoutRepo = jest.fn().mockImplementation(() => {
throw new Error('Mocked error');
});
await checkout(mockContext);
expect(mockLogger.error).toHaveBeenCalledWith(new Error('Mocked error'));
expect(mockSpinner.fail).toHaveBeenCalledWith('Failed to check out repo; skipping');
});
});
2 changes: 1 addition & 1 deletion src/commands/checkout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default async (context: IMigrationContext) => {
repos = selectedRepos;
} else {
const spinner = logger.spinner('Loading candidate repos');
repos = await adapter.getCandidateRepos(onRetry);
repos = (await adapter.getCandidateRepos(onRetry)) || [];
spinner.succeed(`Loaded ${repos.length} repos`);
}

Expand Down
18 changes: 18 additions & 0 deletions src/logger/logger.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { ILogger } from '.';
import mockSpinner from './spinner.mock';

const mockLogger: ILogger = {
// Basic logging
debug: jest.fn() as unknown as (message: string) => void,
info: jest.fn() as unknown as (message: string) => void,
warn: jest.fn() as unknown as (message: string) => void,
error: jest.fn() as unknown as (message: string) => void,
fatal: jest.fn() as unknown as (message: string) => void,
succeedIcon: jest.fn() as unknown as (message: string) => void,
failIcon: jest.fn() as unknown as (message: string) => void,
warnIcon: jest.fn() as unknown as (message: string) => void,
infoIcon: jest.fn() as unknown as (message: string) => void,
spinner: jest.fn().mockImplementation(() => mockSpinner),
};

export default mockLogger;
15 changes: 15 additions & 0 deletions src/logger/spinner.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { ISpinner } from '.';

const mockSpinner: ISpinner = {
start: jest.fn(),
stop: jest.fn(),
succeed: jest.fn(),
fail: jest.fn(),
warn: jest.fn(),
info: jest.fn(),
clear: jest.fn(),
render: jest.fn(),
destroy: jest.fn(),
};

export default mockSpinner;

0 comments on commit 36fb8e5

Please sign in to comment.