mirror of
https://github.com/home-assistant/frontend.git
synced 2025-06-06 18:26:35 +00:00
Rspack (#22807)
* 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:
parent
09c5dab69f
commit
bd0bfc1fbe
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@ -4,6 +4,7 @@
|
||||
"esbenp.prettier-vscode",
|
||||
"runem.lit-plugin",
|
||||
"github.vscode-pull-request-github",
|
||||
"eamodio.gitlens"
|
||||
"eamodio.gitlens",
|
||||
"vitest.explorer"
|
||||
]
|
||||
}
|
||||
|
@ -152,7 +152,6 @@ module.exports.babelOptions = ({
|
||||
exclude: [
|
||||
// \\ for Windows, / for Mac OS and Linux
|
||||
/node_modules[\\/]core-js/,
|
||||
/node_modules[\\/]webpack[\\/]buildin/,
|
||||
],
|
||||
sourceMaps: !isTestBuild,
|
||||
overrides: [
|
||||
|
@ -9,7 +9,7 @@ import "./locale-data.js";
|
||||
import "./service-worker.js";
|
||||
import "./translations.js";
|
||||
import "./wds.js";
|
||||
import "./webpack.js";
|
||||
import "./rspack.js";
|
||||
|
||||
gulp.task(
|
||||
"develop-app",
|
||||
@ -26,7 +26,7 @@ gulp.task(
|
||||
"build-locale-data"
|
||||
),
|
||||
"copy-static-app",
|
||||
env.useWDS() ? "wds-watch-app" : "webpack-watch-app"
|
||||
env.useWDS() ? "wds-watch-app" : "rspack-watch-app"
|
||||
)
|
||||
);
|
||||
|
||||
@ -39,9 +39,20 @@ gulp.task(
|
||||
"clean",
|
||||
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
||||
"copy-static-app",
|
||||
"webpack-prod-app",
|
||||
"rspack-prod-app",
|
||||
gulp.parallel("gen-pages-app-prod", "gen-service-worker-app-prod"),
|
||||
// Don't compress running tests
|
||||
...(env.isTestBuild() ? [] : ["compress-app"])
|
||||
...(env.isTestBuild() || env.isStatsBuild() ? [] : ["compress-app"])
|
||||
)
|
||||
);
|
||||
|
||||
gulp.task(
|
||||
"analyze-app",
|
||||
gulp.series(
|
||||
async function setEnv() {
|
||||
process.env.STATS = "1";
|
||||
},
|
||||
"clean",
|
||||
"rspack-prod-app"
|
||||
)
|
||||
);
|
||||
|
@ -4,7 +4,7 @@ import "./entry-html.js";
|
||||
import "./gather-static.js";
|
||||
import "./service-worker.js";
|
||||
import "./translations.js";
|
||||
import "./webpack.js";
|
||||
import "./rspack.js";
|
||||
|
||||
gulp.task(
|
||||
"develop-cast",
|
||||
@ -17,7 +17,7 @@ gulp.task(
|
||||
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
||||
"copy-static-cast",
|
||||
"gen-pages-cast-dev",
|
||||
"webpack-dev-server-cast"
|
||||
"rspack-dev-server-cast"
|
||||
)
|
||||
);
|
||||
|
||||
@ -31,7 +31,7 @@ gulp.task(
|
||||
"translations-enable-merge-backend",
|
||||
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
||||
"copy-static-cast",
|
||||
"webpack-prod-cast",
|
||||
"rspack-prod-cast",
|
||||
"gen-pages-cast-prod"
|
||||
)
|
||||
);
|
||||
|
@ -5,7 +5,7 @@ import "./gather-static.js";
|
||||
import "./gen-icons-json.js";
|
||||
import "./service-worker.js";
|
||||
import "./translations.js";
|
||||
import "./webpack.js";
|
||||
import "./rspack.js";
|
||||
|
||||
gulp.task(
|
||||
"develop-demo",
|
||||
@ -22,7 +22,7 @@ gulp.task(
|
||||
"build-locale-data"
|
||||
),
|
||||
"copy-static-demo",
|
||||
"webpack-dev-server-demo"
|
||||
"rspack-dev-server-demo"
|
||||
)
|
||||
);
|
||||
|
||||
@ -37,7 +37,18 @@ gulp.task(
|
||||
"translations-enable-merge-backend",
|
||||
gulp.parallel("gen-icons-json", "build-translations", "build-locale-data"),
|
||||
"copy-static-demo",
|
||||
"webpack-prod-demo",
|
||||
"rspack-prod-demo",
|
||||
"gen-pages-demo-prod"
|
||||
)
|
||||
);
|
||||
|
||||
gulp.task(
|
||||
"analyze-demo",
|
||||
gulp.series(
|
||||
async function setEnv() {
|
||||
process.env.STATS = "1";
|
||||
},
|
||||
"clean",
|
||||
"rspack-prod-demo"
|
||||
)
|
||||
);
|
||||
|
@ -11,7 +11,7 @@ import "./gather-static.js";
|
||||
import "./gen-icons-json.js";
|
||||
import "./service-worker.js";
|
||||
import "./translations.js";
|
||||
import "./webpack.js";
|
||||
import "./rspack.js";
|
||||
|
||||
gulp.task("gather-gallery-pages", async function gatherPages() {
|
||||
const pageDir = path.resolve(paths.gallery_dir, "src/pages");
|
||||
@ -156,7 +156,7 @@ gulp.task(
|
||||
"copy-static-gallery",
|
||||
"gen-pages-gallery-dev",
|
||||
gulp.parallel(
|
||||
"webpack-dev-server-gallery",
|
||||
"rspack-dev-server-gallery",
|
||||
async function watchMarkdownFiles() {
|
||||
gulp.watch(
|
||||
[
|
||||
@ -185,7 +185,7 @@ gulp.task(
|
||||
"gather-gallery-pages"
|
||||
),
|
||||
"copy-static-gallery",
|
||||
"webpack-prod-gallery",
|
||||
"rspack-prod-gallery",
|
||||
"gen-pages-gallery-prod"
|
||||
)
|
||||
);
|
||||
|
@ -6,7 +6,7 @@ import "./entry-html.js";
|
||||
import "./gather-static.js";
|
||||
import "./gen-icons-json.js";
|
||||
import "./translations.js";
|
||||
import "./webpack.js";
|
||||
import "./rspack.js";
|
||||
|
||||
gulp.task(
|
||||
"develop-hassio",
|
||||
@ -21,7 +21,7 @@ gulp.task(
|
||||
"copy-translations-supervisor",
|
||||
"build-locale-data",
|
||||
"copy-static-supervisor",
|
||||
"webpack-watch-hassio"
|
||||
"rspack-watch-hassio"
|
||||
)
|
||||
);
|
||||
|
||||
@ -37,7 +37,7 @@ gulp.task(
|
||||
"copy-translations-supervisor",
|
||||
"build-locale-data",
|
||||
"copy-static-supervisor",
|
||||
"webpack-prod-hassio",
|
||||
"rspack-prod-hassio",
|
||||
"gen-pages-hassio-prod",
|
||||
...// Don't compress running tests
|
||||
(env.isTestBuild() ? [] : ["compress-hassio"])
|
||||
|
@ -5,7 +5,7 @@ import "./entry-html.js";
|
||||
import "./gather-static.js";
|
||||
import "./gen-icons-json.js";
|
||||
import "./translations.js";
|
||||
import "./webpack.js";
|
||||
import "./rspack.js";
|
||||
|
||||
gulp.task(
|
||||
"develop-landing-page",
|
||||
@ -20,7 +20,7 @@ gulp.task(
|
||||
"build-locale-data",
|
||||
"copy-static-landing-page",
|
||||
"gen-pages-landing-page-dev",
|
||||
"webpack-watch-landing-page"
|
||||
"rspack-watch-landing-page"
|
||||
)
|
||||
);
|
||||
|
||||
@ -35,7 +35,7 @@ gulp.task(
|
||||
"copy-translations-landing-page",
|
||||
"build-locale-data",
|
||||
"copy-static-landing-page",
|
||||
"webpack-prod-landing-page",
|
||||
"rspack-prod-landing-page",
|
||||
"gen-pages-landing-page-prod"
|
||||
)
|
||||
);
|
||||
|
@ -1,11 +1,11 @@
|
||||
// Tasks to run webpack.
|
||||
// Tasks to run rspack.
|
||||
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import log from "fancy-log";
|
||||
import gulp from "gulp";
|
||||
import webpack from "webpack";
|
||||
import WebpackDevServer from "webpack-dev-server";
|
||||
import rspack from "@rspack/core";
|
||||
import { RspackDevServer } from "@rspack/dev-server";
|
||||
import env from "../env.cjs";
|
||||
import paths from "../paths.cjs";
|
||||
import {
|
||||
@ -15,7 +15,7 @@ import {
|
||||
createGalleryConfig,
|
||||
createHassioConfig,
|
||||
createLandingPageConfig,
|
||||
} from "../webpack.cjs";
|
||||
} from "../rspack.cjs";
|
||||
|
||||
const bothBuilds = (createConfigFunc, params) => [
|
||||
createConfigFunc({ ...params, latestBuild: true }),
|
||||
@ -31,7 +31,7 @@ const isWsl =
|
||||
|
||||
/**
|
||||
* @param {{
|
||||
* compiler: import("webpack").Compiler,
|
||||
* compiler: import("@rspack/core").Compiler,
|
||||
* contentBase: string,
|
||||
* port: number,
|
||||
* listenHost?: string
|
||||
@ -48,7 +48,7 @@ const runDevServer = async ({
|
||||
// For dev container, we need to listen on all hosts
|
||||
listenHost = env.isDevContainer() ? "0.0.0.0" : "localhost";
|
||||
}
|
||||
const server = new WebpackDevServer(
|
||||
const server = new RspackDevServer(
|
||||
{
|
||||
hot: false,
|
||||
open: true,
|
||||
@ -65,7 +65,7 @@ const runDevServer = async ({
|
||||
|
||||
await server.start();
|
||||
// Server listening
|
||||
log("[webpack-dev-server]", `Project is running at http://localhost:${port}`);
|
||||
log("[rspack-dev-server]", `Project is running at http://localhost:${port}`);
|
||||
};
|
||||
|
||||
const doneHandler = (done) => (err, stats) => {
|
||||
@ -90,16 +90,16 @@ const doneHandler = (done) => (err, stats) => {
|
||||
|
||||
const prodBuild = (conf) =>
|
||||
new Promise((resolve) => {
|
||||
webpack(
|
||||
rspack(
|
||||
conf,
|
||||
// Resolve promise when done. Because we pass a callback, webpack closes itself
|
||||
// Resolve promise when done. Because we pass a callback, rspack closes itself
|
||||
doneHandler(resolve)
|
||||
);
|
||||
});
|
||||
|
||||
gulp.task("webpack-watch-app", () => {
|
||||
gulp.task("rspack-watch-app", () => {
|
||||
// This command will run forever because we don't close compiler
|
||||
webpack(
|
||||
rspack(
|
||||
process.env.ES5
|
||||
? bothBuilds(createAppConfig, { isProdBuild: false })
|
||||
: createAppConfig({ isProdBuild: false, latestBuild: true })
|
||||
@ -110,7 +110,7 @@ gulp.task("webpack-watch-app", () => {
|
||||
);
|
||||
});
|
||||
|
||||
gulp.task("webpack-prod-app", () =>
|
||||
gulp.task("rspack-prod-app", () =>
|
||||
prodBuild(
|
||||
bothBuilds(createAppConfig, {
|
||||
isProdBuild: true,
|
||||
@ -120,9 +120,9 @@ gulp.task("webpack-prod-app", () =>
|
||||
)
|
||||
);
|
||||
|
||||
gulp.task("webpack-dev-server-demo", () =>
|
||||
gulp.task("rspack-dev-server-demo", () =>
|
||||
runDevServer({
|
||||
compiler: webpack(
|
||||
compiler: rspack(
|
||||
createDemoConfig({ isProdBuild: false, latestBuild: true })
|
||||
),
|
||||
contentBase: paths.demo_output_root,
|
||||
@ -130,17 +130,18 @@ gulp.task("webpack-dev-server-demo", () =>
|
||||
})
|
||||
);
|
||||
|
||||
gulp.task("webpack-prod-demo", () =>
|
||||
gulp.task("rspack-prod-demo", () =>
|
||||
prodBuild(
|
||||
bothBuilds(createDemoConfig, {
|
||||
isProdBuild: true,
|
||||
isStatsBuild: env.isStatsBuild(),
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
gulp.task("webpack-dev-server-cast", () =>
|
||||
gulp.task("rspack-dev-server-cast", () =>
|
||||
runDevServer({
|
||||
compiler: webpack(
|
||||
compiler: rspack(
|
||||
createCastConfig({ isProdBuild: false, latestBuild: true })
|
||||
),
|
||||
contentBase: paths.cast_output_root,
|
||||
@ -150,7 +151,7 @@ gulp.task("webpack-dev-server-cast", () =>
|
||||
})
|
||||
);
|
||||
|
||||
gulp.task("webpack-prod-cast", () =>
|
||||
gulp.task("rspack-prod-cast", () =>
|
||||
prodBuild(
|
||||
bothBuilds(createCastConfig, {
|
||||
isProdBuild: true,
|
||||
@ -158,9 +159,9 @@ gulp.task("webpack-prod-cast", () =>
|
||||
)
|
||||
);
|
||||
|
||||
gulp.task("webpack-watch-hassio", () => {
|
||||
gulp.task("rspack-watch-hassio", () => {
|
||||
// This command will run forever because we don't close compiler
|
||||
webpack(
|
||||
rspack(
|
||||
createHassioConfig({
|
||||
isProdBuild: false,
|
||||
latestBuild: true,
|
||||
@ -173,7 +174,7 @@ gulp.task("webpack-watch-hassio", () => {
|
||||
);
|
||||
});
|
||||
|
||||
gulp.task("webpack-prod-hassio", () =>
|
||||
gulp.task("rspack-prod-hassio", () =>
|
||||
prodBuild(
|
||||
bothBuilds(createHassioConfig, {
|
||||
isProdBuild: true,
|
||||
@ -183,9 +184,9 @@ gulp.task("webpack-prod-hassio", () =>
|
||||
)
|
||||
);
|
||||
|
||||
gulp.task("webpack-dev-server-gallery", () =>
|
||||
gulp.task("rspack-dev-server-gallery", () =>
|
||||
runDevServer({
|
||||
compiler: webpack(
|
||||
compiler: rspack(
|
||||
createGalleryConfig({ isProdBuild: false, latestBuild: true })
|
||||
),
|
||||
contentBase: paths.gallery_output_root,
|
||||
@ -194,7 +195,7 @@ gulp.task("webpack-dev-server-gallery", () =>
|
||||
})
|
||||
);
|
||||
|
||||
gulp.task("webpack-prod-gallery", () =>
|
||||
gulp.task("rspack-prod-gallery", () =>
|
||||
prodBuild(
|
||||
createGalleryConfig({
|
||||
isProdBuild: true,
|
||||
@ -203,9 +204,9 @@ gulp.task("webpack-prod-gallery", () =>
|
||||
)
|
||||
);
|
||||
|
||||
gulp.task("webpack-watch-landing-page", () => {
|
||||
gulp.task("rspack-watch-landing-page", () => {
|
||||
// This command will run forever because we don't close compiler
|
||||
webpack(
|
||||
rspack(
|
||||
process.env.ES5
|
||||
? bothBuilds(createLandingPageConfig, { isProdBuild: false })
|
||||
: createLandingPageConfig({ isProdBuild: false, latestBuild: true })
|
||||
@ -220,7 +221,7 @@ gulp.task("webpack-watch-landing-page", () => {
|
||||
);
|
||||
});
|
||||
|
||||
gulp.task("webpack-prod-landing-page", () =>
|
||||
gulp.task("rspack-prod-landing-page", () =>
|
||||
prodBuild(
|
||||
bothBuilds(createLandingPageConfig, {
|
||||
isProdBuild: true,
|
@ -1,16 +1,13 @@
|
||||
const { existsSync } = require("fs");
|
||||
const path = require("path");
|
||||
const webpack = require("webpack");
|
||||
const rspack = require("@rspack/core");
|
||||
const { RsdoctorRspackPlugin } = require("@rsdoctor/rspack-plugin");
|
||||
const { StatsWriterPlugin } = require("webpack-stats-plugin");
|
||||
const filterStats = require("@bundle-stats/plugin-webpack-filter").default;
|
||||
const TerserPlugin = require("terser-webpack-plugin");
|
||||
const { WebpackManifestPlugin } = require("webpack-manifest-plugin");
|
||||
const { WebpackManifestPlugin } = require("rspack-manifest-plugin");
|
||||
const log = require("fancy-log");
|
||||
const WebpackBar = require("webpackbar");
|
||||
const {
|
||||
TransformAsyncModulesPlugin,
|
||||
} = require("transform-async-modules-webpack-plugin");
|
||||
const { dependencies } = require("../package.json");
|
||||
const WebpackBar = require("webpackbar/rspack");
|
||||
const paths = require("./paths.cjs");
|
||||
const bundle = require("./bundle.cjs");
|
||||
|
||||
@ -28,7 +25,7 @@ class LogStartCompilePlugin {
|
||||
}
|
||||
}
|
||||
|
||||
const createWebpackConfig = ({
|
||||
const createRspackConfig = ({
|
||||
name,
|
||||
entry,
|
||||
outputPath,
|
||||
@ -102,13 +99,18 @@ const createWebpackConfig = ({
|
||||
splitChunks: {
|
||||
// Disable splitting for web workers and worklets because imports of
|
||||
// external chunks are broken for:
|
||||
// - ESM output: https://github.com/webpack/webpack/issues/17014
|
||||
chunks: !isProdBuild
|
||||
? // improve incremental build speed, but blows up bundle size
|
||||
new RegExp(
|
||||
`^(?!(${Object.keys(entry).join("|")}|.*work(?:er|let))$)`
|
||||
)
|
||||
: // - ESM output: https://github.com/webpack/webpack/issues/17014
|
||||
// - Worklets use `importScripts`: https://github.com/webpack/webpack/issues/11543
|
||||
chunks: (chunk) =>
|
||||
(chunk) =>
|
||||
!chunk.canBeInitial() &&
|
||||
!new RegExp(`^.+-work${latestBuild ? "(?:let|er)" : "let"}$`).test(
|
||||
chunk.name
|
||||
),
|
||||
!new RegExp(
|
||||
`^.+-work${latestBuild ? "(?:let|er)" : "let"}$`
|
||||
).test(chunk.name),
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
@ -117,10 +119,10 @@ const createWebpackConfig = ({
|
||||
// Only include the JS of entrypoints
|
||||
filter: (file) => file.isInitial && !file.name.endsWith(".map"),
|
||||
}),
|
||||
new webpack.DefinePlugin(
|
||||
new rspack.DefinePlugin(
|
||||
bundle.definedVars({ isProdBuild, latestBuild, defineOverlay })
|
||||
),
|
||||
new webpack.IgnorePlugin({
|
||||
new rspack.IgnorePlugin({
|
||||
checkResource(resource, context) {
|
||||
// Only use ignore to intercept imports that we don't control
|
||||
// inside node_module dependencies.
|
||||
@ -152,7 +154,7 @@ const createWebpackConfig = ({
|
||||
);
|
||||
},
|
||||
}),
|
||||
new webpack.NormalModuleReplacementPlugin(
|
||||
new rspack.NormalModuleReplacementPlugin(
|
||||
new RegExp(
|
||||
bundle.emptyPackages({ latestBuild, isHassioBuild }).join("|")
|
||||
),
|
||||
@ -168,10 +170,14 @@ const createWebpackConfig = ({
|
||||
stats: { assets: true, chunks: true, modules: true },
|
||||
transform: (stats) => JSON.stringify(filterStats(stats)),
|
||||
}),
|
||||
!latestBuild &&
|
||||
new TransformAsyncModulesPlugin({
|
||||
browserslistEnv: "legacy",
|
||||
runtime: { version: dependencies["@babel/runtime"] },
|
||||
isProdBuild &&
|
||||
isStatsBuild &&
|
||||
new RsdoctorRspackPlugin({
|
||||
reportDir: path.join(paths.build_dir, "rsdoctor"),
|
||||
features: ["plugins", "bundle"],
|
||||
supports: {
|
||||
generateTileGraph: true,
|
||||
},
|
||||
}),
|
||||
].filter(Boolean),
|
||||
resolve: {
|
||||
@ -210,8 +216,6 @@ const createWebpackConfig = ({
|
||||
isProdBuild && !isStatsBuild ? "[id].[contenthash][ext]" : "[id][ext]",
|
||||
crossOriginLoading: "use-credentials",
|
||||
hashFunction: "xxhash64",
|
||||
hashDigest: "base64url",
|
||||
hashDigestLength: 11, // full length of 64 bit base64url
|
||||
path: outputPath,
|
||||
publicPath,
|
||||
// To silence warning in worker plugin
|
||||
@ -253,17 +257,17 @@ const createAppConfig = ({
|
||||
isStatsBuild,
|
||||
isTestBuild,
|
||||
}) =>
|
||||
createWebpackConfig(
|
||||
createRspackConfig(
|
||||
bundle.config.app({ isProdBuild, latestBuild, isStatsBuild, isTestBuild })
|
||||
);
|
||||
|
||||
const createDemoConfig = ({ isProdBuild, latestBuild, isStatsBuild }) =>
|
||||
createWebpackConfig(
|
||||
createRspackConfig(
|
||||
bundle.config.demo({ isProdBuild, latestBuild, isStatsBuild })
|
||||
);
|
||||
|
||||
const createCastConfig = ({ isProdBuild, latestBuild }) =>
|
||||
createWebpackConfig(bundle.config.cast({ isProdBuild, latestBuild }));
|
||||
createRspackConfig(bundle.config.cast({ isProdBuild, latestBuild }));
|
||||
|
||||
const createHassioConfig = ({
|
||||
isProdBuild,
|
||||
@ -271,7 +275,7 @@ const createHassioConfig = ({
|
||||
isStatsBuild,
|
||||
isTestBuild,
|
||||
}) =>
|
||||
createWebpackConfig(
|
||||
createRspackConfig(
|
||||
bundle.config.hassio({
|
||||
isProdBuild,
|
||||
latestBuild,
|
||||
@ -281,10 +285,10 @@ const createHassioConfig = ({
|
||||
);
|
||||
|
||||
const createGalleryConfig = ({ isProdBuild, latestBuild }) =>
|
||||
createWebpackConfig(bundle.config.gallery({ isProdBuild, latestBuild }));
|
||||
createRspackConfig(bundle.config.gallery({ isProdBuild, latestBuild }));
|
||||
|
||||
const createLandingPageConfig = ({ isProdBuild, latestBuild }) =>
|
||||
createWebpackConfig(bundle.config.landingPage({ isProdBuild, latestBuild }));
|
||||
createRspackConfig(bundle.config.landingPage({ isProdBuild, latestBuild }));
|
||||
|
||||
module.exports = {
|
||||
createAppConfig,
|
||||
@ -292,6 +296,6 @@ module.exports = {
|
||||
createCastConfig,
|
||||
createHassioConfig,
|
||||
createGalleryConfig,
|
||||
createRspackConfig,
|
||||
createLandingPageConfig,
|
||||
createWebpackConfig,
|
||||
};
|
@ -1,8 +0,0 @@
|
||||
import webpack from "../build-scripts/webpack.cjs";
|
||||
import env from "../build-scripts/env.cjs";
|
||||
|
||||
export default webpack.createCastConfig({
|
||||
isProdBuild: env.isProdBuild(),
|
||||
isStatsBuild: env.isStatsBuild(),
|
||||
latestBuild: true,
|
||||
});
|
@ -4,11 +4,6 @@
|
||||
# Stop on errors
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
cd "$(dirname "$0")/../.."
|
||||
|
||||
export STATS=1
|
||||
statsfile="compilation-stats-demo.json"
|
||||
|
||||
./node_modules/.bin/webpack-cli --profile --node-env=production --json=$statsfile
|
||||
npx webpack-bundle-analyzer $statsfile dist/frontend_latest
|
||||
rm -f $statsfile
|
||||
./node_modules/.bin/gulp analyze-demo
|
@ -1,11 +0,0 @@
|
||||
import webpack from "../build-scripts/webpack.cjs";
|
||||
import env from "../build-scripts/env.cjs";
|
||||
|
||||
// File just used for stats builds
|
||||
const latestBuild = true;
|
||||
|
||||
export default webpack.createDemoConfig({
|
||||
isProdBuild: env.isProdBuild(),
|
||||
isStatsBuild: env.isStatsBuild(),
|
||||
latestBuild,
|
||||
});
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable import/no-extraneous-dependencies */
|
||||
import unusedImports from "eslint-plugin-unused-imports";
|
||||
import globals from "globals";
|
||||
import tsParser from "@typescript-eslint/parser";
|
||||
@ -57,7 +58,7 @@ export default [
|
||||
settings: {
|
||||
"import/resolver": {
|
||||
webpack: {
|
||||
config: "./webpack.config.cjs",
|
||||
config: "./rspack.config.cjs",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1,4 +1,3 @@
|
||||
/* eslint-disable lit/no-template-arrow */
|
||||
import type { TemplateResult } from "lit";
|
||||
import { LitElement, html, css } from "lit";
|
||||
import { customElement, state } from "lit/decorators";
|
||||
|
@ -1,8 +0,0 @@
|
||||
import webpack from "../build-scripts/webpack.cjs";
|
||||
import env from "../build-scripts/env.cjs";
|
||||
|
||||
export default webpack.createGalleryConfig({
|
||||
isProdBuild: env.isProdBuild(),
|
||||
isStatsBuild: env.isStatsBuild(),
|
||||
latestBuild: true,
|
||||
});
|
@ -1,8 +0,0 @@
|
||||
import webpack from "../build-scripts/webpack.cjs";
|
||||
import env from "../build-scripts/env.cjs";
|
||||
|
||||
export default webpack.createHassioConfig({
|
||||
isProdBuild: env.isProdBuild(),
|
||||
isStatsBuild: env.isStatsBuild(),
|
||||
latestBuild: true,
|
||||
});
|
@ -1,8 +0,0 @@
|
||||
import webpack from "../build-scripts/webpack.cjs";
|
||||
import env from "../build-scripts/env.cjs";
|
||||
|
||||
export default webpack.createLandingPageConfig({
|
||||
isProdBuild: env.isProdBuild(),
|
||||
isStatsBuild: env.isStatsBuild(),
|
||||
latestBuild: true,
|
||||
});
|
14
package.json
14
package.json
@ -19,7 +19,7 @@
|
||||
"postinstall": "husky",
|
||||
"prepack": "pinst --disable",
|
||||
"postpack": "pinst --enable",
|
||||
"test": "instant-mocha --webpack-config ./test/webpack.config.js --require ./test/setup.cjs \"test/**/*.ts\""
|
||||
"test": "vitest run --config test/vitest.config.ts"
|
||||
},
|
||||
"author": "Paulus Schoutsen <Paulus@PaulusSchoutsen.nl> (http://paulusschoutsen.nl)",
|
||||
"license": "Apache-2.0",
|
||||
@ -166,6 +166,9 @@
|
||||
"@octokit/plugin-retry": "7.1.2",
|
||||
"@octokit/rest": "21.0.2",
|
||||
"@open-wc/dev-server-hmr": "0.1.4",
|
||||
"@rsdoctor/rspack-plugin": "0.4.8",
|
||||
"@rspack/cli": "1.1.4",
|
||||
"@rspack/core": "1.1.4",
|
||||
"@types/babel__plugin-transform-runtime": "7.9.5",
|
||||
"@types/chromecast-caf-receiver": "6.0.19",
|
||||
"@types/chromecast-caf-sender": "1.0.11",
|
||||
@ -190,7 +193,6 @@
|
||||
"babel-loader": "9.2.1",
|
||||
"babel-plugin-template-html-minifier": "4.1.0",
|
||||
"browserslist-useragent-regexp": "4.1.3",
|
||||
"chai": "5.1.2",
|
||||
"del": "8.0.0",
|
||||
"eslint": "9.15.0",
|
||||
"eslint-config-airbnb-base": "15.0.0",
|
||||
@ -212,7 +214,6 @@
|
||||
"gulp-zopfli-green": "6.0.2",
|
||||
"html-minifier-terser": "7.2.0",
|
||||
"husky": "9.1.7",
|
||||
"instant-mocha": "1.5.3",
|
||||
"jszip": "3.10.1",
|
||||
"lint-staged": "15.2.10",
|
||||
"lit-analyzer": "2.0.3",
|
||||
@ -220,11 +221,11 @@
|
||||
"lodash.template": "4.5.0",
|
||||
"magic-string": "0.30.13",
|
||||
"map-stream": "0.0.7",
|
||||
"mocha": "10.8.2",
|
||||
"object-hash": "3.0.0",
|
||||
"open": "10.1.0",
|
||||
"pinst": "3.0.0",
|
||||
"prettier": "3.3.3",
|
||||
"rspack-manifest-plugin": "5.0.2",
|
||||
"serve-handler": "6.1.6",
|
||||
"sinon": "19.0.2",
|
||||
"systemjs": "6.15.1",
|
||||
@ -233,10 +234,7 @@
|
||||
"transform-async-modules-webpack-plugin": "1.1.1",
|
||||
"ts-lit-plugin": "2.0.2",
|
||||
"typescript": "5.7.2",
|
||||
"webpack": "5.96.1",
|
||||
"webpack-cli": "5.1.4",
|
||||
"webpack-dev-server": "5.1.0",
|
||||
"webpack-manifest-plugin": "5.0.0",
|
||||
"vitest": "2.1.5",
|
||||
"webpack-stats-plugin": "1.1.3",
|
||||
"webpackbar": "7.0.0",
|
||||
"workbox-build": "patch:workbox-build@npm%3A7.1.1#~/.yarn/patches/workbox-build-npm-7.1.1-a854f3faae.patch"
|
||||
|
@ -1,12 +1,12 @@
|
||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||
// Needs to remain CommonJS until eslint-import-resolver-webpack supports ES modules
|
||||
const webpack = require("./build-scripts/webpack.cjs");
|
||||
const rspack = require("./build-scripts/rspack.cjs");
|
||||
const env = require("./build-scripts/env.cjs");
|
||||
|
||||
// This file exists because we haven't migrated the stats script yet
|
||||
|
||||
const configs = [
|
||||
webpack.createAppConfig({
|
||||
rspack.createAppConfig({
|
||||
isProdBuild: env.isProdBuild(),
|
||||
isStatsBuild: env.isStatsBuild(),
|
||||
isTestBuild: env.isTestBuild(),
|
||||
@ -16,7 +16,7 @@ const configs = [
|
||||
|
||||
if (env.isProdBuild() && !env.isStatsBuild()) {
|
||||
configs.push(
|
||||
webpack.createAppConfig({
|
||||
rspack.createAppConfig({
|
||||
isProdBuild: env.isProdBuild(),
|
||||
isStatsBuild: env.isStatsBuild(),
|
||||
isTestBuild: env.isTestBuild(),
|
@ -6,9 +6,4 @@ set -e
|
||||
|
||||
cd "$(dirname "$0")/.."
|
||||
|
||||
export STATS=1
|
||||
statsfile="compilation-stats.json"
|
||||
|
||||
./node_modules/.bin/webpack-cli --profile --node-env=production --json=$statsfile
|
||||
npx webpack-bundle-analyzer $statsfile hass_frontend/frontend_latest
|
||||
rm -f $statsfile
|
||||
./node_modules/.bin/gulp analyze-app
|
||||
|
@ -1,15 +1,12 @@
|
||||
import { TimeZone } from "../../data/translation";
|
||||
|
||||
const RESOLVED_TIME_ZONE = Intl.DateTimeFormat?.().resolvedOptions?.().timeZone;
|
||||
|
||||
// Browser time zone can be determined from Intl, with fallback to UTC for polyfill or no support.
|
||||
// Alternatively, we could fallback to a fixed offset IANA zone (e.g. "Etc/GMT+5") using
|
||||
// Date.prototype.getTimeOffset(), but IANA only has whole hour Etc zones, and problems
|
||||
// might occur with relative time due to DST.
|
||||
// Use optional chain instead of polyfill import since polyfill will always return UTC
|
||||
export const LOCAL_TIME_ZONE =
|
||||
Intl.DateTimeFormat?.().resolvedOptions?.().timeZone ?? "UTC";
|
||||
export const LOCAL_TIME_ZONE = RESOLVED_TIME_ZONE ?? "UTC";
|
||||
|
||||
// Pick time zone based on user profile option. Core zone is used when local cannot be determined.
|
||||
export const resolveTimeZone = (option: TimeZone, serverTimeZone: string) =>
|
||||
option === TimeZone.local && LOCAL_TIME_ZONE !== "UTC"
|
||||
option === TimeZone.local && RESOLVED_TIME_ZONE
|
||||
? LOCAL_TIME_ZONE
|
||||
: serverTimeZone;
|
||||
|
@ -262,7 +262,6 @@ export interface IconSelector {
|
||||
}
|
||||
|
||||
export interface ImageSelector {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
image: { original?: boolean; crop?: CropOptions } | null;
|
||||
}
|
||||
|
||||
@ -334,7 +333,6 @@ export interface ObjectSelector {
|
||||
}
|
||||
|
||||
export interface AssistPipelineSelector {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
assist_pipeline: {
|
||||
include_last_used?: boolean;
|
||||
} | null;
|
||||
@ -453,7 +451,6 @@ export interface UiActionSelector {
|
||||
}
|
||||
|
||||
export interface UiColorSelector {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
ui_color: {
|
||||
default_color?: string;
|
||||
include_none?: boolean;
|
||||
@ -462,7 +459,6 @@ export interface UiColorSelector {
|
||||
}
|
||||
|
||||
export interface UiStateContentSelector {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
ui_state_content: {
|
||||
entity_id?: string;
|
||||
allow_name?: boolean;
|
||||
|
@ -60,7 +60,7 @@ declare global {
|
||||
};
|
||||
}
|
||||
|
||||
// For loading workers in webpack
|
||||
// For loading workers in rspack
|
||||
interface ImportMeta {
|
||||
url: string;
|
||||
}
|
||||
|
@ -1,7 +1,4 @@
|
||||
{
|
||||
"env": {
|
||||
"mocha": true
|
||||
},
|
||||
"rules": {
|
||||
"import/no-extraneous-dependencies": 0
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
import { atLeastVersion } from "../../../src/common/config/version";
|
||||
|
||||
const testTruthyData = [
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import checkValidDate from "../../../src/common/datetime/check_valid_date";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import { formatDuration } from "../../../src/common/datetime/duration";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import durationToSeconds from "../../../src/common/datetime/duration_to_seconds";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import { formatDate } from "../../../src/common/datetime/format_date";
|
||||
import {
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import {
|
||||
formatDateTime,
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import {
|
||||
formatTime,
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import millisecondsToDuration from "../../../src/common/datetime/milliseconds_to_duration";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import { relativeTime } from "../../../src/common/datetime/relative_time";
|
||||
import {
|
12
test/common/datetime/resolve-time-zone.test.ts
Normal file
12
test/common/datetime/resolve-time-zone.test.ts
Normal 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);
|
||||
});
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import secondsToDuration from "../../../src/common/datetime/seconds_to_duration";
|
||||
|
@ -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", () => {
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import { canToggleDomain } from "../../../src/common/entity/can_toggle_domain";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import { canToggleState } from "../../../src/common/entity/can_toggle_state";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import { computeDomain } from "../../../src/common/entity/compute_domain";
|
||||
|
@ -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"
|
||||
);
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import { computeStateDomain } from "../../../src/common/entity/compute_state_domain";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import { generateFilter } from "../../../src/common/entity/entity_filter";
|
||||
|
@ -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";
|
@ -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 = {
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import { getGroupEntities } from "../../../src/common/entity/get_group_entities";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import { getViewEntities } from "../../../src/common/entity/get_view_entities";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import { hasLocation } from "../../../src/common/entity/has_location";
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import { splitByGroups } from "../../../src/common/entity/split_by_groups";
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import { stateCardType } from "../../../src/common/entity/state_card_type";
|
||||
|
@ -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";
|
||||
|
@ -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";
|
@ -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
|
||||
);
|
||||
});
|
||||
|
12
test/common/string/is_date.test.ts
Normal file
12
test/common/string/is_date.test.ts
Normal 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);
|
||||
});
|
@ -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);
|
||||
});
|
@ -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", () => {
|
||||
|
37
test/common/string/slugify.test.ts
Normal file
37
test/common/string/slugify.test.ts
Normal 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");
|
||||
});
|
||||
});
|
@ -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");
|
||||
});
|
@ -1,4 +1,4 @@
|
||||
import { assert } from "chai";
|
||||
import { assert, describe, it } from "vitest";
|
||||
|
||||
import parseAspectRatio from "../../../src/common/util/parse-aspect-ratio";
|
||||
|
@ -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 () => {
|
@ -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(
|
@ -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,
|
@ -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
8
test/setup.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import { beforeAll } from "vitest";
|
||||
|
||||
beforeAll(() => {
|
||||
global.window = {} as any;
|
||||
global.navigator = {} as any;
|
||||
|
||||
global.__DEMO__ = false;
|
||||
});
|
@ -1 +0,0 @@
|
||||
global.__BACKWARDS_COMPAT__ = false;
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
@ -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);
|
@ -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", () => {
|
@ -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
11
test/vitest.config.ts
Normal 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"],
|
||||
},
|
||||
});
|
@ -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;
|
Loading…
x
Reference in New Issue
Block a user