Commit b9a3b8b2 by luoqi

Merge completed Meyer integration and patient fact fixes into test

parents 5b80c042 7cf6a1e1
Pipeline #3856 failed in 0 seconds
This source diff could not be displayed because it is too large. You can view the blob instead.
import { z } from 'zod';
import { ImageFileRefsSchema } from '@pac/types';
// 新接口专属白名单;不复用入库 passthrough,内部增加字段不会自动扩大公开契约。
const s = z.string().nullable().optional();
......@@ -148,22 +149,9 @@ export const LookupContentSchemas = {
finding: s,
capturedAt: s,
fileLocation: s,
fileRefs: ImageFileRefsSchema.nullable().optional(),
fileName: s,
fileType: s,
fileRefs: z
.array(
z
.object({
provider: z.string().min(1),
connectionId: s,
fileId: z.string().min(1),
role: z.enum(['original', 'thumbnail', 'slice']),
index: z.number().int().nonnegative().optional(),
})
.strict(),
)
.nullable()
.optional(),
analysis: LookupAnalysisSchema.nullable(),
})
.strict(),
......
......@@ -34,7 +34,7 @@ describe('shared image file references', () => {
expect(() => projectMeyerImageFiles({ ...old, raw: { ...old.raw, image: { ...old.raw.image, patientId: 'other' } } }, old.image)).toThrow('ownership');
expect(() => projectMeyerImageFiles(old, { ...old.image, fileRefs: [{ provider: 'meyer', fileId: 'foreign', role: 'original' }] })).toThrow('differ');
});
test('common canonical → parser → fact validation → lookup works for any provider; fileUrl is unchanged', () => {
test('common canonical → parser → fact validation → lookup works for any provider; source file location is preserved', () => {
const refs = [{ provider: 'another-provider', fileId: '13812345678', role: 'original' as const }];
const image = ImageStudyCanonicalSchema.parse({ ...meyerBundle().image, fileRefs: refs, fileUrl: 'tenant/path.png' });
const fact = new ImageParser().parse({ canonicalRow: image, transaction: {
......@@ -43,10 +43,10 @@ describe('shared image file references', () => {
} })[0]!;
const content = validateFactContent(fact.type, fact.subjectId, fact.content);
expect(content).toMatchObject({ file_refs: refs, file_url: 'tenant/path.png' });
const publicFact = toLookupFact({ fact_id: 'fact', host_name: 'friday', subject_id: fact.subjectId,
const publicFact = toLookupFact({ fact_id: '11111111-1111-4111-8111-111111111111', host_name: 'friday', subject_id: fact.subjectId,
type: fact.type, kind: fact.kind, status: fact.status ?? 'active', clinic_id: 'clinic-a', occurred_at: new Date(image.uploadedAt),
planned_for: null, valid_until: null, title: null, summary: null, content }, '诊所');
expect(publicFact.content).toMatchObject({ fileRefs: refs, fileUrl: 'tenant/path.png' });
expect(publicFact.content).toMatchObject({ fileRefs: refs, fileLocation: 'tenant/path.png' });
expect(publicFact.content).not.toHaveProperty('file_refs');
expect(redactJson({ finding: '电话13812345678', file_refs: refs })).toMatchObject({ finding: '电话138****5678', file_refs: refs });
expect(redactJson({ file_refs: [{ ...refs[0], secret: 'no' }] })).toEqual({});
......
......@@ -139,6 +139,13 @@ describe('lookup content whitelist', () => {
run('emr_record', { clinical_signals: [{ field: 'staff_notes' }] }).content,
).toMatchObject({ clinicalSignals: [{ sourceField: null }] });
});
it('preserves stable image file references under the strict public contract', () => {
const refs = [{ provider: 'meyer', connectionId: 'clinic-a', fileId: 'file-1', role: 'original' }];
const fact = run('image_record', { file_refs: refs.map(ref => ({ ...ref, internalToken: 'secret' })) });
expect(fact.content).toMatchObject({ fileRefs: refs });
expect(JSON.stringify(fact.content)).not.toContain('internalToken');
expect(LookupFactSchema.safeParse(fact).success).toBe(true);
});
it('projects image findings and complaint child events; removes arbitrary nested fields', () => {
const image = run('image_record', {
analysis: {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment