Photo: one async method per EXIF field (closes #148)
check / check (push) Successful in 1m37s
check / check (push) Successful in 1m37s
`Photo` gains thirteen async methods, one per `PhotoExif` field and named after it: `make()`, `model()`, `lensModel()`, `dateTimeOriginal()`, `offsetTimeOriginal()`, `exposureTime()`, `fNumber()`, `iso()`, `focalLength()`, `orientation()`, `gpsLatitude()`, `gpsLongitude()` and `gpsAltitude()`. Each calls `exif()` and returns its one field, or `undefined` when the file lacks it. `exif()` is unchanged. `Photo` implements a type built from `PhotoExif`'s keys, so the type check fails when a field has no method. Each call reads the original again; a caller that wants several fields calls `exif()` once. Model: opus-5-5
This commit was merged in pull request #149.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
* a cached path shows up on the projected record. A library opened without a
|
||||
* content source leaves those methods throwing rather than silently doing
|
||||
* nothing. It also covers a `Photo`'s `savePath`, `isLocal`, `download()`,
|
||||
* `content()` and `exif()`.
|
||||
* `content()`, `exif()` and the methods that each return one field of `exif()`.
|
||||
*/
|
||||
|
||||
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
||||
@@ -644,8 +644,8 @@ describe("Photo save path, local copy, content and EXIF", () => {
|
||||
await lib.close();
|
||||
});
|
||||
|
||||
// What exif() returns for HEIC_WITH_EXIF, which holds the same values as
|
||||
// JPEG_WITH_EXIF.
|
||||
// What exif() returns for HEIC_WITH_EXIF, and for JPEG_WITH_EXIF, which
|
||||
// holds the same values.
|
||||
const heicFields: PhotoExif = {
|
||||
make: "Canon",
|
||||
model: "EOS R5",
|
||||
@@ -686,9 +686,35 @@ describe("Photo save path, local copy, content and EXIF", () => {
|
||||
await lib.close();
|
||||
});
|
||||
|
||||
// The build's type check, not this test, makes sure `Photo` has a method
|
||||
// for every `PhotoExif` field, whatever the fixtures hold: `Photo`
|
||||
// implements a type with one method per field. This test checks that each
|
||||
// method gives the same value as exif().
|
||||
it.each([
|
||||
["JPEG", JPEG_WITH_EXIF],
|
||||
["HEIC", HEIC_WITH_EXIF],
|
||||
])(
|
||||
"has a method for each field exif() returns, giving the same value, for a %s",
|
||||
async (_, bytes) => {
|
||||
const lib = await open({ contentSource: stubSource(bytes) });
|
||||
const photo = lib.photos.byID({ fileID: 1 })!;
|
||||
const exif = await photo.exif();
|
||||
// The file holds every field, so every method is checked.
|
||||
expect(exif).toStrictEqual(heicFields);
|
||||
for (const [field, value] of Object.entries(exif)) {
|
||||
expect(await photo[field as keyof PhotoExif]()).toStrictEqual(
|
||||
value,
|
||||
);
|
||||
}
|
||||
await lib.close();
|
||||
},
|
||||
);
|
||||
|
||||
it("returns no EXIF fields for an original that is not an image", async () => {
|
||||
const lib = await open();
|
||||
expect(await lib.photos.byID({ fileID: 1 })!.exif()).toStrictEqual({});
|
||||
const photo = lib.photos.byID({ fileID: 1 })!;
|
||||
expect(await photo.exif()).toStrictEqual({});
|
||||
expect(await photo.dateTimeOriginal()).toBeUndefined();
|
||||
await lib.close();
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user