twonly-app-dependencies/qr/test/verify_qr_tool_test.dart
2026-02-12 22:01:59 +01:00

173 lines
4.4 KiB
Dart

@Tags(['require-zbar'])
library;
import 'dart:io';
import 'package:path/path.dart' as p;
import 'package:test/test.dart';
import 'package:test_process/test_process.dart';
void main() {
late Directory tempDir;
setUpAll(() {
tempDir = Directory.systemTemp.createTempSync('qr_tool_test');
});
tearDownAll(() {
tempDir.deleteSync(recursive: true);
});
final configurations = [
(version: null, correction: null),
(version: 40, correction: 'H'),
];
final inputs = [
'123456',
'HELLO WORLD',
'Hello 👋 World 🌍',
'👩🏽❤️💋👨🏾',
'👩🏽‍❤️‍💋‍👨🏾',
];
for (final config in configurations) {
for (final input in inputs) {
test(
'Generate QR with config $config and input "$input"',
() async {
final bmpPath = p.join(
tempDir.path,
'test_${config.hashCode}_${input.hashCode}.bmp',
);
final args = [
'tool/write_qr.dart',
'-o',
bmpPath,
if (config.version != null) ...['-v', config.version.toString()],
if (config.correction != null) ...['-c', config.correction!],
'--scale',
'10',
input,
];
final process = await TestProcess.start('dart', args);
await process.shouldExit(0);
expect(
File(bmpPath).existsSync(),
isTrue,
reason: 'BMP file should be created',
);
// Validate with zbarimg
// zbarimg output format: QR-Code:content
final zbar = await TestProcess.start('zbarimg', ['--quiet', bmpPath]);
await zbar.shouldExit(0);
final output = (await zbar.stdout.rest.toList()).join('\n').trim();
if (output != 'QR-Code:$input') {
print('zbarimg failed to match input.');
print('Input: $input');
print('Output: "$output"');
}
expect(output, 'QR-Code:$input');
},
timeout: const Timeout(Duration(seconds: 20)),
);
}
}
test('Generate QR with Version 1 (numeric input)', () async {
const input = '123456';
final bmpPath = p.join(tempDir.path, 'test_v1_numeric.bmp');
final args = [
'tool/write_qr.dart',
'-o',
bmpPath,
'-v',
'1',
'-c',
'L',
'--scale',
'10',
input,
];
final process = await TestProcess.start('dart', args);
await process.shouldExit(0);
expect(
File(bmpPath).existsSync(),
isTrue,
reason: 'BMP file should be created',
);
final zbar = await TestProcess.start('zbarimg', ['--quiet', bmpPath]);
await zbar.shouldExit(0);
final output = (await zbar.stdout.rest.toList()).join('\n').trim();
if (output != 'QR-Code:$input') {
print('zbarimg failed to match input.');
print('Input: $input');
print('Output: "$output"');
}
expect(output, 'QR-Code:$input');
});
test('Error case: Missing output argument', () async {
final process = await TestProcess.start('dart', [
'tool/write_qr.dart',
'content',
]);
await process.shouldExit(1);
final output = await process.stdout.next;
expect(
output,
contains('Error: Invalid argument(s): Option output is mandatory.'),
);
});
test('Error case: Invalid version', () async {
final bmpPath = p.join(tempDir.path, 'invalid_version.bmp');
final process = await TestProcess.start('dart', [
'tool/write_qr.dart',
'-o',
bmpPath,
'-v',
'41',
'content',
]);
await process.shouldExit(1);
});
test('Error case: Invalid correction', () async {
final bmpPath = p.join(tempDir.path, 'invalid_correction.bmp');
final process = await TestProcess.start('dart', [
'tool/write_qr.dart',
'-o',
bmpPath,
'-c',
'X',
'content',
]);
await process.shouldExit(1); // ArgParser error
});
test('Error case: Input too long for version (explicit version)', () async {
const input =
'This string is definitely too long for Version 1 with '
'High error correction level.';
final bmpPath = p.join(tempDir.path, 'too_long.bmp');
final process = await TestProcess.start('dart', [
'tool/write_qr.dart',
'-o',
bmpPath,
'-v',
'1',
'-c',
'H', // High error correction reduces capacity
input,
]);
await process.shouldExit(1);
});
}