feat: duplicates resolve themselves without Lidarr (M502 #5517)
release / govulncheck (push) Successful in 37s
release / web (push) Successful in 1m13s
release / go (push) Successful in 1m29s
release / integration (push) Successful in 4m46s
release / android (push) Successful in 5m36s
release / Build signed APK (releases and dev) (push) Successful in 5m54s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 6m48s
release / Verify release artifacts (tag releases only) (push) Skipped
release / govulncheck (push) Successful in 37s
release / web (push) Successful in 1m13s
release / go (push) Successful in 1m29s
release / integration (push) Successful in 4m46s
release / android (push) Successful in 5m36s
release / Build signed APK (releases and dev) (push) Successful in 5m54s
release / Attach APK to the Release (tag releases only) (push) Skipped
release / Build + push container image (push) Successful in 6m48s
release / Verify release artifacts (tag releases only) (push) Skipped
Lidarr is off, and with it the resolver had stopped merging: it only merged when Lidarr had said which copies it mapped. Minstrel is now the only program writing the library, so the rule is about the copies: - A song held twice on one album: the extra copies merge into the one whose tags fit best (then lossless, larger, older). - Across releases or under another title: when every copy but one is a video rip (held back, or named like one and not marked fine), the rips merge into the one that is not. - Clean copies on different releases are linked as one song, as before. - Anything else waits for the operator. Gone with Lidarr: release switches and their settle window, the unmapped-file read, the rip search, the merge guard and its 409/503, lidarr.Client's release methods, and duplicate_group_members.lidarr_state (migration 0078). The duplicates page drops the per-copy Lidarr badge and the blocked-merge notice; past release changes stay in its history. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -66,7 +66,6 @@ function member(id: string, extra: Partial<AdminDuplicatesResponse['groups'][num
|
||||
added_at: ago(500 * HOUR),
|
||||
like_count: 0,
|
||||
play_count: 0,
|
||||
lidarr_state: null,
|
||||
disc_number: null,
|
||||
track_number: null,
|
||||
...extra
|
||||
@@ -332,7 +331,9 @@ describe('admin duplicates', () => {
|
||||
expect(dismissDuplicateGroup).toHaveBeenCalledWith('g-1');
|
||||
});
|
||||
|
||||
test('Resolved automatically lists merges and release changes', async () => {
|
||||
// Release changes stopped with Lidarr (M502), but the ones made before stay
|
||||
// in the history.
|
||||
test('Resolved automatically lists merges and past release changes', async () => {
|
||||
renderWith(response(), [
|
||||
{
|
||||
id: 'a-1',
|
||||
@@ -340,7 +341,7 @@ describe('admin duplicates', () => {
|
||||
created_at: ago(HOUR),
|
||||
details: {
|
||||
survivor_path: '/music/Gorillaz/Humanz (2017)/03 - Saturnz Barz.mp3',
|
||||
survivor_reason: 'the copy Lidarr tracks',
|
||||
survivor_reason: 'the copy that is not a video rip',
|
||||
removed: [{ track_id: 't-2', file_path: '/music/Gorillaz/Humanz (2017)/03 - Saturnz Barz (Official Video).mp3' }]
|
||||
}
|
||||
},
|
||||
@@ -358,47 +359,26 @@ describe('admin duplicates', () => {
|
||||
]);
|
||||
await fireEvent.click(screen.getByRole('tab', { name: /resolved automatically/i }));
|
||||
const items = screen.getAllByTestId('resolved-item').map(text);
|
||||
expect(items[0]).toContain('Kept 03 - Saturnz Barz.mp3 (the copy Lidarr tracks) and removed 1 file');
|
||||
expect(items[0]).toContain('Kept 03 - Saturnz Barz.mp3 (the copy that is not a video rip) and removed 1 file.');
|
||||
expect(items[1]).toContain('Lidarr now monitors Digital Media (40 tracks) of Humanz by Gorillaz');
|
||||
expect(screen.queryByTestId('duplicate-group')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Lidarr's view of each copy", () => {
|
||||
function tracked() {
|
||||
describe("the resolver's note", () => {
|
||||
test('shows above the group it explains', () => {
|
||||
const r = response();
|
||||
r.groups[0] = {
|
||||
...r.groups[0],
|
||||
resolve_note: 'Lidarr tracks every copy as its own track.',
|
||||
members: [member('www-01', { lidarr_state: 'tracked' }), member('www-02', { lidarr_state: 'unmapped' })]
|
||||
};
|
||||
return r;
|
||||
}
|
||||
|
||||
test('each copy says whether Lidarr uses it, and the resolver note shows', () => {
|
||||
renderWith(tracked());
|
||||
expect(screen.getAllByTestId('lidarr-state').map(text)).toEqual([
|
||||
'Lidarr uses this',
|
||||
"Lidarr doesn't use this"
|
||||
]);
|
||||
expect(text(screen.getByTestId('resolve-note'))).toBe('Lidarr tracks every copy as its own track.');
|
||||
r.groups[0] = { ...r.groups[0], resolve_note: 'Identical audio filed under different titles.' };
|
||||
renderWith(r);
|
||||
expect(text(screen.getByTestId('resolve-note'))).toBe('Identical audio filed under different titles.');
|
||||
});
|
||||
|
||||
// Keeping the unmapped copy would remove the one Lidarr uses. The server
|
||||
// refuses that; the confirm says so first and offers no button to press.
|
||||
test('a merge that would remove the copy Lidarr uses is blocked before it is sent', async () => {
|
||||
renderWith(tracked());
|
||||
test('a merge confirms and sends the copy chosen to keep', async () => {
|
||||
renderWith(response());
|
||||
await fireEvent.click(screen.getAllByRole('radio')[1]);
|
||||
await fireEvent.click(screen.getByRole('button', { name: 'Merge…' }));
|
||||
expect(text(screen.getByTestId('merge-blocked'))).toContain('Lidarr uses a copy this would remove');
|
||||
const confirm = screen.getByRole('button', { name: 'Remove 1 file and merge' }) as HTMLButtonElement;
|
||||
expect(confirm.disabled).toBe(true);
|
||||
|
||||
// Choosing the copy Lidarr uses clears it.
|
||||
await fireEvent.click(screen.getAllByRole('radio')[0]);
|
||||
expect(screen.queryByTestId('merge-blocked')).toBeNull();
|
||||
await fireEvent.click(screen.getByRole('button', { name: 'Remove 1 file and merge' }));
|
||||
expect(mergeDuplicateGroup).toHaveBeenCalledWith('g-1', { survivor_track_id: 'www-01', unmonitor: false });
|
||||
expect(mergeDuplicateGroup).toHaveBeenCalledWith('g-1', { survivor_track_id: 'www-02', unmonitor: false });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user