chore: Migrate from @lit-labs/task to @lit/task (#2704)

- Closes: #2703
This commit is contained in:
Dermot Duffy
2026-08-22 14:15:07 -07:00
committed by GitHub
parent 0aebf3c484
commit 60e01cf537
8 changed files with 61 additions and 37 deletions
+1 -1
View File
@@ -22,7 +22,7 @@
"@egjs/hammerjs": "^2.0.17",
"@graphiteds/core": "^1.9.21",
"@lit-labs/scoped-registry-mixin": "^1.0.3",
"@lit-labs/task": "^1.1.3",
"@lit/task": "^1.0.3",
"@use-gesture/vanilla": "^10.3.1",
"any-date-parser": "^2.2.0",
"component-emitter": "^1.3.1",
+1 -1
View File
@@ -1,4 +1,4 @@
import { Task } from '@lit-labs/task';
import { Task } from '@lit/task';
import {
html,
LitElement,
@@ -1,4 +1,4 @@
import { TaskStatus, type Task } from '@lit-labs/task';
import { TaskStatus, type Task } from '@lit/task';
import {
html,
LitElement,
+2 -2
View File
@@ -1,4 +1,4 @@
import type { Task } from '@lit-labs/task';
import type { Task } from '@lit/task';
import { html, type TemplateResult } from 'lit';
import { renderProgressIndicator } from '../components/progress-indicator';
@@ -14,7 +14,7 @@ import { errorToConsole } from './basic';
* @returns A template.
*/
export const renderTask = <R>(
task: Task<unknown[], R>,
task: Task<readonly unknown[], R>,
completeFunc: (result: R) => TemplateResult | void,
options?: {
cardWideConfig?: CardWideConfig;
+1 -1
View File
@@ -1,4 +1,4 @@
import { Task } from '@lit-labs/task';
import { Task } from '@lit/task';
import type { ReactiveControllerHost } from 'lit';
import type { HomeAssistant } from '../ha/types';
+1 -1
View File
@@ -1,4 +1,4 @@
import type { Task } from '@lit-labs/task';
import type { Task } from '@lit/task';
import { html, render, type TemplateResult } from 'lit';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { mock } from 'vitest-mock-extended';
+47 -14
View File
@@ -1,12 +1,30 @@
import { Task } from '@lit-labs/task';
import { Task, type TaskConfig, type TaskFunctionOptions } from '@lit/task';
import type { ReactiveControllerHost } from 'lit';
import { afterEach, assert, describe, expect, it, vi } from 'vitest';
import { mock } from 'vitest-mock-extended';
import { createFetchThumbnailTask } from '../../src/utils/thumbnail';
import {
createFetchThumbnailTask,
type FetchThumbnailTaskArgs,
} from '../../src/utils/thumbnail';
import { createHASS, flushPromises } from '../test-utils';
vi.mock('@lit-labs/task');
vi.mock('@lit/task');
// The Task constructor accepts either (host, config) or (host, taskFunction,
// argsFunction). When the tests read the constructor arguments back from the
// mock, TypeScript types them using only the last of those overloads, so the
// second argument appears to be a task function even though
// createFetchThumbnailTask always passes a config object. This check narrows it
// back to the config type.
const isTaskConfig = (
value: unknown,
): value is TaskConfig<FetchThumbnailTaskArgs, string | null> =>
typeof value === 'object' && value !== null && 'task' in value;
const createTaskFunctionOptions = (): TaskFunctionOptions => ({
signal: new AbortController().signal,
});
describe('thumbnail utilities', () => {
afterEach(() => {
@@ -28,7 +46,8 @@ describe('thumbnail utilities', () => {
assert(call);
const options = call[1];
const result = await options.task([true, thumbnailURL]);
assert(isTaskConfig(options));
const result = await options.task([true, thumbnailURL], createTaskFunctionOptions());
expect(result).toBe(thumbnailURL);
expect(hass.fetchWithAuth).not.toHaveBeenCalled();
@@ -48,7 +67,8 @@ describe('thumbnail utilities', () => {
assert(call);
const options = call[1];
const result = await options.task([true, thumbnailURL]);
assert(isTaskConfig(options));
const result = await options.task([true, thumbnailURL], createTaskFunctionOptions());
expect(result).toBe(thumbnailURL);
});
@@ -88,7 +108,8 @@ describe('thumbnail utilities', () => {
assert(call);
const options = call[1];
const runPromise = options.task([true, thumbnailURL]);
assert(isTaskConfig(options));
const runPromise = options.task([true, thumbnailURL], createTaskFunctionOptions());
await flushPromises();
mockFileReader.onload?.(mock<ProgressEvent<FileReader>>());
@@ -117,7 +138,10 @@ describe('thumbnail utilities', () => {
assert(call);
const options = call[1];
await expect(options.task([true, thumbnailURL])).rejects.toThrow('Not Found');
assert(isTaskConfig(options));
await expect(
options.task([true, thumbnailURL], createTaskFunctionOptions()),
).rejects.toThrow('Not Found');
});
it('should handle reader error', async () => {
@@ -147,7 +171,8 @@ describe('thumbnail utilities', () => {
assert(call);
const options = call[1];
const runPromise = options.task([true, thumbnailURL]);
assert(isTaskConfig(options));
const runPromise = options.task([true, thumbnailURL], createTaskFunctionOptions());
await flushPromises();
mockFileReader.onerror?.(
@@ -186,7 +211,8 @@ describe('thumbnail utilities', () => {
assert(call);
const options = call[1];
const runPromise = options.task([true, thumbnailURL]);
assert(isTaskConfig(options));
const runPromise = options.task([true, thumbnailURL], createTaskFunctionOptions());
await flushPromises();
mockFileReader.onload?.(mock<ProgressEvent<FileReader>>());
@@ -206,7 +232,8 @@ describe('thumbnail utilities', () => {
assert(call);
const options = call[1];
const result = await options.task([false, undefined]);
assert(isTaskConfig(options));
const result = await options.task([false, undefined], createTaskFunctionOptions());
expect(result).toBeNull();
});
@@ -221,9 +248,12 @@ describe('thumbnail utilities', () => {
() => thumbnailURL,
);
const call = vi.mocked(Task).mock.calls[0];
assert(call && call[1].args);
assert(call);
const args = call[1].args();
const options = call[1];
assert(isTaskConfig(options) && options.args);
const args = options.args();
expect(args).toEqual([true, thumbnailURL]);
vi.mocked(Task).mockClear();
@@ -234,9 +264,12 @@ describe('thumbnail utilities', () => {
() => undefined,
);
const call2 = vi.mocked(Task).mock.calls[0];
assert(call2 && call2[1].args);
assert(call2);
const args2 = call2[1].args();
const options2 = call2[1];
assert(isTaskConfig(options2) && options2.args);
const args2 = options2.args();
expect(args2).toEqual([false, undefined]);
});
});
+7 -16
View File
@@ -648,22 +648,13 @@ __metadata:
languageName: node
linkType: hard
"@lit-labs/ssr-dom-shim@npm:^1.0.0, @lit-labs/ssr-dom-shim@npm:^1.2.0":
"@lit-labs/ssr-dom-shim@npm:^1.2.0":
version: 1.2.0
resolution: "@lit-labs/ssr-dom-shim@npm:1.2.0"
checksum: 10c0/016168cf6901ab343462c13fb168dda6d549f8b42680aa394e6b7cd0af7cce51271e00dbfa5bbbe388912bf89cbb8f941a21cc3ec9bf95d6a84b6241aa9e5a72
languageName: node
linkType: hard
"@lit-labs/task@npm:^1.1.3":
version: 1.1.3
resolution: "@lit-labs/task@npm:1.1.3"
dependencies:
"@lit/reactive-element": "npm:^1.1.0"
checksum: 10c0/bea28fbd87a486a06d4f2f51ba63db27419e659a97e723dc6c0009375262fb0f526a7436273589830fdf42dc1117f7aec372c5bf975c6adfca69cf64eaeecfd0
languageName: node
linkType: hard
"@lit/reactive-element@npm:^1.0.0 || ^2.0.0, @lit/reactive-element@npm:^2.0.4":
version: 2.0.4
resolution: "@lit/reactive-element@npm:2.0.4"
@@ -673,12 +664,12 @@ __metadata:
languageName: node
linkType: hard
"@lit/reactive-element@npm:^1.1.0":
version: 1.6.3
resolution: "@lit/reactive-element@npm:1.6.3"
"@lit/task@npm:^1.0.3":
version: 1.0.3
resolution: "@lit/task@npm:1.0.3"
dependencies:
"@lit-labs/ssr-dom-shim": "npm:^1.0.0"
checksum: 10c0/10f1d25e24e32feb21c4c6f9e11d062901241602e12c4ecf746b3138f87fed4d8394194645514d5c1bfd5f33f3fd56ee8ef41344e2cb4413c40fe4961ec9d419
"@lit/reactive-element": "npm:^1.0.0 || ^2.0.0"
checksum: 10c0/538ae891209bcfd6d0dcc20d2314b1233609d97caf59d3e3c69a7a83a7fa070f539d58ea903060b2bb3fd9cf3cab528acb3fcc258a6e2e5091aff1b6191ccabc
languageName: node
linkType: hard
@@ -2549,7 +2540,7 @@ __metadata:
"@graphiteds/core": "npm:^1.9.21"
"@ianvs/prettier-plugin-sort-imports": "npm:^4.7.1"
"@lit-labs/scoped-registry-mixin": "npm:^1.0.3"
"@lit-labs/task": "npm:^1.1.3"
"@lit/task": "npm:^1.0.3"
"@semantic-release/github": "npm:^10.3.3"
"@types/js-yaml": "npm:^4"
"@types/lodash-es": "npm:^4.17.12"