Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add next test button #7247

Merged
merged 7 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions models/test-management/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ export function createModel (builder: Builder): void {
defineTestSuite(builder)
defineTestCase(builder)
defineTestRun(builder)
defineTestResult(builder)

definePresenters(builder)

Expand Down Expand Up @@ -261,7 +262,7 @@ function defineTestSuite (builder: Builder): void {
// Actions

builder.mixin(testManagement.class.TestSuite, core.class.Class, view.mixin.IgnoreActions, {
actions: [print.action.Print, tracker.action.EditRelatedTargets]
actions: [print.action.Print, tracker.action.EditRelatedTargets, tracker.action.NewRelatedIssue]
})

createAction(
Expand Down Expand Up @@ -331,7 +332,7 @@ function defineTestCase (builder: Builder): void {

builder.mixin(testManagement.class.TestCase, core.class.Class, view.mixin.ClassFilters, {
filters: ['priority', 'status'],
ignoreKeys: ['createdBy', 'modifiedBy', 'createdOn', 'modifiedOn']
ignoreKeys: ['createdBy', 'modifiedBy', 'createdOn', 'modifiedOn', 'name']
})

builder.createDoc(
Expand Down Expand Up @@ -419,6 +420,12 @@ function defineTestRun (builder: Builder): void {
component: testManagement.component.TestResultStatusPresenter
})

builder.mixin(testManagement.class.TestRun, core.class.Class, view.mixin.IgnoreActions, {
actions: [print.action.Print, tracker.action.EditRelatedTargets, tracker.action.NewRelatedIssue]
})
}

function defineTestResult (builder: Builder): void {
builder.mixin(testManagement.class.TestResult, core.class.Class, view.mixin.ObjectPresenter, {
presenter: testManagement.component.TestResultPresenter
})
Expand Down Expand Up @@ -448,7 +455,7 @@ function defineTestRun (builder: Builder): void {

builder.mixin(testManagement.class.TestResult, core.class.Class, view.mixin.ClassFilters, {
filters: ['assignee', 'status', 'testSuite'],
ignoreKeys: ['createdBy', 'modifiedBy', 'createdOn', 'modifiedOn']
ignoreKeys: ['createdBy', 'modifiedBy', 'createdOn', 'modifiedOn', 'name', 'attachedTo']
})

const viewOptions: ViewOptionsModel = {
Expand Down
3 changes: 2 additions & 1 deletion models/test-management/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ import type { ActionCategory } from '@hcengineering/view'
export default mergeIds(testManagementId, testManganement, {
category: {
TestSuite: '' as Ref<ActionCategory>,
TestCase: '' as Ref<ActionCategory>
TestCase: '' as Ref<ActionCategory>,
TestResult: '' as Ref<ActionCategory>
},
component: {
CreateTestCase: '' as AnyComponent,
Expand Down
3 changes: 3 additions & 0 deletions models/test-management/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,15 @@ export class TTestResult extends TAttachedDoc implements TestResult {
testCase!: Ref<TestCase>

@Prop(TypeRef(testManagement.class.TestSuite), testManagement.string.TestSuite)
@Index(IndexKind.Indexed)
testSuite?: Ref<TestSuite>

@Prop(TypeTestRunStatus(), testManagement.string.TestRunStatus)
@Index(IndexKind.Indexed)
status?: TestRunStatus

@Prop(TypeRef(contact.mixin.Employee), testManagement.string.TestAssignee)
@Index(IndexKind.Indexed)
assignee?: Ref<Employee>

@Prop(Collection(attachment.class.Attachment), attachment.string.Attachments, { shortLabel: attachment.string.Files })
Expand Down
4 changes: 3 additions & 1 deletion plugins/test-management-assets/lang/cs.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
"DueDate": "Termín",
"RunTestCases": "Spustit",
"TestCaseDescription": "Popis testovacího případu",
"TestResultAttributes": "Výsledek"
"TestResultAttributes": "Výsledek",
"GoToNextTest": "Další",
"GoToNextTestTooltip": "Přejít na další test"
}
}
4 changes: 3 additions & 1 deletion plugins/test-management-assets/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
"DueDate": "Due date",
"RunTestCases": "Run",
"TestCaseDescription": "Test case description",
"TestResultAttributes": "Result"
"TestResultAttributes": "Result",
"GoToNextTest": "Next",
"GoToNextTestTooltip": "Go to next test"
}
}
4 changes: 3 additions & 1 deletion plugins/test-management-assets/lang/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
"DueDate": "Fecha de vencimiento",
"RunTestCases": "Ejecutar",
"TestCaseDescription": "Descripción del caso de prueba",
"TestResultAttributes": "Resultado"
"TestResultAttributes": "Resultado",
"GoToNextTest": "Siguiente",
"GoToNextTestTooltip": "Ir al siguiente test"
}
}
4 changes: 3 additions & 1 deletion plugins/test-management-assets/lang/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
"DueDate": "Date d'échéance",
"RunTestCases": "Exécuter",
"TestCaseDescription": "Description du cas de test",
"TestResultAttributes": "Résultat"
"TestResultAttributes": "Résultat",
"GoToNextTest": "Suivant",
"GoToNextTestTooltip": "Aller au test suivant"
}
}
4 changes: 3 additions & 1 deletion plugins/test-management-assets/lang/it.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
"DueDate": "Data di scadenza",
"RunTestCases": "Esegui",
"TestCaseDescription": "Descrizione del caso di test",
"TestResultAttributes": "Risultato"
"TestResultAttributes": "Risultato",
"GoToNextTest": "Successivo",
"GoToNextTestTooltip": "Vai al test successivo"
}
}
4 changes: 3 additions & 1 deletion plugins/test-management-assets/lang/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
"DueDate": "Data de vencimento",
"RunTestCases": "Executar",
"TestCaseDescription": "Descrição do caso de teste",
"TestResultAttributes": "Resultado"
"TestResultAttributes": "Resultado",
"GoToNextTest": "Próximo",
"GoToNextTestTooltip": "Ir para o próximo teste"
}
}
4 changes: 3 additions & 1 deletion plugins/test-management-assets/lang/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
"DueDate": "Выполнить до",
"RunTestCases": "Выполнить",
"TestCaseDescription": "Описание тест-кейса",
"TestResultAttributes": "Результат"
"TestResultAttributes": "Результат",
"GoToNextTest": "Следующий",
"GoToNextTestTooltip": "Перейти к следующему тесту"
}
}
4 changes: 3 additions & 1 deletion plugins/test-management-assets/lang/zh.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
"DueDate": "到期日",
"RunTestCases": "运行",
"TestCaseDescription": "測試用例描述",
"TestResultAttributes": "結果"
"TestResultAttributes": "結果",
"GoToNextTest": "下一個",
"GoToNextTestTooltip": "轉到下一個測試"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import { DocAttributeBar, getDocMixins } from '@hcengineering/view-resources'

