1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00

Mobile: Fixes #10313: Fix error on retry or ignore attachment too large error (#10314)

This commit is contained in:
Henry Heino 2024-04-15 10:13:41 -07:00 committed by GitHub
parent 9fe31544f7
commit 87f7fb6841
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 75 additions and 19 deletions

View File

@ -1,22 +1,25 @@
import SyncTargetRegistry from '../SyncTargetRegistry';
import { _ } from '../locale';
import ReportService, { ReportSection } from './ReportService';
import { createNTestNotes, decryptionWorker, setupDatabaseAndSynchronizer, switchClient, synchronizerStart } from '../testing/test-utils';
import { createNTestNotes, decryptionWorker, setupDatabaseAndSynchronizer, supportDir, switchClient, syncTargetId, synchronizer, synchronizerStart } from '../testing/test-utils';
import Folder from '../models/Folder';
import BaseItem from '../models/BaseItem';
import DecryptionWorker from './DecryptionWorker';
import Note from '../models/Note';
import shim from '../shim';
const getSectionsWithTitle = (report: ReportSection[], title: string) => {
return report.filter(section => section.title === title);
const firstSectionWithTitle = (report: ReportSection[], title: string) => {
const sections = report.filter(section => section.title === title);
if (sections.length === 0) return null;
return sections[0];
};
const getCannotSyncSection = (report: ReportSection[]) => {
return getSectionsWithTitle(report, _('Items that cannot be synchronised'))[0];
return firstSectionWithTitle(report, _('Items that cannot be synchronised'));
};
const getIgnoredSection = (report: ReportSection[]) => {
return getSectionsWithTitle(report, _('Ignored items that cannot be synchronised'))[0];
return firstSectionWithTitle(report, _('Ignored items that cannot be synchronised'));
};
const sectionBodyToText = (section: ReportSection) => {
@ -32,8 +35,8 @@ const sectionBodyToText = (section: ReportSection) => {
describe('ReportService', () => {
beforeEach(async () => {
await setupDatabaseAndSynchronizer(1);
await setupDatabaseAndSynchronizer(2);
await switchClient(1);
await synchronizerStart();
// For compatibility with code that calls DecryptionWorker.instance()
DecryptionWorker.instance_ = decryptionWorker();
});
@ -43,15 +46,14 @@ describe('ReportService', () => {
const noteCount = 5;
const testNotes = await createNTestNotes(noteCount, folder);
await synchronizerStart();
const syncTargetId = SyncTargetRegistry.nameToId('memory');
const disabledReason = 'Test reason';
for (const testNote of testNotes) {
await BaseItem.saveSyncDisabled(syncTargetId, testNote, disabledReason);
await BaseItem.saveSyncDisabled(syncTargetId(), testNote, disabledReason);
}
const service = new ReportService();
let report = await service.status(syncTargetId);
let report = await service.status(syncTargetId());
// Items should all initially be listed as "cannot be synchronized", but should be ignorable.
const unsyncableSection = getCannotSyncSection(report);
@ -65,16 +67,16 @@ describe('ReportService', () => {
expect(sectionBodyToText(unsyncableSection)).toContain(disabledReason);
// Ignore all
expect(await BaseItem.syncDisabledItemsCount(syncTargetId)).toBe(noteCount);
expect(await BaseItem.syncDisabledItemsCountIncludingIgnored(syncTargetId)).toBe(noteCount);
expect(await BaseItem.syncDisabledItemsCount(syncTargetId())).toBe(noteCount);
expect(await BaseItem.syncDisabledItemsCountIncludingIgnored(syncTargetId())).toBe(noteCount);
for (const item of ignorableItems) {
await item.ignoreHandler();
}
expect(await BaseItem.syncDisabledItemsCount(syncTargetId)).toBe(0);
expect(await BaseItem.syncDisabledItemsCountIncludingIgnored(syncTargetId)).toBe(noteCount);
expect(await BaseItem.syncDisabledItemsCount(syncTargetId())).toBe(0);
expect(await BaseItem.syncDisabledItemsCountIncludingIgnored(syncTargetId())).toBe(noteCount);
await synchronizerStart();
report = await service.status(syncTargetId);
report = await service.status(syncTargetId());
// Should now be in the ignored section
const ignoredSection = getIgnoredSection(report);
@ -92,7 +94,7 @@ describe('ReportService', () => {
}
}
// Should have the correct number of ignored items
expect(await BaseItem.syncDisabledItemsCountIncludingIgnored(syncTargetId)).toBe(ignoredItemCount);
expect(await BaseItem.syncDisabledItemsCountIncludingIgnored(syncTargetId())).toBe(ignoredItemCount);
expect(ignoredItemCount).toBe(noteCount);
// Clicking "retry" should un-ignore
@ -103,6 +105,58 @@ describe('ReportService', () => {
break;
}
}
expect(await BaseItem.syncDisabledItemsCountIncludingIgnored(syncTargetId)).toBe(noteCount - 1);
expect(await BaseItem.syncDisabledItemsCountIncludingIgnored(syncTargetId())).toBe(noteCount - 1);
});
it('should support ignoring sync errors for resources that failed to download', async () => {
const createAttachmentDownloadError = async () => {
await switchClient(2);
const note1 = await Note.save({ title: 'note' });
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
await synchronizerStart();
await switchClient(1);
const previousMax = synchronizer().maxResourceSize_;
synchronizer().maxResourceSize_ = 1;
await synchronizerStart();
synchronizer().maxResourceSize_ = previousMax;
};
await createAttachmentDownloadError();
const service = new ReportService();
let report = await service.status(syncTargetId());
const unsyncableSection = getCannotSyncSection(report);
expect(sectionBodyToText(unsyncableSection)).toContain('could not be downloaded');
// Item for the download error should be ignorable
const ignorableItems = [];
for (const item of unsyncableSection.body) {
if (typeof item === 'object' && item.canIgnore) {
ignorableItems.push(item);
}
}
expect(ignorableItems).toHaveLength(1);
await ignorableItems[0].ignoreHandler();
// Should now be ignored.
report = await service.status(syncTargetId());
const ignoredItem = getIgnoredSection(report).body.find(item => typeof item === 'object' && item.canRetry === true);
expect(ignoredItem).not.toBeFalsy();
// Type narrowing
if (typeof ignoredItem === 'string') throw new Error('should be an object');
// Should be possible to retry
await ignoredItem.retryHandler();
await synchronizerStart();
// Should be fixed after retrying
report = await service.status(syncTargetId());
expect(getIgnoredSection(report)).toBeNull();
expect(getCannotSyncSection(report)).toBeNull();
});
});

View File

@ -194,16 +194,18 @@ export default class ReportService {
msg = _('Item "%s" could not be downloaded: %s', row.syncInfo.item_id, row.syncInfo.sync_disabled_reason);
}
// row.item may be undefined when location !== SYNC_ITEM_LOCATION_LOCAL
const item = { type_: row.syncInfo.item_type, id: row.syncInfo.item_id };
section.body.push({
text: msg,
canRetry: true,
canRetryType: CanRetryType.ItemSync,
retryHandler: async () => {
await BaseItem.saveSyncEnabled(row.item.type_, row.item.id);
await BaseItem.saveSyncEnabled(item.type_, item.id);
},
canIgnore: !row.warning_ignored,
ignoreHandler: async () => {
await BaseItem.ignoreItemSyncWarning(syncTarget, row.item);
await BaseItem.ignoreItemSyncWarning(syncTarget, item);
},
});
};