From d8f93ec5c3fe8e5e0e78f4c23c60f71ce3300e3a Mon Sep 17 00:00:00 2001 From: uttk-dev <97154037+uttk-dev@users.noreply.github.com> Date: Thu, 14 Sep 2023 13:34:05 +0900 Subject: [PATCH 1/3] =?UTF-8?q?chore:=20zenn-cli=20=E3=81=AE=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=81=AE=E3=82=BF=E3=82=A4=E3=83=88=E3=83=AB?= =?UTF-8?q?=E3=82=92=E6=97=A5=E6=9C=AC=E8=AA=9E=E3=81=AB=E7=B5=B1=E4=B8=80?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/client/__tests__/lib/helper.test.ts | 6 +- .../src/common/__tests__/helper.test.ts | 20 ++--- .../server/__tests__/commands/help.test.ts | 4 +- .../server/__tests__/commands/init.test.ts | 12 +-- .../__tests__/commands/new-article.test.ts | 28 +++---- .../__tests__/commands/new-book.test.ts | 18 ++--- .../server/__tests__/commands/preview.test.ts | 18 ++--- .../server/__tests__/commands/version.test.ts | 4 +- .../src/server/__tests__/lib/helper.test.ts | 74 ++++++++++--------- .../src/server/__tests__/lib/log.test.ts | 10 +-- 10 files changed, 93 insertions(+), 101 deletions(-) diff --git a/packages/zenn-cli/src/client/__tests__/lib/helper.test.ts b/packages/zenn-cli/src/client/__tests__/lib/helper.test.ts index 39eed687..e087ef7c 100644 --- a/packages/zenn-cli/src/client/__tests__/lib/helper.test.ts +++ b/packages/zenn-cli/src/client/__tests__/lib/helper.test.ts @@ -1,14 +1,14 @@ import { encodeUrlPeriod, decodeUrlPeriod } from '../../lib/helper'; -describe('pair of encodeUrlPeriod and decodeUrlPeriod', () => { - test('return original text `a.b.c` throgh encoding and decoding', () => { +describe('encodeUrlPeriod と decodeUrlPeriod を使った処理のテスト', () => { + test('エンコードしてデコードすると元のテキスト"a.b.c"を返す', () => { const original = 'a.b.c'; const encoded = encodeUrlPeriod(original); expect(encoded).not.toContain('.'); const decoded = decodeUrlPeriod(encoded); expect(decoded).toEqual(original); }); - test('return original text `2E.` throgh encoding and decoding', () => { + test('エンコードしてデコードすると元のテキスト"2E."を返す', () => { const original = '2E.'; const encoded = encodeUrlPeriod(original); expect(encoded).not.toContain('.'); diff --git a/packages/zenn-cli/src/common/__tests__/helper.test.ts b/packages/zenn-cli/src/common/__tests__/helper.test.ts index 0ec6cad7..48b87155 100644 --- a/packages/zenn-cli/src/common/__tests__/helper.test.ts +++ b/packages/zenn-cli/src/common/__tests__/helper.test.ts @@ -1,30 +1,30 @@ import * as helper from '../helper'; -describe('validateSlug', () => { - test('should return true with 12 valid characters', () => { +describe('validateSlug() のテスト', () => { + test('12文字の有効な文字列には true を返す', () => { const result = helper.validateSlug('abcd-efg_123'); expect(result).toBe(true); }); - test('should return false with 12 invalid characters', () => { + test('12文字の無効な文字列には false を返す', () => { expect(helper.validateSlug('abcd-efg%12')).toBe(false); expect(helper.validateSlug('abcd-efg/12')).toBe(false); expect(helper.validateSlug('abcd-efg"12')).toBe(false); }); - test('should return false with 11 valid characters', () => { + test('11文字の有効な文字列には false を返す', () => { const result = helper.validateSlug('abcd-efg_12'); expect(result).toBe(false); }); - test('should return false with 50 valid characters', () => { + test('50文字の有効な文字列には false を返す', () => { const result = helper.validateSlug( 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwx' ); expect(result).toBe(true); }); - test('should return false with 51 valid characters', () => { + test('51文字の有効な文字列には false を返す', () => { const result = helper.validateSlug( 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxy' ); @@ -32,18 +32,18 @@ describe('validateSlug', () => { }); }); -describe('validateChapterSlug', () => { - test('should return true with 12 valid characters', () => { +describe('validateChapterSlug()のテスト', () => { + test('12文字の有効な文字列には true を返す', () => { const result = helper.validateSlug('abcd-efg_123'); expect(result).toBe(true); }); - test('should return false with single valid character', () => { + test('1文字の有効な文字列には false を返す', () => { const result = helper.validateSlug('a'); expect(result).toBe(false); }); - test('should return false with 51 valid characters', () => { + test('51文字の有効な文字列には false を返す', () => { const result = helper.validateSlug( 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxy' ); diff --git a/packages/zenn-cli/src/server/__tests__/commands/help.test.ts b/packages/zenn-cli/src/server/__tests__/commands/help.test.ts index 8de6a19e..fe16ec2b 100644 --- a/packages/zenn-cli/src/server/__tests__/commands/help.test.ts +++ b/packages/zenn-cli/src/server/__tests__/commands/help.test.ts @@ -1,12 +1,12 @@ import { exec } from '../../commands/help'; import { commandListText } from '../../lib/messages'; -describe('cli exec help', () => { +describe('helpコマンドのテスト', () => { beforeEach(() => { console.log = jest.fn(); }); - test('should log help message', () => { + test('ヘルプメッセージを表示する', () => { exec([]); expect(console.log).toHaveBeenCalledWith( expect.stringContaining(commandListText) diff --git a/packages/zenn-cli/src/server/__tests__/commands/init.test.ts b/packages/zenn-cli/src/server/__tests__/commands/init.test.ts index 3ca4ace1..72d3ea8c 100644 --- a/packages/zenn-cli/src/server/__tests__/commands/init.test.ts +++ b/packages/zenn-cli/src/server/__tests__/commands/init.test.ts @@ -3,7 +3,7 @@ import { exec } from '../../commands/init'; import * as helper from '../../lib/helper'; import { initHelpText } from '../../lib/messages'; -describe('cli exec init', () => { +describe('initコマンドのテスト', () => { beforeEach(() => { // mock jest.spyOn(helper, 'generateFileIfNotExist').mockImplementation(); @@ -11,7 +11,7 @@ describe('cli exec init', () => { console.error = jest.fn(); }); - test('should call generateFileIfNotExist for directories', () => { + test('ディレクトリに対して generateFileIfNotExist を実行する', () => { exec([]); expect(helper.generateFileIfNotExist).toHaveBeenCalledWith( expect.stringContaining(path.join(process.cwd(), 'articles/.keep')), @@ -23,7 +23,7 @@ describe('cli exec init', () => { ); }); - test('should call generateFileIfNotExist for .gitignore', () => { + test('.gitignore に対して generateFileIfNotExist を実行する', () => { exec([]); expect(helper.generateFileIfNotExist).toHaveBeenCalledWith( expect.stringContaining(path.join(process.cwd(), '.gitignore')), @@ -31,7 +31,7 @@ describe('cli exec init', () => { ); }); - test('should call generateFileIfNotExist for README', () => { + test('README に対して generateFileIfNotExist を実行する', () => { exec([]); expect(helper.generateFileIfNotExist).toHaveBeenCalledWith( expect.stringContaining(path.join(process.cwd(), 'README.md')), @@ -39,14 +39,14 @@ describe('cli exec init', () => { ); }); - test('should log success message', () => { + test('成功メッセージを表示する', () => { exec([]); expect(console.log).toHaveBeenCalledWith( expect.stringContaining('🎉 Done!') ); }); - test('should log help text with --help', () => { + test('--helpでもヘルプメッセージを表示する', () => { exec(['--help']); expect(console.log).toHaveBeenCalledWith( expect.stringContaining(initHelpText) diff --git a/packages/zenn-cli/src/server/__tests__/commands/new-article.test.ts b/packages/zenn-cli/src/server/__tests__/commands/new-article.test.ts index 212449a6..34b217b4 100644 --- a/packages/zenn-cli/src/server/__tests__/commands/new-article.test.ts +++ b/packages/zenn-cli/src/server/__tests__/commands/new-article.test.ts @@ -4,7 +4,7 @@ import * as helper from '../../lib/helper'; import * as Log from '../../lib/log'; import { newArticleHelpText } from '../../lib/messages'; -describe('cli exec new:article', () => { +describe('new:articleコマンドのテスト', () => { const expectedArticlesDirpath = path.join(process.cwd(), 'articles'); beforeEach(() => { @@ -14,7 +14,7 @@ describe('cli exec new:article', () => { console.log = jest.fn(); }); - test('should call generateFileIfNotExist with proper arguments', () => { + test('有効な引数に generateFileIfNotExist を実行する', () => { exec(['--emoji', '💭']); expect(helper.generateFileIfNotExist).toHaveBeenCalledWith( @@ -33,7 +33,7 @@ describe('cli exec new:article', () => { ); }); - test('should call generateFileIfNotExist with specified title', () => { + test('指定されたタイトルで generateFileIfNotExist を実行する', () => { exec(['--title', 'A"B/C']); expect(helper.generateFileIfNotExist).toHaveBeenCalledWith( expect.stringContaining(expectedArticlesDirpath), @@ -41,7 +41,7 @@ describe('cli exec new:article', () => { ); }); - test('should call generateFileIfNotExist with specified published value true', () => { + test('`published: true` で generateFileIfNotExist を実行する', () => { exec(['--published', 'true']); expect(helper.generateFileIfNotExist).toHaveBeenCalledWith( expect.stringContaining(expectedArticlesDirpath), @@ -49,7 +49,7 @@ describe('cli exec new:article', () => { ); }); - test('should call generateFileIfNotExist with specified published value false', () => { + test('`published: false` で generateFileIfNotExist を実行する', () => { exec(['--published', 'false']); expect(helper.generateFileIfNotExist).toHaveBeenCalledWith( expect.stringContaining(expectedArticlesDirpath), @@ -57,7 +57,7 @@ describe('cli exec new:article', () => { ); }); - test('should call generateFileIfNotExist with the path including slug', () => { + test('指定した slug を含むパスで generateFileIfNotExist を実行する', () => { const slug = 'example-article'; exec(['--slug', slug]); @@ -67,17 +67,7 @@ describe('cli exec new:article', () => { ); }); - test('should call generateFileIfNotExist with the path including slug', () => { - const slug = 'example-article'; - exec(['--slug', slug]); - - expect(helper.generateFileIfNotExist).toHaveBeenCalledWith( - expect.stringMatching(`${expectedArticlesDirpath}/${slug}.md`), - expect.stringContaining(`---`) - ); - }); - - test('should call generateFileIfNotExist with specified publication name', () => { + test('指定された Publication 名で generateFileIfNotExist を実行する', () => { exec(['--publication-name', 'myPublication']); expect(helper.generateFileIfNotExist).toHaveBeenCalledWith( expect.stringContaining(expectedArticlesDirpath), @@ -85,14 +75,14 @@ describe('cli exec new:article', () => { ); }); - test('should log help text with --help', () => { + test('--help オプションを渡すとヘルプメッセージを表示する', () => { exec(['--help']); expect(console.log).toHaveBeenCalledWith( expect.stringContaining(newArticleHelpText) ); }); - test('should log error with invalid slug', () => { + test('無効な slug が渡されたらエラーメッセージを表示する', () => { exec(['--slug', 'invalid/slug']); expect(Log.error).toHaveBeenCalledWith( expect.stringContaining( diff --git a/packages/zenn-cli/src/server/__tests__/commands/new-book.test.ts b/packages/zenn-cli/src/server/__tests__/commands/new-book.test.ts index 19ac01f9..0153a163 100644 --- a/packages/zenn-cli/src/server/__tests__/commands/new-book.test.ts +++ b/packages/zenn-cli/src/server/__tests__/commands/new-book.test.ts @@ -4,7 +4,7 @@ import * as helper from '../../lib/helper'; import * as Log from '../../lib/log'; import { newBookHelpText } from '../../lib/messages'; -describe('cli exec new:book', () => { +describe('new:book コマンドのテスト', () => { const expectedBooksDirpath = path.join(process.cwd(), 'books'); const anyConfigYamlPathRegex = new RegExp( `${expectedBooksDirpath}/[a-zA-Z0-9-_]+/config.yaml` @@ -20,7 +20,7 @@ describe('cli exec new:book', () => { console.log = jest.fn(); }); - test('should call generateFileIfNotExist for config.yaml with proper arguments', () => { + test('config.yaml のデフォルト値で generateFileIfNotExist を実行する', () => { exec([]); expect(helper.generateFileIfNotExist).toHaveBeenCalledWith( expect.stringMatching(anyConfigYamlPathRegex), @@ -40,7 +40,7 @@ describe('cli exec new:book', () => { ); }); - test('should call generateFileIfNotExist for chapter files with proper arguments', () => { + test('チャプターの初期値で generateFileIfNotExist を2回実行する', () => { const expectedChapterBody = [`---`, `title: ""`, `---`].join('\n'); exec([]); expect(helper.generateFileIfNotExist).toHaveBeenNthCalledWith( @@ -55,7 +55,7 @@ describe('cli exec new:book', () => { ); }); - test('should call generateFileIfNotExist with the path including slug', () => { + test('指定した slug を含むパスで generateFileIfNotExist を実装する', () => { const slug = 'example-book'; exec(['--slug', slug]); @@ -75,7 +75,7 @@ describe('cli exec new:book', () => { ); }); - test('should call generateFileIfNotExist for config.yaml with specified title', () => { + test('指定したタイトル文字列と config.yaml のパスで generateFileIfNotExist を実行する', () => { exec(['--title', 'A"B/C']); expect(helper.generateFileIfNotExist).toHaveBeenCalledWith( expect.stringMatching(anyConfigYamlPathRegex), @@ -83,7 +83,7 @@ describe('cli exec new:book', () => { ); }); - test('should call generateFileIfNotExist for config.yaml with specified published value true', () => { + test('`published: true` と config.yaml のパスで generateFileIfNotExist を実行する', () => { exec(['--published', 'true']); expect(helper.generateFileIfNotExist).toHaveBeenCalledWith( expect.stringMatching(anyConfigYamlPathRegex), @@ -91,7 +91,7 @@ describe('cli exec new:book', () => { ); }); - test('should call generateFileIfNotExist for config.yaml with specified published value false', () => { + test('`published: false` と config.yaml のパスで generateFileIfNotExist を実行する', () => { exec(['--published', 'false']); expect(helper.generateFileIfNotExist).toHaveBeenCalledWith( expect.stringMatching(anyConfigYamlPathRegex), @@ -99,14 +99,14 @@ describe('cli exec new:book', () => { ); }); - test('should log help text with --help', () => { + test('--help オプションを渡すとヘルプメッセージを表示する', () => { exec(['--help']); expect(console.log).toHaveBeenCalledWith( expect.stringContaining(newBookHelpText) ); }); - test('should log error with invalid slug', () => { + test('無効な slug が渡されたらエラーメッセージを表示する', () => { exec(['--slug', 'invalid/slug']); expect(Log.error).toHaveBeenCalledWith( expect.stringContaining( diff --git a/packages/zenn-cli/src/server/__tests__/commands/preview.test.ts b/packages/zenn-cli/src/server/__tests__/commands/preview.test.ts index 479946e8..d5a4b0e2 100644 --- a/packages/zenn-cli/src/server/__tests__/commands/preview.test.ts +++ b/packages/zenn-cli/src/server/__tests__/commands/preview.test.ts @@ -2,19 +2,19 @@ import { exec } from '../../commands/preview'; import { previewHelpText } from '../../lib/messages'; import * as server from '../../lib/server'; -describe('cli exec preview', () => { +describe('preview コマンドのテスト', () => { beforeEach(() => { console.log = jest.fn(); jest.spyOn(server, 'startServer').mockImplementation(); jest.spyOn(server, 'startLocalChangesWatcher').mockImplementation(); }); - test('should log help message with --help args', async () => { + test('--help オプションを渡すとヘルプメッセージを表示する', async () => { await exec(['--help']); expect(console.log).toHaveBeenCalledWith(previewHelpText); }); - test('should listen with port 8000', async () => { + test('8000 ポートでサーバーを起動する', async () => { await exec([]); expect(server.startServer).toHaveBeenCalledWith({ port: 8000, @@ -23,7 +23,7 @@ describe('cli exec preview', () => { }); }); - test('should listen with spcified port', async () => { + test('--port オプションで特定のポートを指定してサーバーを起動できる', async () => { await exec(['--port', '8001']); expect(server.startServer).toHaveBeenCalledWith({ port: 8001, @@ -32,7 +32,7 @@ describe('cli exec preview', () => { }); }); - test('should not open browser by default', async () => { + test('デフォルトではサーバー起動時にブラウザを開かない', async () => { await exec([]); expect(server.startServer).toHaveBeenCalledWith({ port: expect.anything(), @@ -41,7 +41,7 @@ describe('cli exec preview', () => { }); }); - test('should open browser if specified', async () => { + test('--open オプションを渡すとブラウザを開く', async () => { await exec(['--open']); expect(server.startServer).toHaveBeenCalledWith({ port: expect.anything(), @@ -50,7 +50,7 @@ describe('cli exec preview', () => { }); }); - test('should listen with passed hostname', async () => { + test('--host オプションで hostname を指定してサーバーを起動できる', async () => { await exec(['--host', '0.0.0.0']); expect(server.startServer).toHaveBeenCalledWith({ hostname: '0.0.0.0', @@ -60,7 +60,7 @@ describe('cli exec preview', () => { }); }); - test('should call startLocalChangesWatcher by default', async () => { + test('デフォルトでは startLocalChangesWatcher を実行する', async () => { await exec([]); expect(server.startLocalChangesWatcher).toHaveBeenCalledWith( undefined, @@ -68,7 +68,7 @@ describe('cli exec preview', () => { ); }); - test('should not call startLocalChangesWatcher if --no-watch specified', async () => { + test('--no-watch オプションを渡した場合は startLocalChangesWatcher を実行しない', async () => { await exec(['--no-watch']); expect(server.startLocalChangesWatcher).toHaveBeenCalledTimes(0); }); diff --git a/packages/zenn-cli/src/server/__tests__/commands/version.test.ts b/packages/zenn-cli/src/server/__tests__/commands/version.test.ts index 10dcd4ad..2904dd74 100644 --- a/packages/zenn-cli/src/server/__tests__/commands/version.test.ts +++ b/packages/zenn-cli/src/server/__tests__/commands/version.test.ts @@ -1,12 +1,12 @@ import { exec } from '../../commands/version'; -describe('cli exec version', () => { +describe('version コマンドのテスト', () => { console.log = jest.fn(); beforeEach(() => { console.log = jest.fn(); }); - test('should log version', () => { + test('バージョン情報をコンソールに出力する', () => { exec([]); expect(console.log).toHaveBeenCalledWith( expect.stringMatching(/^0\.[0-9.]+/) diff --git a/packages/zenn-cli/src/server/__tests__/lib/helper.test.ts b/packages/zenn-cli/src/server/__tests__/lib/helper.test.ts index 581af15d..cedee3cd 100644 --- a/packages/zenn-cli/src/server/__tests__/lib/helper.test.ts +++ b/packages/zenn-cli/src/server/__tests__/lib/helper.test.ts @@ -6,22 +6,22 @@ import { validateSlug } from '../../../common/helper'; const fixtureDirPath = path.resolve(__dirname, '..', 'fixtures'); -describe('generateSlug', () => { - test('should return valid slug', () => { +describe('generateSlug() のテスト', () => { + test('有効な slug を返す', () => { const str = helper.generateSlug(); const result = validateSlug(str); expect(result).toBe(true); }); }); -describe('getCurrentCliVersion', () => { - test('should return version number', () => { +describe('getCurrentCliVersion() のテスト', () => { + test('バージョン番号を返す', () => { const str = helper.getCurrentCliVersion(); expect(str).toMatch(/^0\.[0-9.]+/); }); }); -describe('getWorkingPath', () => { +describe('getWorkingPath() のテスト', () => { beforeEach(() => { // mock jest.spyOn(process, 'cwd').mockReturnValue('foo'); @@ -29,12 +29,12 @@ describe('getWorkingPath', () => { jest.spyOn(Log, 'error').mockImplementation(); }); - test('should return joined path properly', () => { + test('結合されたパスを返す', () => { expect(helper.getWorkingPath('bar')).toEqual('foo/bar'); expect(helper.getWorkingPath('/bar')).toEqual('foo/bar'); }); - test('should exit if ../ is included to prevent directory traversal', () => { + test('ディレクトリトラバーサルを防ぐために "../" が含まれている場合はエラーを出す', () => { helper.getWorkingPath('../foo'); expect(process.exit).toHaveBeenCalledWith(1); expect(Log.error).toHaveBeenCalledWith( @@ -43,61 +43,61 @@ describe('getWorkingPath', () => { }); }); -describe('getFileRaw', () => { - test('should return file content with valid path to file', () => { +describe('getFileRaw() のテスト', () => { + test('有効なパスの場合はファイル内容を返す', () => { const result = helper.getFileRaw(`${fixtureDirPath}/markdown-body-only.md`); expect(result).toContain(`# Hello\n\nHola!`); }); - test('should return null with invalid path', () => { + test('無効なパスの場合は `null` を返す', () => { const result = helper.getFileRaw('invalid-path'); expect(result).toBe(null); }); }); -describe('getImageRaw', () => { - test('should return file binary with valid path to image', () => { +describe('getImageRaw() のテスト', () => { + test('有効なパスの場合は画像のバイナリデータを返す', () => { const result = helper.getFileRaw(`${fixtureDirPath}/images/test.jpg`); expect(result?.length).toBeGreaterThanOrEqual(500); }); - test('should return null with invalid path', () => { + test('無効なパスの場合は `null` を返す', () => { const result = helper.getFileRaw('invalid-path'); expect(result).toBe(null); }); }); -describe('listDirnames', () => { - test('should return dir names in the dir', () => { +describe('listDirnames() のテスト', () => { + test('有効なパスの場合はディレクトリ名の配列を返す', () => { const result = helper.listDirnames(`${fixtureDirPath}/books`); expect(result).toEqual(['my-first-book', 'my-second-book']); }); - test('should return null with invalid path', () => { + test('無効なパスの場合は `null` を返す', () => { const result = helper.listDirnames('invalid-path'); expect(result).toBe(null); }); }); -describe('listFilenames', () => { - test('should return file names in the dir ', () => { +describe('listFilenames() のテスト', () => { + test('指定したディレクトリ内のファイル名の配列を返す', () => { const result = helper.listFilenames(`${fixtureDirPath}/articles`); // use sort() to ignore array position expect(result?.sort()).toEqual( ['my-first-post.md', 'my-second-post.md'].sort() ); }); - test('should return null with invalid path', () => { + test('無効なパスの場合は `null` を返す', () => { const result = helper.listFilenames('invalid-path'); expect(result).toBe(null); }); }); -describe('listFilenamesOrderByModified', () => { +describe('listFilenamesOrderByModified() のテスト', () => { function touchFile(articleFilename: string) { const fullpath = path.join(fixtureDirPath, `articles/${articleFilename}`); const currentTime = new Date().getTime() / 1000; // The value should be a Unix timestamp in seconds. For example, Date.now() returns milliseconds, so it should be divided by 1000 before passing it in. fs.utimesSync(fullpath, currentTime, currentTime); } - test('should return file names order by modified time', () => { + test('変更時刻順にファイル名を返す', () => { // update my-second-post.md mtime touchFile('my-second-post.md'); expect( @@ -110,20 +110,22 @@ describe('listFilenamesOrderByModified', () => { ).toEqual(['my-first-post.md', 'my-second-post.md']); }); - test('should return null with invalid path', () => { + test('無効なパスの場合は `null` を返す', () => { const result = helper.listFilenamesOrderByModified('invalid-path'); expect(result).toBe(null); }); }); -describe('getImageSize', () => { - const result = helper.getImageSize( - `${fixtureDirPath}/images/test-1036bytes.jpg` - ); - expect(result).toEqual(1036); +describe('getImageSize() のテスト', () => { + test('指定した画像のサイズ', () => { + const result = helper.getImageSize( + `${fixtureDirPath}/images/test-1036bytes.jpg` + ); + expect(result).toEqual(1036); + }); }); -describe('generateFileIfNotExist', () => { +describe('generateFileIfNotExist() のテスト', () => { const tempFilepath = path.join(process.cwd(), '.temp/test/example.md'); afterEach(() => { // clean up @@ -132,14 +134,14 @@ describe('generateFileIfNotExist', () => { }); }); - test('should generate file with specified body', () => { + test('指定された本文を持つファイルを生成する', () => { const body = 'Hello!'; helper.generateFileIfNotExist(tempFilepath, body); const result = fs.readFileSync(tempFilepath, 'utf8'); expect(result).toEqual(body); }); - test('should not overwrite if already exists', () => { + test('既に存在するファイルを上書きしない', () => { helper.generateFileIfNotExist(tempFilepath, 'Hello!'); // trying to write same file should throw error expect(() => @@ -151,35 +153,35 @@ describe('generateFileIfNotExist', () => { }); }); -describe('completeHtml', () => { +describe('completeHtml() のテスト', () => { beforeEach(() => { // process.cwdがfixturesディレクトリを指すようにする jest.spyOn(process, 'cwd').mockReturnValue(fixtureDirPath); }); - test('If src is a URL, validation succeeds.', () => { + test.only('src の値が URL なら検証に成功する', () => { const html = helper.completeHtml( '' ); expect(html).not.toContain('表示できません'); }); - test('If src is a valid path, validation succeeds.', () => { + test('src の値が有効なパスなら検証に成功する', () => { const html = helper.completeHtml(''); // fixtures/images/test.jpgを参照 expect(html).not.toContain('表示できません'); }); - test('If src is pointing nonexistent image, validation fails.', () => { + test('src に指定された画像がなければ "ファイルが存在しません" を出力する', () => { const html = helper.completeHtml(''); // fixtures/images/notexist.jpgを参照 expect(html).toContain('ファイルが存在しません'); }); - test('If src is a invalid path, validation fails.', () => { + test('src の値が無効なパスなら "表示できません" を出力する', () => { const html = helper.completeHtml(''); expect(html).toContain('表示できません'); }); - test('If src is a path with invalid extension, validation fails.', () => { + test('src の値が無効な拡張子なら "表示できません" を出力する', () => { const html = helper.completeHtml(''); expect(html).toContain('表示できません'); }); diff --git a/packages/zenn-cli/src/server/__tests__/lib/log.test.ts b/packages/zenn-cli/src/server/__tests__/lib/log.test.ts index 583ac987..04ba0f36 100644 --- a/packages/zenn-cli/src/server/__tests__/lib/log.test.ts +++ b/packages/zenn-cli/src/server/__tests__/lib/log.test.ts @@ -1,7 +1,7 @@ import * as Log from '../../lib/log'; import colors from 'colors/safe'; -describe('log.error', () => { +describe('Log のテスト', () => { beforeEach(() => { // mock console.log = jest.fn(); @@ -9,12 +9,12 @@ describe('log.error', () => { console.error = jest.fn(); }); - test('should log error message', () => { + test('エラーメッセージを表示する', () => { Log.error('message'); expect(console.error).toHaveBeenCalledWith(colors.red('error:'), 'message'); }); - test('should log warn message', () => { + test('警告メッセージを表示する', () => { Log.warn('message'); expect(console.warn).toHaveBeenCalledWith( colors.yellow('warn:'), @@ -22,7 +22,7 @@ describe('log.error', () => { ); }); - test('should log success message', () => { + test('成功メッセージを表示する', () => { Log.success('message'); expect(console.log).toHaveBeenCalledWith( colors.green('success:'), @@ -30,7 +30,7 @@ describe('log.error', () => { ); }); - test('should log created message', () => { + test('作成成功メッセージを表示する', () => { Log.created('filename'); expect(console.log).toHaveBeenCalledWith( 'created:', From 299d8afb0839ac3dcb3e44150257a9b730408c6c Mon Sep 17 00:00:00 2001 From: uttk-dev <97154037+uttk-dev@users.noreply.github.com> Date: Thu, 14 Sep 2023 16:46:15 +0900 Subject: [PATCH 2/3] =?UTF-8?q?chore:=20zenn-model=20=E3=81=AE=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=81=AE=E3=82=BF=E3=82=A4=E3=83=88=E3=83=AB?= =?UTF-8?q?=E3=82=92=E6=97=A5=E6=9C=AC=E8=AA=9E=E3=81=AB=E7=B5=B1=E4=B8=80?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../zenn-model/__tests__/validator.test.ts | 226 ++++++++---------- 1 file changed, 106 insertions(+), 120 deletions(-) diff --git a/packages/zenn-model/__tests__/validator.test.ts b/packages/zenn-model/__tests__/validator.test.ts index 4c5d5974..b37eb583 100644 --- a/packages/zenn-model/__tests__/validator.test.ts +++ b/packages/zenn-model/__tests__/validator.test.ts @@ -4,7 +4,7 @@ import { validateBookChapter, } from '../src/index'; -describe('validateArticle', () => { +describe('validateArticle()のテスト', () => { const validArticle = { slug: 'example-slug', title: 'title', @@ -16,13 +16,13 @@ describe('validateArticle', () => { publication_name: 'team_publisher', }; - test('return no errors with valid article', () => { + test('有効な記事ならエラーを返さない', () => { const errors = validateArticle(validArticle); expect(errors).toEqual([]); }); - describe('validateItemSlug', () => { - test('return error with too short slug', () => { + describe('validateItemSlug()のテスト', () => { + test('短すぎる slug ならエラーを返す', () => { const errors = validateArticle({ ...validArticle, slug: 'too-short', @@ -30,7 +30,7 @@ describe('validateArticle', () => { expect(errors.length).toEqual(1); expect(errors[0].message).toContain('12〜50字の組み合わせ'); }); - test('return error with slug which includes invalid letters', () => { + test('slug に使えない文字が含まれている場合はエラーを返す', () => { const errors = validateArticle({ ...validArticle, slug: 'invalid/slug', @@ -40,8 +40,8 @@ describe('validateArticle', () => { }); }); - describe('validateMissingTitle', () => { - test('return error without title', () => { + describe('validateMissingTitle()のテスト', () => { + test('タイトルが無かったらエラーを返す', () => { const errors = validateArticle({ ...validArticle, title: undefined, @@ -51,7 +51,7 @@ describe('validateArticle', () => { 'title(タイトル)を文字列で入力してください' ); }); - test('return error with empty title', () => { + test('タイトルが空文字列ならエラーを返す', () => { const errors = validateArticle({ ...validArticle, title: '', @@ -63,8 +63,8 @@ describe('validateArticle', () => { }); }); - describe('validateTitleLength', () => { - test('return error with too long title', () => { + describe('validateTitleLength()のテスト', () => { + test('タイトルが長すぎる場合はエラーを返す', () => { const errors = validateArticle({ ...validArticle, title: @@ -75,8 +75,8 @@ describe('validateArticle', () => { }); }); - describe('validatePublishedStatus', () => { - test('return error if published is specified as string', () => { + describe('validatePublishedStatus()のテスト', () => { + test('published の値が string 型ならエラーを返す', () => { const errors = validateArticle({ ...validArticle, published: 'true' as any, @@ -86,7 +86,7 @@ describe('validateArticle', () => { 'published(公開設定)を true か false で指定してください(クオテーション " で囲まないでください)' ); }); - test('return error if published is specified as string', () => { + test('published の値が number 型ならエラーを返す', () => { const errors = validateArticle({ ...validArticle, published: 1 as any, @@ -98,8 +98,8 @@ describe('validateArticle', () => { }); }); - describe('validateArticleType', () => { - test('return error if articleType is neither tech or idea', () => { + describe('validateArticleType()のテスト', () => { + test('articleType が "tech" または "idea" 以外ならエラーを返す', () => { const errors = validateArticle({ ...validArticle, type: 'hello' as any, @@ -109,7 +109,7 @@ describe('validateArticle', () => { 'type(記事のタイプ)に tech もしくは idea を指定してください。技術記事の場合は tech を指定してください' ); }); - test('return error if articleType is missing', () => { + test('articleType が指定されてなければエラーを返す', () => { const errors = validateArticle({ ...validArticle, type: undefined, @@ -121,8 +121,8 @@ describe('validateArticle', () => { }); }); - describe('validateMissingEmoji', () => { - test('return error with undefined emoji', () => { + describe('validateMissingEmoji()のテスト', () => { + test('emoji の値が undefined ならエラーを返す', () => { const errors = validateArticle({ ...validArticle, emoji: undefined, @@ -132,7 +132,7 @@ describe('validateArticle', () => { 'アイキャッチとなる emoji(絵文字)を指定してください' ); }); - test('return error with empty emoji', () => { + test('emoji の値が空文字列ならエラーを返す', () => { const errors = validateArticle({ ...validArticle, emoji: '', @@ -144,8 +144,8 @@ describe('validateArticle', () => { }); }); - describe('validateEmojiFormat', () => { - test('return error with non emoji string for emoji property', () => { + describe('validateEmojiFormat()のテスト', () => { + test('絵文字以外の文字列ならエラーを返す', () => { const errors = validateArticle({ ...validArticle, emoji: '絵', @@ -156,8 +156,8 @@ describe('validateArticle', () => { ); }); }); - describe('validateMissingTopics', () => { - test('return error with undefined topics', () => { + describe('validateMissingTopics()のテスト', () => { + test('topics の値が undefined ならエラーを返す', () => { const errors = validateArticle({ ...validArticle, topics: undefined, @@ -167,7 +167,7 @@ describe('validateArticle', () => { 'topics(記事に関連する言語や技術)を配列で指定してください。' ); }); - test('return error with empty topics', () => { + test('topics の値が空配列ならエラーを返す', () => { const errors = validateArticle({ ...validArticle, topics: [], @@ -178,8 +178,8 @@ describe('validateArticle', () => { ); }); }); - describe('validateTooManyTopics', () => { - test('return error with 6 topics', () => { + describe('validateTooManyTopics()のテスト', () => { + test('topics の数が 6 以上ならエラーを返す', () => { const errors = validateArticle({ ...validArticle, topics: ['a', 'b', 'c', 'd', 'e', 'f'], @@ -188,8 +188,8 @@ describe('validateArticle', () => { expect(errors[0].message).toContain('topicsは最大5つまで指定できます'); }); }); - describe('validateInvalidTopicLetters', () => { - test('return error with topic including symbols', () => { + describe('validateInvalidTopicLetters()のテスト', () => { + test('topics に記号が含まれている場合はエラーを返す', () => { const errors = validateArticle({ ...validArticle, topics: ['a', 'vue.js'], @@ -200,8 +200,8 @@ describe('validateArticle', () => { ); }); }); - describe('validateTopicType', () => { - test('return error with number value', () => { + describe('validateTopicType()のテスト', () => { + test('topics の配列に number 型があればエラーを返す', () => { const errors = validateArticle({ ...validArticle, topics: [123] as any, @@ -211,7 +211,7 @@ describe('validateArticle', () => { 'topicsは全て文字列で指定してください' ); }); - test('return error with empty string topic', () => { + test('topics の配列に空文字列があればエラーを返す', () => { const errors = validateArticle({ ...validArticle, topics: [''], @@ -222,8 +222,8 @@ describe('validateArticle', () => { ); }); }); - describe('validateUseTags', () => { - test('return error with tag property', () => { + describe('validateUseTags()のテスト', () => { + test('tags プロパティを使っている場合はエラーを返す', () => { const errors = validateArticle({ ...validArticle, tags: ['a', 'b'], @@ -232,8 +232,8 @@ describe('validateArticle', () => { expect(errors[0].message).toContain('tagsではなくtopicsを使ってください'); }); }); - describe('validatePublicationName', () => { - test('return error with too short publication name', () => { + describe('validatePublicationName()のテスト', () => { + test('Publication 名が短すぎる場合はエラーを返す', () => { const errors = validateArticle({ ...validArticle, publication_name: 't', @@ -241,7 +241,7 @@ describe('validateArticle', () => { expect(errors.length).toEqual(1); expect(errors[0].message).toContain('2〜15字の組み合わせ'); }); - test('return error with publication name which includes invalid letters', () => { + test('Publication 名に使えない文字列が含まれる場合はエラーを返す', () => { const errors = validateArticle({ ...validArticle, publication_name: 'invalid/name', @@ -252,7 +252,7 @@ describe('validateArticle', () => { }); }); -describe('validateBook', () => { +describe('validateBook()のテスト', () => { const validBook = { slug: 'example-slug', title: 'title', @@ -268,34 +268,32 @@ describe('validateBook', () => { coverHeight: 700, }; - test('return no errors with valid book', () => { + test('有効な本であればエラーを返さない', () => { const errors = validateBook(validBook); expect(errors).toEqual([]); }); - describe('validateItemSlug', () => { - describe('validateItemSlug', () => { - test('return error with too short slug', () => { - const errors = validateBook({ - ...validBook, - slug: 'too-short', - }); - expect(errors.length).toEqual(1); - expect(errors[0].message).toContain('12〜50字の組み合わせ'); + describe('validateItemSlug()のテスト', () => { + test('slug が短すぎる場合はエラーを返す', () => { + const errors = validateBook({ + ...validBook, + slug: 'too-short', }); - test('return error with slug which includes invalid letters', () => { - const errors = validateBook({ - ...validBook, - slug: 'invalid/slug', - }); - expect(errors.length).toEqual(1); - expect(errors[0].message).toContain('半角英数字'); + expect(errors.length).toEqual(1); + expect(errors[0].message).toContain('12〜50字の組み合わせ'); + }); + test('slug に使えない文字列が含まれる場合はエラーを返す', () => { + const errors = validateBook({ + ...validBook, + slug: 'invalid/slug', }); + expect(errors.length).toEqual(1); + expect(errors[0].message).toContain('半角英数字'); }); }); - describe('validateMissingTitle', () => { - test('return error without title', () => { + describe('validateMissingTitle()のテスト', () => { + test('title が無い場合はエラーを返す', () => { const errors = validateBook({ ...validBook, title: undefined, @@ -305,7 +303,7 @@ describe('validateBook', () => { 'title(タイトル)を文字列で入力してください' ); }); - test('return error with empty title', () => { + test('title が空文字列の場合はエラーを返す', () => { const errors = validateBook({ ...validBook, title: '', @@ -317,8 +315,8 @@ describe('validateBook', () => { }); }); - describe('validateTitleLength', () => { - test('return error with too long title', () => { + describe('validateTitleLength()のテスト', () => { + test('title が長すぎる場合はエラーを返す', () => { const errors = validateBook({ ...validBook, title: @@ -329,8 +327,8 @@ describe('validateBook', () => { }); }); - describe('validatePublishedStatus', () => { - test('return error if published is specified as string', () => { + describe('validatePublishedStatus()のテスト', () => { + test('published の値が string 型の場合はエラーを返す', () => { const errors = validateBook({ ...validBook, published: 'true' as any, @@ -340,7 +338,7 @@ describe('validateBook', () => { 'published(公開設定)を true か false で指定してください(クオテーション " で囲まないでください)' ); }); - test('return error if published is specified as string', () => { + test('published の値が number 型の場合はエラーを返す', () => { const errors = validateBook({ ...validBook, published: 1 as any, @@ -352,8 +350,8 @@ describe('validateBook', () => { }); }); - describe('validateMissingTopics', () => { - test('return error with undefined topics', () => { + describe('validateMissingTopics()のテスト', () => { + test('topics の値が undefined ならエラーを返す', () => { const errors = validateBook({ ...validBook, topics: undefined, @@ -363,7 +361,7 @@ describe('validateBook', () => { 'topics(記事に関連する言語や技術)を配列で指定してください。' ); }); - test('return error with empty topics', () => { + test('topics の値が空配列ならエラーを返す', () => { const errors = validateBook({ ...validBook, topics: [], @@ -375,8 +373,8 @@ describe('validateBook', () => { }); }); - describe('validateTooManyTopics', () => { - test('return error with 6 topics', () => { + describe('validateTooManyTopics()のテスト', () => { + test('topics の数が 6 以上ならエラーを返す', () => { const errors = validateBook({ ...validBook, topics: ['a', 'b', 'c', 'd', 'e', 'f'], @@ -386,8 +384,8 @@ describe('validateBook', () => { }); }); - describe('validateInvalidTopicLetters', () => { - test('return error with topic including symbols', () => { + describe('validateInvalidTopicLetters()のテスト', () => { + test('topics に記号が含まれている場合はエラーを返す', () => { const errors = validateBook({ ...validBook, topics: ['a', 'vue.js'], @@ -399,8 +397,8 @@ describe('validateBook', () => { }); }); - describe('validateTopicType', () => { - test('return error with number value', () => { + describe('validateTopicType()のテスト', () => { + test('topics の配列に number 型があればエラーを返す', () => { const errors = validateBook({ ...validBook, topics: [123] as any, @@ -410,7 +408,7 @@ describe('validateBook', () => { 'topicsは全て文字列で指定してください' ); }); - test('return error with empty string topic', () => { + test('topics の配列に空文字列があればエラーを返す', () => { const errors = validateBook({ ...validBook, topics: [''], @@ -422,8 +420,8 @@ describe('validateBook', () => { }); }); - describe('validateUseTags', () => { - test('return error with tag property', () => { + describe('validateUseTags()のテスト', () => { + test('tags プロパティを使っている場合はエラーを返す', () => { const errors = validateBook({ ...validBook, tags: ['a', 'b'], @@ -433,8 +431,8 @@ describe('validateBook', () => { }); }); - describe('validateBookSummary', () => { - test('return error with undefined summary', () => { + describe('validateBookSummary()のテスト', () => { + test('summary が undefined の場合はエラーを返す', () => { const errors = validateBook({ ...validBook, summary: undefined, @@ -446,8 +444,8 @@ describe('validateBook', () => { }); }); - describe('validateBookPriceType', () => { - test('return error with undefined price', () => { + describe('validateBookPriceType()のテスト', () => { + test('price が undefined の場合はエラーを返す', () => { const errors = validateBook({ ...validBook, price: undefined, @@ -459,8 +457,8 @@ describe('validateBook', () => { }); }); - describe('validateBookPriceRange', () => { - test('return error with price more than 6000', () => { + describe('validateBookPriceRange()のテスト', () => { + test('price が 5000 よりも大きいならエラーを返す', () => { const errors = validateBook({ ...validBook, price: 6000, @@ -470,7 +468,7 @@ describe('validateBook', () => { 'price(本の価格)を有料にする場合、200〜5000の間で指定してください' ); }); - test('return error with price less than 200', () => { + test('price が 200 よりも小さいならエラーを返す', () => { const errors = validateBook({ ...validBook, price: 100, @@ -482,8 +480,8 @@ describe('validateBook', () => { }); }); - describe('validateBookPriceFraction', () => { - test('return error if price is not divisible by 100', () => { + describe('validateBookPriceFraction()のテスト', () => { + test('price が 100 で割り切れない場合はエラーを返す', () => { const errors = validateBook({ ...validBook, price: 1050, @@ -495,8 +493,8 @@ describe('validateBook', () => { }); }); - describe('validateMissingBookCover', () => { - test('return error with undefined coverDataUrl', () => { + describe('validateMissingBookCover()のテスト', () => { + test('coverDataUrl が undefined の場合はエラーを返す', () => { const errors = validateBook({ ...validBook, coverDataUrl: undefined, @@ -508,8 +506,8 @@ describe('validateBook', () => { }); }); - describe('validateBookCoverSize', () => { - test('return error with undefined coverDataUrl', () => { + describe('validateBookCoverSize()のテスト', () => { + test('カバー画像のサイズが1MBより大きい場合はエラーを返す', () => { const errors = validateBook({ ...validBook, coverFilesize: 1024 * 1024 * 2, @@ -521,8 +519,8 @@ describe('validateBook', () => { }); }); - describe('validateBookCoverAspectRatio', () => { - test('return error if cover aspect ratios is not 1.4', () => { + describe('validateBookCoverAspectRatio()のテスト', () => { + test('カバー画像のアスペクト比が 1 : 1.4 でない場合はエラーを返す', () => { const errors = validateBook({ ...validBook, coverHeight: 800, @@ -534,19 +532,7 @@ describe('validateBook', () => { ); }); - test('return error if cover aspect ratios is not 1.4', () => { - const errors = validateBook({ - ...validBook, - coverHeight: 500, - coverWidth: 700, - }); - expect(errors.length).toEqual(1); - expect(errors[0].message).toContain( - `カバー画像の「幅 : 高さ」の比率は「1 : 1.4」にすることをおすすめします` - ); - }); - - test('return no errors with allowable aspect ratio', () => { + test('カバー画像のアスペクト比が有効な場合はエラーを返さない', () => { const errors = validateBook({ ...validBook, coverHeight: 710, @@ -556,8 +542,8 @@ describe('validateBook', () => { }); }); - describe('validateBookChapterSlugs', () => { - test('return no errors with undefined specifiedChapterSlugs', () => { + describe('validateBookChapterSlugs()のテスト', () => { + test('specifiedChapterSlugs が undefined ならエラーを返さない', () => { // specifiedChapterSlugs is optional const errors = validateBook({ ...validBook, @@ -566,7 +552,7 @@ describe('validateBook', () => { }); expect(errors).toEqual([]); }); - test('return error if specifiedChapterSlugs is not array of string', () => { + test('specifiedChapterSlugsが文字列の配列でない場合はエラーを返します', () => { // specifiedChapterSlugs is optional const errors = validateBook({ ...validBook, @@ -579,8 +565,8 @@ describe('validateBook', () => { }); }); - describe('validateBookChaptersFormat', () => { - test('return error if specifiedChapterSlugs includes .md', () => { + describe('validateBookChaptersFormat()のテスト', () => { + test('specifiedChapterSlugsに".md"が含まれている場合はエラーを返す', () => { const errors = validateBook({ ...validBook, specifiedChapterSlugs: ['example1.md', 'example2.md'], @@ -593,7 +579,7 @@ describe('validateBook', () => { }); }); -describe('validateBookChapter', () => { +describe('validateBookChapter()のテスト', () => { const validChapter = { slug: 'example', filename: 'example.md', @@ -603,20 +589,20 @@ describe('validateBookChapter', () => { position: 0, }; - test('return no errors with valid chapter', () => { + test('有効なチャプターならエラーを返さない', () => { const errors = validateBookChapter(validChapter); expect(errors).toEqual([]); }); - describe('validateChapterItemSlug', () => { - test('return no errors with short slug', () => { + describe('validateChapterItemSlug()のテスト', () => { + test('slug が短すぎる場合はエラーを返す', () => { const errors = validateBookChapter({ ...validChapter, slug: 's', }); expect(errors).toEqual([]); }); - test('return error with slug which includes invalid letters', () => { + test('slug に使えない文字を含む場合はエラーを返す', () => { const errors = validateBookChapter({ ...validChapter, slug: 'invalid/slug', @@ -626,8 +612,8 @@ describe('validateBookChapter', () => { }); }); - describe('validateMissingTitle', () => { - test('return error without title', () => { + describe('validateMissingTitle()のテスト', () => { + test('title が無ければエラーを返す', () => { const errors = validateBookChapter({ ...validChapter, title: undefined, @@ -637,7 +623,7 @@ describe('validateBookChapter', () => { 'title(タイトル)を文字列で入力してください' ); }); - test('return error with empty title', () => { + test('title が空文字列ならエラーを返す', () => { const errors = validateBookChapter({ ...validChapter, title: '', @@ -649,8 +635,8 @@ describe('validateBookChapter', () => { }); }); - describe('validateTitleLength', () => { - test('return error with too long title', () => { + describe('validateTitleLength()のテスト', () => { + test('title が長すぎる場合はエラーを返す', () => { const errors = validateBookChapter({ ...validChapter, title: @@ -661,8 +647,8 @@ describe('validateBookChapter', () => { }); }); - describe('validateChapterFreeType', () => { - test('return error if free property is not boolean', () => { + describe('validateChapterFreeType()のテスト', () => { + test('free が boolean 型じゃ無ければエラーを返す', () => { const errors = validateBookChapter({ ...validChapter, free: 'true' as any, @@ -673,7 +659,7 @@ describe('validateBookChapter', () => { ); }); - test('return no error if free property is undefined', () => { + test('free が undefined ならエラーを返さない', () => { const errors = validateBookChapter({ ...validChapter, free: undefined, From 1a457e36df9ee1b2f2be2fe25f7083162fdf0d4d Mon Sep 17 00:00:00 2001 From: uttk-dev <97154037+uttk-dev@users.noreply.github.com> Date: Fri, 15 Sep 2023 14:35:34 +0900 Subject: [PATCH 3/3] =?UTF-8?q?chore:=20zenn-markdown-html=20=E3=81=AE?= =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=81=AE=E3=82=BF=E3=82=A4=E3=83=88?= =?UTF-8?q?=E3=83=AB=E3=82=92=E6=97=A5=E6=9C=AC=E8=AA=9E=E3=81=AB=E7=B5=B1?= =?UTF-8?q?=E4=B8=80=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__tests__/basic.test.ts | 10 +-- .../zenn-markdown-html/__tests__/br.test.ts | 10 +-- .../__tests__/dollar.test.ts | 26 +++---- .../__tests__/highlight.test.ts | 30 ++++---- .../zenn-markdown-html/__tests__/link.test.ts | 70 +++++++++---------- .../zenn-markdown-html/__tests__/xss.test.ts | 22 +++--- 6 files changed, 84 insertions(+), 84 deletions(-) diff --git a/packages/zenn-markdown-html/__tests__/basic.test.ts b/packages/zenn-markdown-html/__tests__/basic.test.ts index 865fc42a..de138f48 100644 --- a/packages/zenn-markdown-html/__tests__/basic.test.ts +++ b/packages/zenn-markdown-html/__tests__/basic.test.ts @@ -1,7 +1,7 @@ import markdownToHtml from '../src/index'; -describe('Convert markdown to html properly', () => { - test('should convert markdown to html properly', () => { +describe('MarkdownからHTMLへの変換テスト', () => { + test('markdownからhtmlへ変換する', () => { const html = markdownToHtml('Hello\n## hey\n\n- first\n- second\n'); expect(html).toContain(`

Hello

`); expect(html).toContain( @@ -10,12 +10,12 @@ describe('Convert markdown to html properly', () => { expect(html).toContain(`\n`); }); - test('should allow inline comment', () => { + test('インラインコメントはhtmlに変換しない', () => { const html = markdownToHtml(``); expect(html).not.toContain('hey'); }); - test('should append docId to footnote', () => { + test('脚注に docId を設定する', () => { const html = markdownToHtml(`Hello[^1]World!\n\n[^1]: hey`); // expect(html).toContain('[1]'); expect(html).toEqual( @@ -25,7 +25,7 @@ describe('Convert markdown to html properly', () => { ); }); - test('should remove data scheme img tag', () => { + test('dataスキーマの画像は除外する', () => { const html = markdownToHtml(`![](data:image/png;base64,xxxx)`); expect(html).toContain(''); }); diff --git a/packages/zenn-markdown-html/__tests__/br.test.ts b/packages/zenn-markdown-html/__tests__/br.test.ts index 02fe31d8..1a0b0b21 100644 --- a/packages/zenn-markdown-html/__tests__/br.test.ts +++ b/packages/zenn-markdown-html/__tests__/br.test.ts @@ -1,14 +1,14 @@ import markdownToHtml from '../src/index'; -describe('Handle br tag properly', () => { - test('should preserve br tag inside paragraph', () => { +describe('
のテスト', () => { + test('段落内の
は保持する', () => { const patterns = ['foo
bar', 'foo
bar', 'foo
bar']; patterns.forEach((pattern) => { const html = markdownToHtml(pattern); expect(html).toMatch(/

foo
bar<\/p>/); }); }); - test('should preserve br tag inside table', () => { + test('テーブル内の
は保持する', () => { const tableString = [ `| a | b |`, `| --- | --- |`, @@ -17,11 +17,11 @@ describe('Handle br tag properly', () => { const html = markdownToHtml(tableString); expect(html).toContain('foo
bar'); }); - test('should escape br tag inside inline code', () => { + test('インラインコード内の
はエスケープする', () => { const html = markdownToHtml('foo`
`bar'); expect(html).toMatch(/

foo<br><\/code>bar<\/p>/); }); - test('should escape br tag inside code block', () => { + test('コードブロック内の
はエスケープする', () => { const html = markdownToHtml('```\n
\n```'); expect(html).toContain('<br>'); }); diff --git a/packages/zenn-markdown-html/__tests__/dollar.test.ts b/packages/zenn-markdown-html/__tests__/dollar.test.ts index 823a72b5..1720e24f 100644 --- a/packages/zenn-markdown-html/__tests__/dollar.test.ts +++ b/packages/zenn-markdown-html/__tests__/dollar.test.ts @@ -1,27 +1,27 @@ import markdownToHtml from '../src/index'; -describe('Handle $ mark properly', () => { - test('should keep $ around link href', () => { +describe('$ マークのテスト', () => { + test('リンクと同じ行にある $ は katex に変換される', () => { const html = markdownToHtml('$a,b,c$foo[foo](https://foo.bar)bar'); expect(html).toEqual( '

a,b,cfoofoobar

\n' ); }); - test('should keep $ around link href', () => { + test('リンクの後に無効な $ が続く場合はそのままにする', () => { const html = markdownToHtml('$a,b,c$foo[foo](http://foo.bar)$bar'); expect(html).toEqual( '

a,b,cfoofoo$bar

\n' ); }); - test('should keep $ around link href', () => { + test('リンク名に $ が含まれる場合はそのままにする', () => { const html = markdownToHtml('$a,b,c$foo[$bar](http://foo.bar)bar'); expect(html).toEqual( '

a,b,cfoo$barbar

\n' ); }); - test('should keep $ around link href', () => { + test('リンクのhrefに $ が含まれる場合はそのままにする', () => { const html = markdownToHtml( '[this $ should be escaped](https://docs.angularjs.org/api/ng/service/$http)' ); @@ -31,8 +31,8 @@ describe('Handle $ mark properly', () => { }); }); -describe('should escape html tag', () => { - test('should escape script tag', () => { +describe('HTMLタグにエスケープするテスト', () => { + test('katex内のをエスケープする', () => { const html = markdownToHtml('$a,,c$'); expect(html).toEqual( `

a,<script>alert("XSS")</script>,c

\n` @@ -40,14 +40,14 @@ describe('should escape html tag', () => { }); }); -describe('Handle twice $ pairs properly', () => { - test('should keep $ single character expression around link href', () => { +describe('$ のペアのテスト', () => { + test('リンクの前後にある一文字だけを含む$のペアをkatexに変換する', () => { const html = markdownToHtml('$a$foo[foo](https://foo.bar)bar,refs:$(2)$'); expect(html).toEqual( '

afoofoobar,refs:(2)

\n' ); }); - test('should keep $ around link href', () => { + test('リンク前後にある$のペアをkatexに変換する', () => { const html = markdownToHtml( '$a,b,c$foo[foo](https://foo.bar)bar,refs:$(2)$' ); @@ -55,7 +55,7 @@ describe('Handle twice $ pairs properly', () => { '

a,b,cfoofoobar,refs:(2)

\n' ); }); - test('should keep $ around link href three times', () => { + test('リンク前後にある三つの$のペアをkatexに変換する', () => { const html = markdownToHtml( '$a,b,c$foo[foo](https://foo.bar)bar,refs:$(2)$,and:$(3)$' ); @@ -63,13 +63,13 @@ describe('Handle twice $ pairs properly', () => { '

a,b,cfoofoobar,refs:(2),and:(3)

\n' ); }); - test('should keep $ around link href without parentheses', () => { + test('リンク周りにある$のペアをkatexに変換する', () => { const html = markdownToHtml('$a,b,c$foo[foo](https://foo.bar)bar,refs:$2$'); expect(html).toEqual( '

a,b,cfoofoobar,refs:2

\n' ); }); - test('should keep $ pairs two times', () => { + test('二つの$のペアをkatexに変換する', () => { const html = markdownToHtml('$a,b,c$foobar,refs:$(2)$'); expect(html).toEqual( '

a,b,cfoobar,refs:(2)

\n' diff --git a/packages/zenn-markdown-html/__tests__/highlight.test.ts b/packages/zenn-markdown-html/__tests__/highlight.test.ts index 9470e7ee..eacfae7e 100644 --- a/packages/zenn-markdown-html/__tests__/highlight.test.ts +++ b/packages/zenn-markdown-html/__tests__/highlight.test.ts @@ -1,7 +1,7 @@ import markdownToHtml from '../src/index'; -describe('Code highlight propley', () => { - test('should generate valid code format html', () => { +describe('コードハイライトのテスト', () => { + test('コードブロックを正しいに変換する', () => { const html = markdownToHtml( `\`\`\`js:foo.js\nconsole.log("hello")\n\`\`\`` ); @@ -9,13 +9,13 @@ describe('Code highlight propley', () => { expect(html).toContain('foo.js'); }); - test('should highlight js syntax', () => { + test('js のコードブロックをハイライトする', () => { const jsString = ['```js', "console.log('foo')", '```'].join('\n'); const html = markdownToHtml(jsString); expect(html).toContain('language-js'); }); - test('should ignore additonal langInfo separated with whitespace', () => { + test('スペースで区切られた追加の言語は無視する', () => { const jsString = ['```js some-info', "console.log('foo')", '```'].join( '\n' ); @@ -23,18 +23,18 @@ describe('Code highlight propley', () => { expect(html).toContain('language-js'); }); - test('should highlight html syntax', () => { + test('htmlのコードブロックをハイライトできる', () => { const jsString = ['```html', '', '```'].join('\n'); const html = markdownToHtml(jsString); expect(html).toContain('language-html'); }); - test('should highlight js syntax and show filename', () => { + test('js のコードブロックをハイライトしてファイル名を表示する', () => { const jsString = ['```js:index.js', "console.log('foo')", '```'].join('\n'); const html = markdownToHtml(jsString); expect(html).toContain('index.js'); expect(html).toContain('language-js'); }); - test('should highlight html syntax and show filename', () => { + test('html のコードブロックをハイライトしてファイル名を表示する', () => { const jsString = ['```html:index.html', '', '```'].join('\n'); const html = markdownToHtml(jsString); expect(html).toContain( @@ -42,7 +42,7 @@ describe('Code highlight propley', () => { ); expect(html).toContain('language-html'); }); - test('should highlight js syntax', () => { + test('js diff のコードブロックをハイライトする', () => { const jsString = [ '```js diff', "- console.log('foo')", @@ -52,7 +52,7 @@ describe('Code highlight propley', () => { const html = markdownToHtml(jsString); expect(html).toContain('diff-highlight language-diff-js'); }); - test('should highlight html syntax', () => { + test('html diff のコードブロックをハイライトする', () => { const jsString = [ '```html diff', '- ', @@ -62,7 +62,7 @@ describe('Code highlight propley', () => { const html = markdownToHtml(jsString); expect(html).toContain('diff-highlight language-diff-html'); }); - test('should highlight js syntax with diff js order', () => { + test('diff js の順番でハイライトする', () => { const jsString = [ '```diff js', "- console.log('foo')", @@ -72,7 +72,7 @@ describe('Code highlight propley', () => { const html = markdownToHtml(jsString); expect(html).toContain('diff-highlight language-diff-js'); }); - test('should highlight html syntax with diff html order', () => { + test('diff html の順番でハイライトする', () => { const jsString = [ '```diff html', '- ', @@ -82,7 +82,7 @@ describe('Code highlight propley', () => { const html = markdownToHtml(jsString); expect(html).toContain('diff-highlight language-diff-html'); }); - test('should highlight js syntax and show filename', () => { + test('js diff のコードブロックをハイライトしてファイル名を表示する', () => { const jsString = [ '```js diff:index.js', "- console.log('foo')", @@ -93,7 +93,7 @@ describe('Code highlight propley', () => { expect(html).toContain('diff-highlight language-diff-js'); expect(html).toContain('index.js'); }); - test('should highlight html syntax and show filename', () => { + test('html diff のコードブロックをハイライトしてファイル名を表示する', () => { const jsString = [ '```html diff:index.html', '- ', @@ -106,7 +106,7 @@ describe('Code highlight propley', () => { 'index.html' ); }); - test('should highlight js syntax and show filename even if space exists before :', () => { + test('":" の前にスペースが存在しても js をハイライトしてファイル名を表示する', () => { const jsString = [ '```js diff :index.js', "- console.log('foo')", @@ -117,7 +117,7 @@ describe('Code highlight propley', () => { expect(html).toContain('diff-highlight language-diff-js'); expect(html).toContain('index.js'); }); - test('should highlight html syntax and show filename even if space exists before :', () => { + test('":" の前にスペースが存在しても html をハイライトしてファイル名を表示する', () => { const jsString = [ '```html diff :index.html', '- ', diff --git a/packages/zenn-markdown-html/__tests__/link.test.ts b/packages/zenn-markdown-html/__tests__/link.test.ts index ac3970bc..e49ca6a2 100644 --- a/packages/zenn-markdown-html/__tests__/link.test.ts +++ b/packages/zenn-markdown-html/__tests__/link.test.ts @@ -10,26 +10,26 @@ const renderLink = (src: string) => { return markdownToHtml(src, options); }; -describe('Link syntax', () => { - test('should convert link syntax properly', () => { +describe('Linkシンタックスのテスト', () => { + test('リンクに変換する', () => { const html = renderLink('[example](https://example.com)'); expect(html).toContain( 'example' ); }); - test('should convert link with no attributes if href starts with slash', () => { + test('hrefが"/"から始まる場合は属性のないリンクに変換する', () => { const html = renderLink('[Articles](/articles)'); expect(html).toContain('Articles'); }); - test('should convert link with no attributes if href starts with #', () => { + test('hrefが"#"で始まる場合は属性のないリンクに変換する', () => { const html = renderLink('[Example](#example)'); expect(html).toContain('Example'); }); }); -describe('Linkify properly', () => { - describe('Raw Link', () => { - test('should linkify url with nofollow if hostname is not zenn.dev', () => { +describe('Linkifyのテスト', () => { + describe('直書きのリンクのテスト', () => { + test('ホスト名が"zenn.dev"じゃない場合はURLを nofollow のリンクに変換する', () => { expect(renderLink('URL is https://example.com')).toContain( 'URL is https://example.com' ); @@ -41,42 +41,42 @@ describe('Linkify properly', () => { ); }); - test('should linkify url without rel if hostname is zenn.dev', () => { + test('ホスト名が"zenn.dev"ならrel無しのリンクに変換する', () => { const html = renderLink('URL is https://zenn.dev'); expect(html).toContain( 'URL is https://zenn.dev' ); }); - test('should not convert links to card if text exists before url', () => { + test('URLの前にテキストが存在する場合はリンクをリンクカードに変換しない', () => { const html = renderLink('foo https://example.com'); expect(html).toEqual( '

foo https://example.com

\n' ); }); - test('should not convert intentional links to card', () => { + test('意図的にリンクしているURLはリンクカードに変換しない', () => { const html = renderLink('[https://example.com](https://example.com)'); expect(html).toEqual( '

https://example.com

\n' ); }); - test('should not convert links inside list', () => { + test('リンク内のリンクを変換しない', () => { const html = renderLink('- https://example.com\n- second'); expect(html).toEqual( '\n' ); }); - test('should not convert links inside block', () => { + test('
内のリンクはリンクカードに変換しない', () => { const html = renderLink(':::message alert\nhttps://example.com\n:::'); expect(html).toEqual( '\n' ); }); - test('should not convert links inside block with 2 paragraphs', () => { + test('
内の2段落空いたリンクをリンクカードに変換しない', () => { const html = renderLink( ':::message alert\nhello\n\nhttps://example.com\n:::' ); @@ -85,35 +85,35 @@ describe('Linkify properly', () => { ); }); - test('should not convert links inside list', () => { + test('リスト内のリンクをリンクカードに変換しない', () => { const html = renderLink('- https://example.com\n- second'); expect(html).toEqual( '\n' ); }); - test('should not convert links if text follows', () => { + test('URLにテキストが続く場合はリンクカードに変換しない', () => { const html = renderLink('https://example.com foo'); expect(html).toEqual( '

https://example.com foo

\n' ); }); - test('should not convert a link with any text in same paragraph', () => { + test('同じ段落内のテキストを含むリンクをリンクカードに変換しない', () => { const html = renderLink(`a: https://example.com\nb: https://example.com`); expect(html).toEqual( '

a: https://example.com
\nb: https://example.com

\n' ); }); - test('should not convert links even when the links are the start of the line unless the next elements are texts', () => { + test('URLにテキストが続くならリンクが先頭であってもリンクカードに変換しない', () => { const html = renderLink('\n\nhttps://example.com text'); expect(html).toEqual( '

https://example.com text

\n' ); }); - test('should not convert links even when the links are the end of the line, unless previous elements are texts', () => { + test('URLの前にテキストがあるならリンクが行末でもリンクカードに変換しない', () => { const html = renderLink('text https://example.com\n\n'); expect(html).toEqual( '

text https://example.com

\n' @@ -121,8 +121,8 @@ describe('Linkify properly', () => { }); }); - describe('Embedded Iframe', () => { - describe('LinkCard', () => { + describe('埋め込みiframeのテスト', () => { + describe('LinkCardのテスト', () => { const validateConvertLinkCardEmbeddedIframe = ( html: string, url: string @@ -138,37 +138,37 @@ describe('Linkify properly', () => { ); }; - test('should convert links to card if prev elem is br', () => { + test('前の要素が
の場合はリンクカードに変換する', () => { const url = 'https://example.com'; const html = renderLink(`foo\n${url}`); validateConvertLinkCardEmbeddedIframe(html, url); }); - test('should convert links when surrounded by softbreaks', () => { + test('改行で囲まれている場合はリンクカードに変換する', () => { const url = 'https://example.com'; const html = renderLink(`\n\n${url}\n\n`); validateConvertLinkCardEmbeddedIframe(html, url); }); - test('should convert links when previous element is a softbreak and the links are end of the paragraph', () => { + test('前に改行があってリンクが段落の終わりならリンクカードに変換する', () => { const url = 'https://example.com'; const html = renderLink(`text\n${url}\n\n`); validateConvertLinkCardEmbeddedIframe(html, url); }); - test('should convert links when the links are the start of the line and the next elements are softbreaks', () => { + test('リンクが段落の先頭でその後に開業が続く場合はリンクカードに変換する', () => { const url = 'https://example.com'; const html = renderLink(`\n\n${url}\ntext`); validateConvertLinkCardEmbeddedIframe(html, url); }); - test('should convert links when previous and next elements are softbreaks', () => { + test('リンクの前後に改行があるならリンクカードに変換する', () => { const url = 'https://example.com'; const html = renderLink(`text\n${url}\ntext`); validateConvertLinkCardEmbeddedIframe(html, url); }); - test('should convert links to card if first element in p', () => { + test('

の最初の要素ならリンクカードに変換する', () => { const url = 'https://example.com'; const html = renderLink(`foo\n\n${url}`); const root = parse(html); @@ -180,7 +180,7 @@ describe('Linkify properly', () => { ).toBeDefined(); }); - test('should convert links even when some links exist in the line, unless softbreaks exist before and after the each links', () => { + test('各リンクの前後に改行があればリンクカードに変換する', () => { const linkCardUrls = ['https://example1.com', 'https://example2.com']; const rawLinkUrls = ['https://example3.com', 'https://example4.com']; // prettier-ignore @@ -199,7 +199,7 @@ describe('Linkify properly', () => { ); }); - test('should convert links even when some links exist in the line, when each links are separated by linebreaks', () => { + test('行内にリンクが存在する場合でも、各リンクが改行で区切られている場合は、リンクを変換する', () => { const linkCardUrls = ['https://example1.com', 'https://example2.com']; const html = renderLink(`${linkCardUrls[0]}\n${linkCardUrls[1]}\n`); const iframes = parse(html).querySelectorAll( @@ -213,8 +213,8 @@ describe('Linkify properly', () => { }); }); - describe('Tweet', () => { - test('should convert a tweet-link to embedded iframe', () => { + describe('Tweet埋め込みのテスト', () => { + test('ツイートリンクを)`; const html = markdownToHtml(content); expect(html).toContain(