import RightHeader from './RightHeader.svelte'
import NextButton from './NextButton.svelte'
import TestCaseDetails from '../test-case/TestCaseDetails.svelte'
import testManagement from '../../plugin'

Expand Down Expand Up @@ -92,6 +93,10 @@
/>
</div>

<svelte:fragment slot="extra">
<NextButton {object} />
</svelte:fragment>

<svelte:fragment slot="aside">
<DocAttributeBar {object} {mixins} ignoreKeys={['name']} />
<RightHeader>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<!--
// Copyright © 2024 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import { onMount, onDestroy } from 'svelte'
import { Button, Loading, Location, navigate } from '@hcengineering/ui'
import { initializeIterator, testResultIteratorProvider, testIteratorStore } from './store/testIteratorStore'
import testManagement, { TestResult } from '@hcengineering/test-management'
import { Doc, type DocumentQuery, WithLookup } from '@hcengineering/core'
import { getClient } from '@hcengineering/presentation'
import { getObjectLinkFragment } from '@hcengineering/view-resources'
import view from '@hcengineering/view'

export let object: WithLookup<TestResult> | undefined
let isLoading = true
let hasNext = false
let navigateToNext = false

const client = getClient()
const hierarchy = client.getHierarchy()

testIteratorStore.subscribe(() => {
haiodo marked this conversation as resolved.
Show resolved Hide resolved
hasNext = testResultIteratorProvider.getIterator()?.hasNext() ?? false
})

onMount(async () => {
const query: DocumentQuery<TestResult> = { attachedTo: object?.attachedTo } as any
await initializeIterator(query, object?._id)
hasNext = testResultIteratorProvider.getIterator()?.hasNext() ?? false
isLoading = false
})
onDestroy(() => {
if (navigateToNext) {
testResultIteratorProvider.reset()
}
})

async function goToNextItem (): Promise<void> {
navigateToNext = true
const iterator = testResultIteratorProvider.getIterator()
if (iterator !== undefined) {
const nextItem = iterator.next()
if (nextItem === undefined) {
console.error('No next item')
return
}
const link = await getLink(nextItem)
if (link !== undefined) {
navigate(link)
}

console.log('Next item:', nextItem)
}
}

async function getLink (object: Doc): Promise<Location> {
const { component } = hierarchy.classHierarchyMixin(testManagement.class.TestResult, view.mixin.ObjectPanel) as any
return await getObjectLinkFragment(hierarchy, object, {}, component)
}
</script>

{#if isLoading}
<Loading />
{:else}
<Button
label={testManagement.string.GoToNextTest}
kind={'primary'}
icon={view.icon.ArrowRight}
disabled={!hasNext}
on:click={goToNextItem}
showTooltip={{ label: testManagement.string.GoToNextTestTooltip }}
/>
{/if}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
//
// Copyright © 2024 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
//

import { writable, get } from 'svelte/store'
import {
type IteratorState,
type StoreAdapter,
ObjectIteratorProvider,
getDefaultIteratorState
} from '@hcengineering/view-resources'
import testManagement, { type TestResult } from '@hcengineering/test-management'
import type { DocumentQuery, Ref } from '@hcengineering/core'

export const testIteratorStore = writable<IteratorState<TestResult>>(getDefaultIteratorState<TestResult>({}))

const adapter: StoreAdapter<TestResult> = {
set (value: IteratorState<TestResult>) {
testIteratorStore.set(value)
},
update (updater: (value: IteratorState<TestResult>) => IteratorState<TestResult>) {
testIteratorStore.update(updater)
},
get () {
return get(testIteratorStore)
}
}

export const testResultIteratorProvider = new ObjectIteratorProvider<TestResult>(adapter)

export async function initializeIterator (
query: DocumentQuery<TestResult>,
currentObject: Ref<TestResult> | undefined
): Promise<void> {
await testResultIteratorProvider.initialize(testManagement.class.TestResult, query, currentObject)
}

export function resetTestObjectIterator (): void {
testResultIteratorProvider.reset()
}
4 changes: 3 additions & 1 deletion plugins/test-management/src/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,9 @@ export const testManagementPlugin = plugin(testManagementId, {
TestResults: '' as IntlString,
RunTestCases: '' as IntlString,
TestCaseDescription: '' as IntlString,
TestResultAttributes: '' as IntlString
TestResultAttributes: '' as IntlString,
GoToNextTest: '' as IntlString,
GoToNextTestTooltip: '' as IntlString
},
category: {
TestManagement: '' as Ref<ActionCategory>
Expand Down
Loading