test: add tests for gitUtils (#6949)

* test: add tests for gitUtils

* debug test

* try fix
This commit is contained in:
Joshua Chen 2022-03-21 18:40:20 +08:00 committed by GitHub
parent 3c7b39b739
commit 5ee7e8c48e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 194 additions and 19 deletions

View file

@ -0,0 +1,170 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import {FileNotTrackedError, getFileCommitDate} from '../gitUtils';
import fs from 'fs-extra';
import path from 'path';
import os from 'os';
import shell from 'shelljs';
// This function is sync so the same mock repo can be shared across tests
/* eslint-disable no-restricted-properties */
function createTempRepo() {
const repoDir = fs.mkdtempSync(path.join(os.tmpdir(), 'git-test-repo'));
class Git {
constructor(private dir: string) {
const res = shell.exec('git init', {cwd: dir, silent: true});
if (res.code !== 0) {
throw new Error(`git init exited with code ${res.code}.
stderr: ${res.stderr}
stdout: ${res.stdout}`);
}
}
commit(msg: string, date: string, author: string) {
const addRes = shell.exec('git add .', {cwd: this.dir, silent: true});
const commitRes = shell.exec(
`git commit -m "${msg}" --date "${date}T00:00:00Z" --author "${author}"`,
{
cwd: this.dir,
env: {
GIT_COMMITTER_DATE: `${date}T00:00:00Z`,
GIT_COMMITTER_NAME: author,
},
silent: true,
},
);
if (addRes.code !== 0) {
throw new Error(`git add exited with code ${addRes.code}.
stderr: ${addRes.stderr}
stdout: ${addRes.stdout}`);
}
if (commitRes.code !== 0) {
throw new Error(`git commit exited with code ${commitRes.code}.
stderr: ${commitRes.stderr}
stdout: ${commitRes.stdout}`);
}
}
}
const git = new Git(repoDir);
fs.writeFileSync(path.join(repoDir, 'test.txt'), 'Some content');
git.commit(
'Create test.txt',
'2020-06-19',
'Caroline <caroline@jc-verse.com>',
);
fs.writeFileSync(path.join(repoDir, 'test.txt'), 'Updated content');
git.commit(
'Update test.txt',
'2020-06-20',
'Josh-Cena <josh-cena@jc-verse.com>',
);
fs.writeFileSync(path.join(repoDir, 'test.txt'), 'Updated content (2)');
fs.writeFileSync(path.join(repoDir, 'moved.txt'), 'This file is moved');
git.commit(
'Update test.txt again, create moved.txt',
'2020-09-13',
'Caroline <caroline@jc-verse.com>',
);
fs.moveSync(path.join(repoDir, 'moved.txt'), path.join(repoDir, 'dest.txt'));
git.commit(
'Rename moved.txt to dest.txt',
'2020-11-13',
'Josh-Cena <josh-cena@jc-verse.com>',
);
fs.writeFileSync(path.join(repoDir, 'untracked.txt'), "I'm untracked");
return repoDir;
}
describe('getFileCommitDate', () => {
const repoDir = createTempRepo();
it('returns earliest commit date', async () => {
expect(getFileCommitDate(path.join(repoDir, 'test.txt'), {})).toEqual({
date: new Date('2020-06-19'),
timestamp: new Date('2020-06-19').getTime() / 1000,
});
expect(getFileCommitDate(path.join(repoDir, 'dest.txt'), {})).toEqual({
date: new Date('2020-09-13'),
timestamp: new Date('2020-09-13').getTime() / 1000,
});
});
it('returns latest commit date', async () => {
expect(
getFileCommitDate(path.join(repoDir, 'test.txt'), {age: 'newest'}),
).toEqual({
date: new Date('2020-09-13'),
timestamp: new Date('2020-09-13').getTime() / 1000,
});
expect(
getFileCommitDate(path.join(repoDir, 'dest.txt'), {age: 'newest'}),
).toEqual({
date: new Date('2020-11-13'),
timestamp: new Date('2020-11-13').getTime() / 1000,
});
});
it('returns latest commit date with author', async () => {
expect(
getFileCommitDate(path.join(repoDir, 'test.txt'), {
age: 'oldest',
includeAuthor: true,
}),
).toEqual({
date: new Date('2020-06-19'),
timestamp: new Date('2020-06-19').getTime() / 1000,
author: 'Caroline',
});
expect(
getFileCommitDate(path.join(repoDir, 'dest.txt'), {
age: 'oldest',
includeAuthor: true,
}),
).toEqual({
date: new Date('2020-09-13'),
timestamp: new Date('2020-09-13').getTime() / 1000,
author: 'Caroline',
});
});
it('returns earliest commit date with author', async () => {
expect(
getFileCommitDate(path.join(repoDir, 'test.txt'), {
age: 'newest',
includeAuthor: true,
}),
).toEqual({
date: new Date('2020-09-13'),
timestamp: new Date('2020-09-13').getTime() / 1000,
author: 'Caroline',
});
expect(
getFileCommitDate(path.join(repoDir, 'dest.txt'), {
age: 'newest',
includeAuthor: true,
}),
).toEqual({
date: new Date('2020-11-13'),
timestamp: new Date('2020-11-13').getTime() / 1000,
author: 'Josh-Cena',
});
});
it('throws custom error when file is not tracked', async () => {
expect(() =>
getFileCommitDate(path.join(repoDir, 'untracked.txt'), {
age: 'newest',
includeAuthor: true,
}),
).toThrowError(FileNotTrackedError);
});
it('throws when file not found', async () => {
expect(() =>
getFileCommitDate(path.join(repoDir, 'nonexistent.txt'), {
age: 'newest',
includeAuthor: true,
}),
).toThrowError(
/Failed to retrieve git history for ".*nonexistent.txt" because the file does not exist./,
);
});
});

View file

@ -12,7 +12,22 @@ export class GitNotFoundError extends Error {}
export class FileNotTrackedError extends Error {}
export const getFileCommitDate = (
export function getFileCommitDate(
file: string,
args: {age?: 'oldest' | 'newest'; includeAuthor?: false},
): {
date: Date;
timestamp: number;
};
export function getFileCommitDate(
file: string,
args: {age?: 'oldest' | 'newest'; includeAuthor: true},
): {
date: Date;
timestamp: number;
author: string;
};
export function getFileCommitDate(
file: string,
{
age = 'oldest',
@ -25,7 +40,7 @@ export const getFileCommitDate = (
date: Date;
timestamp: number;
author?: string;
} => {
} {
if (!shell.which('git')) {
throw new GitNotFoundError(
`Failed to retrieve git history for "${file}" because git is not installed.`,
@ -38,9 +53,6 @@ export const getFileCommitDate = (
);
}
const fileBasename = path.basename(file);
const fileDirname = path.dirname(file);
let formatArg = '--format=%ct';
if (includeAuthor) {
formatArg += ',%an';
@ -54,10 +66,10 @@ export const getFileCommitDate = (
}
const result = shell.exec(
`git log ${extraArgs} ${formatArg} -- "${fileBasename}"`,
`git log ${extraArgs} ${formatArg} -- "${path.basename(file)}"`,
{
// cwd is important, see: https://github.com/facebook/docusaurus/pull/5048
cwd: fileDirname,
cwd: path.dirname(file),
silent: true,
},
);
@ -81,22 +93,17 @@ export const getFileCommitDate = (
const match = output.match(regex);
if (
!match ||
!match.groups ||
!match.groups.timestamp ||
(includeAuthor && !match.groups.author)
) {
if (!match) {
throw new Error(
`Failed to retrieve the git history for file "${file}" with unexpected output: ${output}`,
);
}
const timestamp = Number(match.groups.timestamp);
const timestamp = Number(match.groups!.timestamp);
const date = new Date(timestamp * 1000);
if (includeAuthor) {
return {date, timestamp, author: match.groups.author};
return {date, timestamp, author: match.groups!.author!};
}
return {date, timestamp};
};
}