mirror of
https://github.com/hcengineering/platform.git
synced 2026-10-01 05:55:09 +02:00
Add Labels support (#2104)
Signed-off-by: Dvinyanin Alexandr <dvinyanin.alexandr@gmail.com>
This commit is contained in:
@@ -6,6 +6,7 @@ Tracker:
|
||||
|
||||
- Issue state history.
|
||||
- Subissue issue popup.
|
||||
- Label support
|
||||
|
||||
Lead:
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
"@anticrm/view": "~0.6.0",
|
||||
"@anticrm/model-presentation": "~0.6.0",
|
||||
"@anticrm/setting": "~0.6.1",
|
||||
"@anticrm/task": "~0.6.0"
|
||||
"@anticrm/task": "~0.6.0",
|
||||
"@anticrm/tags": "~0.6.2"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ import {
|
||||
Team
|
||||
} from '@anticrm/tracker'
|
||||
import { KeyBinding } from '@anticrm/view'
|
||||
import tags from '@anticrm/tags'
|
||||
import tracker from './plugin'
|
||||
|
||||
import presentation from '@anticrm/model-presentation'
|
||||
@@ -184,8 +185,8 @@ export class TIssue extends TAttachedDoc implements Issue {
|
||||
@Prop(Collection(attachment.class.Attachment), tracker.string.Attachments)
|
||||
attachments!: number
|
||||
|
||||
// @Prop(Collection(core.class.TypeString), tracker.string.Labels)
|
||||
labels?: string[]
|
||||
@Prop(Collection(tags.class.TagReference), tracker.string.Labels)
|
||||
labels?: number
|
||||
|
||||
declare space: Ref<Team>
|
||||
|
||||
|
||||
@@ -14,8 +14,9 @@
|
||||
//
|
||||
|
||||
import core, { Doc, generateId, Ref, SortingOrder, TxOperations, TxResult } from '@anticrm/core'
|
||||
import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@anticrm/model'
|
||||
import { createOrUpdate, MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@anticrm/model'
|
||||
import { IssueStatus, IssueStatusCategory, Team, genRanks, Issue } from '@anticrm/tracker'
|
||||
import tags from '@anticrm/tags'
|
||||
import { DOMAIN_TRACKER } from '.'
|
||||
import tracker from './plugin'
|
||||
|
||||
@@ -256,6 +257,19 @@ async function upgradeProjectIcons (tx: TxOperations): Promise<void> {
|
||||
|
||||
async function createDefaults (tx: TxOperations): Promise<void> {
|
||||
await createDefaultTeam(tx)
|
||||
await createOrUpdate(
|
||||
tx,
|
||||
tags.class.TagCategory,
|
||||
tags.space.Tags,
|
||||
{
|
||||
icon: tags.icon.Tags,
|
||||
label: 'Other',
|
||||
targetClass: tracker.class.Issue,
|
||||
tags: [],
|
||||
default: true
|
||||
},
|
||||
tracker.category.Other
|
||||
)
|
||||
}
|
||||
|
||||
async function upgradeTeams (tx: TxOperations): Promise<void> {
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
"Unassigned": "Unassigned",
|
||||
"Back": "Back",
|
||||
"List": "List",
|
||||
"NumberLabels": "{count, plural, =0 {no labels} =1 {1 label} other {# labels}}",
|
||||
|
||||
"CategoryBacklog": "Backlog",
|
||||
"CategoryUnstarted": "Unstarted",
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
"Unassigned": "Не назначен",
|
||||
"Back": "Назад",
|
||||
"List": "Список",
|
||||
"NumberLabels": "{count, plural, =0 {нет меток} =1 {1 метка} =2 {2 метки} =3 {3 метки} =4 {4 метки} other {# меток}}",
|
||||
|
||||
"CategoryBacklog": "Пул",
|
||||
"CategoryUnstarted": "Не запущенные",
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
"@anticrm/login": "~0.6.1",
|
||||
"@anticrm/setting": "~0.6.1",
|
||||
"@anticrm/calendar": "~0.6.0",
|
||||
"@anticrm/tags": "~0.6.2",
|
||||
"@anticrm/task": "~0.6.0",
|
||||
"@anticrm/chunter": "~0.6.1",
|
||||
"@anticrm/notification": "~0.6.0",
|
||||
|
||||
@@ -15,12 +15,14 @@
|
||||
<script lang="ts">
|
||||
import { AttachmentStyledBox } from '@anticrm/attachment-resources'
|
||||
import { Employee } from '@anticrm/contact'
|
||||
import core, { AttachedData, generateId, Ref, SortingOrder, WithLookup } from '@anticrm/core'
|
||||
import { Card, createQuery, getClient, SpaceSelector } from '@anticrm/presentation'
|
||||
import core, { Account, AttachedData, Doc, generateId, Ref, SortingOrder, WithLookup } from '@anticrm/core'
|
||||
import { Card, createQuery, getClient, KeyedAttribute, SpaceSelector } from '@anticrm/presentation'
|
||||
import { calcRank, Issue, IssuePriority, IssueStatus, Project, Team } from '@anticrm/tracker'
|
||||
import tags, { TagElement, TagReference } from '@anticrm/tags'
|
||||
import {
|
||||
ActionIcon,
|
||||
Button,
|
||||
Component,
|
||||
DatePresenter,
|
||||
EditBox,
|
||||
IconAttachment,
|
||||
@@ -48,6 +50,7 @@
|
||||
let currentAssignee: Ref<Employee> | null = assignee
|
||||
let issueStatuses: WithLookup<IssueStatus>[] | undefined
|
||||
let parentIssue: Issue | undefined
|
||||
let labels: TagReference[] = []
|
||||
|
||||
let objectId: Ref<Issue> = generateId()
|
||||
let object: AttachedData<Issue> = {
|
||||
@@ -70,6 +73,11 @@
|
||||
|
||||
let descriptionBox: AttachmentStyledBox
|
||||
|
||||
const key: KeyedAttribute = {
|
||||
key: 'labels',
|
||||
attr: client.getHierarchy().getAttribute(tracker.class.Issue, 'labels')
|
||||
}
|
||||
|
||||
$: _space = space
|
||||
$: updateIssueStatusId(space, status)
|
||||
$: canSave = getTitle(object.title ?? '').length > 0
|
||||
@@ -147,6 +155,13 @@
|
||||
value,
|
||||
objectId
|
||||
)
|
||||
for (const label of labels) {
|
||||
await client.addCollection(label._class, label.space, objectId, tracker.class.Issue, 'labels', {
|
||||
title: label.title,
|
||||
color: label.color,
|
||||
tag: label.tag
|
||||
})
|
||||
}
|
||||
await descriptionBox.createAttachments()
|
||||
objectId = generateId()
|
||||
}
|
||||
@@ -201,6 +216,25 @@
|
||||
|
||||
object = { ...object, project: projectId }
|
||||
}
|
||||
|
||||
function addTagRef (tag: TagElement): void {
|
||||
labels = [
|
||||
...labels,
|
||||
{
|
||||
_class: tags.class.TagReference,
|
||||
_id: generateId() as Ref<TagReference>,
|
||||
attachedTo: '' as Ref<Doc>,
|
||||
attachedToClass: tracker.class.Issue,
|
||||
collection: 'labels',
|
||||
space: tags.space.Tags,
|
||||
modifiedOn: 0,
|
||||
modifiedBy: '' as Ref<Account>,
|
||||
title: tag.title,
|
||||
tag: tag._id,
|
||||
color: tag.color
|
||||
}
|
||||
]
|
||||
}
|
||||
</script>
|
||||
|
||||
<Card
|
||||
@@ -246,14 +280,16 @@
|
||||
/>
|
||||
<svelte:fragment slot="pool">
|
||||
{#if issueStatuses}
|
||||
<StatusEditor
|
||||
value={object}
|
||||
statuses={issueStatuses}
|
||||
kind="no-border"
|
||||
size="small"
|
||||
shouldShowLabel={true}
|
||||
on:change={({ detail }) => (object.status = detail)}
|
||||
/>
|
||||
<div id="status-editor">
|
||||
<StatusEditor
|
||||
value={object}
|
||||
statuses={issueStatuses}
|
||||
kind="no-border"
|
||||
size="small"
|
||||
shouldShowLabel={true}
|
||||
on:change={({ detail }) => (object.status = detail)}
|
||||
/>
|
||||
</div>
|
||||
<PriorityEditor
|
||||
value={object}
|
||||
shouldShowLabel
|
||||
@@ -270,13 +306,21 @@
|
||||
tooltipFill={false}
|
||||
on:change={({ detail }) => (currentAssignee = detail)}
|
||||
/>
|
||||
<!-- <Button
|
||||
label={tracker.string.Labels}
|
||||
icon={tracker.icon.Labels}
|
||||
width="min-content"
|
||||
size="small"
|
||||
kind="no-border"
|
||||
/> -->
|
||||
<Component
|
||||
is={tags.component.TagsDropdownEditor}
|
||||
props={{
|
||||
items: labels,
|
||||
key,
|
||||
targetClass: tracker.class.Issue,
|
||||
countLabel: tracker.string.NumberLabels
|
||||
}}
|
||||
on:open={(evt) => {
|
||||
addTagRef(evt.detail)
|
||||
}}
|
||||
on:delete={(evt) => {
|
||||
labels = labels.filter((it) => it._id !== evt.detail)
|
||||
}}
|
||||
/>
|
||||
<ProjectSelector value={object.project} onProjectIdChange={handleProjectIdChanged} />
|
||||
{#if object.dueDate !== null}
|
||||
<DatePresenter bind:value={object.dueDate} editable />
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
<script lang="ts">
|
||||
import { WithLookup } from '@anticrm/core'
|
||||
import type { Issue, IssueStatus } from '@anticrm/tracker'
|
||||
import { Button, Label } from '@anticrm/ui'
|
||||
import { Component, Label } from '@anticrm/ui'
|
||||
import tags from '@anticrm/tags'
|
||||
import tracker from '../../../plugin'
|
||||
import PriorityEditor from '../PriorityEditor.svelte'
|
||||
import StatusEditor from '../StatusEditor.svelte'
|
||||
@@ -46,14 +47,7 @@
|
||||
<span class="label">
|
||||
<Label label={tracker.string.Labels} />
|
||||
</span>
|
||||
<Button
|
||||
label={tracker.string.Labels}
|
||||
icon={tracker.icon.Labels}
|
||||
size={'large'}
|
||||
kind={'link'}
|
||||
width={'100%'}
|
||||
justify={'left'}
|
||||
/>
|
||||
<Component is={tags.component.TagsAttributeEditor} props={{ object: issue }} />
|
||||
|
||||
<div class="divider" />
|
||||
|
||||
|
||||
@@ -14,11 +14,12 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import core, { AttachedData, Ref, SortingOrder, WithLookup } from '@anticrm/core'
|
||||
import presentation, { getClient } from '@anticrm/presentation'
|
||||
import core, { Account, AttachedData, Doc, generateId, Ref, SortingOrder, WithLookup } from '@anticrm/core'
|
||||
import presentation, { getClient, KeyedAttribute } from '@anticrm/presentation'
|
||||
import { StyledTextArea } from '@anticrm/text-editor'
|
||||
import { IssueStatus, IssuePriority, Issue, Team, calcRank } from '@anticrm/tracker'
|
||||
import { Button, EditBox } from '@anticrm/ui'
|
||||
import { Button, Component, EditBox } from '@anticrm/ui'
|
||||
import tags, { TagElement, TagReference } from '@anticrm/tags'
|
||||
import tracker from '../../../plugin'
|
||||
import AssigneeEditor from '../AssigneeEditor.svelte'
|
||||
import StatusEditor from '../StatusEditor.svelte'
|
||||
@@ -34,6 +35,12 @@
|
||||
let newIssue: AttachedData<Issue> = getIssueDefaults()
|
||||
let thisRef: HTMLDivElement
|
||||
let focusIssueTitle: () => void
|
||||
let labels: TagReference[] = []
|
||||
|
||||
const key: KeyedAttribute = {
|
||||
key: 'labels',
|
||||
attr: client.getHierarchy().getAttribute(tracker.class.Issue, 'labels')
|
||||
}
|
||||
|
||||
function getIssueDefaults (): AttachedData<Issue> {
|
||||
return {
|
||||
@@ -90,10 +97,43 @@
|
||||
rank: calcRank(lastOne, undefined)
|
||||
}
|
||||
|
||||
await client.addCollection(tracker.class.Issue, space, parentIssue._id, parentIssue._class, 'subIssues', value)
|
||||
const objectId = await client.addCollection(
|
||||
tracker.class.Issue,
|
||||
space,
|
||||
parentIssue._id,
|
||||
parentIssue._class,
|
||||
'subIssues',
|
||||
value
|
||||
)
|
||||
for (const label of labels) {
|
||||
await client.addCollection(label._class, label.space, objectId, tracker.class.Issue, 'labels', {
|
||||
title: label.title,
|
||||
color: label.color,
|
||||
tag: label.tag
|
||||
})
|
||||
}
|
||||
resetToDefaults()
|
||||
}
|
||||
|
||||
function addTagRef (tag: TagElement): void {
|
||||
labels = [
|
||||
...labels,
|
||||
{
|
||||
_class: tags.class.TagReference,
|
||||
_id: generateId() as Ref<TagReference>,
|
||||
attachedTo: '' as Ref<Doc>,
|
||||
attachedToClass: tracker.class.Issue,
|
||||
collection: 'labels',
|
||||
space: tags.space.Tags,
|
||||
modifiedOn: 0,
|
||||
modifiedBy: '' as Ref<Account>,
|
||||
title: tag.title,
|
||||
tag: tag._id,
|
||||
color: tag.color
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
$: thisRef && thisRef.scrollIntoView({ behavior: 'smooth' })
|
||||
$: canSave = getTitle(newIssue.title ?? '').length > 0
|
||||
$: if (!newIssue.status && currentTeam?.defaultIssueStatus) {
|
||||
@@ -150,6 +190,21 @@
|
||||
tooltipFill={false}
|
||||
on:change={({ detail }) => (newIssue.assignee = detail)}
|
||||
/>
|
||||
<Component
|
||||
is={tags.component.TagsDropdownEditor}
|
||||
props={{
|
||||
items: labels,
|
||||
key,
|
||||
targetClass: tracker.class.Issue,
|
||||
countLabel: tracker.string.NumberLabels
|
||||
}}
|
||||
on:open={(evt) => {
|
||||
addTagRef(evt.detail)
|
||||
}}
|
||||
on:delete={(evt) => {
|
||||
labels = labels.filter((it) => it._id !== evt.detail)
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<div class="buttons-group small-gap">
|
||||
<Button label={presentation.string.Cancel} size="small" kind="transparent" on:click={close} />
|
||||
|
||||
@@ -136,6 +136,7 @@ export default mergeIds(trackerId, tracker, {
|
||||
ProjectLeadSearchPlaceholder: '' as IntlString,
|
||||
ProjectMembersSearchPlaceholder: '' as IntlString,
|
||||
List: '' as IntlString,
|
||||
NumberLabels: '' as IntlString,
|
||||
|
||||
IssueTitlePlaceholder: '' as IntlString,
|
||||
IssueDescriptionPlaceholder: '' as IntlString,
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
"@anticrm/chunter": "~0.6.1",
|
||||
"@anticrm/attachment": "~0.6.1",
|
||||
"@anticrm/task": "~0.6.0",
|
||||
"@anticrm/tags": "~0.6.2",
|
||||
"lexorank": "~1.0.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import { Action, ActionCategory } from '@anticrm/view'
|
||||
import type { Asset, IntlString, Plugin } from '@anticrm/platform'
|
||||
import { plugin } from '@anticrm/platform'
|
||||
import { AnyComponent } from '@anticrm/ui'
|
||||
import type { TagCategory } from '@anticrm/tags'
|
||||
|
||||
/**
|
||||
* @public
|
||||
@@ -114,7 +115,7 @@ export interface Issue extends AttachedDoc {
|
||||
|
||||
comments: number
|
||||
attachments?: number
|
||||
labels?: string[]
|
||||
labels?: number
|
||||
|
||||
space: Ref<Team>
|
||||
|
||||
@@ -261,6 +262,7 @@ export default plugin(trackerId, {
|
||||
CopyBranch: '' as Asset
|
||||
},
|
||||
category: {
|
||||
Other: '' as Ref<TagCategory>,
|
||||
Tracker: '' as Ref<ActionCategory>
|
||||
},
|
||||
action: {
|
||||
|
||||
@@ -3,35 +3,6 @@ import { generateId, PlatformSetting, PlatformURI } from './utils'
|
||||
test.use({
|
||||
storageState: PlatformSetting
|
||||
})
|
||||
test('create-issue-and-sub-issue', async ({ page }) => {
|
||||
await page.goto(`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp`)
|
||||
await page.click('[id="app-tracker\\:string\\:TrackerApplication"]')
|
||||
await expect(page).toHaveURL(`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/tracker%3Aapp%3ATracker`)
|
||||
await page.click('button:has-text("New issue")')
|
||||
await page.click('[placeholder="Issue\\ title"]')
|
||||
await page.fill('[placeholder="Issue\\ title"]', 'test-issue')
|
||||
await page.fill('.ProseMirror', 'some description')
|
||||
await page.click('button:has-text("Backlog")')
|
||||
await page.click('button:has-text("Todo")')
|
||||
await page.click('button:has-text("No priority")')
|
||||
await page.click('button:has-text("Urgent")')
|
||||
await page.click('button:has-text("Save issue")')
|
||||
|
||||
await page.click('.antiNav-element__dropbox :text("Issues")')
|
||||
await page.click('.antiList__row :has-text("test-issue") .issuePresenter')
|
||||
await page.click('#add-sub-issue')
|
||||
await page.click('[placeholder="Issue\\ title"]')
|
||||
await page.fill('[placeholder="Issue\\ title"]', 'sub-issue')
|
||||
await page.fill('.ProseMirror', 'sub-issue description')
|
||||
await page.click('#status-editor')
|
||||
await page.click('.selectPopup button:has-text("In Progress")')
|
||||
await page.click('.button:has-text("Assignee")')
|
||||
await page.click('.selectPopup button:has-text("John Appleseed")')
|
||||
await page.click('button:has-text("No priority")')
|
||||
await page.click('.selectPopup button:has-text("High")')
|
||||
await page.click('button:has-text("Save")')
|
||||
await page.click('span.name:text("sub-issue")')
|
||||
})
|
||||
|
||||
async function navigate (page: Page): Promise<void> {
|
||||
await page.goto(`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp`)
|
||||
@@ -39,17 +10,153 @@ async function navigate (page: Page): Promise<void> {
|
||||
await expect(page).toHaveURL(`${PlatformURI}/workbench%3Acomponent%3AWorkbenchApp/tracker%3Aapp%3ATracker`)
|
||||
}
|
||||
|
||||
async function createIssue (page: Page, props: { [p: string]: string } = {}): Promise<void> {
|
||||
await page.click('button:has-text("New issue")')
|
||||
await page.click('[placeholder="Issue\\ title"]')
|
||||
await page.fill('[placeholder="Issue\\ title"]', props.name ?? '')
|
||||
if (props.status !== undefined) {
|
||||
await page.click('button:has-text("Backlog")')
|
||||
await page.click(`.menu-item:has-text("${props.status}")`)
|
||||
interface IssueProps {
|
||||
name: string
|
||||
description?: string
|
||||
status?: string
|
||||
labels?: string[]
|
||||
priority?: string
|
||||
assignee?: string
|
||||
}
|
||||
|
||||
async function fillIssueForm (
|
||||
page: Page,
|
||||
{ name, description, status, assignee, labels, priority }: IssueProps
|
||||
): Promise<void> {
|
||||
await page.fill('[placeholder="Issue\\ title"]', name)
|
||||
if (description !== undefined) {
|
||||
await page.fill('.ProseMirror', description)
|
||||
}
|
||||
if (status !== undefined) {
|
||||
await page.click('#status-editor')
|
||||
await page.click(`.menu-item:has-text("${status}")`)
|
||||
}
|
||||
if (priority !== undefined) {
|
||||
await page.click('button:has-text("No priority")')
|
||||
await page.click(`.selectPopup button:has-text("${priority}")`)
|
||||
}
|
||||
if (labels !== undefined) {
|
||||
await page.click('.button:has-text("Labels")')
|
||||
for (const label of labels) {
|
||||
await page.click(`.selectPopup button:has-text("${label}") >> nth=0`)
|
||||
}
|
||||
await page.keyboard.press('Escape')
|
||||
}
|
||||
if (assignee !== undefined) {
|
||||
await page.click('.button:has-text("Assignee")')
|
||||
await page.click(`.selectPopup button:has-text("${assignee}")`)
|
||||
}
|
||||
}
|
||||
|
||||
async function createIssue (page: Page, props: IssueProps): Promise<void> {
|
||||
await page.click('button:has-text("New issue")')
|
||||
await fillIssueForm(page, props)
|
||||
await page.click('button:has-text("Save issue")')
|
||||
}
|
||||
|
||||
async function createSubissue (page: Page, props: IssueProps): Promise<void> {
|
||||
await page.click('button:has-text("Add sub-issue")')
|
||||
await fillIssueForm(page, props)
|
||||
await page.click('button:has-text("Save")')
|
||||
}
|
||||
|
||||
interface LabelProps {
|
||||
label: string
|
||||
}
|
||||
async function createLabel (page: Page, { label }: LabelProps): Promise<void> {
|
||||
await page.click('button:has-text("New issue")')
|
||||
await page.click('button:has-text("Labels")')
|
||||
await page.click('.buttons-group >> button >> nth=-1')
|
||||
await page.fill('[id="tags:string:AddTag"] >> input >> nth=0', label)
|
||||
await page.click('[id="tags:string:AddTag"] >> button:has-text("Create")')
|
||||
await page.waitForTimeout(100)
|
||||
await page.keyboard.press('Escape')
|
||||
await page.waitForTimeout(100)
|
||||
await page.keyboard.press('Escape')
|
||||
}
|
||||
|
||||
async function checkIssue (
|
||||
page: Page,
|
||||
{ name, description, status, assignee, labels, priority }: IssueProps
|
||||
): Promise<void> {
|
||||
if (name !== undefined) {
|
||||
await expect(page.locator('.popupPanel')).toContainText(name)
|
||||
}
|
||||
if (description !== undefined) {
|
||||
await expect(page.locator('.popupPanel')).toContainText(description)
|
||||
}
|
||||
const asideLocator = page.locator('.popupPanel-body__aside')
|
||||
if (status !== undefined) {
|
||||
await expect(asideLocator).toContainText(status)
|
||||
}
|
||||
if (labels !== undefined) {
|
||||
await expect(asideLocator).toContainText(labels)
|
||||
}
|
||||
if (priority !== undefined) {
|
||||
await expect(asideLocator).toContainText(priority)
|
||||
}
|
||||
if (assignee !== undefined) {
|
||||
await expect(asideLocator).toContainText(assignee)
|
||||
}
|
||||
}
|
||||
|
||||
const defaultStatuses = ['Backlog', 'Todo', 'In Progress', 'Done', 'Canceled']
|
||||
const defaultPriorities = ['No priority', 'Urgent', 'High', 'Medium', 'Low']
|
||||
const defaultUser = 'John Appleseed'
|
||||
|
||||
test.describe('create-issue-and-sub-issue', () => {
|
||||
const labels = ['label', 'another-label']
|
||||
async function testIssue (page: Page, props: IssueProps): Promise<void> {
|
||||
await createIssue(page, props)
|
||||
await page.click('text="Issues"')
|
||||
await page.click(`.antiList__row :has-text("${props.name}") .issuePresenter`)
|
||||
await checkIssue(page, props)
|
||||
props.name = `sub${props.name}`
|
||||
await createSubissue(page, props)
|
||||
await page.click(`span:has-text("${props.name}")`)
|
||||
await checkIssue(page, props)
|
||||
}
|
||||
test.beforeEach(async ({ page }) => await navigate(page))
|
||||
|
||||
test('with-description', async ({ page }) =>
|
||||
await testIssue(page, { name: getIssueName(), description: 'some-description' }))
|
||||
|
||||
test('with-assignee', async ({ page }) => await testIssue(page, { name: getIssueName(), assignee: defaultUser }))
|
||||
|
||||
test.describe('with-status', () => {
|
||||
for (const status of defaultStatuses) {
|
||||
test(status, async ({ page }) => await testIssue(page, { name: getIssueName(), status }))
|
||||
}
|
||||
})
|
||||
|
||||
test.describe('with-priority', () => {
|
||||
for (const priority of defaultPriorities) {
|
||||
test(priority, async ({ page }) => await testIssue(page, { name: getIssueName(), priority }))
|
||||
}
|
||||
})
|
||||
|
||||
test('with-labels', async ({ page }) => {
|
||||
for (const label of labels) {
|
||||
await createLabel(page, { label })
|
||||
}
|
||||
await testIssue(page, { name: getIssueName(), labels })
|
||||
})
|
||||
|
||||
test('with-all-props', async ({ page }) => {
|
||||
for (const label of labels) {
|
||||
await createLabel(page, { label })
|
||||
}
|
||||
await testIssue(page, {
|
||||
name: getIssueName(),
|
||||
description: 'description',
|
||||
labels,
|
||||
status: defaultStatuses[0],
|
||||
priority: defaultPriorities[0],
|
||||
assignee: defaultUser
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
const getIssueName = (postfix: string = generateId(5)): string => `issue-${postfix}`
|
||||
|
||||
test('use-kanban', async ({ page }) => {
|
||||
@@ -63,8 +170,6 @@ test('use-kanban', async ({ page }) => {
|
||||
await expect(page.locator(`.panel-container:has-text("${status}")`)).toContainText(name)
|
||||
})
|
||||
|
||||
const defaultStatuses = ['Backlog', 'Todo', 'In Progress', 'Done', 'Canceled']
|
||||
|
||||
test.describe('issues-status-display', () => {
|
||||
const panelStatusMap = new Map([
|
||||
['Issues', defaultStatuses],
|
||||
|
||||
Reference in New Issue
Block a user