fix: Preserve parsers/matches on folder navigation (#2249)
- Closes #2231
This commit is contained in:
@@ -2,7 +2,7 @@ import { ConditionState } from '../../conditions/types';
|
|||||||
import { FolderConfig, FolderType, folderTypeSchema } from '../../config/schema/folders';
|
import { FolderConfig, FolderType, folderTypeSchema } from '../../config/schema/folders';
|
||||||
import { HomeAssistant } from '../../ha/types';
|
import { HomeAssistant } from '../../ha/types';
|
||||||
import { Endpoint } from '../../types';
|
import { Endpoint } from '../../types';
|
||||||
import { ViewItem } from '../../view/item';
|
import { ViewFolder, ViewItem } from '../../view/item';
|
||||||
import { ViewItemCapabilities } from '../../view/types';
|
import { ViewItemCapabilities } from '../../view/types';
|
||||||
import { sortItems } from '../view/sort';
|
import { sortItems } from '../view/sort';
|
||||||
import { HAFoldersEngine } from './ha/engine';
|
import { HAFoldersEngine } from './ha/engine';
|
||||||
@@ -21,6 +21,18 @@ export class FoldersExecutor {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public generateChildFolderQuery(
|
||||||
|
query: FolderQuery,
|
||||||
|
folder: ViewFolder,
|
||||||
|
): FolderQuery | null {
|
||||||
|
return (
|
||||||
|
this._getFolderEngine(query.folder.type)?.generateChildFolderQuery(
|
||||||
|
query,
|
||||||
|
folder,
|
||||||
|
) ?? null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public async expandFolder(
|
public async expandFolder(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
query: FolderQuery,
|
query: FolderQuery,
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import {
|
|||||||
FolderConfig,
|
FolderConfig,
|
||||||
folderTypeSchema,
|
folderTypeSchema,
|
||||||
HA_MEDIA_SOURCE_ROOT,
|
HA_MEDIA_SOURCE_ROOT,
|
||||||
HAFolderConfig,
|
|
||||||
HAFolderPathComponent,
|
HAFolderPathComponent,
|
||||||
|
HAFolderConfig,
|
||||||
} from '../../../config/schema/folders';
|
} from '../../../config/schema/folders';
|
||||||
import { getViewItemsFromBrowseMediaArray } from '../../../ha/browse-media/browse-media-to-view-media';
|
import { getViewItemsFromBrowseMediaArray } from '../../../ha/browse-media/browse-media-to-view-media';
|
||||||
import { BrowseMediaViewFolder } from '../../../ha/browse-media/item';
|
import { BrowseMediaViewFolder } from '../../../ha/browse-media/item';
|
||||||
@@ -23,15 +23,15 @@ import {
|
|||||||
import { getMediaDownloadPath } from '../../../ha/download';
|
import { getMediaDownloadPath } from '../../../ha/download';
|
||||||
import { HomeAssistant } from '../../../ha/types';
|
import { HomeAssistant } from '../../../ha/types';
|
||||||
import { Endpoint } from '../../../types';
|
import { Endpoint } from '../../../types';
|
||||||
import { ViewItem } from '../../../view/item';
|
import { ViewFolder, ViewItem } from '../../../view/item';
|
||||||
import { ViewItemClassifier } from '../../../view/item-classifier';
|
import { ViewItemClassifier } from '../../../view/item-classifier';
|
||||||
import { ViewItemCapabilities } from '../../../view/types';
|
import { ViewItemCapabilities } from '../../../view/types';
|
||||||
import {
|
import {
|
||||||
DownloadHelpers,
|
DownloadHelpers,
|
||||||
EngineOptions,
|
EngineOptions,
|
||||||
FolderPathComponent,
|
|
||||||
FolderQuery,
|
FolderQuery,
|
||||||
FoldersEngine,
|
FoldersEngine,
|
||||||
|
FolderPathComponent,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import { MediaMatcher } from './media-matcher';
|
import { MediaMatcher } from './media-matcher';
|
||||||
import { MetadataGenerator } from './metadata-generator.js';
|
import { MetadataGenerator } from './metadata-generator.js';
|
||||||
@@ -96,7 +96,8 @@ export class HAFoldersEngine implements FoldersEngine {
|
|||||||
private getDefaultFolderPathComponents(
|
private getDefaultFolderPathComponents(
|
||||||
haFolderConfig?: HAFolderConfig,
|
haFolderConfig?: HAFolderConfig,
|
||||||
): NonEmptyTuple<FolderPathComponent> {
|
): NonEmptyTuple<FolderPathComponent> {
|
||||||
const shouldAddDefaultRoot = !haFolderConfig?.url && !haFolderConfig?.path?.[0]?.id;
|
const shouldAddDefaultRoot =
|
||||||
|
!haFolderConfig?.url && haFolderConfig?.path?.[0]?.id !== HA_MEDIA_SOURCE_ROOT;
|
||||||
|
|
||||||
const path: HAFolderPathComponent[] = [
|
const path: HAFolderPathComponent[] = [
|
||||||
...(shouldAddDefaultRoot ? [{ id: HA_MEDIA_SOURCE_ROOT }] : []),
|
...(shouldAddDefaultRoot ? [{ id: HA_MEDIA_SOURCE_ROOT }] : []),
|
||||||
@@ -190,4 +191,27 @@ export class HAFoldersEngine implements FoldersEngine {
|
|||||||
folder: query.folder,
|
folder: query.folder,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public generateChildFolderQuery(
|
||||||
|
query: FolderQuery,
|
||||||
|
folder: ViewFolder,
|
||||||
|
): FolderQuery | null {
|
||||||
|
const id = folder.getID();
|
||||||
|
if (query.folder.type !== folderTypeSchema.enum.ha || !id) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the full configured path to find parsers/matchers for this depth.
|
||||||
|
const fullPath = this.getDefaultFolderPathComponents(query.folder.ha);
|
||||||
|
const nextConfiguredComponent = fullPath[query.path.length];
|
||||||
|
|
||||||
|
// Use the configured component's parsers/matchers if available, otherwise
|
||||||
|
// just use the ID from the folder.
|
||||||
|
const ha = nextConfiguredComponent?.ha ?? { id };
|
||||||
|
|
||||||
|
return {
|
||||||
|
...query,
|
||||||
|
path: [...query.path, { folder, ha }],
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { ConditionState } from '../../conditions/types';
|
|||||||
import { FolderConfig, FolderConfigWithoutID } from '../../config/schema/folders';
|
import { FolderConfig, FolderConfigWithoutID } from '../../config/schema/folders';
|
||||||
import { localize } from '../../localize/localize';
|
import { localize } from '../../localize/localize';
|
||||||
import { Endpoint } from '../../types';
|
import { Endpoint } from '../../types';
|
||||||
import { ViewItem } from '../../view/item';
|
import { ViewFolder, ViewItem } from '../../view/item';
|
||||||
import { ViewItemCapabilities } from '../../view/types';
|
import { ViewItemCapabilities } from '../../view/types';
|
||||||
import { CardFoldersAPI } from '../types';
|
import { CardFoldersAPI } from '../types';
|
||||||
import { FoldersExecutor } from './executor';
|
import { FoldersExecutor } from './executor';
|
||||||
@@ -62,6 +62,13 @@ export class FoldersManager {
|
|||||||
return _folder ? this._executor.generateDefaultFolderQuery(_folder) : null;
|
return _folder ? this._executor.generateDefaultFolderQuery(_folder) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public generateChildFolderQuery(
|
||||||
|
query: FolderQuery,
|
||||||
|
folder: ViewFolder,
|
||||||
|
): FolderQuery | null {
|
||||||
|
return this._executor.generateChildFolderQuery(query, folder);
|
||||||
|
}
|
||||||
|
|
||||||
public async expandFolder(
|
public async expandFolder(
|
||||||
query: FolderQuery,
|
query: FolderQuery,
|
||||||
conditionState?: ConditionState,
|
conditionState?: ConditionState,
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ export interface DownloadHelpers {
|
|||||||
|
|
||||||
export interface FoldersEngine {
|
export interface FoldersEngine {
|
||||||
generateDefaultFolderQuery(folder: FolderConfig): FolderQuery | null;
|
generateDefaultFolderQuery(folder: FolderConfig): FolderQuery | null;
|
||||||
|
generateChildFolderQuery(query: FolderQuery, folder: ViewFolder): FolderQuery | null;
|
||||||
|
|
||||||
expandFolder(
|
expandFolder(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
query: FolderQuery,
|
query: FolderQuery,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { FoldersManager } from '../../card-controller/folders/manager';
|
||||||
import { ViewManagerInterface } from '../../card-controller/view/types';
|
import { ViewManagerInterface } from '../../card-controller/view/types';
|
||||||
import { THUMBNAIL_WIDTH_DEFAULT } from '../../config/schema/common/controls/thumbnails';
|
import { THUMBNAIL_WIDTH_DEFAULT } from '../../config/schema/common/controls/thumbnails';
|
||||||
import { MediaGalleryThumbnailsConfig } from '../../config/schema/media-gallery';
|
import { MediaGalleryThumbnailsConfig } from '../../config/schema/media-gallery';
|
||||||
@@ -43,6 +44,7 @@ export class FolderGalleryController {
|
|||||||
viewManager: ViewManagerInterface,
|
viewManager: ViewManagerInterface,
|
||||||
item: ViewItem,
|
item: ViewItem,
|
||||||
ev: Event,
|
ev: Event,
|
||||||
|
foldersManager?: FoldersManager,
|
||||||
): void {
|
): void {
|
||||||
stopEventFromActivatingCardWideActions(ev);
|
stopEventFromActivatingCardWideActions(ev);
|
||||||
|
|
||||||
@@ -64,16 +66,18 @@ export class FolderGalleryController {
|
|||||||
QueryClassifier.isFolderQuery(view.query)
|
QueryClassifier.isFolderQuery(view.query)
|
||||||
) {
|
) {
|
||||||
const rawQuery = view.query.getQuery();
|
const rawQuery = view.query.getQuery();
|
||||||
const id = item.getID();
|
if (!rawQuery || !foldersManager) {
|
||||||
if (!rawQuery || !id) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const newQuery = foldersManager.generateChildFolderQuery(rawQuery, item);
|
||||||
|
if (!newQuery) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
viewManager.setViewByParametersWithExistingQuery({
|
viewManager.setViewByParametersWithExistingQuery({
|
||||||
params: {
|
params: {
|
||||||
query: view.query.clone().setQuery({
|
query: view.query.clone().setQuery(newQuery),
|
||||||
folder: rawQuery.folder,
|
|
||||||
path: [...rawQuery.path, { folder: item }],
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import {
|
|||||||
} from 'lit';
|
} from 'lit';
|
||||||
import { customElement, property } from 'lit/decorators.js';
|
import { customElement, property } from 'lit/decorators.js';
|
||||||
import { classMap } from 'lit/directives/class-map.js';
|
import { classMap } from 'lit/directives/class-map.js';
|
||||||
|
import { FoldersManager } from '../../card-controller/folders/manager.js';
|
||||||
import { ViewItemManager } from '../../card-controller/view/item-manager.js';
|
import { ViewItemManager } from '../../card-controller/view/item-manager.js';
|
||||||
import { ViewManagerEpoch } from '../../card-controller/view/types.js';
|
import { ViewManagerEpoch } from '../../card-controller/view/types.js';
|
||||||
import {
|
import {
|
||||||
@@ -41,6 +42,9 @@ export class AdvancedCameraCardFolderGallery extends LitElement {
|
|||||||
@property({ attribute: false })
|
@property({ attribute: false })
|
||||||
public galleryConfig?: MediaGalleryConfig;
|
public galleryConfig?: MediaGalleryConfig;
|
||||||
|
|
||||||
|
@property({ attribute: false })
|
||||||
|
public foldersManager?: FoldersManager;
|
||||||
|
|
||||||
protected _controller = new FolderGalleryController(this);
|
protected _controller = new FolderGalleryController(this);
|
||||||
|
|
||||||
protected willUpdate(changedProps: PropertyValues): void {
|
protected willUpdate(changedProps: PropertyValues): void {
|
||||||
@@ -88,7 +92,7 @@ export class AdvancedCameraCardFolderGallery extends LitElement {
|
|||||||
this._renderThumbnail(item, item === selected, (item: ViewItem, ev: Event) => {
|
this._renderThumbnail(item, item === selected, (item: ViewItem, ev: Event) => {
|
||||||
const manager = this.viewManagerEpoch?.manager;
|
const manager = this.viewManagerEpoch?.manager;
|
||||||
if (manager) {
|
if (manager) {
|
||||||
this._controller.itemClickHandler(manager, item, ev);
|
this._controller.itemClickHandler(manager, item, ev, this.foldersManager);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -218,6 +218,7 @@ export class AdvancedCameraCardViews extends LitElement {
|
|||||||
.viewManagerEpoch=${this.viewManagerEpoch}
|
.viewManagerEpoch=${this.viewManagerEpoch}
|
||||||
.viewItemManager=${this.viewItemManager}
|
.viewItemManager=${this.viewItemManager}
|
||||||
.galleryConfig=${this.config.media_gallery}
|
.galleryConfig=${this.config.media_gallery}
|
||||||
|
.foldersManager=${this.foldersManager}
|
||||||
></advanced-camera-card-folder-gallery>`
|
></advanced-camera-card-folder-gallery>`
|
||||||
: ``}
|
: ``}
|
||||||
${
|
${
|
||||||
|
|||||||
@@ -130,6 +130,38 @@ describe('FoldersExecutor', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('generateChildFolderQuery', () => {
|
||||||
|
it('should generate child folder query', () => {
|
||||||
|
const folder: FolderConfig = createFolder();
|
||||||
|
const query: FolderQuery = {
|
||||||
|
folder,
|
||||||
|
path: [{ ha: { id: 'media-source://' } }],
|
||||||
|
};
|
||||||
|
const viewFolder = new ViewFolder(folder);
|
||||||
|
|
||||||
|
const haFolderEngine = mock<HAFoldersEngine>();
|
||||||
|
haFolderEngine.generateChildFolderQuery.mockReturnValue(query);
|
||||||
|
const executor = new FoldersExecutor({ ha: haFolderEngine });
|
||||||
|
|
||||||
|
expect(executor.generateChildFolderQuery(query, viewFolder)).toEqual(query);
|
||||||
|
expect(haFolderEngine.generateChildFolderQuery).toBeCalledWith(query, viewFolder);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return null for non-existent folder engine', () => {
|
||||||
|
const folder: FolderConfig = {
|
||||||
|
type: 'UNKNOWN',
|
||||||
|
} as unknown as FolderConfig;
|
||||||
|
const query: FolderQuery = {
|
||||||
|
folder,
|
||||||
|
path: [{ ha: { id: 'media-source://' } }],
|
||||||
|
};
|
||||||
|
const viewFolder = new ViewFolder(folder);
|
||||||
|
const executor = new FoldersExecutor();
|
||||||
|
|
||||||
|
expect(executor.generateChildFolderQuery(query, viewFolder)).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('expandFolder', () => {
|
describe('expandFolder', () => {
|
||||||
it('should reject folders of the wrong type', async () => {
|
it('should reject folders of the wrong type', async () => {
|
||||||
const query = {
|
const query = {
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ describe('HAFoldersEngine', () => {
|
|||||||
|
|
||||||
describe('should generate default folder query', () => {
|
describe('should generate default folder query', () => {
|
||||||
it('should generate default folder query', () => {
|
it('should generate default folder query', () => {
|
||||||
const folder: FolderConfig = { type: 'ha' };
|
const folder: FolderConfig = { type: 'ha', id: 'test' };
|
||||||
const engine = new HAFoldersEngine();
|
const engine = new HAFoldersEngine();
|
||||||
|
|
||||||
const query = engine.generateDefaultFolderQuery(folder);
|
const query = engine.generateDefaultFolderQuery(folder);
|
||||||
@@ -143,7 +143,7 @@ describe('HAFoldersEngine', () => {
|
|||||||
|
|
||||||
it('should expand folder with cache by default', async () => {
|
it('should expand folder with cache by default', async () => {
|
||||||
const query: FolderQuery = {
|
const query: FolderQuery = {
|
||||||
folder: { type: 'ha' },
|
folder: { type: 'ha', id: 'test' },
|
||||||
path: [{ ha: { id: 'media-source://id' } }],
|
path: [{ ha: { id: 'media-source://id' } }],
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ describe('HAFoldersEngine', () => {
|
|||||||
|
|
||||||
it('should expand folder without cache when requested', async () => {
|
it('should expand folder without cache when requested', async () => {
|
||||||
const query: FolderQuery = {
|
const query: FolderQuery = {
|
||||||
folder: { type: 'ha' },
|
folder: { type: 'ha', id: 'test' },
|
||||||
path: [{ ha: { id: 'media-source://id' } }],
|
path: [{ ha: { id: 'media-source://id' } }],
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -231,7 +231,7 @@ describe('HAFoldersEngine', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const query: FolderQuery = {
|
const query: FolderQuery = {
|
||||||
folder: { type: 'ha' },
|
folder: { type: 'ha', id: 'test' },
|
||||||
path: [
|
path: [
|
||||||
{
|
{
|
||||||
folder: new BrowseMediaViewFolder(createFolder(), browseMedia),
|
folder: new BrowseMediaViewFolder(createFolder(), browseMedia),
|
||||||
@@ -259,7 +259,7 @@ describe('HAFoldersEngine', () => {
|
|||||||
|
|
||||||
it('should not expand without a folder with an id', async () => {
|
it('should not expand without a folder with an id', async () => {
|
||||||
const query: FolderQuery = {
|
const query: FolderQuery = {
|
||||||
folder: { type: 'ha' },
|
folder: { type: 'ha', id: 'test' },
|
||||||
// There's no component in the query with an id to start from.
|
// There's no component in the query with an id to start from.
|
||||||
path: [{ ha: {} }],
|
path: [{ ha: {} }],
|
||||||
};
|
};
|
||||||
@@ -293,7 +293,7 @@ describe('HAFoldersEngine', () => {
|
|||||||
],
|
],
|
||||||
])('%s', async (_name: string, matcher: Matcher, expectedMatches: number) => {
|
])('%s', async (_name: string, matcher: Matcher, expectedMatches: number) => {
|
||||||
const query: FolderQuery = {
|
const query: FolderQuery = {
|
||||||
folder: { type: 'ha' },
|
folder: { type: 'ha', id: 'test' },
|
||||||
path: [{ ha: { id: 'media-source://' } }, { ha: { matchers: [matcher] } }, {}],
|
path: [{ ha: { id: 'media-source://' } }, { ha: { matchers: [matcher] } }, {}],
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -330,4 +330,80 @@ describe('HAFoldersEngine', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('generateChildFolderQuery', () => {
|
||||||
|
it('should return null if folder type is not ha', () => {
|
||||||
|
const engine = new HAFoldersEngine();
|
||||||
|
const query: FolderQuery = {
|
||||||
|
folder: { type: 'other' } as unknown as FolderConfig,
|
||||||
|
path: [{ ha: { id: 'root' } }],
|
||||||
|
};
|
||||||
|
const folder = new ViewFolder(createFolder());
|
||||||
|
|
||||||
|
expect(engine.generateChildFolderQuery(query, folder)).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return null if folder has no id', () => {
|
||||||
|
const engine = new HAFoldersEngine();
|
||||||
|
const query: FolderQuery = {
|
||||||
|
folder: { type: 'ha', id: 'test' },
|
||||||
|
path: [{ ha: { id: 'root' } }],
|
||||||
|
};
|
||||||
|
const folder = new ViewFolder(createFolder(), { id: '' });
|
||||||
|
|
||||||
|
expect(engine.generateChildFolderQuery(query, folder)).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should extend query with configured component', () => {
|
||||||
|
const engine = new HAFoldersEngine();
|
||||||
|
const folderConfig: FolderConfig = {
|
||||||
|
type: 'ha',
|
||||||
|
id: 'test',
|
||||||
|
ha: {
|
||||||
|
path: [{ id: 'child', matchers: [{ type: 'title', title: 'foo' }] }],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const query: FolderQuery = {
|
||||||
|
folder: folderConfig,
|
||||||
|
path: [{ ha: { id: 'media-source://' } }],
|
||||||
|
};
|
||||||
|
const folder = new ViewFolder(createFolder(), { id: 'child' });
|
||||||
|
|
||||||
|
const result = engine.generateChildFolderQuery(query, folder);
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
folder: folderConfig,
|
||||||
|
path: [
|
||||||
|
{ ha: { id: 'media-source://' } },
|
||||||
|
{
|
||||||
|
folder,
|
||||||
|
ha: { id: 'child', matchers: [{ type: 'title', title: 'foo' }] },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should extend query with default component when no configuration exists', () => {
|
||||||
|
const engine = new HAFoldersEngine();
|
||||||
|
const folderConfig: FolderConfig = { type: 'ha', id: 'test' };
|
||||||
|
const query: FolderQuery = {
|
||||||
|
folder: folderConfig,
|
||||||
|
path: [{ ha: { id: 'media-source://' } }],
|
||||||
|
};
|
||||||
|
const folder = new ViewFolder(createFolder(), { id: 'child' });
|
||||||
|
|
||||||
|
const result = engine.generateChildFolderQuery(query, folder);
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
folder: folderConfig,
|
||||||
|
path: [
|
||||||
|
{ ha: { id: 'media-source://' } },
|
||||||
|
{
|
||||||
|
folder,
|
||||||
|
ha: { id: 'child' },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import { FolderQuery } from '../../../src/card-controller/folders/types';
|
|||||||
import { FolderConfig, FolderConfigWithoutID } from '../../../src/config/schema/folders';
|
import { FolderConfig, FolderConfigWithoutID } from '../../../src/config/schema/folders';
|
||||||
import { ResolvedMediaCache } from '../../../src/ha/resolved-media';
|
import { ResolvedMediaCache } from '../../../src/ha/resolved-media';
|
||||||
import { Endpoint } from '../../../src/types';
|
import { Endpoint } from '../../../src/types';
|
||||||
|
import { ViewFolder } from '../../../src/view/item';
|
||||||
import { ViewItemCapabilities } from '../../../src/view/types';
|
import { ViewItemCapabilities } from '../../../src/view/types';
|
||||||
import {
|
import {
|
||||||
createCardAPI,
|
createCardAPI,
|
||||||
@@ -180,6 +181,25 @@ describe('FoldersManager', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('generateChildFolderQuery', () => {
|
||||||
|
it('should generate child folder query', () => {
|
||||||
|
const folder: FolderConfig = createFolder();
|
||||||
|
const query: FolderQuery = {
|
||||||
|
folder,
|
||||||
|
path: [{ ha: { id: 'media-source://' } }],
|
||||||
|
};
|
||||||
|
const viewFolder = new ViewFolder(folder);
|
||||||
|
|
||||||
|
const executor = mock<FoldersExecutor>();
|
||||||
|
vi.mocked(executor.generateChildFolderQuery).mockReturnValue(query);
|
||||||
|
|
||||||
|
const manager = new FoldersManager(createCardAPI(), executor);
|
||||||
|
|
||||||
|
expect(manager.generateChildFolderQuery(query, viewFolder)).toEqual(query);
|
||||||
|
expect(executor.generateChildFolderQuery).toBeCalledWith(query, viewFolder);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('should expand folder', () => {
|
describe('should expand folder', () => {
|
||||||
it('should expand folder with hass', async () => {
|
it('should expand folder with hass', async () => {
|
||||||
const hass = createHASS();
|
const hass = createHASS();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { describe, expect, it } from 'vitest';
|
import { describe, expect, it } from 'vitest';
|
||||||
import { mock } from 'vitest-mock-extended';
|
import { mock } from 'vitest-mock-extended';
|
||||||
import { ViewManagerInterface } from '../../../src/card-controller/view/types';
|
import { ViewManagerInterface } from '../../../src/card-controller/view/types';
|
||||||
|
import { FoldersManager } from '../../../src/card-controller/folders/manager';
|
||||||
import {
|
import {
|
||||||
FOLDER_GALLERY_THUMBNAIL_DETAILS_WIDTH_MIN,
|
FOLDER_GALLERY_THUMBNAIL_DETAILS_WIDTH_MIN,
|
||||||
FolderGalleryController,
|
FolderGalleryController,
|
||||||
@@ -168,7 +169,16 @@ describe('FolderGalleryController', () => {
|
|||||||
const viewManager = mock<ViewManagerInterface>();
|
const viewManager = mock<ViewManagerInterface>();
|
||||||
viewManager.getView.mockReturnValue(view);
|
viewManager.getView.mockReturnValue(view);
|
||||||
|
|
||||||
controller.itemClickHandler(viewManager, folderItem, event);
|
const foldersManager = mock<FoldersManager>();
|
||||||
|
foldersManager.generateChildFolderQuery.mockReturnValue({
|
||||||
|
folder,
|
||||||
|
path: [
|
||||||
|
{ ha: { id: 'grandparent' } },
|
||||||
|
{ folder: folderItem, ha: { id: 'parent' } },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
controller.itemClickHandler(viewManager, folderItem, event, foldersManager);
|
||||||
|
|
||||||
expect(viewManager.setViewByParametersWithExistingQuery).toHaveBeenCalledWith({
|
expect(viewManager.setViewByParametersWithExistingQuery).toHaveBeenCalledWith({
|
||||||
params: {
|
params: {
|
||||||
@@ -182,10 +192,41 @@ describe('FolderGalleryController', () => {
|
|||||||
expect(newQuery).toBeInstanceOf(FolderViewQuery);
|
expect(newQuery).toBeInstanceOf(FolderViewQuery);
|
||||||
expect(newQuery?.getQuery()).toEqual({
|
expect(newQuery?.getQuery()).toEqual({
|
||||||
folder,
|
folder,
|
||||||
path: [{ ha: { id: 'grandparent' } }, { folder: folderItem }],
|
path: [
|
||||||
|
{ ha: { id: 'grandparent' } },
|
||||||
|
{ folder: folderItem, ha: { id: 'parent' } },
|
||||||
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should ignore folder click without folders manager', () => {
|
||||||
|
const folder = createFolder();
|
||||||
|
const folderItem = new ViewFolder(folder, {
|
||||||
|
id: 'parent',
|
||||||
|
});
|
||||||
|
|
||||||
|
const controller = new FolderGalleryController(document.createElement('div'));
|
||||||
|
const event = new Event('click');
|
||||||
|
|
||||||
|
const view = createView({
|
||||||
|
queryResults: new QueryResults({
|
||||||
|
results: [new TestViewMedia(), folderItem],
|
||||||
|
selectedIndex: 0,
|
||||||
|
}),
|
||||||
|
query: new FolderViewQuery({
|
||||||
|
folder,
|
||||||
|
path: [{ ha: { id: 'grandparent' } }],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const viewManager = mock<ViewManagerInterface>();
|
||||||
|
viewManager.getView.mockReturnValue(view);
|
||||||
|
|
||||||
|
controller.itemClickHandler(viewManager, folderItem, event);
|
||||||
|
|
||||||
|
expect(viewManager.setViewByParametersWithExistingQuery).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle folder click without query', () => {
|
it('should handle folder click without query', () => {
|
||||||
const controller = new FolderGalleryController(document.createElement('div'));
|
const controller = new FolderGalleryController(document.createElement('div'));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user