Move view model code to shared components package (#31024)

* Remove vm related code from element-web/src

* Add and export view model code from package

* Update imports

* Rewrite vm tests using vitest

* Add github action to run vm tests

* Fix lint errors

* Mvoe tests over to jest

* Try fixing code coverage

* Second attempt at fixing code coverage
This commit is contained in:
R Midhun Suresh
2025-10-15 19:19:12 +05:30
committed by GitHub
parent ac96ab0d46
commit 2598e4ea22
22 changed files with 29 additions and 17 deletions

View File

@@ -46,6 +46,7 @@ const config: Config = {
],
collectCoverageFrom: [
"<rootDir>/src/**/*.{js,ts,tsx}",
"<rootDir>/packages/**/*.{js,ts,tsx}",
// getSessionLock is piped into a different JS context via stringification, and the coverage functionality is
// not available in that contest. So, turn off coverage instrumentation for it.
"!<rootDir>/src/utils/SessionLock.ts",

View File

@@ -54,7 +54,6 @@
"@storybook/test-runner": "^0.23.0",
"concurrently": "^9.2.1",
"eslint": "8",
"jest-image-snapshot": "^6.5.1",
"eslint-plugin-storybook": "^9.1.10",
"jest-image-snapshot": "^6.5.1",
"patch-package": "^8.0.1",

View File

@@ -8,8 +8,8 @@
import React, { type JSX, useMemo, type ComponentType } from "react";
import { omitBy, pickBy } from "lodash";
import { MockViewModel } from "./MockViewModel";
import { type ViewModel } from "./ViewModel";
import { MockViewModel } from "./viewmodel/MockViewModel";
import { type ViewModel } from "./viewmodel/ViewModel";
interface ViewWrapperProps<V> {
/**

View File

@@ -13,7 +13,7 @@ import { fireEvent } from "@testing-library/dom";
import * as stories from "./AudioPlayerView.stories.tsx";
import { AudioPlayerView, type AudioPlayerViewActions, type AudioPlayerViewSnapshot } from "./AudioPlayerView";
import { MockViewModel } from "../../MockViewModel";
import { MockViewModel } from "../../viewmodel/MockViewModel.ts";
const { Default, NoMediaName, NoSize, HasError } = composeStories(stories);

View File

@@ -7,7 +7,7 @@
import React, { type ChangeEventHandler, type JSX, type KeyboardEventHandler, type MouseEventHandler } from "react";
import { type ViewModel } from "../../ViewModel";
import { type ViewModel } from "../../viewmodel/ViewModel";
import { useViewModel } from "../../useViewModel";
import { MediaBody } from "../../message-body/MediaBody";
import { Flex } from "../../utils/Flex";

View File

@@ -9,7 +9,7 @@ import React from "react";
import { type Meta, type StoryFn } from "@storybook/react-vite";
import { TextualEventView as TextualEventComponent } from "./TextualEventView";
import { MockViewModel } from "../../MockViewModel";
import { MockViewModel } from "../../viewmodel/MockViewModel";
export default {
title: "Event/TextualEvent",

View File

@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
import React, { type ReactNode, type JSX } from "react";
import { type ViewModel } from "../../ViewModel";
import { type ViewModel } from "../../viewmodel/ViewModel";
import { useViewModel } from "../../useViewModel";
export type TextualEventViewSnapshot = {

View File

@@ -27,7 +27,6 @@ export * from "./utils/DateUtils";
export * from "./utils/numbers";
// MVVM
export * from "./viewmodel";
export * from "./ViewWrapper";
export type * from "./ViewModel";
export * from "./useViewModel";
export * from "./MockViewModel";

View File

@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
import { useSyncExternalStore } from "react";
import { type ViewModel } from "./ViewModel";
import { type ViewModel } from "./viewmodel/ViewModel";
/**
* A small wrapper around useSyncExternalStore to use a view model in a shared component view

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type ViewModel } from "../../../packages/shared-components/src/ViewModel";
import { type ViewModel } from "./ViewModel";
import { Disposables } from "./Disposables";
import { Snapshot } from "./Snapshot";
import { ViewModelSubscriptions } from "./ViewModelSubscriptions";

View File

@@ -0,0 +1,13 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
export * from "./BaseViewModel";
export * from "./Disposables";
export * from "./Snapshot";
export * from "./ViewModelSubscriptions";
export type * from "./ViewModel";
export * from "./MockViewModel";

View File

@@ -6,7 +6,7 @@ Please see LICENSE files in the repository root for full details.
import { EventEmitter } from "events";
import { Disposables } from "../../../src/viewmodels/base/Disposables";
import { Disposables } from "..";
describe("Disposable", () => {
it("isDisposed is true after dispose() is called", () => {

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { Snapshot } from "../../../src/viewmodels/base/Snapshot";
import { Snapshot } from "..";
interface TestSnapshot {
key1: string;

View File

@@ -5,7 +5,7 @@ sonar.organization=element-hq
#sonar.sourceEncoding=UTF-8
sonar.sources=src,res,packages/shared-components/src
sonar.tests=test,playwright,src
sonar.tests=test,playwright,src,packages
sonar.test.inclusions=test/*,playwright/*,src/**/*.test.*,packages/*/src/**/*.test.*
sonar.exclusions=__mocks__,docs,element.io,nginx

View File

@@ -17,7 +17,7 @@ import { UPDATE_EVENT } from "../../stores/AsyncStore";
import { percentageOf } from "../../../packages/shared-components/src/utils/numbers";
import { getKeyBindingsManager } from "../../KeyBindingsManager";
import { KeyBindingAction } from "../../accessibility/KeyboardShortcuts";
import { BaseViewModel } from "../base/BaseViewModel";
import { BaseViewModel } from "../../../packages/shared-components/src/viewmodel";
/**
* The number of seconds to skip when the user presses the left or right arrow keys.

View File

@@ -11,7 +11,7 @@ import { type EventTileTypeProps } from "../../events/EventTileFactory";
import { MatrixClientPeg } from "../../MatrixClientPeg";
import { textForEvent } from "../../TextForEvent";
import { type TextualEventViewSnapshot } from "../../../packages/shared-components/src/event-tiles/TextualEventView/TextualEventView";
import { BaseViewModel } from "../base/BaseViewModel";
import { BaseViewModel } from "../../../packages/shared-components/src/viewmodel";
export class TextualEventViewModel extends BaseViewModel<TextualEventViewSnapshot, EventTileTypeProps> {
public constructor(props: EventTileTypeProps) {

View File

@@ -3999,7 +3999,7 @@
resolved "https://registry.yarnpkg.com/@vector-im/matrix-wysiwyg/-/matrix-wysiwyg-2.40.0.tgz#53c9ca5ea907d91e4515da64f20a82e5586b882c"
integrity sha512-8LRFLs5PEKYs4lOL7aJ4lL/hGCrvEvOYkCR3JggXYXDVMtX4LmfdlKYucSAe98pCmqAAbLRvlRcR1bTOYvM8ug==
dependencies:
"@vector-im/matrix-wysiwyg-wasm" "link:../../Library/Caches/Yarn/v6/npm-@vector-im-matrix-wysiwyg-2.40.0-53c9ca5ea907d91e4515da64f20a82e5586b882c-integrity/node_modules/bindings/wysiwyg-wasm"
"@vector-im/matrix-wysiwyg-wasm" "link:../../.cache/yarn/v6/npm-@vector-im-matrix-wysiwyg-2.40.0-53c9ca5ea907d91e4515da64f20a82e5586b882c-integrity/node_modules/bindings/wysiwyg-wasm"
"@vitest/expect@3.2.4":
version "3.2.4"