@@ -134,6 +134,41 @@ describe("user turn transcript persistence", () => {
|
134 | 134 | expect(buildPersistedUserTurnMediaInputsFromFields(undefined)).toEqual([]); |
135 | 135 | expect(buildPersistedUserTurnMediaInputsFromFields({})).toEqual([]); |
136 | 136 | }); |
| 137 | + |
| 138 | +it("preserves index alignment when an earlier attachment lacks a content type", () => { |
| 139 | +// Writer pads missing types with "" to keep MediaPaths/MediaTypes index-aligned. |
| 140 | +// The reader must NOT compact those "" holes away before indexing or a later |
| 141 | +// attachment's type lands on the wrong attachment. |
| 142 | +const result = buildPersistedUserTurnMediaInputsFromFields({ |
| 143 | +MediaPaths: ["/media/a.bin", "/media/b.png"], |
| 144 | +MediaTypes: ["", "image/png"], |
| 145 | +}); |
| 146 | +expect(result).toHaveLength(2); |
| 147 | +const [first, second] = result; |
| 148 | +// a.bin has no explicit type in the "" hole. Its contentType must NOT be |
| 149 | +// "image/png" — that belongs to b.png at index 1. |
| 150 | +expect(first).toMatchObject({ path: "/media/a.bin" }); |
| 151 | +expect(first?.contentType).not.toBe("image/png"); |
| 152 | +// b.png at index 1 must keep its own type correctly aligned. |
| 153 | +expect(second).toEqual({ path: "/media/b.png", contentType: "image/png" }); |
| 154 | +}); |
| 155 | + |
| 156 | +it("preserves index alignment when an earlier attachment lacks a url", () => { |
| 157 | +// Same misalignment risk for MediaUrls: a "" hole for a path-only attachment |
| 158 | +// must not shift a later attachment's URL to the wrong index. |
| 159 | +expect( |
| 160 | +buildPersistedUserTurnMediaInputsFromFields({ |
| 161 | +MediaPaths: ["/media/local.bin", ""], |
| 162 | +MediaUrls: ["", "https://example.test/remote.png"], |
| 163 | +MediaTypes: ["application/octet-stream", "image/png"], |
| 164 | +}), |
| 165 | +).toEqual([ |
| 166 | +// local.bin has a path but no url (the "" was a placeholder, not a real url). |
| 167 | +{ path: "/media/local.bin", contentType: "application/octet-stream" }, |
| 168 | +// remote.png has no path (the "" was a placeholder) but does have a url. |
| 169 | +{ url: "https://example.test/remote.png", contentType: "image/png" }, |
| 170 | +]); |
| 171 | +}); |
137 | 172 | }); |
138 | 173 | |
139 | 174 | describe("mergePreparedUserTurnMessageForRuntime", () => { |
|