293 lines
8.2 KiB
TypeScript
293 lines
8.2 KiB
TypeScript
import {
|
|
getAllResultUrlsFromAgentProjectState,
|
|
mergeAgentProjectStateForSave,
|
|
} from "@/lib/agents/agent-project-save-merge";
|
|
import { normalizeAgentGenerationProjectPersistedState } from "@/lib/agents/generation-project-state";
|
|
import type { AgentGenerationProjectPersistedState } from "@/types/agent";
|
|
|
|
const DETAIL_RESULT_URL = "https://scqny.jiansun.vip/uploads/1785470582893-rmh0xr.png";
|
|
const DETAIL_RESULT_URL_2 = "https://scqny.jiansun.vip/uploads/1785470577924-owj79k.png";
|
|
const SKU_RESULT_URL = "https://scqny.jiansun.vip/uploads/1785470458027-c6yuar.png";
|
|
const DETAIL_REFERENCE_URL = "https://example.com/detail-reference.png";
|
|
|
|
function createWorkflowState(params?: {
|
|
detailReferences?: number;
|
|
skuReferences?: number;
|
|
}) {
|
|
return {
|
|
inputs: {
|
|
primarySku: "",
|
|
secondarySku: "",
|
|
brand: "",
|
|
store: "",
|
|
thirdCategory: "",
|
|
fourthCategory: "",
|
|
fifthCategory: "",
|
|
priceBand: "",
|
|
},
|
|
selections: {},
|
|
currentStage: "mode",
|
|
agentModeState: {
|
|
detailReplacement: {
|
|
query: "766308902517",
|
|
references: Array.from({ length: params?.detailReferences || 0 }, (_, index) => ({
|
|
id: `detail-card-${index + 1}`,
|
|
label: `Detail ${index + 1}`,
|
|
imageUrl: DETAIL_REFERENCE_URL,
|
|
previewUrl: DETAIL_REFERENCE_URL,
|
|
})),
|
|
},
|
|
skuReplacement: {
|
|
query: "sku-query",
|
|
references: Array.from({ length: params?.skuReferences || 0 }, (_, index) => ({
|
|
id: `sku-card-${index + 1}`,
|
|
label: `SKU ${index + 1}`,
|
|
imageUrl: DETAIL_REFERENCE_URL,
|
|
previewUrl: DETAIL_REFERENCE_URL,
|
|
})),
|
|
},
|
|
},
|
|
};
|
|
}
|
|
|
|
function createExistingDetailProjectState(): AgentGenerationProjectPersistedState {
|
|
return normalizeAgentGenerationProjectPersistedState({
|
|
workflowState: createWorkflowState({ detailReferences: 1 }),
|
|
workspaceState: {
|
|
input: "legacy detail replacement",
|
|
selectedModelId: "auto",
|
|
},
|
|
resultCollections: {
|
|
detail_replacement: [DETAIL_RESULT_URL],
|
|
},
|
|
replacementResultState: {
|
|
detail_replacement: {
|
|
"detail-card-1": {
|
|
url: DETAIL_RESULT_URL,
|
|
text: "completed",
|
|
status: "completed",
|
|
updatedAt: 1,
|
|
compareSourceUrl: DETAIL_REFERENCE_URL,
|
|
referenceImageUrl: DETAIL_REFERENCE_URL,
|
|
referencePreviewUrl: DETAIL_REFERENCE_URL,
|
|
label: "Detail 1",
|
|
},
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
function expect(condition: boolean, message: string) {
|
|
if (!condition) {
|
|
throw new Error(message);
|
|
}
|
|
}
|
|
|
|
function expectEqual<T>(actual: T, expected: T, label: string) {
|
|
if (!Object.is(actual, expected)) {
|
|
throw new Error(`${label}: expected ${String(expected)}, received ${String(actual)}`);
|
|
}
|
|
}
|
|
|
|
function expectIncludesUrl(urls: string[] | undefined, url: string) {
|
|
expect(Boolean(urls?.includes(url)), `expected ${url} to be present`);
|
|
}
|
|
|
|
function expectExcludesUrl(urls: string[] | undefined, url: string) {
|
|
expect(!urls?.includes(url), `expected ${url} to be absent`);
|
|
}
|
|
|
|
const legacyDetailState = createExistingDetailProjectState();
|
|
expectEqual(
|
|
legacyDetailState.workspaceState?.activeBusinessModeKey,
|
|
"detail",
|
|
"legacy detail mode"
|
|
);
|
|
expectIncludesUrl(legacyDetailState.resultCollections?.detail_replacement, DETAIL_RESULT_URL);
|
|
expectEqual(
|
|
legacyDetailState.workflowState.agentModeState?.detailReplacement.references.length,
|
|
1,
|
|
"legacy detail reference count"
|
|
);
|
|
|
|
const resultOnlyLegacyState = normalizeAgentGenerationProjectPersistedState({
|
|
workflowState: createWorkflowState(),
|
|
workspaceState: {
|
|
input: "legacy result-only detail replacement",
|
|
selectedModelId: "auto",
|
|
},
|
|
resultCollections: {
|
|
detail_replacement: [DETAIL_RESULT_URL_2],
|
|
},
|
|
});
|
|
expectEqual(
|
|
resultOnlyLegacyState.workspaceState?.activeBusinessModeKey,
|
|
"detail",
|
|
"result-only detail mode"
|
|
);
|
|
expectIncludesUrl(
|
|
resultOnlyLegacyState.resultCollections?.detail_replacement,
|
|
DETAIL_RESULT_URL_2
|
|
);
|
|
|
|
const emptyProjectState = normalizeAgentGenerationProjectPersistedState({
|
|
workflowState: createWorkflowState(),
|
|
workspaceState: {
|
|
input: "",
|
|
selectedModelId: "auto",
|
|
},
|
|
});
|
|
expectEqual(
|
|
emptyProjectState.workspaceState?.activeBusinessModeKey,
|
|
"main_sku",
|
|
"empty project mode"
|
|
);
|
|
|
|
const staleEmptySaveState = mergeAgentProjectStateForSave({
|
|
existingState: legacyDetailState,
|
|
incomingState: {
|
|
workflowState: createWorkflowState(),
|
|
workspaceState: {
|
|
input: "",
|
|
selectedModelId: "auto",
|
|
activeBusinessModeKey: "main_sku",
|
|
imageParams: {
|
|
aspectRatio: "auto",
|
|
imageSize: "2K",
|
|
imageCount: 1,
|
|
},
|
|
},
|
|
resultImageUrls: [],
|
|
resultCollections: {},
|
|
replacementResultState: {},
|
|
},
|
|
});
|
|
expectEqual(
|
|
staleEmptySaveState.workspaceState?.activeBusinessModeKey,
|
|
"detail",
|
|
"stale empty save mode"
|
|
);
|
|
expectIncludesUrl(
|
|
staleEmptySaveState.resultCollections?.detail_replacement,
|
|
DETAIL_RESULT_URL
|
|
);
|
|
expectIncludesUrl(getAllResultUrlsFromAgentProjectState(staleEmptySaveState), DETAIL_RESULT_URL);
|
|
expectEqual(
|
|
staleEmptySaveState.workflowState.agentModeState?.detailReplacement.references.length,
|
|
1,
|
|
"stale empty save reference count"
|
|
);
|
|
expectEqual(
|
|
staleEmptySaveState.replacementResultState?.detail_replacement?.["detail-card-1"]?.url,
|
|
DETAIL_RESULT_URL,
|
|
"stale empty save replacement record"
|
|
);
|
|
|
|
const replacementStateOnlySave = mergeAgentProjectStateForSave({
|
|
existingState: normalizeAgentGenerationProjectPersistedState({
|
|
workflowState: createWorkflowState({ detailReferences: 1 }),
|
|
workspaceState: {
|
|
input: "",
|
|
selectedModelId: "auto",
|
|
},
|
|
}),
|
|
incomingState: {
|
|
workflowState: createWorkflowState({ detailReferences: 1 }),
|
|
workspaceState: {
|
|
input: "",
|
|
selectedModelId: "auto",
|
|
},
|
|
replacementResultState: {
|
|
detail_replacement: {
|
|
"detail-card-1": {
|
|
url: DETAIL_RESULT_URL_2,
|
|
text: "completed",
|
|
status: "completed",
|
|
updatedAt: 2,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
expectEqual(
|
|
replacementStateOnlySave.workspaceState?.activeBusinessModeKey,
|
|
"detail",
|
|
"replacement-state-only mode"
|
|
);
|
|
expectIncludesUrl(
|
|
replacementStateOnlySave.resultCollections?.detail_replacement,
|
|
DETAIL_RESULT_URL_2
|
|
);
|
|
expectIncludesUrl(
|
|
getAllResultUrlsFromAgentProjectState(replacementStateOnlySave),
|
|
DETAIL_RESULT_URL_2
|
|
);
|
|
|
|
const deletedResultSave = mergeAgentProjectStateForSave({
|
|
existingState: legacyDetailState,
|
|
incomingState: {
|
|
workflowState: createWorkflowState({ detailReferences: 1 }),
|
|
workspaceState: {
|
|
input: "",
|
|
selectedModelId: "auto",
|
|
activeBusinessModeKey: "detail",
|
|
},
|
|
deletedResultCollections: {
|
|
detail_replacement: [DETAIL_RESULT_URL],
|
|
},
|
|
resultCollections: {},
|
|
replacementResultState: {},
|
|
},
|
|
});
|
|
expectExcludesUrl(deletedResultSave.resultCollections?.detail_replacement, DETAIL_RESULT_URL);
|
|
expectExcludesUrl(getAllResultUrlsFromAgentProjectState(deletedResultSave), DETAIL_RESULT_URL);
|
|
expectEqual(
|
|
deletedResultSave.replacementResultState?.detail_replacement?.["detail-card-1"],
|
|
undefined,
|
|
"deleted replacement record"
|
|
);
|
|
|
|
const skuReplacementState = normalizeAgentGenerationProjectPersistedState({
|
|
workflowState: createWorkflowState({ skuReferences: 1 }),
|
|
workspaceState: {
|
|
input: "",
|
|
selectedModelId: "auto",
|
|
},
|
|
replacementResultState: {
|
|
sku_replacement: {
|
|
"sku-card-1": {
|
|
url: SKU_RESULT_URL,
|
|
text: "completed",
|
|
status: "completed",
|
|
updatedAt: 3,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
expectEqual(
|
|
skuReplacementState.workspaceState?.activeBusinessModeKey,
|
|
"detail",
|
|
"sku replacement mode"
|
|
);
|
|
expectIncludesUrl(skuReplacementState.resultCollections?.sku_replacement, SKU_RESULT_URL);
|
|
|
|
console.log(
|
|
JSON.stringify(
|
|
{
|
|
ok: true,
|
|
covered: [
|
|
"legacy detail mode inference",
|
|
"result-only detail mode inference",
|
|
"empty project stays main_sku",
|
|
"stale empty save keeps detail results",
|
|
"stale empty save keeps detail reference cards",
|
|
"replacementResultState repopulates resultCollections",
|
|
"explicit deletion is respected",
|
|
"sku replacement recovery",
|
|
],
|
|
},
|
|
null,
|
|
2
|
|
)
|
|
);
|