exiftool-vendored
Version:
Efficient, cross-platform access to ExifTool
220 lines • 11 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const node_fs_1 = require("node:fs");
const node_os_1 = require("node:os");
const node_path_1 = require("node:path");
const _chai_spec_1 = require("./_chai.spec");
const ExifTool_1 = require("./ExifTool");
const TagDescriptions_1 = require("./TagDescriptions");
after(() => (0, _chai_spec_1.end)(ExifTool_1.exiftool));
describe("TagDescriptions", function () {
this.slow(5000);
this.timeout(30000);
// Tests that need fresh unloaded state for each test
describe("loading behavior", () => {
let descriptions;
let testCacheDir;
beforeEach(function () {
testCacheDir = (0, node_path_1.join)((0, node_os_1.tmpdir)(), "exiftool-test-" + (0, _chai_spec_1.randomChars)());
(0, node_fs_1.mkdirSync)(testCacheDir, { recursive: true });
descriptions = new TagDescriptions_1.TagDescriptions(ExifTool_1.exiftool, {
cacheDir: testCacheDir,
});
});
afterEach(() => {
descriptions.clear();
if ((0, node_fs_1.existsSync)(testCacheDir)) {
(0, node_fs_1.rmSync)(testCacheDir, { recursive: true, force: true });
}
});
it("starts unloaded and loads descriptions from ExifTool", async () => {
(0, _chai_spec_1.expect)(descriptions.isLoaded).to.equal(false);
await descriptions.preload();
(0, _chai_spec_1.expect)(descriptions.isLoaded).to.equal(true);
(0, _chai_spec_1.expect)(descriptions.size).to.be.greaterThan(1000);
});
it("get() returns curated descriptions even when not loaded", () => {
// Curated descriptions are available immediately without preload
(0, _chai_spec_1.expect)(descriptions.get("DateTimeOriginal")).to.not.equal(undefined);
// But non-curated tags require loading (use a rare tag not in CuratedDescriptions)
(0, _chai_spec_1.expect)(descriptions.get("BitsPerSample")).to.equal(undefined);
});
it("getAsync() auto-loads descriptions for non-curated tags", async () => {
(0, _chai_spec_1.expect)(descriptions.isLoaded).to.equal(false);
// Use a non-curated tag to verify auto-loading (BitsPerSample is in ExifTool but not curated)
const desc = await descriptions.getAsync("BitsPerSample");
(0, _chai_spec_1.expect)(descriptions.isLoaded).to.equal(true);
(0, _chai_spec_1.expect)(desc).to.not.equal(undefined);
});
it("clear() clears the in-memory cache", async () => {
await descriptions.preload();
(0, _chai_spec_1.expect)(descriptions.isLoaded).to.equal(true);
descriptions.clear();
(0, _chai_spec_1.expect)(descriptions.isLoaded).to.equal(false);
});
});
// Tests that need fresh cache directories
describe("caching", () => {
let descriptions;
let testCacheDir;
beforeEach(function () {
testCacheDir = (0, node_path_1.join)((0, node_os_1.tmpdir)(), "exiftool-test-" + (0, _chai_spec_1.randomChars)());
(0, node_fs_1.mkdirSync)(testCacheDir, { recursive: true });
descriptions = new TagDescriptions_1.TagDescriptions(ExifTool_1.exiftool, {
cacheDir: testCacheDir,
});
});
afterEach(() => {
descriptions.clear();
if ((0, node_fs_1.existsSync)(testCacheDir)) {
(0, node_fs_1.rmSync)(testCacheDir, { recursive: true, force: true });
}
});
it("creates cache file after first load", async () => {
await descriptions.preload();
const files = (0, node_fs_1.readdirSync)(testCacheDir);
(0, _chai_spec_1.expect)(files.length).to.equal(1);
(0, _chai_spec_1.expect)(files[0]).to.match(/^tag-descriptions-.*\.json$/);
});
it("loads from cache on second instantiation", async () => {
await descriptions.preload();
const size1 = descriptions.size;
const descriptions2 = new TagDescriptions_1.TagDescriptions(ExifTool_1.exiftool, {
cacheDir: testCacheDir,
});
await descriptions2.preload();
(0, _chai_spec_1.expect)(descriptions2.size).to.equal(size1);
});
it("respects disableDiskCache option", async () => {
const noCacheDir = (0, node_path_1.join)((0, node_os_1.tmpdir)(), "exiftool-nocache-" + (0, _chai_spec_1.randomChars)());
(0, node_fs_1.mkdirSync)(noCacheDir, { recursive: true });
try {
const noCacheDescriptions = new TagDescriptions_1.TagDescriptions(ExifTool_1.exiftool, {
cacheDir: noCacheDir,
disableDiskCache: true,
});
await noCacheDescriptions.preload();
const files = (0, node_fs_1.readdirSync)(noCacheDir);
(0, _chai_spec_1.expect)(files.length).to.equal(0);
}
finally {
(0, node_fs_1.rmSync)(noCacheDir, { recursive: true, force: true });
}
});
});
// Tests that just need loaded data - share one instance
describe("with loaded descriptions", () => {
let descriptions;
let testCacheDir;
before(async function () {
testCacheDir = (0, node_path_1.join)((0, node_os_1.tmpdir)(), "exiftool-test-" + (0, _chai_spec_1.randomChars)());
(0, node_fs_1.mkdirSync)(testCacheDir, { recursive: true });
descriptions = new TagDescriptions_1.TagDescriptions(ExifTool_1.exiftool, {
cacheDir: testCacheDir,
});
});
after(() => {
descriptions.clear();
if ((0, node_fs_1.existsSync)(testCacheDir)) {
(0, node_fs_1.rmSync)(testCacheDir, { recursive: true, force: true });
}
});
it("preload() is idempotent", async () => {
await descriptions.preload();
const size1 = descriptions.size;
await descriptions.preload();
(0, _chai_spec_1.expect)(descriptions.size).to.equal(size1);
});
it("getAsync() returns curated descriptions for important tags", async () => {
const desc = await descriptions.getAsync("DateTimeOriginal");
(0, _chai_spec_1.expect)(desc).to.not.equal(undefined);
(0, _chai_spec_1.expect)(desc.desc).to.include("photo was taken");
(0, _chai_spec_1.expect)(desc.see).to.include("exiftool.org");
});
it("get() returns ExifTool descriptions for standard tags", async () => {
const desc = await descriptions.getAsync("ImageWidth");
(0, _chai_spec_1.expect)(desc).to.not.equal(undefined);
(0, _chai_spec_1.expect)(desc.desc.length).to.be.greaterThan(0);
});
it("getAsync() returns undefined for unknown tags", async () => {
(0, _chai_spec_1.expect)(await descriptions.getAsync("NotARealTagName12345")).to.equal(undefined);
});
it("get() returns undefined for unknown tags", async () => {
await descriptions.preload();
(0, _chai_spec_1.expect)(descriptions.get("NotARealTagName12345")).to.equal(undefined);
});
it("getAll() returns all descriptions", async () => {
const all = await descriptions.getAll();
(0, _chai_spec_1.expect)(all.size).to.be.greaterThan(1000);
(0, _chai_spec_1.expect)(all.get("DateTimeOriginal")).to.not.equal(undefined);
});
it("decodes XML entities without double-unescaping", async () => {
const all = await descriptions.getAll();
for (const [tag, info] of all) {
(0, _chai_spec_1.expect)(info.desc, `${tag} has undecoded entity`).to.not.match(/&(?:lt|gt|amp|quot|apos);/);
}
});
// Curated description tests - verify our curated descriptions are used
const curatedTags = [
"DateTimeOriginal",
"CreateDate",
"ModifyDate",
"Copyright",
"Description",
"Keywords",
"Rating",
"Orientation",
"GPSLatitudeRef",
"GPSLongitudeRef",
"Make",
"Model",
"ISO",
];
for (const tag of curatedTags) {
it(`getAsync has curated description for ${tag}`, async () => {
const desc = await descriptions.getAsync(tag);
(0, _chai_spec_1.expect)(desc, `Missing description for ${tag}`).to.not.equal(undefined);
(0, _chai_spec_1.expect)(desc.desc.length).to.be.greaterThan(50);
});
}
});
describe("non-English language", () => {
let descriptions;
let testCacheDir;
before(async function () {
testCacheDir = (0, node_path_1.join)((0, node_os_1.tmpdir)(), "exiftool-test-de-" + (0, _chai_spec_1.randomChars)());
(0, node_fs_1.mkdirSync)(testCacheDir, { recursive: true });
descriptions = new TagDescriptions_1.TagDescriptions(ExifTool_1.exiftool, {
cacheDir: testCacheDir,
language: "de",
});
await descriptions.preload();
});
after(() => {
descriptions.clear();
if ((0, node_fs_1.existsSync)(testCacheDir)) {
(0, node_fs_1.rmSync)(testCacheDir, { recursive: true, force: true });
}
});
it("uses ExifTool descriptions instead of curated ones for non-English", async () => {
const desc = await descriptions.getAsync("DateTimeOriginal");
(0, _chai_spec_1.expect)(desc).to.not.equal(undefined);
// Our curated description contains "photo was taken" - ExifTool's German one won't
(0, _chai_spec_1.expect)(desc.desc).to.not.include("photo was taken");
// Should have some German description from ExifTool
(0, _chai_spec_1.expect)(desc.desc.length).to.be.greaterThan(0);
});
it("get() also uses ExifTool descriptions for non-English", () => {
const desc = descriptions.get("DateTimeOriginal");
(0, _chai_spec_1.expect)(desc).to.not.equal(undefined);
(0, _chai_spec_1.expect)(desc.desc).to.not.include("photo was taken");
});
it("does not include 'see' URLs from curated descriptions", async () => {
const desc = await descriptions.getAsync("DateTimeOriginal");
(0, _chai_spec_1.expect)(desc).to.not.equal(undefined);
// Our curated descriptions have 'see' URLs, ExifTool's don't
(0, _chai_spec_1.expect)(desc.see).to.equal(undefined);
});
});
});
//# sourceMappingURL=TagDescriptions.spec.js.map