mirror of
https://github.com/facebook/docusaurus.git
synced 2025-05-10 23:57:22 +02:00
test: add tests for gitUtils (#6949)
* test: add tests for gitUtils * debug test * try fix
This commit is contained in:
parent
3c7b39b739
commit
5ee7e8c48e
3 changed files with 194 additions and 19 deletions
170
packages/docusaurus-utils/src/__tests__/gitUtils.test.ts
Normal file
170
packages/docusaurus-utils/src/__tests__/gitUtils.test.ts
Normal 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./,
|
||||
);
|
||||
});
|
||||
});
|
|
@ -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};
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue