Skip to content

Commit f9e0270

Browse files
committed
test: add withDisposable, add tests for ExifRational, ExifSRational
- Add withDisposable to automatically dispose in tests (even if the test fails prematurely) - Replace instances when necessary - Update ExifTagUnified tests to make more logical sense - Add tests for ExifRational and ExifSRational
1 parent 5284355 commit f9e0270

9 files changed

Lines changed: 115 additions & 78 deletions

File tree

src/__utils__/withDisposable.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { onTestFinished } from "vitest";
2+
3+
const withDisposable = <T extends Disposable>(initializer: T | (() => T)) => {
4+
const disposable =
5+
typeof initializer === "function" ? initializer() : initializer;
6+
7+
onTestFinished(() => disposable[Symbol.dispose]());
8+
9+
return disposable;
10+
};
11+
12+
export { withDisposable };

src/enums/ExifTagUnified.test.ts

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ import { ExifTagUnified } from "./ExifTagUnified.ts";
1313
*/
1414
describe("ExifTagUnified", () => {
1515
test("should be an object", () => {
16-
expect(typeof ExifTagUnified).toBe("object");
16+
expect(ExifTagUnified).toBeTypeOf("object");
1717
});
1818
test("should have an iterator", () => {
1919
expect(ExifTagUnified[Symbol.iterator]).toBeDefined();
20-
expect(typeof ExifTagUnified[Symbol.iterator]).toBe("function");
20+
expect(ExifTagUnified[Symbol.iterator]).toBeTypeOf("function");
2121
expect(ExifTagUnified[Symbol.iterator]()).toHaveProperty("next");
2222
});
2323
test("should have all ExifTag keys with correct values", () => {
@@ -32,21 +32,15 @@ describe("ExifTagUnified", () => {
3232
});
3333
test("should have correct entries in order", () => {
3434
// After the first `ExifTag` entries, the `ExifTagGps` entries are added
35-
const exifTagLength = Array.from(ExifTag).length;
36-
const exifTagUnifiedEntries = Array.from(ExifTagUnified);
37-
expect(exifTagUnifiedEntries.slice(undefined, exifTagLength)).toEqual(
38-
Array.from(ExifTag),
35+
const exifTagArray = Array.from(ExifTag);
36+
const exifTagGpsArray = Array.from(ExifTagGps);
37+
const exifTagUnifiedArray = Array.from(ExifTagUnified);
38+
expect(exifTagUnifiedArray.slice(undefined, exifTagArray.length)).toEqual(
39+
exifTagArray,
3940
);
40-
expect(exifTagUnifiedEntries.slice(exifTagLength)).toEqual(
41-
Array.from(ExifTagGps),
41+
expect(exifTagUnifiedArray.slice(exifTagArray.length)).toEqual(
42+
exifTagGpsArray,
4243
);
43-
expect([...ExifTag, ...ExifTagGps]).toEqual(Array.from(ExifTagUnified));
44+
expect([...exifTagArray, ...exifTagGpsArray]).toEqual(exifTagUnifiedArray);
4445
});
45-
46-
test.skip.each([...ExifTag, ...ExifTagGps])(
47-
"should have value %j for key %j",
48-
(key, value) => {
49-
expect(ExifTagUnified).toHaveProperty(key, value);
50-
},
51-
);
5246
});

src/libexif/ExifContent.test.ts

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
import { describe, expect, onTestFinished, test } from "vitest";
1+
import { describe, expect, test } from "vitest";
22

33
import { ExifContent } from "./ExifContent.ts";
44
import { ExifData } from "./ExifData.ts";
55
import { ExifEntry } from "./ExifEntry.ts";
66
import { getTestFixture } from "../__utils__/getTestFixture.ts";
7+
import { withDisposable } from "../__utils__/withDisposable.ts";
78
import { ExifIfd } from "../enums/ExifIfd.ts";
89
import { getEnumKeyFromValue } from "../utils/getEnumKeyFromValue.ts";
910

1011
describe("ExifContent", () => {
1112
describe("ExifContent.new()", () => {
1213
test("should create a new ExifContent instance", () => {
13-
const exifContent = ExifContent.new();
14-
onTestFinished(() => exifContent.free());
14+
const exifContent = withDisposable(ExifContent.new());
1515
expect(exifContent).toBeInstanceOf(ExifContent);
1616
expect(exifContent.byteOffset).toBeGreaterThan(0);
1717
expect(exifContent).toHaveProperty("entriesPtr", 0);
@@ -28,8 +28,9 @@ describe("ExifContent", () => {
2828
test("should create an array of new ExifContent instances", async () => {
2929
const testFixture = await getTestFixture(testFixtureFile);
3030

31-
const exifData = ExifData.newFromData(testFixture.buffer);
32-
onTestFinished(() => exifData.free());
31+
const exifData = withDisposable(
32+
ExifData.newFromData(testFixture.buffer),
33+
);
3334
exifData.ifd.forEach((exifContent, index) => {
3435
expect(exifContent).toBeInstanceOf(ExifContent);
3536
expect(exifContent.byteOffset).toBeGreaterThan(0);
@@ -43,12 +44,10 @@ describe("ExifContent", () => {
4344
);
4445
describe("exifContent.addEntry()", () => {
4546
test("should add an entry to ExifContent", () => {
46-
const exifContent = ExifContent.new();
47-
onTestFinished(() => exifContent.free());
47+
const exifContent = withDisposable(ExifContent.new());
4848
expect(exifContent).toHaveProperty("count", 0);
4949

50-
const exifEntry = ExifEntry.new();
51-
onTestFinished(() => exifEntry.free());
50+
const exifEntry = withDisposable(ExifEntry.new());
5251
exifContent.addEntry(exifEntry);
5352
expect(exifContent.entriesPtr).toBeGreaterThan(0);
5453
expect(exifContent).toHaveProperty("count", 1);
@@ -64,26 +63,22 @@ describe("ExifContent", () => {
6463
});
6564
describe("exifContent.getEntry()", () => {
6665
test("should get an entry from ExifContent", () => {
67-
const exifContent = ExifContent.new();
68-
onTestFinished(() => exifContent.free());
66+
const exifContent = withDisposable(ExifContent.new());
67+
// withDisposable is not necessary since exifEntry now belongs to exifData
6968
const exifEntry = ExifEntry.new();
70-
onTestFinished(() => exifEntry.free());
7169
exifEntry.tag = "IMAGE_DESCRIPTION";
7270
exifContent.addEntry(exifEntry);
7371
expect(exifContent.getEntry("IMAGE_DESCRIPTION")).toEqual(exifEntry);
7472
});
7573
test("should return null if entry not found", () => {
76-
const exifContent = ExifContent.new();
77-
onTestFinished(() => exifContent.free());
74+
const exifContent = withDisposable(ExifContent.new());
7875
expect(exifContent.getEntry("LATITUDE")).toBeNull();
7976
});
8077
});
8178
describe("exifContent.removeEntry()", () => {
8279
test("should remove an entry from ExifContent", () => {
83-
const exifContent = ExifContent.new();
84-
onTestFinished(() => exifContent.free());
85-
const exifEntry = ExifEntry.new();
86-
onTestFinished(() => exifEntry.free());
80+
const exifContent = withDisposable(ExifContent.new());
81+
const exifEntry = withDisposable(ExifEntry.new());
8782
exifEntry.tag = "IMAGE_DESCRIPTION";
8883
exifContent.addEntry(exifEntry);
8984
expect(exifContent.getEntry("IMAGE_DESCRIPTION")).toEqual(exifEntry);
@@ -94,11 +89,9 @@ describe("ExifContent", () => {
9489
});
9590
describe("exifContent.ifd", () => {
9691
test("should return correct ifd", () => {
92+
// withDisposable is not necessary since exifContent now belongs to exifData
9793
const exifContent = ExifContent.new();
98-
// Not necessary since exifContent now belongs to exifData
99-
// onTestFinished(() => exifContent.free());
100-
const exifData = ExifData.new();
101-
onTestFinished(() => exifData.free());
94+
const exifData = withDisposable(ExifData.new());
10295

10396
expect(exifContent).toHaveProperty("ifd", null);
10497
exifData.ifd[0].free();

src/libexif/ExifData.test.ts

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ import {
1111
type TestFixture,
1212
getTestFixture,
1313
} from "../__utils__/getTestFixture.ts";
14+
import { withDisposable } from "../__utils__/withDisposable.ts";
1415
import { ExifIfd } from "../enums/ExifIfd.ts";
1516
import type { Tag } from "../enums/ExifTagUnified.ts";
1617
import type { Entry } from "../interfaces/utils.ts";
1718

1819
describe("ExifData", () => {
1920
describe("ExifData.new()", () => {
2021
test("should create a new ExifData instance", () => {
21-
const exifData = ExifData.new();
22+
const exifData = withDisposable(ExifData.new());
2223
expect(exifData).toBeInstanceOf(ExifData);
2324
expect(exifData.byteOffset).toBeGreaterThan(0);
2425
expect(exifData.data).toHaveLength(0);
@@ -36,13 +37,13 @@ describe("ExifData", () => {
3637
expect(exifData.byteOrder).toBe("MOTOROLA");
3738
expect(exifData.mnoteData).toBeNull();
3839
expect(exifData.dataType).toBeNull();
39-
exifData.free();
4040
});
4141
});
4242
describe("exifData.ifd", () => {
4343
describe("setter", () => {
4444
test("should set exifData.ifd", () => {
45-
const exifData = ExifData.new();
45+
const exifData = withDisposable(ExifData.new());
46+
// withDisposable is not necessary since exifContent now belongs to exifData
4647
const exifContent = ExifContent.new();
4748

4849
exifData.ifd[0].free();
@@ -52,8 +53,6 @@ describe("ExifData", () => {
5253
"byteOffset",
5354
exifContent.byteOffset,
5455
);
55-
56-
exifData.free();
5756
});
5857
});
5958
});
@@ -62,7 +61,9 @@ describe("ExifData", () => {
6261
(testFixtureFile) => {
6362
test("should create a new ExifData instance from data", async () => {
6463
const testFixture = await getTestFixture(testFixtureFile);
65-
const exifData = ExifData.newFromData(testFixture.buffer);
64+
const exifData = withDisposable(
65+
ExifData.newFromData(testFixture.buffer),
66+
);
6667

6768
expect(exifData).not.toBeNull();
6869
expect(exifData).toBeInstanceOf(ExifData);
@@ -125,34 +126,33 @@ describe("ExifData", () => {
125126
testFixture.json.mnoteData === null,
126127
);
127128
expect(exifData.dataType).toBeNull();
128-
exifData.free();
129129
});
130130
},
131131
);
132132
describe("exifData.setByteOrder()", () => {
133133
test("should set the byte order", () => {
134-
const exifData = ExifData.new();
134+
const exifData = withDisposable(ExifData.new());
135135
expect(exifData.byteOrder).toBe("MOTOROLA");
136136
exifData.byteOrder = "INTEL";
137137
expect(exifData.byteOrder).toBe("INTEL");
138-
exifData.free();
139138
});
140139
});
141140
describe("exifData.setDataType()", () => {
142141
test("should set the data type", () => {
143-
const exifData = ExifData.new();
142+
const exifData = withDisposable(ExifData.new());
144143
expect(exifData.dataType).toBeNull();
145144
exifData.dataType = "COMPRESSED";
146145
expect(exifData.dataType).toBe("COMPRESSED");
147-
exifData.free();
148146
});
149147
});
150148
describe.each(["T-45A_Goshawk_03.jpg", "Sumo_Museum.jpg"])(
151149
"exifData.getEntry(%s)",
152150
(testFixtureFile) => {
153151
test("should get an entry by tag", async () => {
154152
const testFixture = await getTestFixture(testFixtureFile);
155-
const exifData = ExifData.newFromData(testFixture.buffer);
153+
const exifData = withDisposable(
154+
ExifData.newFromData(testFixture.buffer),
155+
);
156156

157157
Object.values(testFixture.json.data)
158158
.flatMap((datum) => Object.entries(datum))
@@ -177,7 +177,6 @@ describe("ExifData", () => {
177177
);
178178
expect(exifEntry?.value).toEqual(expectedExifEntry.value);
179179
});
180-
exifData.free();
181180
});
182181
},
183182
);

src/libexif/ExifEntry.test.ts

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ import { describe, expect, test } from "vitest";
33
import { ExifData } from "./ExifData.ts";
44
import { ExifEntry } from "./ExifEntry.ts";
55
import { EXIF_SENTINEL_TAG } from "./ExifTag.ts";
6+
import { withDisposable } from "../__utils__/withDisposable.ts";
67
import { ExifIfd } from "../enums/ExifIfd.ts";
78
import { intArrayFromString } from "../internal/emscripten.ts";
89

910
describe("ExifEntry", () => {
1011
describe("ExifEntry.new()", () => {
1112
test("should create a new ExifEntry instance", () => {
12-
const exifEntry = ExifEntry.new();
13+
const exifEntry = withDisposable(ExifEntry.new());
1314
// By default, `tagVal` is 0, which is the GPS `VERSION_ID` tag. For this
1415
// library's convention, `tagVal` is set to `EXIF_SENTINEL_TAG` to indicate
1516
// that the tag is not set
@@ -25,12 +26,11 @@ describe("ExifEntry", () => {
2526
expect(exifEntry.data).toHaveLength(0);
2627
expect(exifEntry.data).toHaveProperty("byteOffset", 0);
2728
expect(exifEntry.data).toHaveProperty("byteLength", 0);
28-
exifEntry.free();
2929
});
3030
});
3131
describe("exifEntry.getValue()", () => {
3232
test("should return empty string on new entry", () => {
33-
const exifEntry = ExifEntry.new();
33+
const exifEntry = withDisposable(ExifEntry.new());
3434
exifEntry.format = "ASCII";
3535
exifEntry.tag = "MAKE";
3636
expect(exifEntry).toHaveProperty("format", "ASCII");
@@ -41,7 +41,7 @@ describe("ExifEntry", () => {
4141
test("should return ASCII value", () => {
4242
const EXPECTED_ASCII_VALUE = "Canon";
4343

44-
const exifEntry = ExifEntry.new();
44+
const exifEntry = withDisposable(ExifEntry.new());
4545
exifEntry.format = "ASCII";
4646
exifEntry.tag = "MAKE";
4747
const data = Buffer.from(`${EXPECTED_ASCII_VALUE}\0`, "ascii");
@@ -54,46 +54,40 @@ describe("ExifEntry", () => {
5454
*
5555
* @see {@link https://github.com/libexif/libexif/blob/master/libexif/exif-entry.c#L884-L885}
5656
*/
57-
const exifData = ExifData.new();
57+
const exifData = withDisposable(ExifData.new());
5858
const exifContent = exifData.ifd[ExifIfd.IFD_0];
5959
exifContent.addEntry(exifEntry);
6060
expect(exifEntry.value).toBe(EXPECTED_ASCII_VALUE);
6161
exifContent.removeEntry(exifEntry);
62-
exifEntry.free();
63-
exifData.free();
6462
});
6563
test("should return byte value", () => {
6664
const EXPECTED_BYTE_VALUE = 0x2a; // 42
67-
const exifEntry = ExifEntry.new();
65+
const exifEntry = withDisposable(ExifEntry.new());
6866
exifEntry.format = "BYTE";
6967
exifEntry.tag = "JPEG_INTERCHANGE_FORMAT";
7068
exifEntry.components = 1;
7169
exifEntry.data = new Uint8Array([EXPECTED_BYTE_VALUE]);
72-
const exifData = ExifData.new();
70+
const exifData = withDisposable(ExifData.new());
7371
const exifContent = exifData.ifd[ExifIfd.IFD_0];
7472
exifContent.addEntry(exifEntry);
7573
expect(exifEntry.value).toBe(`0x${EXPECTED_BYTE_VALUE.toString(16)}`);
7674
exifContent.removeEntry(exifEntry);
77-
exifEntry.free();
78-
exifData.free();
7975
});
8076
});
8177
describe("ExifEntry.toTypedArray()", () => {
8278
test("should return empty array on new entry", () => {
83-
const exifEntry = ExifEntry.new();
79+
const exifEntry = withDisposable(ExifEntry.new());
8480
expect(exifEntry.toTypedArray()).toStrictEqual(new Uint8Array([]));
85-
exifEntry.free();
8681
});
8782
test("should return ASCII uint8array on new entry", () => {
88-
const exifEntry = ExifEntry.new();
83+
const exifEntry = withDisposable(ExifEntry.new());
8984
exifEntry.format = "ASCII";
9085
const asciiIntArray = new Uint8Array(
9186
intArrayFromString("My Ascii String", false),
9287
);
9388
exifEntry.data = asciiIntArray;
9489
exifEntry.components = asciiIntArray.length;
9590
expect(exifEntry.toTypedArray()).toStrictEqual(asciiIntArray);
96-
exifEntry.free();
9791
});
9892
});
9993
});

src/libexif/ExifLoader.test.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { describe, expect, test } from "vitest";
33
import { ExifData } from "./ExifData.ts";
44
import { ExifLoader } from "./ExifLoader.ts";
55
import { getTestFixture } from "../__utils__/getTestFixture.ts";
6+
import { withDisposable } from "../__utils__/withDisposable.ts";
67

78
describe("ExifLoader", () => {
89
describe("ExifLoader.new()", () => {
@@ -12,7 +13,6 @@ describe("ExifLoader", () => {
1213
expect(exifLoader.byteOffset).toBeGreaterThan(0);
1314
expect(exifLoader.getData()).toBeNull();
1415
expect(exifLoader.getBuf()).toBeNull();
15-
exifLoader.unref();
1616
});
1717
});
1818
describe.each(["T-45A_Goshawk_03.jpg", "Sumo_Museum.jpg"])(
@@ -33,16 +33,19 @@ describe("ExifLoader", () => {
3333
expect(buf).toBeInstanceOf(Uint8Array);
3434
expect(buf).not.toHaveLength(0);
3535

36-
const exifData = exifLoader.getData();
37-
expect(exifData).not.toBeNull();
36+
const exifData = withDisposable(() => {
37+
const exifData = exifLoader.getData();
38+
if (exifData === null) {
39+
throw new Error("exifData is null");
40+
}
41+
return exifData;
42+
});
3843
expect(exifData).toBeInstanceOf(ExifData);
3944
expect(exifData?.byteOffset).toBeGreaterThan(0);
4045

4146
exifLoader.reset();
4247
expect(exifLoader.getBuf()).toBeNull();
4348
expect(exifLoader.getData()).toBeNull();
44-
45-
exifData?.free();
4649
exifLoader.unref();
4750
});
4851
},

0 commit comments

Comments
 (0)