Skip to content

Commit e816372

Browse files
committed
feat(WriteTask): enhance boolean handling and add new tests for boolean values. Addresses #228.
1 parent 7eaa6eb commit e816372

File tree

2 files changed

+54
-29
lines changed

2 files changed

+54
-29
lines changed

src/WriteTask.spec.ts

+52-28
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,14 @@ import { WriteTags } from "./WriteTags";
3333

3434
describe("WriteTask", function () {
3535
this.slow(1); // always show timings
36+
37+
const ImageExifData = {
38+
UserComment: "This is a user comment added by exiftool.",
39+
Artist: "Arturo DeImage",
40+
Copyright: "© Chuckles McSnortypants, Inc.",
41+
Credit: "photo by Jenny Snapsalot",
42+
};
43+
3644
for (const opts of [
3745
{ maxProcs: 1, maxRetries: 0, useMWG: true },
3846
{ maxProcs: 3, maxRetries: 3, useMWG: false },
@@ -101,7 +109,7 @@ describe("WriteTask", function () {
101109
});
102110
});
103111

104-
type InputValue = string | number | Struct | ResourceEvent;
112+
type InputValue = string | number | Struct | ResourceEvent | boolean;
105113

106114
async function assertRoundTrip({
107115
dest,
@@ -324,6 +332,28 @@ describe("WriteTask", function () {
324332
return;
325333
});
326334

335+
it("round-trips a boolean true value", async () => {
336+
const file = await dest();
337+
// Using a native boolean tag
338+
return assertRoundTrip({
339+
dest: file,
340+
tagName: "AlreadyApplied",
341+
inputValue: true,
342+
expectedValue: true,
343+
});
344+
});
345+
346+
it("round-trips a boolean false value", async () => {
347+
const file = await dest();
348+
// Using a native boolean tag
349+
return assertRoundTrip({
350+
dest: file,
351+
tagName: "AlreadyApplied",
352+
inputValue: false,
353+
expectedValue: false,
354+
});
355+
});
356+
327357
function randomFloat(min: number, max: number) {
328358
return Math.random() * (max - min) + min;
329359
}
@@ -418,6 +448,17 @@ describe("WriteTask", function () {
418448
).to.match(/Value below int16u minimum/i);
419449
});
420450

451+
it("rejects an invalid string Orientation", async () => {
452+
const src = await dest();
453+
expect(
454+
(
455+
await exiftool.write(src, {
456+
Orientation: "this isn't a valid orientation",
457+
})
458+
).warnings?.join("\n"),
459+
).to.be.match(/Can't convert IFD0:Orientation/i);
460+
});
461+
421462
it("tags case-insensitively", async () => {
422463
const src = await dest();
423464
await exiftool.write(src, { rating: 12 } as any, [
@@ -441,17 +482,6 @@ describe("WriteTask", function () {
441482
).to.match(/ImageOffset is not writable/i);
442483
});
443484

444-
it("rejects an invalid string Orientation", async () => {
445-
const src = await dest();
446-
expect(
447-
(
448-
await exiftool.write(src, {
449-
Orientation: "this isn't a valid orientation",
450-
})
451-
).warnings?.join("\n"),
452-
).to.be.match(/Can't convert IFD0:Orientation/i);
453-
});
454-
455485
it("handles deleting tags from empty files", async () => {
456486
const src = await dest();
457487
const isSidecar = isSidecarExt(src);
@@ -757,13 +787,6 @@ describe("WriteTask", function () {
757787
const exiftool = new ExifTool();
758788
after(() => end(exiftool));
759789

760-
const exp = {
761-
UserComment: "This is a user comment added by exiftool.",
762-
Artist: "Arturo DeImage",
763-
Copyright: "© Chuckles McSnortypants, Inc.",
764-
Credit: "photo by Jenny Snapsalot",
765-
};
766-
767790
const expectedDefinedTags = [
768791
"Make",
769792
"Model",
@@ -820,13 +843,14 @@ describe("WriteTask", function () {
820843
it("deletes all tags by default", async () => {
821844
const img = await testImg({ srcBasename: "oly.jpg" });
822845
const before = await exiftool.read(img);
823-
expect(before).to.containSubset(exp);
846+
847+
expect(before).to.containSubset(ImageExifData);
824848
assertDefinedGeneralTags(before);
825849
await exiftool.deleteAllTags(img);
826850
const after = await exiftool.read(img);
827851
assertMissingGeneralTags(after);
828-
expect(after).to.not.containSubset(exp);
829-
for (const k in exp) {
852+
expect(after).to.not.containSubset(ImageExifData);
853+
for (const k in ImageExifData) {
830854
expect(after).to.not.haveOwnProperty(k);
831855
}
832856
// And make sure everything else is gone:
@@ -840,17 +864,17 @@ describe("WriteTask", function () {
840864
}
841865
});
842866

843-
for (const key in exp) {
867+
for (const key in ImageExifData) {
844868
it(`deletes all tags except ${key}`, async () => {
845869
const img = await testImg({ srcBasename: "oly.jpg" });
846870
const before = await exiftool.read(img);
847-
expect(before).to.containSubset(exp);
871+
expect(before).to.containSubset(ImageExifData);
848872
assertDefinedGeneralTags(before);
849873
await exiftool.deleteAllTags(img, { retain: [key] });
850874
const after = await exiftool.read(img);
851875
assertMissingGeneralTags(after);
852876
expect(after).to.haveOwnProperty(key);
853-
for (const k in Object.keys(exp)) {
877+
for (const k in Object.keys(ImageExifData)) {
854878
if (k !== key) {
855879
expect(after).to.not.haveOwnProperty(k);
856880
}
@@ -860,12 +884,12 @@ describe("WriteTask", function () {
860884
it("supports deleting everything-except (issue #178)", async () => {
861885
const img = await testImg({ srcBasename: "oly.jpg" });
862886
const before = await exiftool.read(img);
863-
expect(before).to.containSubset(exp);
887+
expect(before).to.containSubset(ImageExifData);
864888
assertDefinedGeneralTags(before);
865-
await exiftool.deleteAllTags(img, { retain: Object.keys(exp) });
889+
await exiftool.deleteAllTags(img, { retain: Object.keys(ImageExifData) });
866890
const after = await exiftool.read(img);
867891
assertMissingGeneralTags(after);
868-
expect(after).to.containSubset(exp);
892+
expect(after).to.containSubset(ImageExifData);
869893
});
870894

871895
it("supports creating arrays in structs", async () => {

src/WriteTask.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,14 @@ function enc(o: unknown, structValue = false): Maybe<string> {
3333
return "";
3434
} else if (isNumber(o)) {
3535
return String(o);
36+
} else if (typeof o === "boolean") {
37+
return o ? "True" : "False";
3638
} else if (isString(o)) {
3739
// Structs need their own escaping here.
3840
// See https://exiftool.org/struct.html#Serialize
3941
return htmlEncode(
4042
structValue ? o.replace(/[,[\]{}|]/g, (ea) => "|" + ea) : o,
4143
);
42-
// const s = htmlEncode(String(o))
4344
} else if (isDateOrTime(o)) {
4445
return toExifString(o);
4546
} else if (Array.isArray(o)) {

0 commit comments

Comments
 (0)