Files
sofarr/tests/unit/ombiHelpers.test.js
T
gronod 33b122d22b
Build and Push Docker Image / build (push) Successful in 1m46s
Licence Check / Licence compatibility and copyright header verification (push) Successful in 1m33s
CI / Security audit (push) Successful in 1m56s
CI / Swagger Validation & Coverage (push) Successful in 2m35s
CI / Tests & coverage (push) Successful in 2m51s
fix(ombi): resolve TV request status, user, and date display (Issue #53)
Ombi's TV API nests all request data (requestedUser, approved, available,
denied, requested, requestedDate) inside childRequests[] sub-objects.
The application previously only inspected top-level properties, causing
TV shows to consistently display 'unknown' status, 'unknown' user, and
no request date.

Changes:
- OmbiRetriever._hydrateRequest(): hydrate requestedUser on each
  childRequests entry and promote requestedDate to top level
- getRequestStatus() (server + client): aggregate status flags from
  childRequests[] when top-level properties are absent
- Client date display: fallback to childRequests[0].requestedDate
- Add 18 unit tests covering childRequests hydration, status
  aggregation, and date promotion

Closes #53
2026-05-27 21:13:17 +01:00

202 lines
6.9 KiB
JavaScript

// Copyright (c) 2026 Gordon Bolton. MIT License.
import { describe, it, expect } from 'vitest';
const {
extractRequestedUser,
filterRequestsByUser
} = require('../../server/utils/ombiHelpers');
describe('ombiHelpers', () => {
describe('extractRequestedUser', () => {
it('returns empty string if request is null or undefined', () => {
expect(extractRequestedUser(null)).toBe('');
expect(extractRequestedUser(undefined)).toBe('');
});
it('returns requestedUser if requestedUser is a string', () => {
const req = { requestedUser: 'testuser', requestedByAlias: 'alias' };
expect(extractRequestedUser(req)).toBe('testuser');
});
it('falls back to requestedByAlias if requestedUser is missing', () => {
const req = { requestedByAlias: 'aliasuser' };
expect(extractRequestedUser(req)).toBe('aliasuser');
});
it('returns alias from requestedUser object if present', () => {
const req = {
requestedUser: {
alias: 'alias_val',
userAlias: 'userAlias_val',
userName: 'userName_val',
normalizedUserName: 'normalized_val'
}
};
expect(extractRequestedUser(req)).toBe('alias_val');
});
it('returns userAlias from requestedUser object if alias is missing', () => {
const req = {
requestedUser: {
userAlias: 'userAlias_val',
userName: 'userName_val',
normalizedUserName: 'normalized_val'
}
};
expect(extractRequestedUser(req)).toBe('userAlias_val');
});
it('returns userName from requestedUser object if alias/userAlias are missing', () => {
const req = {
requestedUser: {
userName: 'userName_val',
normalizedUserName: 'normalized_val'
}
};
expect(extractRequestedUser(req)).toBe('userName_val');
});
it('returns normalizedUserName from requestedUser object if other fields are missing', () => {
const req = {
requestedUser: {
normalizedUserName: 'normalized_val'
}
};
expect(extractRequestedUser(req)).toBe('normalized_val');
});
it('falls back to requestedByAlias when requestedUser is empty object {} (bug fix)', () => {
const req = {
requestedUser: {},
requestedByAlias: 'fallback_alias'
};
expect(extractRequestedUser(req)).toBe('fallback_alias');
});
it('returns empty string if requestedUser is empty object {} and requestedByAlias is missing', () => {
const req = {
requestedUser: {}
};
expect(extractRequestedUser(req)).toBe('');
});
it('returns userName from nested user object', () => {
const req = { user: { userName: 'user_val' } };
expect(extractRequestedUser(req)).toBe('user_val');
});
it('returns alias from nested requestedBy object', () => {
const req = { requestedBy: { alias: 'req_alias' } };
expect(extractRequestedUser(req)).toBe('req_alias');
});
it('returns normalizedUserName from nested ombiUser object', () => {
const req = { ombiUser: { normalizedUserName: 'norm_ombi' } };
expect(extractRequestedUser(req)).toBe('norm_ombi');
});
it('returns userAlias from nested requestedByUser object', () => {
const req = { requestedByUser: { userAlias: 'alias_user' } };
expect(extractRequestedUser(req)).toBe('alias_user');
});
it('returns username from a string source value', () => {
const req = { requestedBy: 'direct_string' };
expect(extractRequestedUser(req)).toBe('direct_string');
});
it('returns username from root fallbacks (requestedByUsername, requester, requestedByEmail)', () => {
expect(extractRequestedUser({ requestedByUsername: 'user_uname' })).toBe('user_uname');
expect(extractRequestedUser({ requester: 'req_val' })).toBe('req_val');
expect(extractRequestedUser({ requestedByEmail: 'test@email.com' })).toBe('test@email.com');
});
it('recursively extracts user from seasons array requests', () => {
const req = {
seasons: [
{},
{ requestedUser: { alias: 'season_user' } }
]
};
expect(extractRequestedUser(req)).toBe('season_user');
});
it('recursively extracts user from childRequests array', () => {
const req = {
childRequests: [
{},
{ user: { userName: 'child_user' } }
]
};
expect(extractRequestedUser(req)).toBe('child_user');
});
it('recursively extracts user from childRequests requestedUser object (hydrated TV)', () => {
const req = {
childRequests: [
{},
{ requestedUser: { userName: 'tv_user', alias: 'tv_alias' } }
]
};
expect(extractRequestedUser(req)).toBe('tv_alias');
});
it('recursively extracts user from childRequests requestedUser as string', () => {
const req = {
childRequests: [
{ requestedUser: 'string_user' }
]
};
expect(extractRequestedUser(req)).toBe('string_user');
});
it('extracts user from deeply nested childRequests with requestedByAlias fallback', () => {
const req = {
childRequests: [
{ requestedByAlias: 'deep_alias' }
]
};
expect(extractRequestedUser(req)).toBe('deep_alias');
});
});
describe('filterRequestsByUser', () => {
const movie1 = { id: 1, requestedUser: { userName: 'user1' }, type: 'movie' };
const movie2 = { id: 2, requestedUser: { userName: 'user2' }, type: 'movie' };
const tv1 = { id: 3, requestedUser: { alias: 'User1' }, type: 'tv' };
it('returns empty array if requests input is not an array', () => {
expect(filterRequestsByUser(null, 'user1', false)).toEqual([]);
expect(filterRequestsByUser({}, 'user1', false)).toEqual([]);
});
it('returns all requests unmodified if showAll is true', () => {
const requests = [movie1, movie2];
expect(filterRequestsByUser(requests, 'user1', true)).toEqual(requests);
});
it('returns all requests unmodified if username is falsy or missing', () => {
const requests = [movie1, movie2];
expect(filterRequestsByUser(requests, '', false)).toEqual(requests);
expect(filterRequestsByUser(requests, null, false)).toEqual(requests);
});
it('filters requests correctly for a specific user', () => {
const requests = [movie1, movie2, tv1];
const result = filterRequestsByUser(requests, 'user1', false);
expect(result).toHaveLength(2);
expect(result).toContainEqual(movie1);
expect(result).toContainEqual(tv1);
expect(result).not.toContainEqual(movie2);
});
it('performs case-insensitive filtering', () => {
const requests = [movie1, movie2, tv1];
const result = filterRequestsByUser(requests, 'USER1', false);
expect(result).toHaveLength(2);
expect(result).toContainEqual(movie1);
expect(result).toContainEqual(tv1);
});
});
});