194 lines
5.6 KiB
Dart
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();
|