// Verifies that when a non-admin edits a recipe tagged 再次审核, // an admin-targeted notification is created containing a before/after diff. describe('Re-review notification on non-admin edit', () => { let adminToken let viewerToken let recipeId before(() => { cy.getAdminToken().then(t => { adminToken = t const uname = 'editor_' + Date.now() cy.request({ method: 'POST', url: '/api/register', body: { username: uname, password: 'pw12345678' } }).then(res => { viewerToken = res.body.token // Look up user id via admin /api/users, then promote to editor cy.request({ url: '/api/users', headers: { Authorization: `Bearer ${adminToken}` } }) .then(r => { const u = r.body.find(x => x.username === uname) cy.request({ method: 'PUT', url: `/api/users/${u.id}`, headers: { Authorization: `Bearer ${adminToken}` }, body: { role: 'editor' }, }) }) }) }) }) it('creates admin notification with diff lines', () => { // Editor creates their own recipe tagged 再次审核 cy.request({ method: 'POST', url: '/api/recipes', headers: { Authorization: `Bearer ${viewerToken}` }, body: { name: 're-review-fixture-' + Date.now(), ingredients: [{ oil_name: '薰衣草', drops: 3 }], tags: ['再次审核'], }, }).then(res => { recipeId = res.body.id expect(recipeId).to.be.a('number') }) // Mark notifications read so we can detect the new one cy.request({ method: 'POST', url: '/api/notifications/read-all', headers: { Authorization: `Bearer ${adminToken}` }, body: {}, }) // Non-admin edits the recipe cy.then(() => { cy.request({ method: 'PUT', url: `/api/recipes/${recipeId}`, headers: { Authorization: `Bearer ${viewerToken}` }, body: { ingredients: [{ oil_name: '薰衣草', drops: 5 }, { oil_name: '柠檬', drops: 2 }], note: '新备注', }, }).then(r => expect(r.status).to.eq(200)) }) // Admin sees a new unread notification mentioning the recipe and diff cy.then(() => { cy.request({ url: '/api/notifications', headers: { Authorization: `Bearer ${adminToken}` } }) .then(res => { const unread = res.body.filter(n => !n.is_read && n.title && n.title.includes('再次审核配方被修改')) expect(unread.length).to.be.greaterThan(0) expect(unread[0].body).to.match(/成分|备注/) expect(unread[0].body).to.contain('→') }) }) }) it('admin edits do NOT create re-review notification', () => { cy.request({ method: 'POST', url: '/api/notifications/read-all', headers: { Authorization: `Bearer ${adminToken}` }, body: {}, }) cy.request({ method: 'PUT', url: `/api/recipes/${recipeId}`, headers: { Authorization: `Bearer ${adminToken}` }, body: { note: '管理员备注' }, }) cy.request({ url: '/api/notifications', headers: { Authorization: `Bearer ${adminToken}` } }) .then(res => { const unread = res.body.filter(n => !n.is_read && n.title && n.title.includes('再次审核配方被修改')) expect(unread.length).to.eq(0) }) }) })