mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
317 lines
9.6 KiB
Dart
317 lines
9.6 KiB
Dart
import 'package:flutter_test/flutter_test.dart';
|
|
import 'package:server_box/data/model/server/server_private_info.dart';
|
|
|
|
void main() {
|
|
group('Server Edit Page Logic Tests', () {
|
|
test('SSH import should only be available on desktop platforms', () {
|
|
final desktopPlatforms = ['linux', 'macos', 'windows'];
|
|
final mobilePlatforms = ['android', 'ios', 'fuchsia'];
|
|
|
|
for (final platform in desktopPlatforms) {
|
|
final isDesktop = desktopPlatforms.contains(platform);
|
|
expect(isDesktop, isTrue, reason: '$platform should support SSH import');
|
|
}
|
|
|
|
for (final platform in mobilePlatforms) {
|
|
final isDesktop = desktopPlatforms.contains(platform);
|
|
expect(isDesktop, isFalse, reason: '$platform should not support SSH import');
|
|
}
|
|
});
|
|
|
|
test('permission prompt conditions are correct', () {
|
|
// Test the conditions for showing permission prompt
|
|
|
|
// Should prompt when: firstTimeReadSSHCfg=true, sshConfigExists=true, isNewServer=true
|
|
bool shouldPrompt(bool firstTime, bool configExists, bool isNew) {
|
|
return firstTime && configExists && isNew;
|
|
}
|
|
|
|
expect(shouldPrompt(true, true, true), isTrue); // All conditions met
|
|
expect(shouldPrompt(false, true, true), isFalse); // Setting disabled
|
|
expect(shouldPrompt(true, false, true), isFalse); // No config file
|
|
expect(shouldPrompt(true, true, false), isFalse); // Editing existing server
|
|
expect(shouldPrompt(false, false, false), isFalse); // No conditions met
|
|
});
|
|
|
|
test('server validation logic works correctly', () {
|
|
// Test server validation without actual form widgets
|
|
|
|
// Valid server
|
|
const validServer = Spi(
|
|
name: 'test-server',
|
|
ip: '192.168.1.100',
|
|
port: 22,
|
|
user: 'root',
|
|
);
|
|
|
|
expect(validServer.name.isNotEmpty, isTrue);
|
|
expect(validServer.ip.isNotEmpty, isTrue);
|
|
expect(validServer.port > 0 && validServer.port <= 65535, isTrue);
|
|
expect(validServer.user.isNotEmpty, isTrue);
|
|
|
|
// Invalid cases
|
|
expect(''.isNotEmpty, isFalse); // Empty name
|
|
expect(0 > 0, isFalse); // Invalid port
|
|
expect(65536 <= 65535, isFalse); // Port too high
|
|
});
|
|
|
|
test('server form data processing is correct', () {
|
|
// Test data processing logic
|
|
|
|
final Map<String, dynamic> formData = {
|
|
'name': 'my-server',
|
|
'ip': '192.168.1.100',
|
|
'port': '2222',
|
|
'user': 'admin',
|
|
};
|
|
|
|
// Process form data into server object
|
|
final server = Spi(
|
|
name: formData['name'] as String,
|
|
ip: formData['ip'] as String,
|
|
port: int.parse(formData['port'] as String),
|
|
user: formData['user'] as String,
|
|
);
|
|
|
|
expect(server.name, 'my-server');
|
|
expect(server.ip, '192.168.1.100');
|
|
expect(server.port, 2222);
|
|
expect(server.user, 'admin');
|
|
});
|
|
|
|
test('SSH key handling is correct', () {
|
|
// Test SSH key field handling
|
|
|
|
const serverWithKey = Spi(
|
|
name: 'key-server',
|
|
ip: '192.168.1.100',
|
|
port: 22,
|
|
user: 'root',
|
|
keyId: '~/.ssh/id_rsa',
|
|
);
|
|
|
|
expect(serverWithKey.keyId, '~/.ssh/id_rsa');
|
|
expect(serverWithKey.keyId?.isNotEmpty, isTrue);
|
|
|
|
const serverWithoutKey = Spi(
|
|
name: 'pwd-server',
|
|
ip: '192.168.1.100',
|
|
port: 22,
|
|
user: 'root',
|
|
pwd: 'password123',
|
|
);
|
|
|
|
expect(serverWithoutKey.keyId, isNull);
|
|
expect(serverWithoutKey.pwd, 'password123');
|
|
});
|
|
|
|
test('server editing vs creation logic', () {
|
|
// Test logic for distinguishing between editing and creating servers
|
|
|
|
const existingServer = Spi(
|
|
name: 'existing',
|
|
ip: '192.168.1.100',
|
|
port: 22,
|
|
user: 'root',
|
|
id: 'server123',
|
|
);
|
|
|
|
// Existing server has non-empty ID
|
|
final isEditing = existingServer.id.isNotEmpty;
|
|
final isCreating = !isEditing;
|
|
|
|
expect(isEditing, isTrue);
|
|
expect(isCreating, isFalse);
|
|
|
|
const newServer = Spi(
|
|
name: 'new-server',
|
|
ip: '192.168.1.100',
|
|
port: 22,
|
|
user: 'root',
|
|
id: '',
|
|
);
|
|
|
|
final isCreatingNew = newServer.id.isEmpty;
|
|
final isEditingExisting = !isCreatingNew;
|
|
|
|
expect(isCreatingNew, isTrue);
|
|
expect(isEditingExisting, isFalse);
|
|
});
|
|
|
|
test('form field population from imported server', () {
|
|
// Test that imported server data correctly populates form fields
|
|
|
|
const importedServer = Spi(
|
|
name: 'imported-prod-web',
|
|
ip: '10.0.1.100',
|
|
port: 2222,
|
|
user: 'deploy',
|
|
keyId: '~/.ssh/production.pem',
|
|
);
|
|
|
|
// Simulate form field population
|
|
final formFields = {
|
|
'name': importedServer.name,
|
|
'ip': importedServer.ip,
|
|
'port': importedServer.port.toString(),
|
|
'user': importedServer.user,
|
|
'keyId': importedServer.keyId,
|
|
};
|
|
|
|
expect(formFields['name'], 'imported-prod-web');
|
|
expect(formFields['ip'], '10.0.1.100');
|
|
expect(formFields['port'], '2222');
|
|
expect(formFields['user'], 'deploy');
|
|
expect(formFields['keyId'], '~/.ssh/production.pem');
|
|
});
|
|
|
|
test('import summary display logic', () {
|
|
// Test import summary formatting
|
|
|
|
const totalFound = 5;
|
|
const duplicatesRemoved = 2;
|
|
const serversToImport = 3;
|
|
|
|
final summary = {
|
|
'total': totalFound,
|
|
'duplicates': duplicatesRemoved,
|
|
'toImport': serversToImport,
|
|
};
|
|
|
|
expect(summary['total'], 5);
|
|
expect(summary['duplicates'], 2);
|
|
expect(summary['toImport'], 3);
|
|
|
|
// Summary validation
|
|
expect(summary['duplicates']! + summary['toImport']!, summary['total']);
|
|
|
|
// Format summary message (simplified)
|
|
final message = 'Found ${summary['total']} servers, '
|
|
'${summary['duplicates']} duplicates removed, '
|
|
'${summary['toImport']} will be imported.';
|
|
|
|
expect(message, 'Found 5 servers, 2 duplicates removed, 3 will be imported.');
|
|
});
|
|
|
|
test('error handling logic', () {
|
|
// Test error handling scenarios
|
|
|
|
final errors = <String>[];
|
|
|
|
// Validation errors
|
|
void validateServer(Spi server) {
|
|
if (server.name.isEmpty) {
|
|
errors.add('Server name is required');
|
|
}
|
|
if (server.ip.isEmpty) {
|
|
errors.add('Server IP is required');
|
|
}
|
|
if (server.port <= 0 || server.port > 65535) {
|
|
errors.add('Port must be between 1 and 65535');
|
|
}
|
|
if (server.user.isEmpty) {
|
|
errors.add('Username is required');
|
|
}
|
|
}
|
|
|
|
// Test with invalid server
|
|
const invalidServer = Spi(
|
|
name: '',
|
|
ip: '',
|
|
port: 0,
|
|
user: '',
|
|
);
|
|
|
|
validateServer(invalidServer);
|
|
|
|
expect(errors.length, 4);
|
|
expect(errors.contains('Server name is required'), isTrue);
|
|
expect(errors.contains('Server IP is required'), isTrue);
|
|
expect(errors.contains('Port must be between 1 and 65535'), isTrue);
|
|
expect(errors.contains('Username is required'), isTrue);
|
|
|
|
// Test with valid server
|
|
errors.clear();
|
|
const validServer = Spi(
|
|
name: 'valid',
|
|
ip: '192.168.1.1',
|
|
port: 22,
|
|
user: 'root',
|
|
);
|
|
|
|
validateServer(validServer);
|
|
expect(errors.isEmpty, isTrue);
|
|
});
|
|
|
|
test('name conflict resolution logic', () {
|
|
// Test name conflict resolution during import
|
|
|
|
final existingNames = ['server1', 'server2', 'server3'];
|
|
|
|
String resolveNameConflict(String proposedName, List<String> existing) {
|
|
if (!existing.contains(proposedName)) {
|
|
return proposedName;
|
|
}
|
|
|
|
int suffix = 2;
|
|
String newName;
|
|
do {
|
|
newName = '$proposedName ($suffix)';
|
|
suffix++;
|
|
} while (existing.contains(newName));
|
|
|
|
return newName;
|
|
}
|
|
|
|
// Test with no conflict
|
|
expect(resolveNameConflict('unique-name', existingNames), 'unique-name');
|
|
|
|
// Test with conflict
|
|
expect(resolveNameConflict('server1', existingNames), 'server1 (2)');
|
|
|
|
// Test with multiple conflicts
|
|
final extendedNames = [...existingNames, 'server1 (2)'];
|
|
expect(resolveNameConflict('server1', extendedNames), 'server1 (3)');
|
|
});
|
|
|
|
test('SSH config import button visibility logic', () {
|
|
// Test when SSH import button should be visible
|
|
|
|
bool shouldShowSSHImport({
|
|
required bool isDesktop,
|
|
required bool firstTimeReadSSHCfg,
|
|
required bool isNewServer,
|
|
}) {
|
|
return isDesktop && (firstTimeReadSSHCfg || !isNewServer);
|
|
}
|
|
|
|
// Desktop, first time, new server - should show
|
|
expect(shouldShowSSHImport(
|
|
isDesktop: true,
|
|
firstTimeReadSSHCfg: true,
|
|
isNewServer: true,
|
|
), isTrue);
|
|
|
|
// Desktop, not first time, new server - should not show auto import but manual import available
|
|
expect(shouldShowSSHImport(
|
|
isDesktop: true,
|
|
firstTimeReadSSHCfg: false,
|
|
isNewServer: true,
|
|
), isFalse);
|
|
|
|
// Desktop, editing existing server - should show manual import
|
|
expect(shouldShowSSHImport(
|
|
isDesktop: true,
|
|
firstTimeReadSSHCfg: false,
|
|
isNewServer: false,
|
|
), isTrue);
|
|
|
|
// Mobile - should never show
|
|
expect(shouldShowSSHImport(
|
|
isDesktop: false,
|
|
firstTimeReadSSHCfg: true,
|
|
isNewServer: true,
|
|
), isFalse);
|
|
});
|
|
});
|
|
} |