forked from wangziqi/gongxue-base
feat: notify tenants about public bank syncs
This commit is contained in:
@@ -4238,6 +4238,46 @@ async function testPublicQuestionBankAdoption() {
|
||||
'public bank sync should insert newly published source questions',
|
||||
);
|
||||
|
||||
const syncNotifications = await request('/api/tenant-content/notifications', {
|
||||
tenantId: PARTNER_TENANT_ID,
|
||||
userId: PARTNER_TENANT_ADMIN_USER_ID,
|
||||
query: { notificationType: 'public_question_bank_synced', adoptionId: adopted.item.id },
|
||||
});
|
||||
const syncNotification = syncNotifications.items?.find(item => item.adoptionId === adopted.item.id && item.status === 'unread');
|
||||
assert.ok(syncNotification?.id, 'public bank sync with inserted questions should create an unread tenant notification');
|
||||
assert.equal(syncNotification?.severity, 'success', 'successful public bank sync notification should be success severity');
|
||||
assert.equal(syncNotifications.summary?.unread >= 1, true, 'notification summary should include unread public bank sync notification');
|
||||
assert.ok(!JSON.stringify(syncNotification).includes('新增公共题应同步到已采纳租户'), 'public bank notification should not leak question explanations');
|
||||
|
||||
const markedSyncNotification = await request('/api/tenant-content/notifications/status', {
|
||||
tenantId: PARTNER_TENANT_ID,
|
||||
userId: PARTNER_TENANT_ADMIN_USER_ID,
|
||||
method: 'POST',
|
||||
body: { notificationIds: [syncNotification.id], status: 'read' },
|
||||
});
|
||||
assert.equal(markedSyncNotification.item?.updatedCount, 1, 'tenant admin should mark content notification as read');
|
||||
const invalidNotificationId = await request('/api/tenant-content/notifications/status', {
|
||||
tenantId: PARTNER_TENANT_ID,
|
||||
userId: PARTNER_TENANT_ADMIN_USER_ID,
|
||||
method: 'POST',
|
||||
body: { notificationIds: ['not-a-uuid'], status: 'read' },
|
||||
expectStatus: 400,
|
||||
});
|
||||
assert.equal(invalidNotificationId.code, 'CONTENT_NOTIFICATION_ID_INVALID', 'notification status API should reject malformed UUIDs before querying');
|
||||
|
||||
const crossTenantNotifications = await request('/api/tenant-content/notifications', {
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
query: { adoptionId: adopted.item.id },
|
||||
});
|
||||
assert.equal(crossTenantNotifications.items?.length, 0, 'content notifications must not expose partner tenant rows to another tenant admin');
|
||||
const crossTenantNotificationsDenied = await request('/api/tenant-content/notifications', {
|
||||
tenantId: PARTNER_TENANT_ID,
|
||||
userId: TENANT_ADMIN_USER_ID,
|
||||
query: { adoptionId: adopted.item.id },
|
||||
expectStatus: 403,
|
||||
});
|
||||
assert.equal(crossTenantNotificationsDenied.code, 'TENANT_CONTENT_EDITOR_REQUIRED', 'content notifications must require tenant content permission in the current tenant');
|
||||
|
||||
const collectionAfterSync = await request('/api/catalog/question-collections/questions', {
|
||||
tenantId: PARTNER_TENANT_ID,
|
||||
userId: false,
|
||||
@@ -4302,6 +4342,16 @@ async function testPublicQuestionBankAdoption() {
|
||||
'public bank sync should identify the source question that conflicts with tenant edits',
|
||||
);
|
||||
|
||||
const conflictNotifications = await request('/api/tenant-content/notifications', {
|
||||
tenantId: PARTNER_TENANT_ID,
|
||||
userId: PARTNER_TENANT_ADMIN_USER_ID,
|
||||
query: { notificationType: 'public_question_bank_conflict', adoptionId: adopted.item.id },
|
||||
});
|
||||
const conflictNotification = conflictNotifications.items?.find(item => item.adoptionId === adopted.item.id && item.status === 'unread');
|
||||
assert.ok(conflictNotification?.id, 'public bank conflicts should create an unread tenant notification');
|
||||
assert.equal(conflictNotification?.severity, 'warning', 'public bank conflict notification should be warning severity');
|
||||
assert.equal(conflictNotification?.metadata?.syncStatus, 'conflict', 'public bank conflict notification should expose conflict status metadata');
|
||||
|
||||
const conflictList = await request('/api/tenant-content/public-question-banks/conflicts', {
|
||||
tenantId: PARTNER_TENANT_ID,
|
||||
userId: PARTNER_TENANT_ADMIN_USER_ID,
|
||||
@@ -4369,6 +4419,15 @@ async function testPublicQuestionBankAdoption() {
|
||||
query: { adoptionId: adopted.item.id },
|
||||
});
|
||||
assert.equal(conflictListAfterAccept.item?.conflictCount, 0, 'resolved conflict list should have no remaining conflicts');
|
||||
const conflictNotificationsAfterAccept = await request('/api/tenant-content/notifications', {
|
||||
tenantId: PARTNER_TENANT_ID,
|
||||
userId: PARTNER_TENANT_ADMIN_USER_ID,
|
||||
query: { notificationType: 'public_question_bank_conflict', adoptionId: adopted.item.id, status: 'resolved' },
|
||||
});
|
||||
assert.ok(
|
||||
conflictNotificationsAfterAccept.items?.some(item => item.id === conflictNotification.id && item.status === 'resolved'),
|
||||
'resolving all public bank conflicts should mark related notifications resolved',
|
||||
);
|
||||
|
||||
const keepLocalContent = `租户再次保留本地公共题副本 ${Date.now()}`;
|
||||
await request('/api/tenant-content/questions', {
|
||||
|
||||
Reference in New Issue
Block a user