Refactor blog tests using former VCS hardcoded values

This commit is contained in:
sebastien 2025-10-31 14:12:17 +01:00
parent 42d0d96b62
commit 2366ca16bf
8 changed files with 118 additions and 48 deletions

View File

@ -10,9 +10,8 @@ import * as path from 'path';
import {normalizePluginOptions} from '@docusaurus/utils-validation';
import {
posixPath,
getFileCommitDate,
LAST_UPDATE_FALLBACK,
getLocaleConfig,
DEFAULT_TEST_VCS_CONFIG,
} from '@docusaurus/utils';
import {DEFAULT_FUTURE_CONFIG} from '@docusaurus/core/src/server/configValidation';
import pluginContentBlog from '../index';
@ -32,6 +31,12 @@ import type {
EditUrlFunction,
} from '@docusaurus/plugin-content-blog';
async function getFileCreationDate(filePath: string): Promise<Date> {
return new Date(
(await DEFAULT_TEST_VCS_CONFIG.getFileCreationInfo(filePath)).timestamp,
);
}
const markdown: MarkdownConfig = {
format: 'mdx',
mermaid: true,
@ -561,10 +566,7 @@ describe('blog plugin', () => {
const blogPosts = await getBlogPosts(siteDir);
const noDateSource = path.posix.join('@site', PluginPath, 'no date.md');
const noDateSourceFile = path.posix.join(siteDir, PluginPath, 'no date.md');
// We know the file exists and we know we have git
const noDateSourceTime = (
await getFileCommitDate(noDateSourceFile, {age: 'oldest'})
).date;
const noDateSourceTime = await getFileCreationDate(noDateSourceFile);
expect({
...getByTitle(blogPosts, 'no date').metadata,
@ -675,29 +677,25 @@ describe('last update', () => {
);
const {blogPosts} = (await plugin.loadContent!())!;
expect(blogPosts[0]?.metadata.lastUpdatedBy).toBe('seb');
expect(blogPosts[0]?.metadata.lastUpdatedAt).toBe(
LAST_UPDATE_FALLBACK.lastUpdatedAt,
const TestLastUpdate = await DEFAULT_TEST_VCS_CONFIG.getFileLastUpdateInfo(
'any path',
);
expect(blogPosts[1]?.metadata.lastUpdatedBy).toBe(
LAST_UPDATE_FALLBACK.lastUpdatedBy,
expect(blogPosts[0]?.metadata.lastUpdatedBy).toBe('seb');
expect(blogPosts[0]?.metadata.lastUpdatedAt).toBe(
lastUpdateFor('2021-01-01'),
);
expect(blogPosts[1]?.metadata.lastUpdatedBy).toBe(TestLastUpdate.author);
expect(blogPosts[1]?.metadata.lastUpdatedAt).toBe(
LAST_UPDATE_FALLBACK.lastUpdatedAt,
lastUpdateFor('2021-01-01'),
);
expect(blogPosts[2]?.metadata.lastUpdatedBy).toBe('seb');
expect(blogPosts[2]?.metadata.lastUpdatedAt).toBe(
lastUpdateFor('2021-01-01'),
);
expect(blogPosts[2]?.metadata.lastUpdatedAt).toBe(TestLastUpdate.timestamp);
expect(blogPosts[3]?.metadata.lastUpdatedBy).toBe(
LAST_UPDATE_FALLBACK.lastUpdatedBy,
);
expect(blogPosts[3]?.metadata.lastUpdatedAt).toBe(
lastUpdateFor('2021-01-01'),
);
expect(blogPosts[3]?.metadata.lastUpdatedBy).toBe(TestLastUpdate.author);
expect(blogPosts[3]?.metadata.lastUpdatedAt).toBe(TestLastUpdate.timestamp);
});
it('time only', async () => {
@ -711,29 +709,29 @@ describe('last update', () => {
);
const {blogPosts} = (await plugin.loadContent!())!;
expect(blogPosts[0]?.metadata.title).toBe('Author');
const TestLastUpdate = await DEFAULT_TEST_VCS_CONFIG.getFileLastUpdateInfo(
'any path',
);
expect(blogPosts[0]?.metadata.title).toBe('Both');
expect(blogPosts[0]?.metadata.lastUpdatedBy).toBeUndefined();
expect(blogPosts[0]?.metadata.lastUpdatedAt).toBe(
LAST_UPDATE_FALLBACK.lastUpdatedAt,
lastUpdateFor('2021-01-01'),
);
expect(blogPosts[1]?.metadata.title).toBe('Nothing');
expect(blogPosts[1]?.metadata.title).toBe('Last update date');
expect(blogPosts[1]?.metadata.lastUpdatedBy).toBeUndefined();
expect(blogPosts[1]?.metadata.lastUpdatedAt).toBe(
LAST_UPDATE_FALLBACK.lastUpdatedAt,
lastUpdateFor('2021-01-01'),
);
expect(blogPosts[2]?.metadata.title).toBe('Both');
expect(blogPosts[2]?.metadata.title).toBe('Author');
expect(blogPosts[2]?.metadata.lastUpdatedBy).toBeUndefined();
expect(blogPosts[2]?.metadata.lastUpdatedAt).toBe(
lastUpdateFor('2021-01-01'),
);
expect(blogPosts[2]?.metadata.lastUpdatedAt).toBe(TestLastUpdate.timestamp);
expect(blogPosts[3]?.metadata.title).toBe('Last update date');
expect(blogPosts[3]?.metadata.title).toBe('Nothing');
expect(blogPosts[3]?.metadata.lastUpdatedBy).toBeUndefined();
expect(blogPosts[3]?.metadata.lastUpdatedAt).toBe(
lastUpdateFor('2021-01-01'),
);
expect(blogPosts[3]?.metadata.lastUpdatedAt).toBe(TestLastUpdate.timestamp);
});
it('author only', async () => {
@ -747,20 +745,20 @@ describe('last update', () => {
);
const {blogPosts} = (await plugin.loadContent!())!;
const TestLastUpdate = await DEFAULT_TEST_VCS_CONFIG.getFileLastUpdateInfo(
'any path',
);
expect(blogPosts[0]?.metadata.lastUpdatedBy).toBe('seb');
expect(blogPosts[0]?.metadata.lastUpdatedAt).toBeUndefined();
expect(blogPosts[1]?.metadata.lastUpdatedBy).toBe(
LAST_UPDATE_FALLBACK.lastUpdatedBy,
);
expect(blogPosts[1]?.metadata.lastUpdatedBy).toBe(TestLastUpdate.author);
expect(blogPosts[1]?.metadata.lastUpdatedAt).toBeUndefined();
expect(blogPosts[2]?.metadata.lastUpdatedBy).toBe('seb');
expect(blogPosts[2]?.metadata.lastUpdatedAt).toBeUndefined();
expect(blogPosts[3]?.metadata.lastUpdatedBy).toBe(
LAST_UPDATE_FALLBACK.lastUpdatedBy,
);
expect(blogPosts[3]?.metadata.lastUpdatedBy).toBe(TestLastUpdate.author);
expect(blogPosts[3]?.metadata.lastUpdatedAt).toBeUndefined();
});

View File

@ -44,9 +44,9 @@ export type FutureV4Config = {
// The agnostic term "VCS" is used instead of "git" to acknowledge the existence
// of other version control systems, and external systems like CMSs and i18n
// translation SaaS (e.g., Crowdin)
type VcsChangeInfo = {timestamp: number; author: string};
export type VcsChangeInfo = {timestamp: number; author: string};
type VscInitializeParams = {
export type VscInitializeParams = {
siteDir: string;
// TODO could it be useful to provide all plugins getPathsToWatch() here?
// this could give the opportunity to find out all VCS roots ahead of times

View File

@ -14,6 +14,8 @@ export {
FasterConfig,
StorageConfig,
VcsConfig,
VcsChangeInfo,
VscInitializeParams,
Config,
} from './config';

View File

@ -131,6 +131,6 @@ export {
type FrontMatterLastUpdate,
} from './lastUpdateUtils';
export {DEFAULT_VCS_CONFIG} from './vcs/vcs';
export {DEFAULT_VCS_CONFIG, DEFAULT_TEST_VCS_CONFIG} from './vcs/vcs';
export {normalizeTags, reportInlineTags} from './tags';

View File

@ -72,6 +72,8 @@ export async function getGitLastUpdate(
}
}
// TODO Docusaurus v4: remove this legacy fallback data
// we now have a Vcs API that does the same for dev/test envs
export const LAST_UPDATE_FALLBACK: LastUpdateData = {
lastUpdatedAt: 1539502055000,
lastUpdatedBy: 'Author',

View File

@ -48,9 +48,13 @@ const realHasGitFn = () => {
const hasGit =
process.env.NODE_ENV === 'test' ? realHasGitFn : _.memoize(realHasGitFn);
// TODO Docusaurus v4: remove this
// Exceptions are not made for control flow logic
/** Custom error thrown when git is not found in `PATH`. */
export class GitNotFoundError extends Error {}
// TODO Docusaurus v4: remove this, only kept for retro-compatibility
// Exceptions are not made for control flow logic
/** Custom error thrown when the current file is not tracked by git. */
export class FileNotTrackedError extends Error {}

View File

@ -5,24 +5,51 @@
* LICENSE file in the root directory of this source tree.
*/
import {VcsHardcoded} from './vcsHardcoded';
import {VcsGitAdHoc} from './vcsGitAdHoc';
import type {VcsConfig} from '@docusaurus/types';
const VcsPresets = {
'git-ad-hoc': VcsGitAdHoc,
hardcoded: VcsHardcoded,
} as const satisfies Record<string, VcsConfig>;
type VscPresetName = keyof typeof VcsPresets;
function getVcsPreset(presetName: VscPresetName): VcsConfig {
return VcsPresets[presetName];
}
function getDefaultVcsConfig(): VcsConfig {
// TODO configure this properly for dev/test envs
// + opt-in for new Git Eager config
// + escape hatch env for forcing a given known config
// Escape hatch to override the default VCS preset we use
if (process.env.DOCUSAURUS_VCS) {
const vcs = getVcsPreset(process.env.DOCUSAURUS_VCS as VscPresetName);
if (vcs) {
return vcs;
} else {
throw new Error(
`Unknown DOCUSAURUS_VCS preset name: ${process.env.DOCUSAURUS_VCS}`,
);
}
}
if (process.env.NODE_ENV === 'production') {
return VcsGitAdHoc;
return getVcsPreset('git-ad-hoc');
}
// Return hardcoded values in dev to improve DX
if (process.env.NODE_ENV === 'development') {
return VcsGitAdHoc;
return getVcsPreset('hardcoded');
}
// Return hardcoded values in test to make tests simpler and faster
if (process.env.NODE_ENV === 'test') {
return VcsGitAdHoc;
return getVcsPreset('hardcoded');
}
return VcsGitAdHoc;
}
export const DEFAULT_TEST_VCS_CONFIG: VcsConfig = VcsHardcoded;
export const DEFAULT_VCS_CONFIG: VcsConfig = getDefaultVcsConfig();

View File

@ -0,0 +1,37 @@
/**
* 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 type {VcsConfig, VcsChangeInfo} from '@docusaurus/types';
export const VCS_CHANGE_HARDCODED_CREATION_INFO: VcsChangeInfo = {
timestamp: 1490997600000, // 1st Apr 2017
author: 'Creator',
};
export const VCS_CHANGE_HARDCODED_LAST_UPDATE_INFO: VcsChangeInfo = {
timestamp: 1539502055000, // 14th Oct 2018
author: 'Author',
};
/**
* This VCS implementation always returns hardcoded values for testing purposes.
* It is also useful in dev environments where VCS info is not important.
* Reading information from the VCS can be slow and is not always necessary.
*/
export const VcsHardcoded: VcsConfig = {
initialize: () => {
// Noop
},
getFileCreationInfo: async (_filePath: string) => {
return VCS_CHANGE_HARDCODED_CREATION_INFO;
},
getFileLastUpdateInfo: async (_filePath: string) => {
return VCS_CHANGE_HARDCODED_LAST_UPDATE_INFO;
},
};