From f8e2283a9082f0da7093aec8eec03c04058fb897 Mon Sep 17 00:00:00 2001 From: wanshan Date: Wed, 12 Nov 2025 12:10:39 +0800 Subject: [PATCH] + [task#152435,doing,2h] add ui test for user module deny --- module/user/test/lib/ui/deny.ui.class.php | 139 ++++++++++++++++++++++ module/user/test/ui/deny.php | 62 ++++++++++ module/user/test/ui/page/deny.php | 15 +++ 3 files changed, 216 insertions(+) create mode 100644 module/user/test/lib/ui/deny.ui.class.php create mode 100755 module/user/test/ui/deny.php create mode 100644 module/user/test/ui/page/deny.php diff --git a/module/user/test/lib/ui/deny.ui.class.php b/module/user/test/lib/ui/deny.ui.class.php new file mode 100644 index 0000000000..ae69b42ac1 --- /dev/null +++ b/module/user/test/lib/ui/deny.ui.class.php @@ -0,0 +1,139 @@ +dao->select('u.*, ug.`group`') + ->from(TABLE_USER)->alias('u') + ->leftJoin(TABLE_USERGROUP)->alias('ug')->on('u.account = ug.account') + ->fetchAll(); + $groupPrivs = $uiTester->dao->select('*')->from(TABLE_GROUPPRIV)->fetchAll(); + + foreach($users as $u) $this->users[$u->account] = $u; + foreach($groupPrivs as $gp) $this->groupPrivs[$gp->group][$gp->module][$gp->method] = $gp; + } + + /** + * 校验没有组权限用户访问页面被拒 + * Verify user without group privileges accessing page fail + * + * @return object 成功或失败对象 + */ + public function verifyUserDenyNopriv() + { + foreach($this->users as $user) + { + $hasGroupPriv = ($user->account == 'admin') || isset($this->groupPrivs[$user->group]['my']['team']); + if($hasGroupPriv) continue; + + $this->login($user->account); + $form = null; + try + { + $form = $this->initForm('my', 'team', [], 'appIframe-system'); + return $this->failed("用户'{$user->account}'无'{m=my&f=team}'页面访问权限却能访问页面"); + } + catch(Exception $e) + { + if(!is_object($form)) $form = $this->openDenyPage('nopriv', array('module' => 'my', 'method' => 'team')); + else $form = $this->loadPage('user', 'deny'); + $form->wait(1); + + $header = $form->dom->denyHeader->getText(); + $denyText = $form->dom->denyAlertMsg->getText(); + if($header == $user->account . ' ' . $this->lang->user->deny) continue; + return $this->failed("用户'{$user->account}'无'{m=my&f=team}'页面访问权限却未显示拒绝框:'{$denyText}'"); + } + } + return $this->success('开源版m=user&f=deny测试成功'); + } + + /** + * 校验没有视图权限用户直接访问页面被拒 + * Verify user without view privileges accessing page fail + * + * @param string $module 例如 'qa' 或 'bug' + * @param string $method 例如 'index' 或 'browse' + * @return object 成功或失败对象 + */ + public function verifyUserDenyNoview($module = 'qa', $method = 'index') + { + // 使用 user1(绑定group=2)具备方法权限但缺少视图权限。 + $this->login('user1'); + + // 直接打开 deny(noview) 页面;控制器根据 rights 与 acls['views'] 判断 noview。 + $form = $this->openDenyPage('noview', array('module' => $module, 'method' => $method)); + $form->wait(1); + + $displayed = strip_tags($form->dom->denyAlertMsg->getText()); + $expected = strip_tags(sprintf($this->lang->user->errorView, $this->lang->{$module}->common)); + if($displayed != $expected) return $this->failed("报错信息, 期望:|{$expected}|,实际:|{$displayed}|"); + return $this->success('开源版m=user&f=deny(noview)测试成功'); + } + + /** + * 校验通过路由触发 noview + * Verify user without view privileges accessing page fail by route + * + * @param string $module 例如 'qa' 或 'bug' + * @param string $method 例如 'index' 或 'browse' + * @return object 成功或失败对象 + */ + public function verifyUserDenyNoviewByRoute(string $module = 'qa', string $method = 'index') + { + $loginAccount = 'user1'; + $this->login($loginAccount); + + try + { + // 访问真实路由,预期由于视图不可见导致切换 iframe 失败并进入拒绝页。 + $form = $this->initForm($module, $method, array(), 'appIframe-system'); + $form->wait(1); + return $this->failed("预期视图不可见触发拒绝访问,但实际可进入 {$module}/{$method}"); + } + catch(Exception $e) + { + $form = $this->openDenyPage('noview', array('module' => $module, 'method' => $method)); + $form->wait(1); + + $header = $form->dom->denyHeader->getText(); + if(strpos($header, $loginAccount) === false) return $this->failed('拒绝框标题未包含账户名'); + + $displayed = strip_tags($form->dom->denyAlertMsg->getText()); + $expected = strip_tags(sprintf($this->lang->user->errorView, $this->lang->user->roleList->{$module})); + if($displayed != $expected) return $this->failed("报错信息,期望:|{$expected}|,实际:|{$displayed}|"); + } + + return $this->success('开源版m=user&f=deny(noview 路由)测试成功'); + } + + /** + * 以 GET 方式直接打开 deny 页面,避免 initForm 的 iframe 检查。 + * Open deny page by GET method, avoid iframe check in initForm. + * + * @param string $denyType 拒绝类型,例如 'noview' 或 'nopriv' + * @param array $params 路由参数,例如 ['module' => 'qa', 'method' => 'index'] + * @return object 成功或失败对象 + */ + private function openDenyPage($denyType, $params = array()) + { + $webRoot = $this->getWebRoot(); + $url = "index.php?m=user&f=deny"; + // 按控制器签名顺序传参,避免 denyType 被当成第一个未命名参数覆盖 module。 + if(isset($params['module'])) $url .= "&module=" . $params['module']; + if(isset($params['method'])) $url .= "&method=" . $params['method']; + if(isset($params['referer'])) $url .= "&referer=" . $params['referer']; + $url .= "&denyType=" . $denyType; + + $this->page->openURL($webRoot . $url); + return $this->loadPage('user', 'deny'); + } +} diff --git a/module/user/test/ui/deny.php b/module/user/test/ui/deny.php new file mode 100755 index 0000000000..862abdf9c4 --- /dev/null +++ b/module/user/test/ui/deny.php @@ -0,0 +1,62 @@ +#!/usr/bin/env php +id->range('1-3'); +$user->account->range('admin,user1,user2'); +$user->realname->range('管理员,用户1,用户2'); +$user->password->range($config->uitest->defaultPassword)->format('md5'); +$user->role->range('admin,dev,qa'); +$user->gender->range('f,m'); +$user->gen(3); + +$userGroup = zenData('usergroup'); +$userGroup->account->range('1,2')->prefix('user'); +$userGroup->group->range('2-3'); +$userGroup->gen(2); + +$groupPriv = zenData('grouppriv'); +$groupPriv->group->range('2'); +$groupPriv->module->range('my,qa'); +$groupPriv->method->range('team,index'); +$groupPriv->gen(2); + +$product = zenData('product'); +$product->id->range('1'); +$product->name->range('产品1'); +$product->code->range('product1'); +$product->type->range('normal'); +$product->status->range('normal'); +$product->PO->range('admin'); +$product->deleted->range('0'); +$product->gen(1); + +$tester = new denyTester(); + +// 先运行 nopriv 测试:访问 my/team 触发拒绝 +r($tester->verifyUserDenyNopriv()) && p('status,message') && e('SUCCESS,开源版m=user&f=deny测试成功'); // 开源版m=user&f=deny测试 +// 再运行 noview 测试:直接打开 deny(noview) +r($tester->verifyUserDenyNoview('my', 'team')) && p('status,message') && e('SUCCESS,开源版m=user&f=deny(noview)测试成功'); // 开源版m=user&f=deny(noview)测试 +// 运行基于真实路由触发的 noview 测试:访问 qa/index,预期 deny(noview) +r($tester->verifyUserDenyNoviewByRoute('qa', 'index')) && p('status,message') && e('SUCCESS,开源版m=user&f=deny(noview 路由)测试成功'); // 开源版m=user&f=deny(noview 路由)测试 + +$tester->closeBrowser(); \ No newline at end of file diff --git a/module/user/test/ui/page/deny.php b/module/user/test/ui/page/deny.php new file mode 100644 index 0000000000..d1eae96ab1 --- /dev/null +++ b/module/user/test/ui/page/deny.php @@ -0,0 +1,15 @@ +xpath = array( + 'denyBox' => "//*[@id='denyBox']", + 'denyHeader' => "//*[@id='denyBox']/div[1]/div", + 'denyAlert' => "//*[@id='denyBox']//div[contains(@class,'alert')]", + 'denyAlertMsg' => "//*[@id='denyBox']//div[contains(@class,'alert')]/div", + ); + $this->dom->xpath = array_merge($this->dom->xpath, $this->xpath); + } +} \ No newline at end of file