fix(frontend): reflect rule-applied tags in batch edit

BulkTagEditor optimistically marked only the clicked tag as common after a bulk
add, so tags applied by auto-tag rules (resolved server-side) never appeared.
Refetch /files/bulk/common-tags after each change and rebuild the common/partial
sets from the response, so rule-applied tags and partial->common shifts show up.

Backend bulk path was already correct — covered now by TestBulkTagAutoRule.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-11 15:06:25 +03:00
parent a78fc5ba9a
commit 03936243e4
2 changed files with 62 additions and 10 deletions
@@ -715,6 +715,53 @@ func TestRecordFileView(t *testing.T) {
require.Equal(t, http.StatusNotFound, resp.StatusCode, resp.String())
}
// TestBulkTagAutoRule verifies the bulk add path also applies then_tags.
func TestBulkTagAutoRule(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test in short mode")
}
h := setupSuite(t)
adminToken := h.login("admin", "admin")
resp := h.doJSON("POST", "/tags", map[string]any{"name": "outdoor"}, adminToken)
require.Equal(t, http.StatusCreated, resp.StatusCode)
var outdoor map[string]any
resp.decode(t, &outdoor)
outdoorID := outdoor["id"].(string)
resp = h.doJSON("POST", "/tags", map[string]any{"name": "nature"}, adminToken)
require.Equal(t, http.StatusCreated, resp.StatusCode)
var nature map[string]any
resp.decode(t, &nature)
natureID := nature["id"].(string)
resp = h.doJSON("POST", "/tags/"+outdoorID+"/rules", map[string]any{"then_tag_id": natureID}, adminToken)
require.Equal(t, http.StatusCreated, resp.StatusCode, resp.String())
file := h.uploadJPEG(adminToken, "park.jpg")
fileID := file["id"].(string)
// Bulk-add only "outdoor" to the file.
resp = h.doJSON("POST", "/files/bulk/tags", map[string]any{
"file_ids": []string{fileID},
"action": "add",
"tag_ids": []string{outdoorID},
}, adminToken)
require.Equal(t, http.StatusOK, resp.StatusCode, resp.String())
// The auto-applied "nature" should be on the file too.
resp = h.doJSON("GET", "/files/"+fileID+"/tags", nil, adminToken)
require.Equal(t, http.StatusOK, resp.StatusCode)
var tagsResp []any
resp.decode(t, &tagsResp)
names := make([]string, 0, len(tagsResp))
for _, tg := range tagsResp {
names = append(names, tg.(map[string]any)["name"].(string))
}
assert.ElementsMatch(t, []string{"outdoor", "nature"}, names)
}
// ---------------------------------------------------------------------------
// Security regression tests
// ---------------------------------------------------------------------------