feat: workflow filter by missing EXIF property (#32713)

Co-authored-by: Daniel Dietzler <mail@ddietzler.dev>
(cherry picked from commit a1a80cb1c416d3a480963a78d7b9df329d867bf6)
This commit is contained in:
austinmdillow
2026-10-28 20:41:41 +03:00
committed by Codex
parent 32e02a05d2
commit dc5553b239
3 changed files with 129 additions and 10 deletions
@@ -530,6 +530,112 @@ describe('core plugin', () => {
});
});
describe('assetExifFilter', () => {
describe('missing', () => {
it('should favorite asset if it has no orientation', async () => {
const { user } = await ctx.newUser();
const { asset } = await ctx.newAsset({ ownerId: user.id, type: AssetType.Video });
await ctx.newExif({ assetId: asset.id, orientation: null });
const workflow = await createWorkflow({
ownerId: user.id,
trigger: WorkflowTrigger.AssetMetadataExtraction,
steps: [
{
method: 'immich-plugin-core#assetExifFilter',
config: { property: 'orientation', matchType: 'missing' },
},
{
method: 'immich-plugin-core#assetFavorite',
},
],
});
await expect(
ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id }),
).resolves.toBeUndefined();
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: true });
});
it('should not favorite asset if it has orientation', async () => {
const { user } = await ctx.newUser();
const { asset } = await ctx.newAsset({ ownerId: user.id, type: AssetType.Video });
await ctx.newExif({ assetId: asset.id, orientation: '2' });
const workflow = await createWorkflow({
ownerId: user.id,
trigger: WorkflowTrigger.AssetMetadataExtraction,
steps: [
{
method: 'immich-plugin-core#assetExifFilter',
config: { property: 'orientation', matchType: 'missing' },
},
{
method: 'immich-plugin-core#assetFavorite',
},
],
});
await expect(
ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id }),
).resolves.toBeUndefined();
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: false });
});
});
describe('present', () => {
it('should favorite asset if it has orientation', async () => {
const { user } = await ctx.newUser();
const { asset } = await ctx.newAsset({ ownerId: user.id, type: AssetType.Video });
await ctx.newExif({ assetId: asset.id, orientation: '2' });
const workflow = await createWorkflow({
ownerId: user.id,
trigger: WorkflowTrigger.AssetMetadataExtraction,
steps: [
{
method: 'immich-plugin-core#assetExifFilter',
config: { property: 'orientation', matchType: 'present' },
},
{
method: 'immich-plugin-core#assetFavorite',
},
],
});
await expect(
ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id }),
).resolves.toBeUndefined();
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: true });
});
it('should not favorite asset if it has no orientation', async () => {
const { user } = await ctx.newUser();
const { asset } = await ctx.newAsset({ ownerId: user.id, type: AssetType.Video });
await ctx.newExif({ assetId: asset.id, orientation: null });
const workflow = await createWorkflow({
ownerId: user.id,
trigger: WorkflowTrigger.AssetMetadataExtraction,
steps: [
{
method: 'immich-plugin-core#assetExifFilter',
config: { property: 'orientation', matchType: 'present' },
},
{
method: 'immich-plugin-core#assetFavorite',
},
],
});
await expect(
ctx.sut.handleAssetTrigger({ workflowId: workflow.id, assetId: asset.id }),
).resolves.toBeUndefined();
await expect(ctx.get(AssetRepository).getById(asset.id)).resolves.toMatchObject({ isFavorite: false });
});
});
});
describe('assetDateFilter', () => {
it('should favorite assets created during the first 7 days of a specific year and month', async () => {
const { user } = await ctx.newUser();