feat: 价格表查看权限隔离用例(#58);应用菜单与授予种子

This commit is contained in:
weicw
2026-10-31 07:04:11 +08:00
parent 45285952e9
commit 99f6992200
@@ -0,0 +1,87 @@
package com.gxwebsoft.approval;
import com.gxwebsoft.support.ApprovalTestData;
import com.gxwebsoft.support.TestAuthentication;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import javax.sql.DataSource;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
/**
* 价格表只读接口(#58):权限点独立于审批列表权限。
*
* <p>当前生效版本/历史版本的排序与「未来生效不切换」由价格表实现的 IT 覆盖;
* 本类只验证权限边界与该接口在任何数据下都返回可用空态结构。</p>
*/
@SpringBootTest
@AutoConfigureMockMvc
@ActiveProfiles({"gxtyzx-test", "test"})
class ApprovalPriceViewIT {
private static final int TENANT = TestAuthentication.TENANT_ID;
private static final String PRICE_VIEW = "approval:price:view";
@Autowired
private MockMvc mockMvc;
@Autowired
private DataSource dataSource;
private ApprovalTestData data;
private Integer organizationId;
private ApprovalTestData.TestUser employee;
@BeforeEach
void setUp() {
data = new ApprovalTestData(dataSource);
organizationId = data.createOrganization("价格查看部门" + data.uniqueSuffix(), 136);
employee = data.createUser("价格查看员工" + data.uniqueSuffix(), organizationId);
}
@AfterEach
void tearDown() {
data.cleanup();
}
@Test
void employeeWithPriceViewPermissionCanReadPage() throws Exception {
mockMvc.perform(get("/api/approval/price")
.header("tenantId", TENANT)
.with(authentication(TestAuthentication.user(employee.userId, employee.username,
organizationId, TENANT, PRICE_VIEW))))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(0))
.andExpect(jsonPath("$.data.history").isArray());
}
@Test
void listPermissionAloneDoesNotGrantPriceView() throws Exception {
// 本仓库约定:业务失败也是 HTTP 200,判定只看 code(403 表示无权限)
mockMvc.perform(get("/api/approval/price")
.header("tenantId", TENANT)
.with(authentication(TestAuthentication.user(employee.userId, employee.username,
organizationId, TENANT, "approval:instance:list"))))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(403));
}
@Test
void priceViewAloneDoesNotGrantApprovalList() throws Exception {
mockMvc.perform(get("/api/approval/instance/page")
.header("tenantId", TENANT)
.with(authentication(TestAuthentication.user(employee.userId, employee.username,
organizationId, TENANT, PRICE_VIEW))))
.andExpect(status().isOk())
.andExpect(jsonPath("$.code").value(403));
}
}