import 'dart:io'; import 'package:teamhydra_idgen/teamhydra_idgen.dart'; import 'package:test/test.dart'; Map 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); }); }