diff --git a/bun.lockb b/bun.lockb index 69cacb8..0645c92 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 2bde455..4e04928 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,7 @@ "preview": "vite preview", "dist": "vite build", "count-source-lines": "exec scripts/src-lc.sh", - "typecheck": "tsc --noEmit --skipLibCheck", - "wdio": "wdio run ./wdio.conf.ts" + "typecheck": "tsc --noEmit --skipLibCheck" }, "keywords": [], "author": "Rubicon", @@ -19,26 +18,17 @@ "devDependencies": { "@solid-devtools/overlay": "^0.30.1", "@suid/vite-plugin": "^0.3.1", - "@testing-library/webdriverio": "^3.2.1", "@types/hammerjs": "^2.0.46", "@types/masonry-layout": "^4.2.8", "@vite-pwa/assets-generator": "^0.2.6", - "@wdio/cli": "^9.4.5", - "@wdio/lighthouse-service": "^9.4.5", - "@wdio/local-runner": "^9.4.5", - "@wdio/mocha-framework": "^9.4.4", - "@wdio/spec-reporter": "^9.4.4", "postcss": "^8.4.49", "prettier": "^3.3.3", - "tsx": "^4.19.2", "typescript": "^5.6.3", "vite": "^5.4.11", "vite-plugin-package-version": "^1.1.0", "vite-plugin-pwa": "^0.20.5", "vite-plugin-solid": "^2.10.2", "vite-plugin-solid-styled": "^0.11.1", - "wdio-vite-service": "^2.0.0", - "wdio-wait-for": "^3.0.11", "workbox-build": "^7.3.0", "wrangler": "^3.86.1" }, diff --git a/src/masto/clients.ts b/src/masto/clients.ts index fc26ee5..f853fa7 100644 --- a/src/masto/clients.ts +++ b/src/masto/clients.ts @@ -4,7 +4,6 @@ import { createMemo, createRenderEffect, createResource, - untrack, useContext, } from "solid-js"; import { Account } from "../accounts/stores"; @@ -58,15 +57,15 @@ export const Provider = Context.Provider; export function useSessions() { const sessions = useSessionsRaw(); - const { push } = useNavigator(); + const {push} = useNavigator(); const location = useLocation(); createRenderEffect(() => { - if (untrack(() => sessions().length) > 0) return; - - push("/accounts/sign-in?back=" + encodeURIComponent(location.pathname), { - replace: true, - }); + if (sessions().length > 0) return; + push( + "/accounts/sign-in?back=" + encodeURIComponent(location.pathname), + { replace: "all" }, + ); }); return sessions; diff --git a/src/material/TextField.tsx b/src/material/TextField.tsx index 6dcfe00..df0f7fc 100644 --- a/src/material/TextField.tsx +++ b/src/material/TextField.tsx @@ -28,14 +28,14 @@ const TextField: Component = (props) => { createEffect(() => { if (hasContent()) { - field!.classList.add("float-label"); + field.classList.add("float-label"); } else { - field!.classList.remove("float-label"); + field.classList.remove("float-label"); } }); onMount(() => { - setHasContent(input!.value.length > 0); + setHasContent(input.value.length > 0); }); const onInputChange = (e: { currentTarget: HTMLInputElement }) => { diff --git a/src/platform/StackedRouter.tsx b/src/platform/StackedRouter.tsx index f79da9a..75e7594 100644 --- a/src/platform/StackedRouter.tsx +++ b/src/platform/StackedRouter.tsx @@ -1,14 +1,10 @@ -import { - Router, - type RouterProps, - type StaticRouterProps, - createRouter, -} from "@solidjs/router"; +import { StaticRouter, type RouterProps } from "@solidjs/router"; import { Component, createContext, createMemo, createRenderEffect, + createUniqueId, Index, onMount, Show, @@ -16,9 +12,6 @@ import { useContext, onCleanup, type Accessor, - children, - createSignal, - createRoot, } from "solid-js"; import { createStore, unwrap } from "solid-js/store"; import "./StackedRouter.css"; @@ -28,12 +21,6 @@ import { makeEventListener } from "@solid-primitives/event-listener"; import { useWindowSize } from "@solid-primitives/resize-observer"; import { isPointNotInRect } from "./dom"; -let uniqueCounter = 0; - -function createUniqueId() { - return `sr-${uniqueCounter++}`; -} - export type StackedRouterProps = Omit; export type StackFrame = { @@ -400,24 +387,6 @@ function animateUntil( execStep(); } -function noOp() {} - -function StaticRouter(props: StaticRouterProps) { - const url = () => props.url || ""; - - // TODO: support onBeforeLeave, see - // https://github.com/solidjs/solid-router/blob/main/src/routers/Router.ts - - return createRouter({ - get: url, - set: noOp, - init(notify) { - createRenderEffect(() => notify(url())); - return noOp; - }, - })(props); -} - /** * The cache key of saved stack for hot reload. * @@ -488,7 +457,7 @@ const StackedRouter: Component = (oprops) => { }; createRenderEffect(() => { - loadStack(); + loadStack() }); } @@ -503,13 +472,10 @@ const StackedRouter: Component = (oprops) => { }; const replace = opts?.replace; - if (replace === "all" || stack.length === 0) { + if (replace === "all") { mutStack([frame]); - } else if (replace) { - const idx = stack.length - 1; - mutStack(idx, frame); } else { - mutStack(stack.length, frame); + mutStack(replace ? stack.length - 1 : stack.length, frame); } const savedStack = serializableStack(stack); @@ -575,15 +541,13 @@ const StackedRouter: Component = (oprops) => { } }); - createRenderEffect(() => - untrack(() => { - if (stack.length === 0) { - pushFrame(window.location.pathname, { - replace: "all", - }); - } - }), - ); + createRenderEffect(() => { + if (stack.length === 0) { + pushFrame(window.location.pathname, { + replace: "all", + }); + } + }); createRenderEffect(() => { makeEventListener(window, "popstate", (event) => { @@ -672,9 +636,7 @@ const StackedRouter: Component = (oprops) => { const currentFrame = () => { return { index, - get frame() { - return frame(); - }, + frame: frame(), }; }; diff --git a/src/platform/polyfills.ts b/src/platform/polyfills.ts index 6bbf700..1af3341 100644 --- a/src/platform/polyfills.ts +++ b/src/platform/polyfills.ts @@ -22,7 +22,7 @@ if (typeof Promise.withResolvers === "undefined") { // Promise.withResolvers is generic and works with subclasses - the typescript built-in decl // could not handle the subclassing case. - (Promise.prototype as any).withResolvers = function (this: AnyPromiseConstructor) { + Promise.withResolvers = function (this: AnyPromiseConstructor) { let resolve!: PromiseWithResolvers["resolve"], reject!: PromiseWithResolvers["reject"]; // These variables are expected to be set after `new this()` diff --git a/src/timelines/Home.tsx b/src/timelines/Home.tsx index 99e4fd1..a016e45 100644 --- a/src/timelines/Home.tsx +++ b/src/timelines/Home.tsx @@ -4,7 +4,6 @@ import { onMount, type ParentComponent, createRenderEffect, - createEffect, } from "solid-js"; import { useDocumentTitle } from "../utils"; import Scaffold from "~material/Scaffold"; @@ -59,7 +58,6 @@ const Home: ParentComponent = (props) => { const recalculateTabIndicator = () => { scrollEventLockReleased = false; try { - if (!panelList!) return; const { x: panelX, width: panelWidth } = panelList.getBoundingClientRect(); let minIdx = +Infinity, @@ -97,9 +95,11 @@ const Home: ParentComponent = (props) => { } }; - createEffect(() => { + createRenderEffect(() => { makeEventListener(window, "resize", requestRecalculateTabIndicator); + }); + onMount(() => { requestAnimationFrame(recalculateTabIndicator); }); @@ -110,7 +110,7 @@ const Home: ParentComponent = (props) => { }; const onTabClick = (idx: number) => { - const items = panelList!.querySelectorAll(".tab-panel"); + const items = panelList.querySelectorAll(".tab-panel"); if (items.length > idx) { items.item(idx).scrollIntoView({ block: "start", behavior: "smooth" }); } diff --git a/test/objects/accounts.ts b/test/objects/accounts.ts deleted file mode 100644 index 117a878..0000000 --- a/test/objects/accounts.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { $, browser } from "@wdio/globals"; -import Page from "./page.js"; - -/** - * sub page containing specific selectors and methods for a specific page - */ -export class SignInPage extends Page { - public static get serverUrlInput() { - return $("[name=serverUrl]"); - } - - public static async urlIsTheCurrent() { - const urlMatched = - new URL(await browser.getUrl()).pathname === "/accounts/sign-in"; - return urlMatched; - } - - /** - * overwrite specific options to adapt it to page object - */ - public static async open() { - return await super.open("accounts/sign-in"); - } -} diff --git a/test/objects/page.ts b/test/objects/page.ts deleted file mode 100644 index 67c03b4..0000000 --- a/test/objects/page.ts +++ /dev/null @@ -1,15 +0,0 @@ -import { browser } from "@wdio/globals"; - -/** - * main page object containing all methods, selectors and functionality - * that is shared across all page objects - */ -export default class Page { - /** - * Opens a sub page of the page - * @param path path of the sub page (e.g. /path/to/page.html) - */ - public static open(path: string) { - return browser.url(`/${path}`); - } -} diff --git a/test/objects/timelines.ts b/test/objects/timelines.ts deleted file mode 100644 index 5562da0..0000000 --- a/test/objects/timelines.ts +++ /dev/null @@ -1,7 +0,0 @@ -import Page from "./page"; - -export class IndexPage extends Page { - public static async open(path: string) { - return await super.open(path); - } -} diff --git a/test/sign-in.spec.ts b/test/sign-in.spec.ts deleted file mode 100644 index 2f5068c..0000000 --- a/test/sign-in.spec.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { expect } from "@wdio/globals"; -import { SignInPage } from "./objects/accounts.js"; -import { IndexPage } from "./objects/timelines.js"; - -describe("The index page", () => { - it("jumps to the sign-in page if no account signed in", async () => { - await IndexPage.open(""); - - expect(await browser.waitUntil(SignInPage.urlIsTheCurrent)); - - expect(await browser.waitUntil(SignInPage.serverUrlInput.isDisplayed)); - }); -}); diff --git a/test/tsconfig.json b/test/tsconfig.json deleted file mode 100644 index 753feaf..0000000 --- a/test/tsconfig.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": ["../tsconfig.super.json"], - "compilerOptions": { - "types": [ - "node", - "@wdio/globals/types", - "@wdio/mocha-framework", - "@wdio/lighthouse-service" - ] - }, - "include": ["./**/*.ts", "../wdio.conf.ts"] -} diff --git a/tsconfig.json b/tsconfig.json index 90a351f..feaab58 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,6 @@ "lib": ["ESNext", "DOM", "DOM.Iterable"] }, "include": ["./src/**/*.ts", "./src/**/*.tsx", "./*.ts", "./types/**.ts"], - "exclude": ["./src/serviceworker/**", "./wdio.conf.ts"], + "exclude": ["./src/serviceworker/**"], "extends": ["./tsconfig.super.json"] } diff --git a/wdio.conf.ts b/wdio.conf.ts deleted file mode 100644 index 1f6b1cf..0000000 --- a/wdio.conf.ts +++ /dev/null @@ -1,329 +0,0 @@ -const chromeDefaultOpts = process.env.CI - ? { - args: ["headless", "disable-gpu"], - } - : {}; - -const firefoxDefaultOpts = process.env.CI - ? { - args: ["-headless"], - } - : {}; - -export const config: WebdriverIO.Config = { - // - // ==================== - // Runner Configuration - // ==================== - // WebdriverIO supports running e2e tests as well as unit and component tests. - runner: "local", - tsConfigPath: "./test/tsconfig.json", - - // - // ================== - // Specify Test Files - // ================== - // Define which test specs should run. The pattern is relative to the directory - // of the configuration file being run. - // - // The specs are defined as an array of spec files (optionally using wildcards - // that will be expanded). The test for each spec file will be run in a separate - // worker process. In order to have a group of spec files run in the same worker - // process simply enclose them in an array within the specs array. - // - // The path of the spec files will be resolved relative from the directory of - // of the config file unless it's absolute. - // - specs: ["./test/**/*.spec.ts"], - // Patterns to exclude. - exclude: ["./test/objects/**/*"], - // - // ============ - // Capabilities - // ============ - // Define your capabilities here. WebdriverIO can run multiple capabilities at the same - // time. Depending on the number of capabilities, WebdriverIO launches several test - // sessions. Within your capabilities you can overwrite the spec and exclude options in - // order to group specific specs to a specific capability. - // - // First, you can define how many instances should be started at the same time. Let's - // say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have - // set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec - // files and you set maxInstances to 10, all spec files will get tested at the same time - // and 30 processes will get spawned. The property handles how many capabilities - // from the same test should run tests. - // - maxInstances: 1, - // - // If you have trouble getting all important capabilities together, check out the - // Sauce Labs platform configurator - a great tool to configure your capabilities: - // https://saucelabs.com/platform/platform-configurator - // - capabilities: [ - { - browserName: "chrome", - "goog:chromeOptions": chromeDefaultOpts, - }, - // Could not find a reliable way to use old chrome, - // skipped here. - { - browserName: "firefox", - "moz:firefoxOptions": firefoxDefaultOpts, - }, - // The browser.url() always timeout on 115. - // Idk what the problem is, let skip it for now. - /* { - browserName: "firefox", - browserVersion: "esr_115.18.0esr", - "moz:firefoxOptions": firefoxDefaultOpts, - }, */ - ...(process.env.TEST_SAFARI - ? [ - { - browserName: "safari", - }, - { - browserName: "safari technology preview", - }, - ] - : []), - ], - - // - // =================== - // Test Configurations - // =================== - // Define all options that are relevant for the WebdriverIO instance here - // - // Level of logging verbosity: trace | debug | info | warn | error | silent - logLevel: "info", - // - // Set specific log levels per logger - // loggers: - // - webdriver, webdriverio - // - @wdio/browserstack-service, @wdio/lighthouse-service, @wdio/sauce-service - // - @wdio/mocha-framework, @wdio/jasmine-framework - // - @wdio/local-runner - // - @wdio/sumologic-reporter - // - @wdio/cli, @wdio/config, @wdio/utils - // Level of logging verbosity: trace | debug | info | warn | error | silent - // logLevels: { - // webdriver: 'info', - // '@wdio/appium-service': 'info' - // }, - // - // If you only want to run your tests until a specific amount of tests have failed use - // bail (default is 0 - don't bail, run all tests). - bail: 0, - // - // Set a base URL in order to shorten url command calls. If your `url` parameter starts - // with `/`, the base url gets prepended, not including the path portion of your baseUrl. - // If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url - // gets prepended directly. - // baseUrl: 'http://localhost:4698', - // - // Default timeout for all waitFor* commands. - waitforTimeout: 10000, - // - // Default timeout in milliseconds for request - // if browser driver or grid doesn't send response - connectionRetryTimeout: 120000, - // - // Default request retries count - connectionRetryCount: 3, - // - // Test runner services - // Services take over a specific job you don't want to take care of. They enhance - // your test setup with almost no effort. Unlike plugins, they don't add new - // commands. Instead, they hook themselves up into the test process. - services: ["vite", "lighthouse"], - - // Framework you want to run your specs with. - // The following are supported: Mocha, Jasmine, and Cucumber - // see also: https://webdriver.io/docs/frameworks - // - // Make sure you have the wdio adapter package for the specific framework installed - // before running any tests. - framework: "mocha", - - // - // The number of times to retry the entire specfile when it fails as a whole - // specFileRetries: 1, - // - // Delay in seconds between the spec file retry attempts - // specFileRetriesDelay: 0, - // - // Whether or not retried spec files should be retried immediately or deferred to the end of the queue - // specFileRetriesDeferred: false, - // - // Test reporter for stdout. - // The only one supported by default is 'dot' - // see also: https://webdriver.io/docs/dot-reporter - reporters: ["spec"], - - // Options to be passed to Mocha. - // See the full list at http://mochajs.org/ - mochaOpts: { - ui: "bdd", - timeout: 60000, - }, - - // - // ===== - // Hooks - // ===== - // WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance - // it and to build services around it. You can either apply a single function or an array of - // methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got - // resolved to continue. - /** - * Gets executed once before all workers get launched. - * @param {object} config wdio configuration object - * @param {Array.} capabilities list of capabilities details - */ - // onPrepare: function (config, capabilities) { - // }, - /** - * Gets executed before a worker process is spawned and can be used to initialize specific service - * for that worker as well as modify runtime environments in an async fashion. - * @param {string} cid capability id (e.g 0-0) - * @param {object} caps object containing capabilities for session that will be spawn in the worker - * @param {object} specs specs to be run in the worker process - * @param {object} args object that will be merged with the main configuration once worker is initialized - * @param {object} execArgv list of string arguments passed to the worker process - */ - // onWorkerStart: function (cid, caps, specs, args, execArgv) { - // }, - /** - * Gets executed just after a worker process has exited. - * @param {string} cid capability id (e.g 0-0) - * @param {number} exitCode 0 - success, 1 - fail - * @param {object} specs specs to be run in the worker process - * @param {number} retries number of retries used - */ - // onWorkerEnd: function (cid, exitCode, specs, retries) { - // }, - /** - * Gets executed just before initialising the webdriver session and test framework. It allows you - * to manipulate configurations depending on the capability or spec. - * @param {object} config wdio configuration object - * @param {Array.} capabilities list of capabilities details - * @param {Array.} specs List of spec file paths that are to be run - * @param {string} cid worker id (e.g. 0-0) - */ - // beforeSession: function (config, capabilities, specs, cid) { - // }, - /** - * Gets executed before test execution begins. At this point you can access to all global - * variables like `browser`. It is the perfect place to define custom commands. - * @param {Array.} capabilities list of capabilities details - * @param {Array.} specs List of spec file paths that are to be run - * @param {object} browser instance of created browser/device session - */ - // before: function (capabilities, specs) { - // }, - /** - * Runs before a WebdriverIO command gets executed. - * @param {string} commandName hook command name - * @param {Array} args arguments that command would receive - */ - // beforeCommand: function (commandName, args) { - // }, - /** - * Hook that gets executed before the suite starts - * @param {object} suite suite details - */ - // beforeSuite: function (suite) { - // }, - /** - * Function to be executed before a test (in Mocha/Jasmine) starts. - */ - // beforeTest: function (test, context) { - // }, - /** - * Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling - * beforeEach in Mocha) - */ - // beforeHook: function (test, context, hookName) { - // }, - /** - * Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling - * afterEach in Mocha) - */ - // afterHook: function (test, context, { error, result, duration, passed, retries }, hookName) { - // }, - /** - * Function to be executed after a test (in Mocha/Jasmine only) - * @param {object} test test object - * @param {object} context scope object the test was executed with - * @param {Error} result.error error object in case the test fails, otherwise `undefined` - * @param {*} result.result return object of test function - * @param {number} result.duration duration of test - * @param {boolean} result.passed true if test has passed, otherwise false - * @param {object} result.retries information about spec related retries, e.g. `{ attempts: 0, limit: 0 }` - */ - // afterTest: function(test, context, { error, result, duration, passed, retries }) { - // }, - - /** - * Hook that gets executed after the suite has ended - * @param {object} suite suite details - */ - // afterSuite: function (suite) { - // }, - /** - * Runs after a WebdriverIO command gets executed - * @param {string} commandName hook command name - * @param {Array} args arguments that command would receive - * @param {number} result 0 - command success, 1 - command error - * @param {object} error error object if any - */ - // afterCommand: function (commandName, args, result, error) { - // }, - /** - * Gets executed after all tests are done. You still have access to all global variables from - * the test. - * @param {number} result 0 - test pass, 1 - test fail - * @param {Array.} capabilities list of capabilities details - * @param {Array.} specs List of spec file paths that ran - */ - // after: function (result, capabilities, specs) { - // }, - /** - * Gets executed right after terminating the webdriver session. - * @param {object} config wdio configuration object - * @param {Array.} capabilities list of capabilities details - * @param {Array.} specs List of spec file paths that ran - */ - // afterSession: function (config, capabilities, specs) { - // }, - /** - * Gets executed after all workers got shut down and the process is about to exit. An error - * thrown in the onComplete hook will result in the test run failing. - * @param {object} exitCode 0 - success, 1 - fail - * @param {object} config wdio configuration object - * @param {Array.} capabilities list of capabilities details - * @param {} results object containing test results - */ - // onComplete: function(exitCode, config, capabilities, results) { - // }, - /** - * Gets executed when a refresh happens. - * @param {string} oldSessionId session ID of the old session - * @param {string} newSessionId session ID of the new session - */ - // onReload: function(oldSessionId, newSessionId) { - // } - /** - * Hook that gets executed before a WebdriverIO assertion happens. - * @param {object} params information about the assertion to be executed - */ - // beforeAssertion: function(params) { - // } - /** - * Hook that gets executed after a WebdriverIO assertion happened. - * @param {object} params information about the assertion that was executed, including its results - */ - // afterAssertion: function(params) { - // } -};