blob: 8b1a18ea5cc5f735f85840a9c67ddd275b7de0d3 [file] [log] [blame]
/**
* @license
* Copyright 2025 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import {assert} from '@open-wc/testing';
import '../test/common-test-setup';
import {
formatCommitMessageString,
detectFormattingErrorsInString,
ErrorType,
FormattingError,
} from './commit-message-formatter-util';
suite('commit-message-formatter-util tests', () => {
suite('formatCommitMessageString', () => {
test('subject exceeding 72 characters is not split', () => {
const longSubject =
'Fix(some-component): This is a very long subject that exceeds 72 characters';
const message = longSubject + '\n\nThis is body.\n\nChange-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
longSubject + '\n\nThis is body.\n\nChange-Id: abcdefg\n'
);
});
test('words are always kept whole', () => {
const message =
'Fix the thing\n\nThis is a very long long long long line with a very-long-word-that-should-not-be-split.\n\nChange-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
'Fix the thing\n\nThis is a very long long long long line with a\nvery-long-word-that-should-not-be-split.\n\nChange-Id: abcdefg\n'
);
});
test('long strings without spaces are not split', () => {
const message =
'Fix the thing\n\nhttps://very-long-url-without-spaces-that-exceeds-72-characters.com/with/some/path/and/query?params=and&more=params\n\nChange-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
'Fix the thing\n\nhttps://very-long-url-without-spaces-that-exceeds-72-characters.com/with/some/path/and/query?params=and&more=params\n\nChange-Id: abcdefg\n'
);
});
test('trailing spaces are removed', () => {
const message =
'Fix the thing \n\nThis is a line with trailing spaces. \nAnd another one. \n\nChange-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
'Fix the thing\n\nThis is a line with trailing spaces. And another one.\n\nChange-Id: abcdefg\n'
);
});
test('leading spaces are removed from subject and first body line', () => {
const message =
' Fix the thing\n\n This is the body.\n\nChange-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
'Fix the thing\n\nThis is the body.\n\nChange-Id: abcdefg\n'
);
});
test('empty lines at the beginning and end are removed', () => {
const message =
'\n\nFix the thing\n\nThis is the body.\n\n\n\nChange-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
'Fix the thing\n\nThis is the body.\n\nChange-Id: abcdefg\n'
);
});
test('consecutive blank lines are combined', () => {
const message =
'Fix the thing\n\nThis is the body.\n\n\nAnd another paragraph.\n\nChange-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
'Fix the thing\n\nThis is the body.\n\nAnd another paragraph.\n\nChange-Id: abcdefg\n'
);
});
test('lines in the same paragraph are merged and split', () => {
const message =
'Fix the thing\n\nThis is a paragraph\nwith lines that should be\nmerged and then split\naccording to the line\nlength limit.\n\nChange-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
'Fix the thing\n\nThis is a paragraph with lines that should be merged and then split\naccording to the line length limit.\n\nChange-Id: abcdefg\n'
);
});
test('lines within footers are not split', () => {
const message =
'Fix the thing\n\nThis is the body.\n\nFixes: #123\nChange-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
'Fix the thing\n\nThis is the body.\n\nFixes: #123\nChange-Id: abcdefg\n'
);
});
test('indented lines are untouched', () => {
const message =
'Fix the thing\n\n This is an indented line.\n This is another indented line.\n\nChange-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
'Fix the thing\n\n This is an indented line.\n This is another indented line.\n\nChange-Id: abcdefg\n'
);
});
test('quoted lines are untouched', () => {
const message =
'Fix the thing\n\n> This is a quoted line.\n> And another one.\n\nChange-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
'Fix the thing\n\n> This is a quoted line.\n> And another one.\n\nChange-Id: abcdefg\n'
);
});
test('code blocks are untouched', () => {
const message =
'Fix the thing\n\n```\nThis is a code block.\n It should not be formatted.\n```\n\nChange-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
'Fix the thing\n\n```\nThis is a code block.\n It should not be formatted.\n```\n\nChange-Id: abcdefg\n'
);
});
test('bullet points are untouched', () => {
const message =
'Fix the thing\n\n - This is a bullet point.\n * This is another one.\n + And one more.\n\nChange-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
'Fix the thing\n\n - This is a bullet point.\n * This is another one.\n + And one more.\n\nChange-Id: abcdefg\n'
);
});
test('body line starting with spaces is untouched', () => {
const message =
'Fix the thing\n\n - This is a body line that starts with spaces and should be untouched\n \n\nChange-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
'Fix the thing\n\n - This is a body line that starts with spaces and should be untouched\n\nChange-Id: abcdefg\n'
);
});
test('bullet points are not split', () => {
const message =
'Fix the thing\n\n- Uses a test buffer to store the result to avoid issue.\n' +
' This new buffer\n' +
'- Test a new buffer\n' +
' call it.\n\nChange-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
'Fix the thing\n\n- Uses a test buffer to store the result to avoid issue.\n' +
' This new buffer\n' +
'- Test a new buffer\n' +
' call it.\n\nChange-Id: abcdefg\n'
);
});
test('bullet points with preceding text are not reordered', () => {
const message =
'Add a content scrim view\n\n' +
'Some description.\n\n' +
'screenshots,\n' +
'- https://example.com/1\n' +
'- https://example.com/2\n' +
'- https://example.com/3\n\n' +
'Change-Id: abcdefg\n';
assert.equal(
formatCommitMessageString(message),
'Add a content scrim view\n\n' +
'Some description.\n\n' +
'screenshots,\n' +
'- https://example.com/1\n' +
'- https://example.com/2\n' +
'- https://example.com/3\n\n' +
'Change-Id: abcdefg\n'
);
});
});
suite('detectFormattingErrorsInString', () => {
function assertError(
errors: FormattingError[],
type: ErrorType,
line: number,
message: string
) {
assert.isTrue(
errors.some(
error =>
error.type === type &&
error.line === line &&
error.message === message
),
`Expected error ${type} on line ${line} with message "${message}, but` +
JSON.stringify(errors)
);
}
test('subject too long', () => {
const longSubject =
'Fix(some-component): This is a very long subject that exceeds 72 characters';
const message = longSubject + '\n\nThis is body.\n\nChange-Id: abcdefg\n';
const errors = detectFormattingErrorsInString(message);
assertError(
errors,
ErrorType.SUBJECT_TOO_LONG,
1,
'Subject exceeds 72 characters'
);
});
test('subject has leading spaces', () => {
const message =
' Fix the thing\n\nThis is the body.\n\nChange-Id: abcdefg\n';
const errors = detectFormattingErrorsInString(message);
assertError(
errors,
ErrorType.LEADING_SPACES,
1,
'Subject should not start with spaces'
);
});
test('subject has trailing spaces', () => {
const message =
'Fix the thing \n\nThis is the body.\n\nChange-Id: abcdefg\n';
const errors = detectFormattingErrorsInString(message);
assertError(
errors,
ErrorType.TRAILING_SPACES,
1,
'Subject should not end with spaces'
);
});
test('line too long', () => {
const message =
'Fix the thing\n\nThis is a very long line that exceeds the maximum allowed length of 72 characters.\n\nChange-Id: abcdefg\n';
const errors = detectFormattingErrorsInString(message);
assertError(
errors,
ErrorType.LINE_TOO_LONG,
3,
'Line exceeds 72 characters'
);
});
test('line too long in footer', () => {
const message =
'Fix the thing\n\nThis is body.\n\nChange-Id: This is a very long line that exceeds the maximum allowed length of 72 characters.\n';
const errors = detectFormattingErrorsInString(message);
assertError(
errors,
ErrorType.LINE_TOO_LONG,
5,
'Line exceeds 72 characters'
);
});
test('line with url not flagged as too long', () => {
const message =
'Fix the thing\n\nThis line has a http://very-long-url-without-spaces-that-exceeds-72-characters.com/with/some/path/and/query?params=and&more=params\n\nChange-Id: abcdefg\n';
const errors = detectFormattingErrorsInString(message);
assert.isEmpty(errors);
});
test('trailing spaces', () => {
const message =
'Fix the thing\n\nThis is a line with trailing spaces. \nAnd another one. \n\nChange-Id: abcdefg\n';
const errors = detectFormattingErrorsInString(message);
assertError(
errors,
ErrorType.TRAILING_SPACES,
3,
'Line should not end with spaces'
);
assertError(
errors,
ErrorType.TRAILING_SPACES,
4,
'Line should not end with spaces'
);
});
test('trailing spaces in footer', () => {
const message =
'Fix the thing\n\nThis is body.\n\nChange-Id: abcdefg \n';
const errors = detectFormattingErrorsInString(message);
assertError(
errors,
ErrorType.TRAILING_SPACES,
5,
'Line should not end with spaces'
);
});
test('extra blank lines', () => {
const message =
'Fix the thing\n\nThis is the body.\n\n\nAnd another paragraph.\n\nChange-Id: abcdefg\n';
const errors = detectFormattingErrorsInString(message);
assertError(
errors,
ErrorType.EXTRA_BLANK_LINE,
5,
'Consecutive blank lines are not allowed'
);
});
test('extra blank lines in footer', () => {
const message =
'Fix the thing\n\nThis is the body.\n\nTest: 123\n\n\nChange-Id: abcdefg\n';
const errors = detectFormattingErrorsInString(message);
assertError(
errors,
ErrorType.EXTRA_BLANK_LINE,
7,
'Consecutive blank lines are not allowed'
);
});
test('line in footer starts with spaces', () => {
const message =
'Fix the thing\n\nThis is body.\n Change-Id: abcdefg\n ';
const errors = detectFormattingErrorsInString(message);
assertError(
errors,
ErrorType.LEADING_SPACES,
4,
'Line should not start with spaces'
);
});
test('comment lines', () => {
const message =
'Fix the thing\n\n# This is a comment line.\nThis is body.\n# Another comment line in body.\n\nChange-Id: abcdefg\n# Comment line in footer\n';
const errors = detectFormattingErrorsInString(message);
assertError(
errors,
ErrorType.COMMENT_LINE,
3,
"'#' at line start is a comment marker in Git. Line will be ignored"
);
assertError(
errors,
ErrorType.COMMENT_LINE,
5,
"'#' at line start is a comment marker in Git. Line will be ignored"
);
});
});
});