このコミットが含まれているのは:
2026-07-16 22:31:32 +09:00
コミット f91b78bd47
11個のファイルの変更、310行の追加、98行の削除
+11 -7
ファイルの表示
@@ -26,22 +26,26 @@ describe ('post import row state', () => {
sourceRow: 2,
skipReason: 'existing',
existingPostId: 20 })
const invalid = buildPostImportRow ({
const manual = buildPostImportRow ({
sourceRow: 3,
skipReason: 'manual' })
const invalid = buildPostImportRow ({
sourceRow: 4,
status: 'error',
validationErrors: { url: ['invalid'] } })
const created = buildPostImportRow ({
sourceRow: 4,
sourceRow: 5,
importStatus: 'created',
createdPostId: 40 })
const rows = [ready, existing, invalid, created]
const rows = [ready, existing, manual, invalid, created]
expect (processableImportRows (rows)).toEqual ([ready, existing])
expect (processableImportRows (rows)).toEqual ([ready])
expect (creatableImportRows (rows)).toEqual ([ready])
expect (reviewSummaryCounts (rows)).toEqual ({
total: 4,
submittable: 1,
skipPlanned: 1 })
creatable: 1,
manualSkipped: 1,
existingSkipped: 1,
pendingOrError: 1 })
})
it ('preserves terminal rows while merging validation results', () => {
+42 -12
ファイルの表示
@@ -2,9 +2,17 @@ import type { PostImportEditableDraft,
PostImportResultRow,
PostImportRow } from '@/lib/postImportTypes'
const hasSkipReason = (row: PostImportRow): boolean =>
export const isExistingSkipRow = (row: PostImportRow): boolean =>
row.skipReason === 'existing'
export const isManualSkipRow = (row: PostImportRow): boolean =>
row.skipReason === 'manual'
const hasSkipReason = (row: PostImportRow): boolean =>
row.skipReason != null
const hasValidationErrors = (row: PostImportRow): boolean =>
Object.keys (row.validationErrors ?? { }).length > 0
@@ -15,6 +23,26 @@ const isRepairableImportStatus = (row: PostImportRow): boolean =>
isRecoverableRow (row)
&& (row.importStatus === 'failed' || row.importStatus === 'pending')
export const isNonRecoverableFailedRow = (row: PostImportRow): boolean =>
row.importStatus === 'failed' && row.recoverable !== true
export const isTerminalRow = (row: PostImportRow): boolean =>
row.importStatus === 'created'
|| row.importStatus === 'skipped'
|| isNonRecoverableFailedRow (row)
export const isCompletedReviewRow = (row: PostImportRow): boolean =>
row.importStatus === 'created'
|| row.importStatus === 'skipped'
|| hasSkipReason (row)
export const validatableImportRows = (rows: PostImportRow[]): PostImportRow[] =>
rows.filter (row => !(hasSkipReason (row)) && !(isTerminalRow (row)))
const buildResetSnapshot = (row: PostImportRow) => ({
url: row.url,
attributes: { ...row.attributes },
@@ -29,7 +57,7 @@ const buildResetSnapshot = (row: PostImportRow) => ({
export const processableImportRows = (rows: PostImportRow[]): PostImportRow[] =>
rows.filter (row => {
validatableImportRows (rows).filter (row => {
if (row.importStatus === 'created')
return false
if (row.importStatus === 'skipped')
@@ -46,13 +74,12 @@ export const creatableImportRows = (rows: PostImportRow[]): PostImportRow[] =>
export const reviewSummaryCounts = (rows: PostImportRow[]) => ({
total: rows.length,
submittable: rows.filter (row =>
creatableImportRows ([row]).length > 0
&& !(hasValidationErrors (row))).length,
skipPlanned: rows.filter (row =>
processableImportRows ([row]).length > 0
&& hasSkipReason (row)).length })
creatable: rows.filter (row => creatableImportRows ([row]).length > 0).length,
manualSkipped: rows.filter (row => isManualSkipRow (row)).length,
existingSkipped: rows.filter (row => isExistingSkipRow (row)).length,
pendingOrError: rows.filter (row =>
!(isCompletedReviewRow (row))
&& creatableImportRows ([row]).length === 0).length })
export const resultSummaryCounts = (rows: PostImportRow[]) =>
@@ -85,19 +112,22 @@ export const resultRepairMode = (
export const canEditReviewRow = (row: PostImportRow): boolean =>
!(row.importStatus === 'created'
!(hasSkipReason (row)
|| row.importStatus === 'created'
|| row.importStatus === 'skipped'
|| (row.importStatus === 'failed' && row.recoverable !== true))
export const canEditResultRow = (row: PostImportRow): boolean =>
row.recoverable === true
row.skipReason == null
&& row.recoverable === true
&& (row.importStatus === 'failed'
|| (row.importStatus === 'pending' && hasValidationErrors (row)))
export const canRetryResultRow = (row: PostImportRow): boolean =>
row.recoverable === true
row.skipReason == null
&& row.recoverable === true
&& (row.importStatus === 'failed'
|| (row.importStatus === 'pending' && !(hasValidationErrors (row))))
+7 -2
ファイルの表示
@@ -24,10 +24,13 @@ describe ('post import storage', () => {
importStatus: 'skipped',
skipReason: 'existing',
existingPostId: 10 })
const manual = buildPostImportRow ({
sourceRow: 3,
skipReason: 'manual' })
expect (savePostImportSession ({
source: skipped.url,
rows: [row, skipped],
rows: [row, skipped, manual],
repairMode: 'all' })).toBe (true)
expect (loadPostImportSession ()).toMatchObject ({
version: 2,
@@ -39,7 +42,9 @@ describe ('post import storage', () => {
{
importStatus: 'skipped',
skipReason: 'existing',
existingPostId: 10 }] })
existingPostId: 10 },
{
skipReason: 'manual' }] })
expect (savePostImportSourceDraft ('https://example.com')).toBe (true)
expect (loadPostImportSourceDraft ()).toEqual ({ source: 'https://example.com' })
+1 -1
ファイルの表示
@@ -129,7 +129,7 @@ const isValidOrigin = (
const isValidSkipReason = (
value: unknown,
): value is PostImportSkipReason =>
value === 'existing'
value === 'existing' || value === 'manual'
const isPositiveInteger = (value: unknown): value is number =>
Number.isInteger (value) && Number (value) > 0
+1 -1
ファイルの表示
@@ -5,7 +5,7 @@ export type PostImportStatus =
| 'created'
| 'skipped'
| 'failed'
export type PostImportSkipReason = 'existing'
export type PostImportSkipReason = 'existing' | 'manual'
export type PostImportResultStatus = 'created' | 'skipped' | 'failed'
export type PostImportAttributeValue = string | number