* Add rspack

* Remove TransformAsyncModulesPlugin from rspack

* Migrate all webpack usage to rspack

* Migrate tests to vitest

* Fix test suites

* Remove chai dependency

* Fix compute_state_display tests

* Fix resolveTimeZone

* Reduces test pipeline

* Revert test ci

* optimize chunk filtering

* Migrate landing-page to rspack

* Update rspack dependencies

* Add rsdoctor

* Fix prod build bundle size

* Use rsdoctor for demo stats

* Remove unused webpack configs

* Update build-scripts/rspack.cjs

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>

* Fix eslint

* Update rspack

* Remove unused code

---------

Co-authored-by: Petar Petrov <MindFreeze@users.noreply.github.com>
This commit is contained in:
Wendelin
2024-11-26 14:49:13 +01:00
committed by GitHub
parent 09c5dab69f
commit bd0bfc1fbe
72 changed files with 2199 additions and 1232 deletions

View File

@ -1,7 +1,4 @@
{
"env": {
"mocha": true
},
"rules": {
"import/no-extraneous-dependencies": 0
}

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { atLeastVersion } from "../../../src/common/config/version";
const testTruthyData = [

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import checkValidDate from "../../../src/common/datetime/check_valid_date";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { formatDuration } from "../../../src/common/datetime/duration";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import durationToSeconds from "../../../src/common/datetime/duration_to_seconds";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { formatDate } from "../../../src/common/datetime/format_date";
import {

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import {
formatDateTime,

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import {
formatTime,

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import millisecondsToDuration from "../../../src/common/datetime/milliseconds_to_duration";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { relativeTime } from "../../../src/common/datetime/relative_time";
import {

View File

@ -0,0 +1,12 @@
import { expect, test } from "vitest";
import {
LOCAL_TIME_ZONE,
resolveTimeZone,
} from "../../../src/common/datetime/resolve-time-zone";
import { TimeZone } from "../../../src/data/translation";
test("resolveTimeZone", () => {
const serverTimeZone = "Vienna/Austria";
expect(resolveTimeZone(TimeZone.local, serverTimeZone)).toBe(LOCAL_TIME_ZONE);
expect(resolveTimeZone(TimeZone.server, serverTimeZone)).toBe(serverTimeZone);
});

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import secondsToDuration from "../../../src/common/datetime/seconds_to_duration";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { attributeClassNames } from "../../../src/common/entity/attribute_class_names";
describe("attributeClassNames", () => {

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { canToggleDomain } from "../../../src/common/entity/can_toggle_domain";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { canToggleState } from "../../../src/common/entity/can_toggle_state";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { computeDomain } from "../../../src/common/entity/compute_domain";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it, beforeEach } from "vitest";
import { computeStateDisplay } from "../../../src/common/entity/compute_state_display";
import { UNKNOWN } from "../../../src/data/entity";
import type { FrontendLocaleData } from "../../../src/data/translation";
@ -67,7 +67,7 @@ describe("computeStateDisplay", () => {
demoConfig,
{}
),
"component.binary_sensor.state.moisture.off"
"component.binary_sensor.entity_component.moisture.state.off"
);
});
@ -94,7 +94,7 @@ describe("computeStateDisplay", () => {
demoConfig,
{}
),
"component.binary_sensor.state.invalid_device_class.off"
"component.binary_sensor.entity_component.invalid_device_class.state.off"
);
});

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { computeStateDomain } from "../../../src/common/entity/compute_state_domain";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { generateFilter } from "../../../src/common/entity/entity_filter";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { DEFAULT_VIEW_ENTITY_ID } from "../../../src/common/const";
import { extractViews } from "../../../src/common/entity/extract_views";
import { createEntities, createView } from "./test_util";

View File

@ -1,7 +1,7 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import type { HassEntity } from "home-assistant-js-websocket";
import { featureClassNames } from "../../../src/common/entity/feature_class_names";
import { HassEntity } from "home-assistant-js-websocket";
describe("featureClassNames", () => {
const classNames = {

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { getGroupEntities } from "../../../src/common/entity/get_group_entities";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { getViewEntities } from "../../../src/common/entity/get_view_entities";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { hasLocation } from "../../../src/common/entity/has_location";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { splitByGroups } from "../../../src/common/entity/split_by_groups";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { stateCardType } from "../../../src/common/entity/state_card_type";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { stateMoreInfoType } from "../../../src/dialogs/more-info/state_more_info_control";

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it, beforeEach, afterEach } from "vitest";
import { useFakeTimers } from "sinon";
import { timerTimeRemaining } from "../../../src/data/timer";

View File

@ -1,5 +1,5 @@
import { assert } from "chai";
import { HassEntity } from "home-assistant-js-websocket";
import { assert, describe, it } from "vitest";
import type { HassEntity } from "home-assistant-js-websocket";
import {
formatNumber,
@ -7,7 +7,7 @@ import {
getNumberFormatOptions,
} from "../../../src/common/number/format_number";
import {
FrontendLocaleData,
type FrontendLocaleData,
NumberFormat,
TimeFormat,
FirstWeekday,
@ -157,7 +157,8 @@ describe("formatNumber", () => {
getNumberFormatOptions({
state: "3.0",
attributes: { step: 0.5 },
} as unknown as HassEntity)
} as unknown as HassEntity),
undefined
);
});

View File

@ -0,0 +1,12 @@
import { expect, test } from "vitest";
import { isDate } from "../../../src/common/string/is_date";
test("isDate", () => {
expect(isDate("ABC")).toBe(false);
expect(isDate("2021-02-03", false)).toBe(true);
expect(isDate("2021-02-03", true)).toBe(true);
expect(isDate("2021-05-25T19:23:52+00:00", true)).toBe(true);
expect(isDate("2021-05-25T19:23:52+00:00", false)).toBe(false);
});

View File

@ -1,12 +0,0 @@
import { assert } from "chai";
import { isDate } from "../../../src/common/string/is_date";
describe("isDate", () => {
assert.strictEqual(isDate("ABC"), false);
assert.strictEqual(isDate("2021-02-03", false), true);
assert.strictEqual(isDate("2021-02-03", true), true);
assert.strictEqual(isDate("2021-05-25T19:23:52+00:00", true), true);
assert.strictEqual(isDate("2021-05-25T19:23:52+00:00", false), false);
});

View File

@ -1,9 +1,9 @@
import { assert } from "chai";
import { describe, assert, it } from "vitest";
import {
fuzzyFilterSort,
fuzzySequentialMatch,
ScorableTextItem,
type ScorableTextItem,
} from "../../../src/common/string/filter/sequence-matching";
describe("fuzzySequentialMatch", () => {

View File

@ -0,0 +1,37 @@
import { assert, describe, it } from "vitest";
import { slugify } from "../../../src/common/string/slugify";
describe("slugify", () => {
it("works", () => {
// With default delimiter
assert.strictEqual(slugify("abc"), "abc");
assert.strictEqual(slugify("ABC"), "abc");
assert.strictEqual(slugify("abc DEF"), "abc_def");
assert.strictEqual(slugify("abc.DEF"), "abc_def");
assert.strictEqual(
slugify("1`-=~!@#$%^&*()_+[];',./{}:\"<>?\\| aA"),
"1_aa"
);
assert.strictEqual(slugify("abc-DEF"), "abc_def");
assert.strictEqual(slugify("abc_DEF"), "abc_def");
assert.strictEqual(slugify("1,1"), "11");
assert.strictEqual(slugify("abc å DEF"), "abc_a_def");
assert.strictEqual(slugify("abc:DEF"), "abc_def");
assert.strictEqual(slugify("abc&DEF"), "abc_def");
assert.strictEqual(slugify("abc^^DEF"), "abc_def");
assert.strictEqual(slugify("abc DEF"), "abc_def");
assert.strictEqual(slugify("_abc DEF"), "abc_def");
assert.strictEqual(slugify("abc DEF_"), "abc_def");
assert.strictEqual(slugify("abc-DEF ghi"), "abc_def_ghi");
assert.strictEqual(slugify("abc-DEF-ghi"), "abc_def_ghi");
assert.strictEqual(slugify("abc - DEF - ghi"), "abc_def_ghi");
assert.strictEqual(slugify("abc---DEF---ghi"), "abc_def_ghi");
assert.strictEqual(slugify("___abc___DEF___ghi___"), "abc_def_ghi");
assert.strictEqual(slugify("___"), "unknown");
assert.strictEqual(slugify(""), "");
// With custom delimiter
assert.strictEqual(slugify("abc def", "-"), "abc-def");
assert.strictEqual(slugify("abc-def", "-"), "abc-def");
});
});

View File

@ -1,32 +0,0 @@
import { assert } from "chai";
import { slugify } from "../../../src/common/string/slugify";
describe("slugify", () => {
// With default delimiter
assert.strictEqual(slugify("abc"), "abc");
assert.strictEqual(slugify("ABC"), "abc");
assert.strictEqual(slugify("abc DEF"), "abc_def");
assert.strictEqual(slugify("abc.DEF"), "abc_def");
assert.strictEqual(slugify("1`-=~!@#$%^&*()_+[];',./{}:\"<>?\\| aA"), "1_aa");
assert.strictEqual(slugify("abc-DEF"), "abc_def");
assert.strictEqual(slugify("abc_DEF"), "abc_def");
assert.strictEqual(slugify("1,1"), "11");
assert.strictEqual(slugify("abc å DEF"), "abc_a_def");
assert.strictEqual(slugify("abc:DEF"), "abc_def");
assert.strictEqual(slugify("abc&DEF"), "abc_def");
assert.strictEqual(slugify("abc^^DEF"), "abc_def");
assert.strictEqual(slugify("abc DEF"), "abc_def");
assert.strictEqual(slugify("_abc DEF"), "abc_def");
assert.strictEqual(slugify("abc DEF_"), "abc_def");
assert.strictEqual(slugify("abc-DEF ghi"), "abc_def_ghi");
assert.strictEqual(slugify("abc-DEF-ghi"), "abc_def_ghi");
assert.strictEqual(slugify("abc - DEF - ghi"), "abc_def_ghi");
assert.strictEqual(slugify("abc---DEF---ghi"), "abc_def_ghi");
assert.strictEqual(slugify("___abc___DEF___ghi___"), "abc_def_ghi");
assert.strictEqual(slugify("___"), "unknown");
assert.strictEqual(slugify(""), "");
// With custom delimiter
assert.strictEqual(slugify("abc def", "-"), "abc-def");
assert.strictEqual(slugify("abc-def", "-"), "abc-def");
});

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import parseAspectRatio from "../../../src/common/util/parse-aspect-ratio";

View File

@ -1,8 +1,8 @@
import { assert } from "chai";
import { assert, describe, it, beforeEach } from "vitest";
import {
ExternalMessaging,
EMMessage,
type EMMessage,
} from "../../src/external_app/external_messaging";
// @ts-ignore
@ -46,7 +46,7 @@ describe("ExternalMessaging", () => {
const result = await sendMessageProm;
assert.deepEqual(result, {
hello: "world",
});
} as any);
});
it("Send fail results", async () => {

View File

@ -1,15 +1,15 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { createHassioSession } from "../../src/data/hassio/ingress";
describe("Create hassio session", function () {
describe("Create hassio session", () => {
const hass = {
config: { version: "1.0.0" },
callApi: async function () {
return { data: { session: "fhdsu73rh3io4h8f3irhjel8ousafehf8f3yh" } };
},
callApi: async () => ({
data: { session: "fhdsu73rh3io4h8f3irhjel8ousafehf8f3yh" },
}),
};
it("Test create session without HTTPS", async function () {
it("Test create session without HTTPS", async () => {
// @ts-ignore
global.document = {};
// @ts-ignore
@ -22,7 +22,7 @@ describe("Create hassio session", function () {
"ingress_session=fhdsu73rh3io4h8f3irhjel8ousafehf8f3yh;path=/api/hassio_ingress/;SameSite=Strict"
);
});
it("Test create session with HTTPS", async function () {
it("Test create session with HTTPS", async () => {
// @ts-ignore
global.document = {};
// @ts-ignore
@ -41,10 +41,10 @@ describe("Create hassio session", function () {
// @ts-ignore
global.location = {};
});
it("Test fail to create", async function () {
it("Test fail to create", async () => {
const createSessionPromise = createHassioSession({
// @ts-ignore
callApi: async function () {
callApi: async () => {
// noop
},
}).then(

View File

@ -1,6 +1,6 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { LovelaceConfig } from "../../../../src/data/lovelace/config/types";
import type { LovelaceConfig } from "../../../../src/data/lovelace/config/types";
import {
moveCardToContainer,
swapView,

View File

@ -1,15 +0,0 @@
const fs = require("fs");
const path = require("path");
process.env.TZ = "Etc/UTC";
process.env.IS_TEST = "true";
global.window = {};
global.navigator = {};
const MDI_OUTPUT_DIR = path.resolve(__dirname, "../build/mdi");
if (!fs.existsSync(MDI_OUTPUT_DIR)) {
fs.mkdirSync(MDI_OUTPUT_DIR, { recursive: true });
fs.writeFileSync(path.resolve(MDI_OUTPUT_DIR, "iconMetadata.json"), "{}");
}

8
test/setup.ts Normal file
View File

@ -0,0 +1,8 @@
import { beforeAll } from "vitest";
beforeAll(() => {
global.window = {} as any;
global.navigator = {} as any;
global.__DEMO__ = false;
});

View File

@ -1 +0,0 @@
global.__BACKWARDS_COMPAT__ = false;

View File

@ -1,7 +0,0 @@
{
"extends": "../tsconfig.json",
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true
}
}

View File

@ -1,23 +1,23 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import {
getValueInPercentage,
normalize,
roundWithOneDecimal,
} from "../../src/util/calculate";
describe("Calculate tests", function () {
it("Test getValueInPercentage", function () {
describe("Calculate tests", () => {
it("Test getValueInPercentage", () => {
assert.strictEqual(getValueInPercentage(10, 0, 100), 10);
assert.strictEqual(getValueInPercentage(120, 0, 100), 120);
assert.strictEqual(getValueInPercentage(-10, 0, 100), -10);
assert.strictEqual(getValueInPercentage(10.33333, 0, 100), 10.33333);
});
it("Test normalize", function () {
it("Test normalize", () => {
assert.strictEqual(normalize(10, 0, 100), 10);
assert.strictEqual(normalize(1, 10, 100), 10);
assert.strictEqual(normalize(100, 0, 10), 10);
});
it("Test roundWithOneDecimal", function () {
it("Test roundWithOneDecimal", () => {
assert.strictEqual(roundWithOneDecimal(10), 10);
assert.strictEqual(roundWithOneDecimal(10.3), 10.3);
assert.strictEqual(roundWithOneDecimal(10.3333), 10.3);

View File

@ -1,4 +1,4 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { brandsUrl } from "../../src/util/brands-url";
describe("Generate brands Url", () => {

View File

@ -1,15 +1,15 @@
import { assert } from "chai";
import { assert, describe, it } from "vitest";
import { documentationUrl } from "../../src/util/documentation-url";
describe("Generate documentation URL", function () {
it("Generate documentation url for stable", function () {
describe("Generate documentation URL", () => {
it("Generate documentation url for stable", () => {
assert.strictEqual(
// @ts-ignore
documentationUrl({ config: { version: "1.0.0" } }, "/blog"),
"https://www.home-assistant.io/blog"
);
});
it("Generate documentation url for rc", function () {
it("Generate documentation url for rc", () => {
assert.strictEqual(
// @ts-ignore
documentationUrl({ config: { version: "1.0.0b0" } }, "/blog"),

11
test/vitest.config.ts Normal file
View File

@ -0,0 +1,11 @@
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
env: {
TZ: "Etc/UTC",
IS_TEST: "true",
},
setupFiles: ["./test/setup.ts"],
},
});

View File

@ -1,13 +0,0 @@
import webpack from "../build-scripts/webpack.cjs";
const config = webpack.createAppConfig({
isProdBuild: false,
latestBuild: true,
isStatsBuild: false,
isTestBuild: true,
});
// instant-mocha forces a CJS library, so cannot output ESM
config.output.module = false;
export default config;