twonly-app-dependencies/qr/test/qr_code_test.dart
2025-12-07 16:28:21 +01:00

194 lines
5.6 KiB
Dart

// ignore_for_file: avoid_dynamic_calls
import 'dart:typed_data';
import 'package:qr/qr.dart';
import 'package:test/test.dart';
import 'qr_code_test_data.dart';
import 'qr_code_test_data_with_mask.dart';
void main() {
test('simple', () {
for (var typeNumber = 1; typeNumber <= 40; typeNumber++) {
for (var quality in QrErrorCorrectLevel.levels) {
final qr = QrImage(QrCode(typeNumber, quality)..addData('shanna!'));
final modules = qr.qrModules;
for (var i = 0; i < modules.length; i++) {
expect(
_encodeBoolListToString(modules[i]),
qrCodeTestData[typeNumber.toString()][quality.toString()][i],
);
}
}
}
});
test('fromData', () {
for (var quality in QrErrorCorrectLevel.levels) {
final qr = QrImage(
QrCode.fromData(data: 'shanna!', errorCorrectLevel: quality),
);
final modules = qr.qrModules;
for (var i = 0; i < modules.length; i++) {
expect(
_encodeBoolListToString(modules[i]),
qrCodeTestData['1'][quality.toString()][i],
);
}
}
});
test('fromUint8List', () {
for (var quality in QrErrorCorrectLevel.levels) {
final qr = QrImage(
QrCode.fromUint8List(
data: Uint8List.fromList([115, 104, 97, 110, 110, 97, 33]),
errorCorrectLevel: quality,
),
);
final modules = qr.qrModules;
for (var i = 0; i < modules.length; i++) {
expect(
_encodeBoolListToString(modules[i]),
qrCodeTestData['1'][quality.toString()][i],
);
}
}
});
test('WHEN mask pattern is provided, SHOULD make a masked QR Code', () {
for (var mask = 0; mask <= 7; mask++) {
final qr = QrImage.withMaskPattern(
QrCode(1, QrErrorCorrectLevel.L)..addData('shanna!'),
mask,
);
final modules = qr.qrModules;
for (var i = 0; i < modules.length; i++) {
expect(
_encodeBoolListToString(modules[i]),
qrCodeTestDataWithMask[mask.toString()][i],
);
}
}
});
test(
'''
WHEN provided mask pattern is smaller than 0,
SHOULD throw an AssertionError
''',
() {
expect(() {
QrImage.withMaskPattern(
QrCode(1, QrErrorCorrectLevel.L)..addData('shanna!'),
-1,
);
}, throwsA(isA<AssertionError>()));
},
);
test(
'''
WHEN provided mask pattern is bigger than 7,
SHOULD throw an AssertionError
''',
() {
expect(() {
QrImage.withMaskPattern(
QrCode(1, QrErrorCorrectLevel.L)..addData('shanna!'),
8,
);
}, throwsA(isA<AssertionError>()));
},
);
group('QrCode.fromData Automatic Mode Detection', () {
// Numeric Mode
test('should use Numeric Mode for numbers', () {
// 9 numeric chars fit version 1 (H level).
final qr = QrCode.fromData(
data: '123456789',
errorCorrectLevel: QrErrorCorrectLevel.H,
);
expect(qr.typeNumber, 1);
});
// Alphanumeric Mode
test('should use Alphanumeric Mode', () {
// 13 alphanumeric chars exceed version 1 (7 chars) but fit
// version 2 (H level, 16 chars).
final qr = QrCode.fromData(
data: 'HELLO WORLD A',
errorCorrectLevel: QrErrorCorrectLevel.H,
);
expect(qr.typeNumber, 2);
});
// Byte Mode
test('should use Byte Mode for non-alphanumeric chars', () {
// Kanji characters are UTF-8 encoded.
// '機械学習' (12 bytes) fits version 2 (H level, 16 bytes).
final qr = QrCode.fromData(
data: '機械学習',
errorCorrectLevel: QrErrorCorrectLevel.H,
);
expect(qr.typeNumber, 2);
});
});
group('QrCode.addData Automatic Mode Detection', () {
// Numeric Mode
test('should use Numeric Mode for numbers', () {
// 9 numeric characters fit version 1 (H level).
final qr = QrCode(1, QrErrorCorrectLevel.H)..addData('123456789');
expect(qr.typeNumber, 1);
});
// Alphanumeric Mode
test('should use Alphanumeric Mode', () {
// 13 alphanumeric characters exceed version 1 (7 chars) but fit
// version 2 (H level, 16 chars).
final qr = QrCode(2, QrErrorCorrectLevel.H)..addData('HELLO WORLD A');
expect(qr.typeNumber, 2);
});
// Byte Mode
test('should use Byte Mode for non-alphanumeric characters', () {
// Kanji characters are UTF-8 encoded.
// '機械学習' (12 bytes) fits version 2 (H level, 16 bytes).
final qr = QrCode(2, QrErrorCorrectLevel.H)..addData('機械学習');
expect(qr.typeNumber, 2);
});
});
group('_calculateTypeNumberFromData - Version 40 Boundary Handling', () {
test('generate v40 for data exceeding v39 capacity', () {
// 2952 bytes exceeds v39 (L) capacity of 2951.
final largeData = '|' * 2952;
final qrCode = QrCode.fromData(
data: largeData,
errorCorrectLevel: QrErrorCorrectLevel.L,
);
expect(qrCode.typeNumber, 40);
});
test('throw InputTooLongException for data exceeding v40 capacity', () {
// Data size (2954 bytes) exceeds v40 capacity (2953 bytes).
final excessivelyLargeData = '|' * 2954;
// An exception should be thrown for data exceeding the capacity
expect(
() => QrCode.fromData(
data: excessivelyLargeData,
errorCorrectLevel: QrErrorCorrectLevel.L,
),
throwsA(isA<InputTooLongException>()),
);
});
});
}
String _encodeBoolListToString(List<bool?> source) =>
source.cast<bool>().map((e) => e ? '1' : '0').join();