mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-13 19:58:09 +00:00
fix: make todos and commands working in meeting minutes (#7244)
Signed-off-by: Alexander Onnikov <Alexander.Onnikov@xored.com>
This commit is contained in:
parent
db5890b831
commit
1d1e9cdd98
@ -19,6 +19,7 @@
|
|||||||
import Icon from './Icon.svelte'
|
import Icon from './Icon.svelte'
|
||||||
import Label from './Label.svelte'
|
import Label from './Label.svelte'
|
||||||
|
|
||||||
|
export let id: string | undefined = undefined
|
||||||
export let label: IntlString
|
export let label: IntlString
|
||||||
export let icon: Asset | AnySvelteComponent | undefined = undefined
|
export let icon: Asset | AnySvelteComponent | undefined = undefined
|
||||||
|
|
||||||
@ -27,7 +28,7 @@
|
|||||||
export let invisible: boolean = false
|
export let invisible: boolean = false
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="antiSection">
|
<div class="antiSection" {id}>
|
||||||
{#if showHeader}
|
{#if showHeader}
|
||||||
<div class="antiSection-header" class:high class:invisible>
|
<div class="antiSection-header" class:high class:invisible>
|
||||||
{#if icon}
|
{#if icon}
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
} from '@hcengineering/activity'
|
} from '@hcengineering/activity'
|
||||||
import { Doc, Ref, SortingOrder } from '@hcengineering/core'
|
import { Doc, Ref, SortingOrder } from '@hcengineering/core'
|
||||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||||
import { Grid, Label, Spinner, location, Lazy } from '@hcengineering/ui'
|
import { Grid, Label, Section, Spinner, location, Lazy } from '@hcengineering/ui'
|
||||||
import { onDestroy, onMount } from 'svelte'
|
import { onDestroy, onMount } from 'svelte'
|
||||||
|
|
||||||
import ActivityExtensionComponent from './ActivityExtension.svelte'
|
import ActivityExtensionComponent from './ActivityExtension.svelte'
|
||||||
@ -235,77 +235,81 @@
|
|||||||
$: void updateActivityMessages(object._id, isNewestFirst ? SortingOrder.Descending : SortingOrder.Ascending)
|
$: void updateActivityMessages(object._id, isNewestFirst ? SortingOrder.Descending : SortingOrder.Ascending)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="antiSection-header high mt-9" class:invisible={transparent}>
|
<div class="step-tb-6">
|
||||||
<span class="antiSection-header__title flex-row-center">
|
<Section label={activity.string.Activity} icon={activity.icon.Activity}>
|
||||||
<Label label={activity.string.Activity} />
|
<svelte:fragment slot="header">
|
||||||
{#if isLoading}
|
{#if isLoading}
|
||||||
<div class="ml-1">
|
<div class="ml-1">
|
||||||
<Spinner size="small" />
|
<Spinner size="small" />
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
<ActivityFilter
|
||||||
<ActivityFilter
|
messages={allMessages}
|
||||||
messages={allMessages}
|
{object}
|
||||||
{object}
|
on:update={(e) => {
|
||||||
on:update={(e) => {
|
filteredMessages = e.detail
|
||||||
filteredMessages = e.detail
|
}}
|
||||||
}}
|
bind:isNewestFirst
|
||||||
bind:isNewestFirst
|
/>
|
||||||
/>
|
</svelte:fragment>
|
||||||
</div>
|
|
||||||
{#if isNewestFirst && showCommenInput}
|
<svelte:fragment slot="content">
|
||||||
<div class="ref-input newest-first">
|
{#if isNewestFirst && showCommenInput}
|
||||||
<ActivityExtensionComponent
|
<div class="ref-input newest-first">
|
||||||
kind="input"
|
<ActivityExtensionComponent
|
||||||
{extensions}
|
kind="input"
|
||||||
props={{ object, boundary, focusIndex, withTypingInfo: true }}
|
{extensions}
|
||||||
/>
|
props={{ object, boundary, focusIndex, withTypingInfo: true }}
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
<div
|
|
||||||
class="p-activity select-text"
|
|
||||||
id={activity.string.Activity}
|
|
||||||
class:newest-first={isNewestFirst}
|
|
||||||
bind:this={activityBox}
|
|
||||||
>
|
|
||||||
{#if filteredMessages.length}
|
|
||||||
<Grid column={1} rowGap={0}>
|
|
||||||
{#each filteredMessages as message, index}
|
|
||||||
{@const canGroup = canGroupMessages(message, filteredMessages[index - 1])}
|
|
||||||
{#if selectedMessageId}
|
|
||||||
<ActivityMessagePresenter
|
|
||||||
value={message}
|
|
||||||
doc={object}
|
|
||||||
hideLink={true}
|
|
||||||
type={canGroup ? 'short' : 'default'}
|
|
||||||
isHighlighted={selectedMessageId === message._id}
|
|
||||||
withShowMore
|
|
||||||
/>
|
/>
|
||||||
{:else}
|
</div>
|
||||||
<Lazy>
|
{/if}
|
||||||
<ActivityMessagePresenter
|
<div
|
||||||
value={message}
|
class="p-activity select-text"
|
||||||
doc={object}
|
id={activity.string.Activity}
|
||||||
hideLink={true}
|
class:newest-first={isNewestFirst}
|
||||||
type={canGroup ? 'short' : 'default'}
|
bind:this={activityBox}
|
||||||
isHighlighted={selectedMessageId === message._id}
|
>
|
||||||
withShowMore
|
{#if filteredMessages.length}
|
||||||
/>
|
<Grid column={1} rowGap={0}>
|
||||||
</Lazy>
|
{#each filteredMessages as message, index}
|
||||||
|
{@const canGroup = canGroupMessages(message, filteredMessages[index - 1])}
|
||||||
|
{#if selectedMessageId}
|
||||||
|
<ActivityMessagePresenter
|
||||||
|
value={message}
|
||||||
|
doc={object}
|
||||||
|
hideLink={true}
|
||||||
|
type={canGroup ? 'short' : 'default'}
|
||||||
|
isHighlighted={selectedMessageId === message._id}
|
||||||
|
withShowMore
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
|
<Lazy>
|
||||||
|
<ActivityMessagePresenter
|
||||||
|
value={message}
|
||||||
|
doc={object}
|
||||||
|
hideLink={true}
|
||||||
|
type={canGroup ? 'short' : 'default'}
|
||||||
|
isHighlighted={selectedMessageId === message._id}
|
||||||
|
withShowMore
|
||||||
|
/>
|
||||||
|
</Lazy>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</Grid>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
</div>
|
||||||
</Grid>
|
{#if showCommenInput && !isNewestFirst}
|
||||||
{/if}
|
<div class="ref-input oldest-first">
|
||||||
|
<ActivityExtensionComponent
|
||||||
|
kind="input"
|
||||||
|
{extensions}
|
||||||
|
props={{ object, boundary, focusIndex, withTypingInfo: true }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</svelte:fragment>
|
||||||
|
</Section>
|
||||||
</div>
|
</div>
|
||||||
{#if showCommenInput && !isNewestFirst}
|
|
||||||
<div class="ref-input oldest-first">
|
|
||||||
<ActivityExtensionComponent
|
|
||||||
kind="input"
|
|
||||||
{extensions}
|
|
||||||
props={{ object, boundary, focusIndex, withTypingInfo: true }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.ref-input {
|
.ref-input {
|
||||||
|
@ -14,16 +14,16 @@
|
|||||||
-->
|
-->
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher } from 'svelte'
|
import { createEventDispatcher } from 'svelte'
|
||||||
|
import { ActivityMessage, ActivityMessagesFilter } from '@hcengineering/activity'
|
||||||
import { Doc, Ref, SortingOrder } from '@hcengineering/core'
|
import { Doc, Ref, SortingOrder } from '@hcengineering/core'
|
||||||
import { getResource } from '@hcengineering/platform'
|
import { getResource } from '@hcengineering/platform'
|
||||||
import { getClient } from '@hcengineering/presentation'
|
import { getClient } from '@hcengineering/presentation'
|
||||||
import { ActionIcon, eventToHTMLElement, Icon, Label, showPopup } from '@hcengineering/ui'
|
import { Button, eventToHTMLElement, Icon, Label, showPopup } from '@hcengineering/ui'
|
||||||
import { ActivityMessage, ActivityMessagesFilter } from '@hcengineering/activity'
|
import view from '@hcengineering/view'
|
||||||
|
|
||||||
import activity from '../plugin'
|
import activity from '../plugin'
|
||||||
import FilterPopup from './FilterPopup.svelte'
|
import FilterPopup from './FilterPopup.svelte'
|
||||||
import IconClose from './icons/Close.svelte'
|
import IconClose from './icons/Close.svelte'
|
||||||
import IconFilter from './icons/Filter.svelte'
|
|
||||||
import { sortActivityMessages } from '../activityMessagesUtils'
|
import { sortActivityMessages } from '../activityMessagesUtils'
|
||||||
|
|
||||||
export let messages: ActivityMessage[]
|
export let messages: ActivityMessage[]
|
||||||
@ -146,4 +146,6 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
<div class="w-4 min-w-4 max-w-4" />
|
<div class="w-4 min-w-4 max-w-4" />
|
||||||
<ActionIcon icon={IconFilter} size={'medium'} action={handleOptions} />
|
<div class="buttons-group small-gap pr-2">
|
||||||
|
<Button icon={view.icon.Configure} size={'small'} kind={'ghost'} on:click={handleOptions} />
|
||||||
|
</div>
|
||||||
|
@ -68,7 +68,7 @@
|
|||||||
let preference: ViewletPreference | undefined
|
let preference: ViewletPreference | undefined
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Section label={contact.string.Members} icon={IconMembersOutline}>
|
<Section id="members" label={contact.string.Members} icon={IconMembersOutline}>
|
||||||
<svelte:fragment slot="header">
|
<svelte:fragment slot="header">
|
||||||
<div class="buttons-group xsmall-gap">
|
<div class="buttons-group xsmall-gap">
|
||||||
<ViewletSelector
|
<ViewletSelector
|
||||||
|
@ -33,15 +33,13 @@
|
|||||||
|
|
||||||
<Section label={love.string.MeetingMinutes} icon={love.icon.Cam}>
|
<Section label={love.string.MeetingMinutes} icon={love.icon.Cam}>
|
||||||
<svelte:fragment slot="header">
|
<svelte:fragment slot="header">
|
||||||
<div class="flex-row-center gap-2 reverse">
|
<ViewletsSettingButton
|
||||||
<ViewletsSettingButton
|
viewletQuery={{ _id: love.viewlet.TableMeetingMinutesEmbedded }}
|
||||||
viewletQuery={{ _id: love.viewlet.TableMeetingMinutesEmbedded }}
|
kind={'tertiary'}
|
||||||
kind={'tertiary'}
|
bind:viewlet
|
||||||
bind:viewlet
|
bind:loading
|
||||||
bind:loading
|
bind:preference
|
||||||
bind:preference
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
|
|
||||||
<svelte:fragment slot="content">
|
<svelte:fragment slot="content">
|
||||||
|
@ -250,37 +250,39 @@
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (withSideMenu) {
|
}
|
||||||
optionalExtensions.push(
|
|
||||||
LeftMenuExtension.configure({
|
if (withSideMenu) {
|
||||||
width: 20,
|
optionalExtensions.push(
|
||||||
height: 20,
|
LeftMenuExtension.configure({
|
||||||
marginX: 8,
|
width: 20,
|
||||||
className: 'tiptap-left-menu',
|
height: 20,
|
||||||
icon: view.icon.Add,
|
marginX: 8,
|
||||||
iconProps: {
|
className: 'tiptap-left-menu',
|
||||||
className: 'svg-tiny',
|
icon: view.icon.Add,
|
||||||
fill: 'currentColor'
|
iconProps: {
|
||||||
},
|
className: 'svg-tiny',
|
||||||
items: [
|
fill: 'currentColor'
|
||||||
...(canEmbedImages ? [{ id: 'image', label: textEditor.string.Image, icon: view.icon.Image }] : []),
|
},
|
||||||
{ id: 'table', label: textEditor.string.Table, icon: view.icon.Table2 },
|
items: [
|
||||||
{ id: 'code-block', label: textEditor.string.CodeBlock, icon: view.icon.CodeBlock },
|
...(canEmbedImages ? [{ id: 'image', label: textEditor.string.Image, icon: view.icon.Image }] : []),
|
||||||
{ id: 'separator-line', label: textEditor.string.SeparatorLine, icon: view.icon.SeparatorLine },
|
{ id: 'table', label: textEditor.string.Table, icon: view.icon.Table2 },
|
||||||
{ id: 'todo-list', label: textEditor.string.TodoList, icon: view.icon.TodoList },
|
{ id: 'code-block', label: textEditor.string.CodeBlock, icon: view.icon.CodeBlock },
|
||||||
{ id: 'drawing-board', label: textEditor.string.DrawingBoard, icon: IconScribble as any }
|
{ id: 'separator-line', label: textEditor.string.SeparatorLine, icon: view.icon.SeparatorLine },
|
||||||
],
|
{ id: 'todo-list', label: textEditor.string.TodoList, icon: view.icon.TodoList },
|
||||||
handleSelect: handleLeftMenuClick
|
{ id: 'drawing-board', label: textEditor.string.DrawingBoard, icon: IconScribble as any }
|
||||||
})
|
],
|
||||||
|
handleSelect: handleLeftMenuClick
|
||||||
|
})
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (withInlineCommands) {
|
||||||
|
optionalExtensions.push(
|
||||||
|
InlineCommandsExtension.configure(
|
||||||
|
inlineCommandsConfig(handleLeftMenuClick, attachFile === undefined || !canEmbedImages ? ['image'] : [])
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
if (withInlineCommands) {
|
|
||||||
optionalExtensions.push(
|
|
||||||
InlineCommandsExtension.configure(
|
|
||||||
inlineCommandsConfig(handleLeftMenuClick, attachFile === undefined || !canEmbedImages ? ['image'] : [])
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let inputImage: HTMLInputElement
|
let inputImage: HTMLInputElement
|
||||||
|
@ -41,10 +41,11 @@
|
|||||||
editor.off('selectionUpdate', handleSelectionUpdate)
|
editor.off('selectionUpdate', handleSelectionUpdate)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
$: todoable = objectId !== undefined && objectClass !== undefined
|
||||||
$: todoId = node.attrs.todoid as Ref<ToDo>
|
$: todoId = node.attrs.todoid as Ref<ToDo>
|
||||||
$: userId = node.attrs.userid as Ref<Person>
|
$: userId = node.attrs.userid as Ref<Person>
|
||||||
$: checked = node.attrs.checked ?? false
|
$: checked = node.attrs.checked ?? false
|
||||||
$: readonly = !editor.isEditable || objectId === undefined
|
$: readonly = !editor.isEditable || (!todoable && todoId != null)
|
||||||
|
|
||||||
let todo: ToDo | undefined = undefined
|
let todo: ToDo | undefined = undefined
|
||||||
$: query.query(
|
$: query.query(
|
||||||
@ -59,7 +60,7 @@
|
|||||||
)
|
)
|
||||||
|
|
||||||
async function syncTodo (todo: ToDo | undefined): Promise<void> {
|
async function syncTodo (todo: ToDo | undefined): Promise<void> {
|
||||||
if (todo !== undefined) {
|
if (todo !== undefined && todo.attachedTo === objectId && todo.attachedToClass === objectClass) {
|
||||||
const todoChecked = todo.doneOn != null
|
const todoChecked = todo.doneOn != null
|
||||||
if (todo._id !== todoId || todo.user !== userId || todoChecked !== checked) {
|
if (todo._id !== todoId || todo.user !== userId || todoChecked !== checked) {
|
||||||
updateAttributes({
|
updateAttributes({
|
||||||
@ -212,16 +213,18 @@
|
|||||||
class:hovered
|
class:hovered
|
||||||
class:focused
|
class:focused
|
||||||
>
|
>
|
||||||
<div class="flex-center assignee" contenteditable="false">
|
{#if todoable}
|
||||||
<EmployeePresenter
|
<div class="flex-center assignee" contenteditable="false">
|
||||||
value={userId}
|
<EmployeePresenter
|
||||||
disabled={readonly}
|
value={userId}
|
||||||
avatarSize={'card'}
|
disabled={readonly}
|
||||||
shouldShowName={false}
|
avatarSize={'card'}
|
||||||
shouldShowPlaceholder
|
shouldShowName={false}
|
||||||
onEmployeeEdit={handleAssigneeEdit}
|
shouldShowPlaceholder
|
||||||
/>
|
onEmployeeEdit={handleAssigneeEdit}
|
||||||
</div>
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<div class="flex-center todo-check" contenteditable="false">
|
<div class="flex-center todo-check" contenteditable="false">
|
||||||
<CheckBox {readonly} {checked} on:value={markDone} kind={'positive'} size={'medium'} />
|
<CheckBox {readonly} {checked} on:value={markDone} kind={'positive'} size={'medium'} />
|
||||||
|
@ -56,23 +56,24 @@ function isTodoableClass (objectClass: Ref<Class<Doc>>): boolean {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function isTodoable (mode: TextEditorMode, objectClass?: Ref<Class<Doc>>): boolean {
|
function isTodoable (mode: TextEditorMode): boolean {
|
||||||
return mode === 'full' && objectClass !== undefined && isTodoableClass(objectClass)
|
return mode === 'full'
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createTodoItemExtension (mode: TextEditorMode, ctx: any): AnyExtension | undefined {
|
export function createTodoItemExtension (mode: TextEditorMode, ctx: any): AnyExtension | undefined {
|
||||||
if (!isTodoable(mode, ctx.objectClass)) {
|
if (!isTodoable(mode)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const { objectId, objectClass, objectSpace } = ctx
|
const { objectId, objectClass, objectSpace } = ctx
|
||||||
|
const componentProps = isTodoableClass(objectClass) ? { objectId, objectClass, objectSpace } : {}
|
||||||
|
|
||||||
return TodoItemExtension.extend({
|
return TodoItemExtension.extend({
|
||||||
addNodeView () {
|
addNodeView () {
|
||||||
return SvelteNodeViewRenderer(ToDoItemNodeView, {
|
return SvelteNodeViewRenderer(ToDoItemNodeView, {
|
||||||
contentAs: 'li',
|
contentAs: 'li',
|
||||||
contentClass: 'todo-item',
|
contentClass: 'todo-item',
|
||||||
componentProps: { objectId, objectClass, objectSpace }
|
componentProps
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}).configure({
|
}).configure({
|
||||||
@ -83,7 +84,7 @@ export function createTodoItemExtension (mode: TextEditorMode, ctx: any): AnyExt
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function createTodoListExtension (mode: TextEditorMode, ctx: any): AnyExtension | undefined {
|
export function createTodoListExtension (mode: TextEditorMode, ctx: any): AnyExtension | undefined {
|
||||||
if (!isTodoable(mode, ctx.objectClass)) {
|
if (!isTodoable(mode)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,9 +95,9 @@
|
|||||||
{/if}
|
{/if}
|
||||||
<ModernButton
|
<ModernButton
|
||||||
icon={view.icon.Configure}
|
icon={view.icon.Configure}
|
||||||
label={view.string.Show}
|
|
||||||
{kind}
|
{kind}
|
||||||
size={'small'}
|
size={'small'}
|
||||||
|
iconSize={'small'}
|
||||||
{disabled}
|
{disabled}
|
||||||
{pressed}
|
{pressed}
|
||||||
tooltip={{ label: view.string.CustomizeView, direction: 'bottom' }}
|
tooltip={{ label: view.string.CustomizeView, direction: 'bottom' }}
|
||||||
|
@ -14,7 +14,7 @@ export class CommonRecruitingPage extends CalendarPage {
|
|||||||
readonly inputComment = (): Locator => this.page.locator('div.text-input div.tiptap')
|
readonly inputComment = (): Locator => this.page.locator('div.text-input div.tiptap')
|
||||||
readonly buttonSendComment = (): Locator => this.page.locator('g#Send')
|
readonly buttonSendComment = (): Locator => this.page.locator('g#Send')
|
||||||
readonly textComment = (): Locator => this.page.locator('div.showMore-content p')
|
readonly textComment = (): Locator => this.page.locator('div.showMore-content p')
|
||||||
readonly inputAddAttachment = (): Locator => this.page.locator('div.antiSection #file')
|
readonly inputAddAttachment = (): Locator => this.page.locator('div.antiSection #file').first()
|
||||||
readonly textAttachmentName = (): Locator => this.page.locator('div.attachment-container > a')
|
readonly textAttachmentName = (): Locator => this.page.locator('div.attachment-container > a')
|
||||||
readonly buttonCreateFirstReview = (): Locator => this.page.locator('span:has-text("Create review")')
|
readonly buttonCreateFirstReview = (): Locator => this.page.locator('span:has-text("Create review")')
|
||||||
readonly buttonMoreActions = (): Locator =>
|
readonly buttonMoreActions = (): Locator =>
|
||||||
|
@ -15,9 +15,12 @@ export class CompanyDetailsPage extends CommonRecruitingPage {
|
|||||||
readonly buttonLocation = (): Locator =>
|
readonly buttonLocation = (): Locator =>
|
||||||
this.page.locator('//span[text()="Location"]/following-sibling::div[1]/button/span')
|
this.page.locator('//span[text()="Location"]/following-sibling::div[1]/button/span')
|
||||||
|
|
||||||
readonly addMemberButton = (): Locator => this.page.locator('[id="contact\\:string\\:AddMember"]')
|
readonly addMemberButton = (): Locator =>
|
||||||
|
this.page.locator('div.antiSection[id="members"]').locator('[id="contact\\:string\\:AddMember"]')
|
||||||
|
|
||||||
readonly selectMember = (memberName: string): Locator => this.page.getByRole('button', { name: memberName })
|
readonly selectMember = (memberName: string): Locator => this.page.getByRole('button', { name: memberName })
|
||||||
readonly member = (memberName: string): Locator => this.page.getByRole('link', { name: memberName })
|
readonly member = (memberName: string): Locator =>
|
||||||
|
this.page.locator('div.antiSection[id="members"]').getByRole('link', { name: memberName })
|
||||||
|
|
||||||
async checkCompany (data: NewCompany): Promise<void> {
|
async checkCompany (data: NewCompany): Promise<void> {
|
||||||
await expect(this.inputName()).toHaveValue(data.name)
|
await expect(this.inputName()).toHaveValue(data.name)
|
||||||
|
Loading…
Reference in New Issue
Block a user