znt/module/user/test/lib/ui/story.ui.class.php

225 lines
8.8 KiB
PHP
Raw Permalink Normal View History

<?php
require_once dirname(__FILE__, 6) . '/test/lib/ui.php';
define('STORY_MENUS', array('assignedTo','openedBy','reviewedBy','closedBy'));
define('STORY_COLUMNS', array('id','title','pri','status','productTitle','planTitle','openedByName','estimate','stage'));
define('PAGESIZE', array(5,10,15,20,25,30,35,40,45,50,100,200,500,1000,2000));
class storyTester extends tester
{
/**
* 验证m=user&f=story的各个子菜单内容和分页功能
* Verify the content and pagination of each sub-menu in m=user&f=story.
*
* @param array $users
* @param array $stories
* @param string $storyType story|requirement
* @param int $pageSize
* @return object 成功或失败对象
*/
public function verifyUserStoryMenus($users = array(), $stories = array(), $storyType = 'story', $pageSize = 5)
{
if(empty($users)) return $this->failed('用户列表不能为空');
if(empty($stories)) return $this->failed('需求列表不能为空');
if(!in_array($pageSize, PAGESIZE, true)) return $this->failed('pageSize无效');
$this->login();
$form = $this->initForm('user', 'story', array('userID' => $users[0]->id, 'storyType' => $storyType), 'appIframe-system');
$form->wait(2);
foreach($users as $user)
{
if($user != $users[0])
{
$form->dom->userPicker->picker($user->realname);
$form->wait(1);
if($form->dom->userPicker->getText() != $user->realname) return $this->failed('task页面切换用户显示失败');
}
foreach(STORY_MENUS as $menu)
{
$form->dom->{$menu}->click();
$form->wait(1);
$ret = $this->verifyUserStoryContentAndPagination($form, $user, $stories, $storyType, $menu, $pageSize);
if($ret) return $ret;
}
}
return $this->success("开源版m=user&f=story&storyType={$storyType}测试成功");
}
/**
* 检查具体子菜单的内容以及分页功能
* Verify the content and pagination of a specific sub-menu in m=user&f=story.
*
* @param object $form 页面对象
* @param array $users 用户列表
* @param array $stories 研发/用户需求数据
* @param string $storyType story|requirement
* @param string $menu assignedTo|openedBy|reviewedBy|closedBy
* @param int $pageSize 每页大小
* @return object 成功返回null失败返回对象
*/
public function verifyUserStoryContentAndPagination($form, $user, $stories = array(), $storyType = 'story', $menu = 'assignedTo', $pageSize = 5)
{
$userStories = $this->filterStoriesByMenu($stories, $user, $menu, $storyType);
$currentPageSize = (int) filter_var($form->dom->pagerSizeMenu->getText(), FILTER_SANITIZE_NUMBER_INT);
if(count($userStories) > $currentPageSize)
{
$form->dom->pagerSizeMenu->click();
$form->wait(1);
$form->dom->dropdownPicker(max(PAGESIZE));
$form->wait(1);
}
$ret = $this->verifyStoryColumns($form, $userStories, $storyType);
if($ret) return $ret;
$ret = $this->verifyStoryPagination($form, $userStories, $pageSize);
if($ret) return $ret;
return null;
}
/**
* 根据菜单过滤数据
* Filter data based on menu
*
* @param array $stories 需求数据
* @param object $user 用户对象
* @param string $menu 菜单
* @param string $storyType story|requirement
* @return array 过滤后的需求列表
*/
private function filterStoriesByMenu($stories, $user, $menu)
{
$account = is_object($user) ? ($user->account ?? '') : ($user['account'] ?? '');
$filtered = array();
foreach($stories as $story)
{
$sid = is_object($story) ? ($story->id ?? null) : ($story['id'] ?? null);
$status = is_object($story) ? ($story->status ?? '') : ($story['status'] ?? '');
$val = is_object($story) ? ($story->{$menu} ?? '') : ($story[$menu] ?? '');
if($val === $account)
{
if($menu != 'closedBy') $filtered[$sid] = $story;
else if($status === 'closed') $filtered[$sid] = $story;
}
}
return $filtered;
}
/**
* 验证列值
* Verify the values in columns
*
* @param object $form 页面对象
* @param array $stories 需求数据
* @param string $storyType story|requirement
* @return object 成功返回null失败返回对象
*/
private function verifyStoryColumns($form, $stories, $storyType = 'story')
{
// Lite 版本或 requirement 类型会隐藏 plan按是否有数据来判断并跳过对齐验证。
$columns = STORY_COLUMNS;
if($storyType === 'requirement' || ($this->config->vision ?? '') === 'lite') $columns = array_diff($columns, array('planTitle'));
if(($this->config->vision ?? '') === 'lite') $columns = array_diff($columns, array('stage'));
$display = array();
foreach($columns as $col) $display[$col] = $form->dom->getElementListByXpathKey($col, true);
if(count($display['id']) != count($stories)) return $this->failed('story页面数据数量与期望不一致');
foreach($display['id'] as $i => $idText)
{
$id = (int)trim($idText);
if(!isset($stories[$id])) return $this->failed("story{$id}不在当前用户视图范围内");
$s = $stories[$id];
// 先检查title
$itemTitle = $display['title'][$i] ?? '';
$itemTitle = str_replace("\xC2\xA0", ' ', $itemTitle);
$itemTitle = preg_replace('/\s+/u', ' ', trim($itemTitle));
// 名称类字段:页面可能在标题前显示“子”(childrenAB)或“SR/UR/undefined/UR”等前缀进行规范化后再比较
foreach(array('SR', 'UR', 'undefined', 'UR', $this->lang->story->childrenAB) as $prefix)
{
if(str_starts_with($itemTitle, $prefix))
{
$itemTitle = trim(substr($itemTitle, strlen($prefix)));
break;
}
}
$expectTitle = str_replace("\xC2\xA0", ' ', $s->title);
$expectTitle = preg_replace('/\s+/u', ' ', trim($expectTitle));
if($itemTitle !== $expectTitle) return $this->failed("ID={$id}名称不匹配");
foreach($columns as $c)
{
switch ($c)
{
case 'id':
case 'title':
continue 2; // 名称在上面已单独验证
case 'status':
case 'stage':
// 根据语言获取对应文本
$expected = $this->lang->story->{$c . 'List'}->{$s->{$c}} ?? $s->{$c};
break;
case 'estimate':
// 根据语言添加后缀
$expected = $s->{$c} . $this->lang->task->suffixHour;
break;
default:
$expected = $s->{$c};
break;
}
if($display[$c][$i] != $expected) return $this->failed("ID={$id} {$c}不匹配,期望'{$expected}',实际'{$display[$c][$i]}'");
}
}
return null;
}
/**
* 验证分页
* verify pagination
*
* @param object $form 页面对象
* @param array $items 需求数据
* @param int $pageSize 每页数量
* @return object 成功返回null失败返回对象
*/
private function verifyStoryPagination($form, $items, $pageSize = 5)
{
$totalTasks = count($items);
$pages = (int) ceil($totalTasks / $pageSize);
if(count($items) > $pageSize)
{
$form->dom->pagerSizeMenu->click();
$form->wait(1);
$form->dom->dropdownPicker($pageSize);
$form->dom->firstPage->click();
$form->wait(1);
}
for($i = 1; $i <= $pages; $i++)
{
$totalActual = count($form->dom->getElementListByXpathKey('id' ));
$totalExpected = ($pages === 1) ? $totalTasks : ($i < $pages ? $pageSize : ($totalTasks - $pageSize * ($pages - 1)));
if($totalActual !== $totalExpected) return $this->failed("分页第{$i}页数量不匹配:期望{$totalExpected},实际{$totalActual}");
if($i < $pages && $form->dom->nextPage)
{
$form->dom->nextPage->click();
$form->wait(1);
}
}
return null;
}
}