このコミットが含まれているのは:
2026-07-16 20:05:09 +09:00
コミット 90d8d3ff08
27個のファイルの変更725行の追加257行の削除
+36
ファイルの表示
@@ -1,6 +1,10 @@
import { describe, expect, it } from 'vitest'
import { creatableImportRows,
canEditResultRow,
canEditReviewRow,
canRetryResultRow,
hasExactSourceRows,
initialisePreviewRows,
mergeImportResults,
mergeValidatedImportRow,
@@ -161,6 +165,38 @@ describe ('post import row state', () => {
expect (resultRepairMode ([complete])).toBe ('all')
})
it ('classifies editable and retryable rows by terminal and recoverable state', () => {
const ready = buildPostImportRow ()
const skipped = buildPostImportRow ({
importStatus: 'skipped',
skipReason: 'existing',
existingPostId: 2 })
const hardFailed = buildPostImportRow ({
importStatus: 'failed',
importErrors: { base: ['failed'] } })
const pendingInvalid = buildPostImportRow ({
importStatus: 'pending',
recoverable: true,
validationErrors: { title: ['invalid'] } })
const pendingValid = buildPostImportRow ({
importStatus: 'pending',
recoverable: true })
expect (canEditReviewRow (ready)).toBe (true)
expect (canEditReviewRow (skipped)).toBe (false)
expect (canEditReviewRow (hardFailed)).toBe (false)
expect (canEditResultRow (pendingInvalid)).toBe (true)
expect (canRetryResultRow (pendingInvalid)).toBe (false)
expect (canRetryResultRow (pendingValid)).toBe (true)
})
it ('detects missing, duplicate, and extra source rows exactly', () => {
expect (hasExactSourceRows ([1, 2], [{ sourceRow: 1 }, { sourceRow: 2 }])).toBe (true)
expect (hasExactSourceRows ([1, 2], [{ sourceRow: 1 }])).toBe (false)
expect (hasExactSourceRows ([1, 2], [{ sourceRow: 1 }, { sourceRow: 1 }])).toBe (false)
expect (hasExactSourceRows ([1, 2], [{ sourceRow: 1 }, { sourceRow: 3 }])).toBe (false)
})
it ('merges only the validated source row and preserves other row edits', () => {
const edited = buildPostImportRow ({
sourceRow: 1,
+31
ファイルの表示
@@ -83,6 +83,24 @@ export const resultRepairMode = (
: 'all'
export const canEditReviewRow = (row: PostImportRow): boolean =>
!(row.importStatus === 'created'
|| row.importStatus === 'skipped'
|| (row.importStatus === 'failed' && row.recoverable !== true))
export const canEditResultRow = (row: PostImportRow): boolean =>
row.recoverable === true
&& (row.importStatus === 'failed'
|| (row.importStatus === 'pending' && hasValidationErrors (row)))
export const canRetryResultRow = (row: PostImportRow): boolean =>
row.recoverable === true
&& (row.importStatus === 'failed'
|| (row.importStatus === 'pending' && !(hasValidationErrors (row))))
export const resultRowMessages = (row: PostImportRow): string[] =>
[...new Set ([
...Object.values (row.validationErrors ?? { }).flat (),
@@ -95,6 +113,19 @@ export const resultRowWarnings = (row: PostImportRow): string[] =>
...row.baseWarnings])]
export const hasExactSourceRows = (
expected: number[],
actual: Array<{ sourceRow: number }>,
): boolean => {
if (expected.length !== actual.length)
return false
const expectedSorted = [...expected].sort ((a, b) => a - b)
const actualSorted = actual.map (_1 => _1.sourceRow).sort ((a, b) => a - b)
return expectedSorted.every ((value, index) => value === actualSorted[index])
}
export const replaceImportRow = (
rows: PostImportRow[],
nextRow: PostImportRow,
+2
ファイルの表示
@@ -16,6 +16,7 @@ describe ('post import storage', () => {
it ('round-trips a valid session and source draft', () => {
const row = buildPostImportRow ({
attributes: { duration: '2.5' },
recoverable: true,
importStatus: 'pending',
validationErrors: { title: ['invalid'] } })
@@ -32,6 +33,7 @@ describe ('post import storage', () => {
version: 2,
source: skipped.url,
rows: [{
attributes: { duration: '2.5' },
recoverable: true,
importStatus: 'pending' },
{