teamhydra_id_generator/test/idgen_dart_test.dart

319 lines
11 KiB
Dart

import 'dart:io';
import 'package:teamhydra_id_generator/teamhydra_idgen.dart';
import 'package:test/test.dart';
Map<String, String> loadRequiredVarsFromEnv() {
// Load the .env file from the current directory
final currentDir = Directory.current;
final envFile = File('${currentDir.path}/.env');
if (!envFile.existsSync()) {
throw Exception(
'Could not locate the .env file in the current directory (tried path: ${envFile.path})');
}
final lines = envFile
.readAsLinesSync()
.where((line) => line.isNotEmpty && !line.startsWith('#'))
.toList(); // Filter out empty lines and comments
String username = '';
String token = '';
// Get the username and token (IDGEN_USERNAME and IDGEN_TOKEN)
for (final line in lines) {
if (line.startsWith('IDGEN_USERNAME=')) {
username = line.split('=')[1].trim();
} else if (line.startsWith('IDGEN_TOKEN=')) {
token = line.split('=')[1].trim();
}
}
// Remove " from the strings
username = username.replaceAll('"', '');
token = token.replaceAll('"', '');
if (username.isEmpty || token.isEmpty) {
throw Exception(
'IDGEN_USERNAME or IDGEN_TOKEN is missing from the .env file');
}
return {'username': username, 'token': token};
}
void main() {
// Load the .env file and get the username and token
final env = loadRequiredVarsFromEnv();
if (env['username'] == null ||
env['token'] == null ||
env['username']!.isEmpty ||
env['token']!.isEmpty) {
print('Please provide a valid username and token in the .env file');
exit(1);
}
final username = env['username']!;
final token = env['token']!;
print(
"[IDGen] Loaded credentials for username: $username and token (last 4): ${token.substring(token.length - 4)} to run tests");
group('IDGen', () {
final idGen = IDGen(username: username, token: token);
// Ensure it errors when invalid user/token combo is used
test('Invalid user/token combo', () async {
final idGen = IDGen(username: 'invalid', token: 'invalid');
try {
await idGen.generateUUIDV4();
fail('Should have thrown an exception');
} on IDGenException catch (e) {
expect(e.message,
'Server rejected ID generation: Invalid username or token');
} catch (e) {
fail('Should have thrown an IDGenException');
}
});
// Ensure it generates a UUID V4
test('Generate UUID V4', () async {
final response = await idGen.generateUUIDV4();
expect(response.id, isNotNull);
expect(response.id, isNotEmpty);
expect(response.id.length, 36);
});
// Ensure it generates a nanoID
test('Generate nanoID', () async {
final response = await idGen.generateNanoID();
expect(response.id, isNotNull);
expect(response.id, isNotEmpty);
expect(response.id.length, 10);
});
// Ensure it generates a nanoID with a custom size
test('Generate nanoID with custom size', () async {
final response = await idGen.generateNanoID(size: 20);
print('[IDGen] Generated nanoID with size 20: ${response.id}');
expect(response.id, isNotNull);
expect(response.id, isNotEmpty);
expect(response.id.length, 20);
});
// Ensure it generates a nanoID with a custom alphabet
test('Generate nanoID with custom alphabet', () async {
final response =
await idGen.generateNanoID(alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ');
print('[IDGen] Generated nanoID with custom alphabet: ${response.id}');
expect(response.id, isNotNull);
expect(response.id, isNotEmpty);
expect(response.id.length, 10);
});
// All together now
test('Generate nanoID with custom size and alphabet', () async {
final response = await idGen.generateNanoID(
size: 20, alphabet: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789');
print(
'[IDGen] Generated nanoID with size 20 and custom alphabet: ${response.id}');
expect(response.id, isNotNull);
expect(response.id, isNotEmpty);
expect(response.id.length, 20);
});
// Ensure it throws an error when generating a nanoID with an empty alphabet
test('Generate nanoID with empty alphabet', () async {
try {
await idGen.generateNanoID(alphabet: '');
fail('Should have thrown an exception');
} on ArgumentError catch (e) {
expect(e.message, 'Cannot generate a nanoID with an empty alphabet');
} catch (e) {
fail('Should have thrown an ArgumentError');
}
});
// Ensure it throws an error when generating a nanoID with an invalid alphabet length
test('Generate nanoID with invalid alphabet length', () async {
try {
await idGen.generateNanoID(alphabet: 'AB');
fail('Should have thrown an exception');
} on ArgumentError catch (e) {
expect(e.message,
'Cannot generate a nanoID with an alphabet of length 2, must be between 3 and 256');
} catch (e) {
fail('Should have thrown an ArgumentError');
}
});
// Ensure it throws an error when generating a nanoID with an invalid size
test('Generate nanoID with invalid size', () async {
try {
await idGen.generateNanoID(size: 0);
fail('Should have thrown an exception');
} on ArgumentError catch (e) {
expect(e.message,
'Cannot generate a nanoID with a length of 0, must be between 1 and 256');
} catch (e) {
fail('Should have thrown an ArgumentError');
}
});
// Ensure it generates a 2FA code pair
test('Generate 2FA code pair', () async {
final response = await idGen.generate2FACode();
print('[IDGen] Generated 2FA code: ${response.id}');
expect(response.id, isNotNull);
expect(response.id, isNotEmpty);
expect(response.id.length, 6);
});
// Ensure it generates a 2FA code pair with a custom length
test('Generate 2FA code pair with custom length', () async {
final response = await idGen.generate2FACode(length: 10);
print('[IDGen] Generated 2FA code with length 10: ${response.id}');
expect(response.id, isNotNull);
expect(response.id, isNotEmpty);
expect(response.id.length, 10);
});
// Ensure it throws an error when generating a 2FA code with an invalid length
test('Generate 2FA code pair with invalid length', () async {
try {
await idGen.generate2FACode(length: 0);
fail('Should have thrown an exception');
} on ArgumentError catch (e) {
expect(e.message,
'Cannot generate a 2FA code with a length of 0, must be between 1 and 256');
} catch (e) {
fail('Should have thrown an ArgumentError');
}
});
// Ensure it generates a license key
test('Generate license key', () async {
final response = await idGen.generateLicenseKey();
print('[IDGen] Generated license key: ${response.id}');
expect(response.id, isNotNull);
expect(response.id, isNotEmpty);
expect(response.id.length, 29);
// Make sure it follows the 5-5-5-5-5 format
final parts = response.id.split('-');
expect(parts.length, 5);
});
// Ensure it generates a word based string
test('Generate word based string', () async {
final response = await idGen.generateWordBasedString();
print('[IDGen] Generated word based string: ${response.id}');
expect(response.id, isNotNull);
expect(response.id, isNotEmpty);
});
// Ensure it generates a word based string with a custom length
test('Generate word based string with custom length', () async {
final response = await idGen.generateWordBasedString(length: 10);
print(
'[IDGen] Generated word based string with length 10: ${response.id}');
expect(response.id, isNotNull);
expect(response.id, isNotEmpty);
// Should contain -'s as the default separator
expect(response.id.contains('-'), isTrue);
});
// Ensure it can generate all separators for word based strings
test('Generate word based string with custom separator', () async {
final responseSlug =
await idGen.generateWordBasedString(separator: 'slug');
print(
'[IDGen] Generated word based string with slug separator: ${responseSlug.id}');
final responseTitle =
await idGen.generateWordBasedString(separator: 'title');
print(
'[IDGen] Generated word based string with title separator: ${responseTitle.id}');
final responseFormal =
await idGen.generateWordBasedString(separator: 'formal');
print(
'[IDGen] Generated word based string with formal separator: ${responseFormal.id}');
expect(responseSlug.id, isNotNull);
expect(responseSlug.id, isNotEmpty);
expect(responseTitle.id, isNotNull);
expect(responseTitle.id, isNotEmpty);
expect(responseFormal.id, isNotNull);
expect(responseFormal.id, isNotEmpty);
});
});
// Ensure it errors when a invalid separator is used for word based strings
test('Generate word based string with invalid separator', () async {
final idGen = IDGen(username: username, token: token);
try {
await idGen.generateWordBasedString(separator: 'invalid');
fail('Should have thrown an exception');
} on ArgumentError catch (e) {
expect(e.message,
'Cannot generate a word based string with an invalid separator');
} catch (e) {
fail('Should have thrown an ArgumentError');
}
});
// Ensure it errors when a invalid length is used for word based strings
test('Generate word based string with invalid length', () async {
final idGen = IDGen(username: username, token: token);
try {
await idGen.generateWordBasedString(length: 0);
fail('Should have thrown an exception');
} on ArgumentError catch (e) {
expect(e.message,
'Cannot generate a word based string with a length of 0, must be between 1 and 16');
} catch (e) {
fail('Should have thrown an ArgumentError');
}
});
// Ensure it generates a snowflake ID
test('Generate snowflake ID', () async {
final idGen = IDGen(username: username, token: token);
final response = await idGen.generateSnowflakeID();
print('[IDGen] Generated snowflake ID: ${response.id}');
expect(response.id, isNotNull);
expect(response.id, isNotEmpty);
expect(response.id.length, 20);
});
// Ensure it generates a keypair
test('Generate keypair', () async {
final idGen = IDGen(username: username, token: token);
final response = await idGen.generateKeypair();
print(
'[IDGen] Generated keypair: ${response.id} and secret: ${response.privateID}');
expect(response.id, isNotNull);
expect(response.id, isNotEmpty);
expect(response.privateID, isNotNull);
expect(response.privateID, isNotEmpty);
});
}