Skip to content

Commit 033773a

Browse files
MOMO0302-02claude
andcommitted
Cover the popup layout and file copy fixes with tests
Both were changed in this branch but had no coverage: the layout delegate now handles a child larger than its viewport, where clamp used to be given an upper bound below its lower one, and safeCopy reports a missing source instead of creating an empty file in its place. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent b3f9489 commit 033773a

2 files changed

Lines changed: 139 additions & 0 deletions

File tree

test/common/file_test.dart

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import 'dart:io';
2+
3+
import 'package:fl_clash/common/file.dart';
4+
import 'package:path/path.dart';
5+
import 'package:test/test.dart';
6+
7+
void main() {
8+
group('FileExt.safeCopy', () {
9+
late Directory dir;
10+
11+
setUp(() {
12+
dir = Directory.systemTemp.createTempSync('fl_clash_file_test');
13+
});
14+
15+
tearDown(() {
16+
if (dir.existsSync()) {
17+
dir.deleteSync(recursive: true);
18+
}
19+
});
20+
21+
test('copies an existing file and reports success', () async {
22+
final source = File(join(dir.path, 'source.txt'))
23+
..writeAsStringSync('payload');
24+
final targetPath = join(dir.path, 'nested', 'target.txt');
25+
26+
expect(await source.safeCopy(targetPath), isTrue);
27+
expect(File(targetPath).readAsStringSync(), 'payload');
28+
});
29+
30+
test('overwrites an existing target', () async {
31+
final source = File(join(dir.path, 'source.txt'))
32+
..writeAsStringSync('new');
33+
final targetPath = join(dir.path, 'target.txt');
34+
File(targetPath).writeAsStringSync('old');
35+
36+
expect(await source.safeCopy(targetPath), isTrue);
37+
expect(File(targetPath).readAsStringSync(), 'new');
38+
});
39+
40+
// It used to create the *source* instead, leaving an empty file behind
41+
// and reporting nothing, so a backup missing a profile restored silently.
42+
test(
43+
'reports failure and creates nothing when the source is missing',
44+
() async {
45+
final source = File(join(dir.path, 'missing.txt'));
46+
final targetPath = join(dir.path, 'target.txt');
47+
48+
expect(await source.safeCopy(targetPath), isFalse);
49+
expect(source.existsSync(), isFalse);
50+
expect(File(targetPath).existsSync(), isFalse);
51+
},
52+
);
53+
});
54+
}

test/widgets/popup_test.dart

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import 'package:fl_clash/widgets/popup.dart';
2+
import 'package:flutter/material.dart';
3+
import 'package:flutter_test/flutter_test.dart';
4+
5+
void main() {
6+
group('OverflowAwareLayoutDelegate', () {
7+
Offset position({
8+
required Offset offset,
9+
required Size size,
10+
required Size childSize,
11+
}) {
12+
return OverflowAwareLayoutDelegate(
13+
offset: offset,
14+
).getPositionForChild(size, childSize);
15+
}
16+
17+
test('places the child to the left of the anchor', () {
18+
expect(
19+
position(
20+
offset: const Offset(300, 200),
21+
size: const Size(800, 600),
22+
childSize: const Size(100, 50),
23+
),
24+
const Offset(200, 200),
25+
);
26+
});
27+
28+
test('keeps the child inside the right and bottom edges', () {
29+
expect(
30+
position(
31+
offset: const Offset(790, 590),
32+
size: const Size(800, 600),
33+
childSize: const Size(100, 50),
34+
),
35+
const Offset(684, 534),
36+
);
37+
});
38+
39+
test('never returns a negative position', () {
40+
expect(
41+
position(
42+
offset: Offset.zero,
43+
size: const Size(800, 600),
44+
childSize: const Size(100, 50),
45+
),
46+
Offset.zero,
47+
);
48+
});
49+
50+
// A child larger than the viewport puts clamp's upper bound below its
51+
// lower one, which throws instead of laying out.
52+
test('does not throw when the child is wider than the viewport', () {
53+
expect(
54+
position(
55+
offset: const Offset(100, 100),
56+
size: const Size(200, 600),
57+
childSize: const Size(400, 50),
58+
),
59+
const Offset(0, 100),
60+
);
61+
});
62+
63+
test('does not throw when the child is taller than the viewport', () {
64+
expect(
65+
position(
66+
offset: const Offset(100, 100),
67+
size: const Size(800, 100),
68+
childSize: const Size(100, 400),
69+
),
70+
const Offset(0, 0),
71+
);
72+
});
73+
74+
test('does not throw when the child exactly fills the viewport', () {
75+
expect(
76+
position(
77+
offset: const Offset(50, 50),
78+
size: const Size(200, 200),
79+
childSize: const Size(200, 200),
80+
),
81+
Offset.zero,
82+
);
83+
});
84+
});
85+
}

0 commit comments

Comments
 (0)