Skip to content

Commit 45ec66d

Browse files
test(action-center): assign tasks to a configured group in integratio… (#520)
* test(action-center): assign tasks to a configured group in integration tests Rename the orphaned USER_GROUP_ID env var to TASKS_TEST_USER_GROUP_ID (following the {SERVICE}_TEST_* convention) and wire it into IntegrationConfig as tasksTestUserGroupId. The task assignment-criteria test now assigns to this configured directory group instead of scanning getUsers() for the first DirectoryGroup, and throws when the var is unset. Wire the variable through CI: pr-checks.yml reads it from the UIPATH_TASKS_TEST_USER_GROUP_ID(_DEV) GitHub secret and writes it into the generated tests/.env.integration. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * test(action-center): pin single-user assignment to a configured user + surface assign errors Add TASKS_TEST_USER_ID (config field, .env.integration.example, and pr-checks.yml secret wiring) so the single-user assignment tests target a known user instead of whatever getUsers() returns first. The assignment-criteria beforeAll now resolves that user's name/email for the userNameOrEmail path and fails fast if either the configured user or group isn't assignable in the folder. Assignment assertions also surface Action Center's per-item error details on failure instead of a bare boolean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 475b1b8 commit 45ec66d

4 files changed

Lines changed: 55 additions & 27 deletions

File tree

.github/workflows/pr-checks.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ jobs:
6969
echo "orchestrator_attachment_id=${{ secrets.UIPATH_ORCHESTRATOR_ATTACHMENT_ID_DEV || secrets.UIPATH_ORCHESTRATOR_ATTACHMENT_ID }}" >> $GITHUB_OUTPUT
7070
echo "jobs_test_folder_id=${{ secrets.UIPATH_JOBS_TEST_FOLDER_ID_DEV || secrets.UIPATH_JOBS_TEST_FOLDER_ID }}" >> $GITHUB_OUTPUT
7171
echo "traces_test_trace_id=${{ secrets.UIPATH_TRACES_TEST_TRACE_ID_DEV || secrets.UIPATH_TRACES_TEST_TRACE_ID }}" >> $GITHUB_OUTPUT
72+
echo "tasks_test_user_group_id=${{ secrets.UIPATH_TASKS_TEST_USER_GROUP_ID_DEV || secrets.UIPATH_TASKS_TEST_USER_GROUP_ID }}" >> $GITHUB_OUTPUT
73+
echo "tasks_test_user_id=${{ secrets.UIPATH_TASKS_TEST_USER_ID_DEV || secrets.UIPATH_TASKS_TEST_USER_ID }}" >> $GITHUB_OUTPUT
7274
7375
- name: Create Integration Test Configuration
7476
if: github.base_ref == 'main'
@@ -92,6 +94,8 @@ jobs:
9294
ORCHESTRATOR_ATTACHMENT_ID=${{ steps.config.outputs.orchestrator_attachment_id }}
9395
JOBS_TEST_FOLDER_ID=${{ steps.config.outputs.jobs_test_folder_id }}
9496
TRACES_TEST_TRACE_ID=${{ steps.config.outputs.traces_test_trace_id }}
97+
TASKS_TEST_USER_GROUP_ID=${{ steps.config.outputs.tasks_test_user_group_id }}
98+
TASKS_TEST_USER_ID=${{ steps.config.outputs.tasks_test_user_id }}
9599
EOF
96100
97101
- name: Run Integration Tests

tests/.env.integration.example

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,12 @@ DATA_FABRIC_TEST_ATTACHMENT_FIELD=
6565
JOBS_TEST_FOLDER_ID=
6666

6767
# Orchestrator attachment ID (UUID) for attachment getById tests
68-
ORCHESTRATOR_ATTACHMENT_ID=
68+
ORCHESTRATOR_ATTACHMENT_ID=
69+
70+
# Directory group ID used by the task assignment-criteria integration tests.
71+
# The group must be assigned to the folder identified by INTEGRATION_TEST_FOLDER_ID.
72+
TASKS_TEST_USER_GROUP_ID=
73+
74+
# User ID (from tasks.getUsers()) used by the single-user task assignment tests.
75+
# The user must have task permissions in the folder identified by INTEGRATION_TEST_FOLDER_ID.
76+
TASKS_TEST_USER_ID=

tests/integration/config/test-config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ export interface IntegrationConfig {
2222
dataFabricTestAttachmentField?: string;
2323
orchestratorAttachmentId?: string;
2424
jobsTestFolderId?: string;
25+
tasksTestUserGroupId?: string;
26+
tasksTestUserId?: string;
2527
}
2628

2729
function isValidUrl(value: string): boolean {
@@ -75,6 +77,8 @@ function validateConfig(rawConfig: Record<string, unknown>): IntegrationConfig {
7577
dataFabricTestAttachmentField: typeof rawConfig.dataFabricTestAttachmentField === 'string' ? rawConfig.dataFabricTestAttachmentField : undefined,
7678
orchestratorAttachmentId: typeof rawConfig.orchestratorAttachmentId === 'string' ? rawConfig.orchestratorAttachmentId : undefined,
7779
jobsTestFolderId: typeof rawConfig.jobsTestFolderId === 'string' ? rawConfig.jobsTestFolderId : undefined,
80+
tasksTestUserGroupId: typeof rawConfig.tasksTestUserGroupId === 'string' ? rawConfig.tasksTestUserGroupId : undefined,
81+
tasksTestUserId: typeof rawConfig.tasksTestUserId === 'string' ? rawConfig.tasksTestUserId : undefined,
7882
};
7983
}
8084

@@ -112,6 +116,8 @@ export function loadIntegrationConfig(): IntegrationConfig {
112116
dataFabricTestAttachmentField: process.env.DATA_FABRIC_TEST_ATTACHMENT_FIELD || undefined,
113117
orchestratorAttachmentId: process.env.ORCHESTRATOR_ATTACHMENT_ID || undefined,
114118
jobsTestFolderId: process.env.JOBS_TEST_FOLDER_ID || undefined,
119+
tasksTestUserGroupId: process.env.TASKS_TEST_USER_GROUP_ID || undefined,
120+
tasksTestUserId: process.env.TASKS_TEST_USER_ID || undefined,
115121
};
116122

117123
cachedConfig = validateConfig(rawConfig);

tests/integration/shared/action-center/tasks.integration.test.ts

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -193,14 +193,10 @@ describe.each(modes)('Action Center Tasks - Integration Tests [%s]', (mode) => {
193193
const folderId = config.folderId ? Number(config.folderId) : undefined;
194194

195195
try {
196-
const users = await tasks.getUsers(folderId!);
197-
198-
const user = users.items.find((u) => u.type === TaskUserType.DirectoryUser || u.type === TaskUserType.User);
199-
if (!user) {
200-
throw new Error('No DirectoryUser available to assign task');
196+
if (!config.tasksTestUserId) {
197+
throw new Error('TASKS_TEST_USER_ID is required in the test config for single-user assignment');
201198
}
202-
203-
const userId = user.id;
199+
const userId = Number(config.tasksTestUserId);
204200

205201
const result = await tasks.assign({
206202
taskId: createdTaskId,
@@ -231,14 +227,10 @@ describe.each(modes)('Action Center Tasks - Integration Tests [%s]', (mode) => {
231227
let task = await tasks.getById(createdTaskId, {}, folderId!);
232228

233229
if (!task.assignedToUser) {
234-
const users = await tasks.getUsers(folderId!);
235-
236-
const user = users.items.find((u) => u.type === TaskUserType.DirectoryUser || u.type === TaskUserType.User);
237-
if (!user) {
238-
throw new Error('No DirectoryUser available to assign task');
230+
if (!config.tasksTestUserId) {
231+
throw new Error('TASKS_TEST_USER_ID is required in the test config for single-user assignment');
239232
}
240-
241-
const userId = user.id;
233+
const userId = Number(config.tasksTestUserId);
242234

243235
const assignResult = await tasks.assign({
244236
taskId: createdTaskId,
@@ -280,21 +272,37 @@ describe.each(modes)('Action Center Tasks - Integration Tests [%s]', (mode) => {
280272
}
281273
folderId = Number(config.folderId);
282274

275+
if (!config.tasksTestUserGroupId) {
276+
throw new Error('TASKS_TEST_USER_GROUP_ID is required in the test config for group assignment-criteria tests');
277+
}
278+
groupId = Number(config.tasksTestUserGroupId);
279+
280+
if (!config.tasksTestUserId) {
281+
throw new Error('TASKS_TEST_USER_ID is required in the test config for single-user assignment-criteria tests');
282+
}
283+
283284
const users = await tasks.getUsers(folderId);
284285

285-
const individual = users.items.find(
286-
(u) => u.type === TaskUserType.User || u.type === TaskUserType.DirectoryUser,
287-
);
288-
if (!individual) {
289-
throw new Error('No individual user (User/DirectoryUser) in the folder to test single-user assignment');
286+
// Resolve the configured user's name/email for the userNameOrEmail path.
287+
const configuredUser = users.items.find((u) => u.id === Number(config.tasksTestUserId));
288+
if (!configuredUser) {
289+
throw new Error(
290+
`TASKS_TEST_USER_ID (${config.tasksTestUserId}) is not a user with task permissions in folder ${folderId}`,
291+
);
290292
}
291-
userNameOrEmail = individual.emailAddress || individual.userName;
293+
userNameOrEmail = configuredUser.emailAddress || configuredUser.userName;
292294

293-
const group = users.items.find((u) => u.type === TaskUserType.DirectoryGroup);
294-
if (!group) {
295-
throw new Error('No DirectoryGroup in the folder to test group assignment');
295+
// Fail fast with a clear message if the configured group isn't an
296+
// assignable directory group in this folder — otherwise the group
297+
// assignment below fails opaquely as success=false.
298+
const configuredGroup = users.items.find(
299+
(u) => u.type === TaskUserType.DirectoryGroup && u.id === groupId,
300+
);
301+
if (!configuredGroup) {
302+
throw new Error(
303+
`TASKS_TEST_USER_GROUP_ID (${groupId}) is not a directory group with task permissions in folder ${folderId}`,
304+
);
296305
}
297-
groupId = group.id;
298306

299307
// One reusable External task; unassigned between cases so each assign
300308
// starts from a clean state. Tasks have no delete API, so cleanup only
@@ -312,7 +320,8 @@ describe.each(modes)('Action Center Tasks - Integration Tests [%s]', (mode) => {
312320

313321
const result = await tasks.assign({ taskId: criteriaTaskId, userNameOrEmail });
314322

315-
expect(result.success).toBe(true);
323+
// On failure, result.data holds Action Center's per-item error details — surface them.
324+
expect(result.success, `assign by userNameOrEmail failed: ${JSON.stringify(result.data)}`).toBe(true);
316325

317326
const task = await tasks.getById(criteriaTaskId, {}, folderId);
318327
expect(task.assignedToUser).toBeDefined();
@@ -334,7 +343,8 @@ describe.each(modes)('Action Center Tasks - Integration Tests [%s]', (mode) => {
334343
// fails. The SDK maps the empty body to success=true and echoes the request
335344
// as `data`; a failure would instead surface error items here. Asserting the
336345
// exact echoed payload proves the response carried no failure details.
337-
expect(result.success).toBe(true);
346+
// On failure, result.data holds Action Center's per-item error details — surface them.
347+
expect(result.success, `group assign failed: ${JSON.stringify(result.data)}`).toBe(true);
338348
expect(result.data).toEqual([
339349
{ taskId: criteriaTaskId, userId: groupId, assignmentCriteria: TaskAssignmentCriteria.AllUsers },
340350
]);

0 commit comments

Comments
 (0)