@@ -7,86 +7,104 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
77Please see LICENSE files in the repository root for full details.
88*/
99
10- import React , { type JSX , type ComponentProps } from "react" ;
10+ import React from "react" ;
1111import { screen , render } from "jest-matrix-react" ;
1212import userEvent from "@testing-library/user-event" ;
13- import { type MatrixClient } from "matrix-js-sdk/src/matrix" ;
14- import { MatrixWidgetType } from "matrix-widget-api" ;
15- import {
16- type ApprovalOpts ,
17- type WidgetInfo ,
18- WidgetLifecycle ,
19- } from "@matrix-org/react-sdk-module-api/lib/lifecycles/WidgetLifecycle" ;
20-
21- import { WidgetContextMenu } from "../../../../../src/components/views/context_menus/WidgetContextMenu" ;
22- import { type IApp } from "../../../../../src/stores/WidgetStore" ;
23- import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext" ;
24- import WidgetUtils from "../../../../../src/utils/WidgetUtils" ;
25- import { ModuleRunner } from "../../../../../src/modules/ModuleRunner" ;
26- import SettingsStore from "../../../../../src/settings/SettingsStore" ;
27-
28- describe ( "<WidgetContextMenu />" , ( ) => {
29- const widgetId = "w1" ;
30- const eventId = "e1" ;
31- const roomId = "r1" ;
32- const userId = "@user-id:server" ;
33-
34- const app : IApp = {
35- id : widgetId ,
36- eventId,
37- roomId,
38- type : MatrixWidgetType . Custom ,
39- url : "https://example.com" ,
40- name : "Example 1" ,
41- creatorUserId : userId ,
42- avatar_url : undefined ,
43- } ;
13+ import { WidgetContextMenuAction , WidgetContextMenuSnapshot , WidgetContextMenuView } from "./WidgetContextMenuView" ;
14+ import * as stories from "./WidgetContextMenuView.stories.tsx" ;
15+ import { MockViewModel } from "../../viewmodel/MockViewModel.ts" ;
16+ import { IconButton } from "@vector-im/compound-web" ;
17+ import { composeStories } from "@storybook/react-vite" ;
18+ import TriggerIcon from "@vector-im/compound-design-tokens/assets/web/icons/overflow-horizontal" ;
19+
20+ const { Default, OnlyBasicModification } = composeStories ( stories ) ;
4421
45- let mockClient : MatrixClient ;
22+ describe ( "<WidgetContextMenuView />" , ( ) => {
4623
47- let onFinished : ( ) => void ;
24+ afterEach ( ( ) => {
25+ jest . resetAllMocks ( ) ;
26+ } ) ;
4827
49- beforeEach ( ( ) => {
50- onFinished = jest . fn ( ) ;
51- jest . spyOn ( WidgetUtils , "canUserModifyWidgets" ) . mockReturnValue ( true ) ;
5228
53- mockClient = {
54- getUserId : jest . fn ( ) . mockReturnValue ( userId ) ,
55- } as unknown as MatrixClient ;
29+ it ( "renders widget contextmenu with all options" , ( ) => {
30+ const { container } = render ( < Default /> ) ;
31+ expect ( container ) . toMatchSnapshot ( ) ;
5632 } ) ;
5733
58- afterEach ( ( ) => {
59- jest . restoreAllMocks ( ) ;
34+ it ( "renders widget contextmenu without only basic modification" , ( ) => {
35+ const { container } = render ( < OnlyBasicModification /> ) ;
36+ expect ( container ) . toMatchSnapshot ( ) ;
6037 } ) ;
6138
62- function getComponent ( props : Partial < ComponentProps < typeof WidgetContextMenu > > = { } ) : JSX . Element {
63- return (
64- < MatrixClientContext . Provider value = { mockClient } >
65- < WidgetContextMenu app = { app } onFinished = { onFinished } { ...props } />
66- </ MatrixClientContext . Provider >
67- ) ;
68- }
39+ const onKeyDown = jest . fn ( ) ;
40+ const togglePlay = jest . fn ( ) ;
41+ const onSeekbarChange = jest . fn ( ) ;
42+
43+ const onStreamAudioClick = jest . fn ( ) ;
44+ const onEditClick = jest . fn ( ) ;
45+ const onSnapshotClick = jest . fn ( ) ;
46+ const onDeleteClick = jest . fn ( ) ;
47+ const onRevokeClick = jest . fn ( ) ;
48+ const onFinished = jest . fn ( ) ;
49+ const onMoveButton = jest . fn ( ) ;
50+ class WidgetContextMenuViewModel
51+ extends MockViewModel < WidgetContextMenuSnapshot >
52+ implements WidgetContextMenuAction
53+ {
54+ public onKeyDown = onKeyDown ;
55+ public togglePlay = togglePlay ;
56+ public onSeekbarChange = onSeekbarChange ;
57+
58+ public onStreamAudioClick = onStreamAudioClick ;
59+ public onEditClick = onEditClick ;
60+ public onSnapshotClick = onSnapshotClick ;
61+ public onDeleteClick = onDeleteClick ;
62+ public onRevokeClick = onRevokeClick ;
63+ public onFinished = onFinished ;
64+ public onMoveButton = onMoveButton ;
65+ } ;
6966
70- it ( "renders revoke button" , async ( ) => {
71- const { rerender } = render ( getComponent ( ) ) ;
67+ const defaultValue : WidgetContextMenuSnapshot = {
68+ showStreamAudioStreamButton : true ,
69+ showEditButton : true ,
70+ showRevokeButton : true ,
71+ showDeleteButton : true ,
72+ showSnapshotButton : true ,
73+ showMoveButtons : [ true , true ] ,
74+ canModify : true ,
75+ widgetMessaging : undefined ,
76+ isMenuOpened : true ,
77+ trigger : (
78+ < IconButton size = "24px" >
79+ < TriggerIcon />
80+ </ IconButton >
81+ ) ,
82+ } ;
7283
73- const revokeButton = screen . getByLabelText ( "Revoke permissions" ) ;
74- expect ( revokeButton ) . toBeInTheDocument ( ) ;
84+ it ( "should attach vm methods" , async ( ) => {
85+ const vm = new WidgetContextMenuViewModel ( defaultValue ) ;
7586
76- jest . spyOn ( ModuleRunner . instance , "invoke" ) . mockImplementation ( ( lifecycleEvent , opts , widgetInfo ) => {
77- if ( lifecycleEvent === WidgetLifecycle . PreLoadRequest && ( widgetInfo as WidgetInfo ) . id === widgetId ) {
78- ( opts as ApprovalOpts ) . approved = true ;
79- }
80- } ) ;
87+ render ( < WidgetContextMenuView vm = { vm } /> ) ;
8188
82- rerender ( getComponent ( ) ) ;
83- expect ( revokeButton ) . not . toBeInTheDocument ( ) ;
84- } ) ;
89+ await userEvent . click ( screen . getByRole ( "menuitem" , { name : "Start audio stream" } ) ) ;
90+ expect ( onStreamAudioClick ) . toHaveBeenCalled ( ) ;
91+
92+ await userEvent . click ( screen . getByRole ( "menuitem" , { name : "Edit" } ) ) ;
93+ expect ( onEditClick ) . toHaveBeenCalled ( ) ;
94+
95+ await userEvent . click ( screen . getByRole ( "menuitem" , { name : "Take a picture" } ) ) ;
96+ expect ( onSnapshotClick ) . toHaveBeenCalled ( ) ;
97+
98+ await userEvent . click ( screen . getByRole ( "menuitem" , { name : "Revoke permissions" } ) ) ;
99+ expect ( onRevokeClick ) . toHaveBeenCalled ( ) ;
100+
101+ await userEvent . click ( screen . getByRole ( "menuitem" , { name : "Remove for everyone" } ) ) ;
102+ expect ( onDeleteClick ) . toHaveBeenCalled ( ) ;
103+
104+ await userEvent . click ( screen . getByRole ( "menuitem" , { name : "Move left" } ) ) ;
105+ expect ( onMoveButton ) . toHaveBeenCalledWith ( - 1 ) ;
85106
86- it ( "revokes permissions" , async ( ) => {
87- render ( getComponent ( ) ) ;
88- await userEvent . click ( screen . getByLabelText ( "Revoke permissions" ) ) ;
89- expect ( onFinished ) . toHaveBeenCalled ( ) ;
90- expect ( SettingsStore . getValue ( "allowedWidgets" , roomId ) [ eventId ] ) . toBe ( false ) ;
107+ await userEvent . click ( screen . getByRole ( "menuitem" , { name : "Move right" } ) ) ;
108+ expect ( onMoveButton ) . toHaveBeenCalledWith ( 1 ) ;
91109 } ) ;
92110} ) ;
0 commit comments