fix(publish): a release sends exactly the tag names the sheet showed (ADR 0019)
The final reading of 22 Oct found that the names were worked out again after the sync that comes before publishing, so a link to a private tag the instance merged in during that sync sent a name nobody saw going. The sheet now hands what it showed to Publish, and the device refuses before anything goes out when the names worked out then differ (PublishProblem.tagNamesChanged), reading them again for the person to look at. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
037abb0cc6
commit
92ff7616a4
3 changed files with 164 additions and 13 deletions
|
|
@ -1,11 +1,12 @@
|
|||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/publish/data/publish_repository.dart';
|
||||
import 'package:halkyon_learn_flutter/src/feature/publish/model/publication.dart';
|
||||
|
||||
import '../../../support/fake_publish_gateway.dart';
|
||||
import '../../../support/memory_published_store.dart';
|
||||
|
||||
/// The instance can't read the person's tags (ADR 0019, D2): publishing
|
||||
/// names them as this device reads them.
|
||||
/// names them as this device reads them, exactly as the sheet showed them.
|
||||
void main() {
|
||||
test('publishing sends the names of the tags the release carries, as this '
|
||||
'device reads them, and no others', () async {
|
||||
|
|
@ -21,7 +22,12 @@ void main() {
|
|||
);
|
||||
addTearDown(publishing.dispose);
|
||||
|
||||
await publishing.publish('studyset-1', slug: 'japanese', notes: '');
|
||||
await publishing.publish(
|
||||
'studyset-1',
|
||||
slug: 'japanese',
|
||||
notes: '',
|
||||
tagNamesShown: {'tag-1': 'JLPT-N5'},
|
||||
);
|
||||
|
||||
expect(gateway.lastTagNames, {'tag-1': 'JLPT-N5'});
|
||||
expect(asked, ['studyset-1']);
|
||||
|
|
@ -32,8 +38,67 @@ void main() {
|
|||
final publishing = PublishRepository(gateway, MemoryPublishedStore());
|
||||
addTearDown(publishing.dispose);
|
||||
|
||||
await publishing.publish('studyset-1', slug: 'japanese', notes: '');
|
||||
await publishing.publish(
|
||||
'studyset-1',
|
||||
slug: 'japanese',
|
||||
notes: '',
|
||||
tagNamesShown: null,
|
||||
);
|
||||
|
||||
expect(gateway.lastTagNames, isNull);
|
||||
});
|
||||
|
||||
test('names that changed since the sheet showed them (a sync merged a tag '
|
||||
'in) are never sent: publishing is refused here', () async {
|
||||
final gateway = FakePublishGateway();
|
||||
var names = {'tag-1': 'JLPT-N5'};
|
||||
final publishing = PublishRepository(
|
||||
gateway,
|
||||
MemoryPublishedStore(),
|
||||
tagNames: (studysetId) async => names,
|
||||
);
|
||||
addTearDown(publishing.dispose);
|
||||
final shown = await publishing.tagNamesOf('studyset-1');
|
||||
|
||||
// The sync before publishing brings a link to a private tag.
|
||||
names = {'tag-1': 'JLPT-N5', 'tag-2': 'あかね噺 S1 E1'};
|
||||
|
||||
await expectLater(
|
||||
publishing.publish(
|
||||
'studyset-1',
|
||||
slug: 'japanese',
|
||||
notes: '',
|
||||
tagNamesShown: shown,
|
||||
),
|
||||
throwsA(
|
||||
isA<PublishRefused>().having(
|
||||
(e) => e.problem,
|
||||
'problem',
|
||||
PublishProblem.tagNamesChanged,
|
||||
),
|
||||
),
|
||||
);
|
||||
expect(gateway.lastTagNames, isNull, reason: 'nothing went out');
|
||||
});
|
||||
|
||||
test('names never shown are never sent', () async {
|
||||
final gateway = FakePublishGateway();
|
||||
final publishing = PublishRepository(
|
||||
gateway,
|
||||
MemoryPublishedStore(),
|
||||
tagNames: (studysetId) async => {'tag-1': 'JLPT-N5'},
|
||||
);
|
||||
addTearDown(publishing.dispose);
|
||||
|
||||
await expectLater(
|
||||
publishing.publish(
|
||||
'studyset-1',
|
||||
slug: 'japanese',
|
||||
notes: '',
|
||||
tagNamesShown: null,
|
||||
),
|
||||
throwsA(isA<PublishRefused>()),
|
||||
);
|
||||
expect(gateway.lastTagNames, isNull);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@ void main() {
|
|||
slug: 'japanese',
|
||||
notes: 'First lessons.',
|
||||
subtree: ['japanese'],
|
||||
tagNames: null,
|
||||
),
|
||||
);
|
||||
return await bloc.stream.firstWhere(
|
||||
|
|
@ -165,7 +166,12 @@ void main() {
|
|||
|
||||
publishing.fail = Exception('offline');
|
||||
publisher.add(
|
||||
const PublishEventRequested(slug: 'japanese', notes: '', subtree: []),
|
||||
const PublishEventRequested(
|
||||
slug: 'japanese',
|
||||
notes: '',
|
||||
subtree: [],
|
||||
tagNames: null,
|
||||
),
|
||||
);
|
||||
final failed = await publisher.stream.firstWhere(
|
||||
(state) => state is PublishStateReady && !state.publishing,
|
||||
|
|
|
|||
|
|
@ -46,7 +46,12 @@ void main() {
|
|||
await pumpEventQueue();
|
||||
|
||||
await publishing.publication('japanese');
|
||||
await publishing.publish('kanji', slug: 'kanji', notes: '');
|
||||
await publishing.publish(
|
||||
'kanji',
|
||||
slug: 'kanji',
|
||||
notes: '',
|
||||
tagNamesShown: null,
|
||||
);
|
||||
await publishing.withdraw('japanese');
|
||||
await pumpEventQueue();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue