Skip to content

Commit

Permalink
Add image url utilities
Browse files Browse the repository at this point in the history
  • Loading branch information
thornbill committed Nov 14, 2023
1 parent 2ee68a2 commit 0f20452
Show file tree
Hide file tree
Showing 5 changed files with 268 additions and 8 deletions.
15 changes: 11 additions & 4 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import { ImageType } from './generated-client/models/image-type';
import type { ClientInfo, DeviceInfo } from './models';
import type { ImageRequestParameters } from './models/api/image-request-parameters';
import { getAuthorizationHeader } from './utils';
import { getImageApi } from './utils/api/image-api';
// NOTE: This import is used for TSDoc
// eslint-disable-next-line @typescript-eslint/no-unused-vars
import type { ImageUrlsApi } from './utils/api/image-urls-api';
import { getSessionApi } from './utils/api/session-api';
import { getUserApi } from './utils/api/user-api';

Expand Down Expand Up @@ -78,6 +82,7 @@ export class Api {

/**
* Get an item image URL.
* @deprecated Use {@link ImageUrlsApi.getItemImageUrlById} instead.
* @param itemId The Item ID.
* @param imageType An optional Image Type (Primary by default).
* @param params Additional request parameters.
Expand All @@ -88,10 +93,12 @@ export class Api {
imageType: ImageType = ImageType.Primary,
params: ImageRequestParameters = {}
): string | undefined {
// TODO: We could probably use ImageApiAxiosParamCreator to make this more robust
return globalInstance.create({
baseURL: this.basePath
}).getUri({ url: `/Items/${itemId}/Images/${imageType}`, params });
return getImageApi(this)
.getItemImageUrlById(
itemId,
imageType,
params
);
}

get authorizationHeader(): string {
Expand Down
114 changes: 114 additions & 0 deletions src/utils/api/__tests__/image-urls-api.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import { Configuration } from '../../../generated-client/configuration';
import { ImageType } from '../../../generated-client/models/image-type';
import { ImageUrlsApi } from '../image-urls-api';

const IMAGE_API = new ImageUrlsApi(new Configuration({ basePath: 'https://example.com' }));

/**
* ImageUrlsApi class tests.
*
* @group unit
*/
describe('ImageUrlsApi', () => {
it('`getItemImageUrlById` should return an item image url', () => {
// Id only
expect(IMAGE_API.getItemImageUrlById('TEST')).toBe('https://example.com/Items/TEST/Images/Primary');
// Id, ImageType, and Params
expect(IMAGE_API.getItemImageUrlById('TEST', ImageType.Backdrop, { fillWidth: 100, fillHeight: 100 }))
.toBe('https://example.com/Items/TEST/Images/Backdrop?fillWidth=100&fillHeight=100');
});

it('`getItemImageUrl` should return an item image url', () => {
// Empty item
expect(IMAGE_API.getItemImageUrl()).toBeUndefined();
expect(IMAGE_API.getItemImageUrl({})).toBeUndefined();
// Item with Id only
expect(IMAGE_API.getItemImageUrl({ Id: 'TEST' })).toBe('https://example.com/Items/TEST/Images/Primary');
// Item with Id and Tag
expect(IMAGE_API.getItemImageUrl({ Id: 'TEST', ImageTags: { [ImageType.Primary]: 'foo' } }))
.toBe('https://example.com/Items/TEST/Images/Primary?tag=foo');
// Item with Id, ImageType, and Params
expect(IMAGE_API.getItemImageUrl(
{ Id: 'TEST' },
ImageType.Backdrop,
{ fillWidth: 100, fillHeight: 100, tag: 'foo' })
).toBe('https://example.com/Items/TEST/Images/Backdrop?fillWidth=100&fillHeight=100&tag=foo');
});

it('`getItemBackdropImageUrls` should return an array of image urls', () => {
// No Item
expect(IMAGE_API.getItemBackdropImageUrls()).toHaveLength(0);
// Item with Id only
expect(IMAGE_API.getItemBackdropImageUrls({ Id: 'TEST' })).toHaveLength(0);
// Item with Id and ParentBackdropItemId
expect(IMAGE_API.getItemBackdropImageUrls({
Id: 'TEST',
ParentBackdropItemId: 'PARENT'
})).toHaveLength(0);
// Item with Id and BackdropImageTags
let backdropUrls = IMAGE_API.getItemBackdropImageUrls({
Id: 'TEST',
BackdropImageTags: [ 'tag1', 'tag2' ]
});
expect(backdropUrls).toHaveLength(2);
expect(backdropUrls[0]).toBe('https://example.com/Items/TEST/Images/Backdrop?tag=tag1');
expect(backdropUrls[1]).toBe('https://example.com/Items/TEST/Images/Backdrop?tag=tag2');
// TODO: Item with Id, ParentBackdropItemId, and ParentBackdropImageTags
backdropUrls = IMAGE_API.getItemBackdropImageUrls({
Id: 'TEST',
ParentBackdropItemId: 'PARENT',
ParentBackdropImageTags: [ 'parent1', 'parent2', 'parent3' ]
});
expect(backdropUrls).toHaveLength(3);
expect(backdropUrls[0]).toBe('https://example.com/Items/PARENT/Images/Backdrop?tag=parent1');
expect(backdropUrls[1]).toBe('https://example.com/Items/PARENT/Images/Backdrop?tag=parent2');
expect(backdropUrls[1]).toBe('https://example.com/Items/PARENT/Images/Backdrop?tag=parent2');
});

it('`getSplashscreenImageUrl` should return an image url', () => {
// No Params
expect(IMAGE_API.getSplashscreenImageUrl()).toBe('https://example.com/Branding/Splashscreen');
// Params
expect(IMAGE_API.getSplashscreenImageUrl({ fillWidth: 100, fillHeight: 100 }))
.toBe('https://example.com/Branding/Splashscreen?fillWidth=100&fillHeight=100');
});

it('`getUserImageUrl` should return a user image url', () => {
// No User
expect(IMAGE_API.getUserImageUrl()).toBeUndefined();
// User with Id
expect(IMAGE_API.getUserImageUrl({ Id: 'TEST' })).toBe('https://example.com/Users/TEST/Images/Primary');
// User with Id and Tag
expect(IMAGE_API.getUserImageUrl({ Id: 'TEST', PrimaryImageTag: 'foo' }))
.toBe('https://example.com/Users/TEST/Images/Primary?tag=foo');
// User with Id and Tag and Params
expect(IMAGE_API.getUserImageUrl({ Id: 'TEST', PrimaryImageTag: 'foo' }, { fillWidth: 100, fillHeight: 100 }))
.toBe('https://example.com/Users/TEST/Images/Primary?fillWidth=100&fillHeight=100&tag=foo');
});

it('should return relative paths when no basePath is configured', () => {
const relativeImageApi = new ImageUrlsApi();
// getItemImageUrlById
expect(relativeImageApi.getItemImageUrlById('TEST')).toBe('/Items/TEST/Images/Primary');
// getItemImageUrl
expect(relativeImageApi.getItemImageUrl({ Id: 'TEST' })).toBe('/Items/TEST/Images/Primary');
// getItemBackdropImageUrls
const backdropUrls = relativeImageApi.getItemBackdropImageUrls({
Id: 'TEST',
BackdropImageTags: [ 'tag1', 'tag2' ]
});
expect(backdropUrls).toHaveLength(2);
expect(backdropUrls[0]).toBe('/Items/TEST/Images/Backdrop?tag=tag1');
expect(backdropUrls[1]).toBe('/Items/TEST/Images/Backdrop?tag=tag2');
// getSplashscreenImageUrl
expect(relativeImageApi.getSplashscreenImageUrl()).toBe('/Branding/Splashscreen');
// getUserImageUrl
expect(relativeImageApi.getUserImageUrl({ Id: 'TEST' })).toBe('/Users/TEST/Images/Primary');
});
});
7 changes: 4 additions & 3 deletions src/utils/api/image-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
*/

import type { Api } from '../../api';
import { ImageApi } from '../../generated-client/api/image-api';

export function getImageApi(api: Api): ImageApi {
return new ImageApi(api.configuration, undefined, api.axiosInstance);
import { ImageUrlsApi } from './image-urls-api';

export function getImageApi(api: Api): ImageUrlsApi {
return new ImageUrlsApi(api.configuration, undefined, api.axiosInstance);
}
138 changes: 138 additions & 0 deletions src/utils/api/image-urls-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

import type { ImageApiGetSplashscreenRequest } from '../../generated-client/api/image-api';
import { ImageApi } from '../../generated-client/api/image-api';
import type { BaseItemDto } from '../../generated-client/models/base-item-dto';
import { ImageType } from '../../generated-client/models/image-type';
import type { UserDto } from '../../generated-client/models/user-dto';
import type { ImageRequestParameters } from '../../models/api/image-request-parameters';

/**
* ImageUrlsApi - ImageApi with URL utility methods
* @export
* @class ImageUrlsApi
* @extends {ImageApi}
*/
export class ImageUrlsApi extends ImageApi {
/**
* Get an Item image URL for a given Item ID.
* @param itemId The Item ID.
* @param [imageType=ImageType.Primary] An optional Image Type.
* @param [params={}] Additional request parameters.
* @returns The image URL.
*/
public getItemImageUrlById(
itemId: string,
imageType: ImageType = ImageType.Primary,
params: ImageRequestParameters = {}
): string {
// TODO: We could probably use ImageApiAxiosParamCreator to make this more robust
return this.axios.getUri({
baseURL: this.configuration?.basePath,
url: `/Items/${itemId}/Images/${imageType}`,
params
});
}

/**
* Get an Item image URL with automatic `tag` param handling.
* @param item The Item.
* @param [imageType] An optional Image Type (Primary by default).
* @param [params={}] Additional request parameters.
* @returns The Item image URL.
*/
public getItemImageUrl(item?: BaseItemDto, imageType: ImageType = ImageType.Primary, params: ImageRequestParameters = {}): string | undefined {
if (!item?.Id) return;

return this.getItemImageUrlById(
item.Id,
imageType,
{
...params,
tag: params.tag ?? item.ImageTags?.[imageType]
}
);
}

/**
* Get an Item's backdrop image URLs.
* @param item The Item.
* @param [params={}] Additional request parameters.
* @returns An array of backdrop image URLs.
*/
public getItemBackdropImageUrls(item?: BaseItemDto, params: ImageRequestParameters = {}): string[] {
const urls: string[] = [];
const id = item?.Id;

if (!id) return urls;

item.BackdropImageTags?.forEach(tag => {
const url = this.getItemImageUrlById(
id,
ImageType.Backdrop,
{
...params,
tag
}
);

urls.push(url);
});

if (urls.length > 0) return urls;

const parentId = item.ParentBackdropItemId;
if (parentId) {
item.ParentBackdropImageTags?.forEach(tag => {
const url = this.getItemImageUrlById(
parentId,
ImageType.Backdrop,
{
...params,
tag
}
);

urls.push(url);
});
}

return urls;
}

/**
* Get the splash screen image URL.
* @param [params={}] Additional request parameters.
* @returns The splash screen image URL.
*/
public getSplashscreenImageUrl(params: ImageApiGetSplashscreenRequest = {}): string {
return this.axios.getUri({
baseURL: this.configuration?.basePath,
url: '/Branding/Splashscreen',
params
});
}

/**
* Get a User's primary image URL.
* @param user The User.
* @param [params={}] Additional request parameters.
* @returns The User's primary image URL.
*/
public getUserImageUrl(user?: UserDto, params: ImageRequestParameters = {}): string | undefined {
if (!user?.Id) return;

return this.axios.getUri({
baseURL: this.configuration?.basePath,
url: `/Users/${user.Id}/Images/Primary`,
params: {
...params,
tag: user.PrimaryImageTag
}
});
}
}
2 changes: 1 addition & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@

export * from './address-candidates';
export * from './authentication';
export * from './url';
export * from './browser-profiles';
export * from './url';
export * from './versioning';

0 comments on commit 0f20452

Please sign in to comment.