mirror of
https://github.com/foss42/apidash.git
synced 2025-12-02 18:57:05 +08:00
genai_testing: Expanded Testing Efforts
This commit is contained in:
@@ -5,6 +5,6 @@ const kKeyStream = 'stream';
|
||||
final kAvailableModels = AvailableModels.fromJson(kModelsData);
|
||||
|
||||
const kModelRemoteUrl =
|
||||
'https://raw.githubusercontent.com/foss42/apidash/package/genai/packages/genai/models.json';
|
||||
'https://raw.githubusercontent.com/foss42/apidash/refs/heads/main/packages/genai/models.json';
|
||||
|
||||
const kBaseOllamaUrl = 'http://localhost:11434';
|
||||
|
||||
@@ -25,4 +25,3 @@ dev_dependencies:
|
||||
freezed: ^2.5.7
|
||||
json_serializable: ^6.7.1
|
||||
test: ^1.25.2
|
||||
mocktail: ^1.0.0
|
||||
|
||||
83
packages/genai/test/models/model_config_test.dart
Normal file
83
packages/genai/test/models/model_config_test.dart
Normal file
@@ -0,0 +1,83 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:genai/models/model_config.dart';
|
||||
import 'package:genai/models/model_config_value.dart';
|
||||
|
||||
void main() {
|
||||
group('ModelConfig', () {
|
||||
test('constructor asserts correct type/value', () {
|
||||
expect(
|
||||
() => ModelConfig(
|
||||
id: '1',
|
||||
name: 'Temperature',
|
||||
description: 'test',
|
||||
type: ConfigType.boolean,
|
||||
value: ConfigBooleanValue(value: true),
|
||||
),
|
||||
returnsNormally,
|
||||
);
|
||||
|
||||
expect(
|
||||
() => ModelConfig(
|
||||
id: '2',
|
||||
name: 'Invalid',
|
||||
description: 'wrong',
|
||||
type: ConfigType.boolean,
|
||||
value: ConfigNumericValue(value: 5),
|
||||
),
|
||||
throwsA(isA<AssertionError>()),
|
||||
);
|
||||
});
|
||||
|
||||
test('updateValue returns new instance with updated value', () {
|
||||
final config = ModelConfig(
|
||||
id: '1',
|
||||
name: 'Numeric',
|
||||
description: 'test',
|
||||
type: ConfigType.numeric,
|
||||
value: ConfigNumericValue(value: 10),
|
||||
);
|
||||
|
||||
final updated = config.updateValue(ConfigNumericValue(value: 20));
|
||||
expect(updated.value.value, 20);
|
||||
expect(updated.id, config.id);
|
||||
});
|
||||
|
||||
test('toJson and fromJson work correctly', () {
|
||||
final config = ModelConfig(
|
||||
id: 'temp',
|
||||
name: 'Temperature',
|
||||
description: 'test config',
|
||||
type: ConfigType.numeric,
|
||||
value: ConfigNumericValue(value: 5),
|
||||
);
|
||||
|
||||
final json = config.toJson();
|
||||
expect(json['id'], 'temp');
|
||||
expect(json['type'], 'numeric');
|
||||
|
||||
final from = ModelConfig.fromJson(json);
|
||||
expect(from.id, 'temp');
|
||||
expect(from.value is ConfigNumericValue, true);
|
||||
expect((from.value as ConfigNumericValue).value, 5);
|
||||
});
|
||||
|
||||
test('copyWith creates modified copy', () {
|
||||
final config = ModelConfig(
|
||||
id: 'slider',
|
||||
name: 'Slider',
|
||||
description: 'range',
|
||||
type: ConfigType.slider,
|
||||
value: ConfigSliderValue(value: (0, 0.3, 1)),
|
||||
);
|
||||
|
||||
final copy = config.copyWith(
|
||||
name: 'Updated Slider',
|
||||
value: ConfigSliderValue(value: (0, 0.7, 1)),
|
||||
);
|
||||
|
||||
expect(copy.name, 'Updated Slider');
|
||||
expect(copy.value.getPayloadValue(), 0.7);
|
||||
expect(copy.id, 'slider'); // unchanged
|
||||
});
|
||||
});
|
||||
}
|
||||
110
packages/genai/test/models/model_config_value_test.dart
Normal file
110
packages/genai/test/models/model_config_value_test.dart
Normal file
@@ -0,0 +1,110 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:genai/models/model_config_value.dart';
|
||||
|
||||
void main() {
|
||||
group('ConfigType Enum', () {
|
||||
test('getConfigTypeEnum returns correct enum', () {
|
||||
expect(getConfigTypeEnum('boolean'), ConfigType.boolean);
|
||||
expect(getConfigTypeEnum('slider'), ConfigType.slider);
|
||||
expect(getConfigTypeEnum('numeric'), ConfigType.numeric);
|
||||
expect(getConfigTypeEnum('text'), ConfigType.text);
|
||||
});
|
||||
|
||||
test('getConfigTypeEnum falls back to text on invalid', () {
|
||||
expect(getConfigTypeEnum('does_not_exist'), ConfigType.text);
|
||||
expect(getConfigTypeEnum(null), ConfigType.text);
|
||||
});
|
||||
});
|
||||
|
||||
group('ConfigBooleanValue', () {
|
||||
test('serialize and deserialize works', () {
|
||||
final value = ConfigBooleanValue(value: true);
|
||||
final serialized = value.serialize();
|
||||
expect(serialized, 'true');
|
||||
|
||||
final deserialized = ConfigBooleanValue.deserialize(serialized);
|
||||
expect(deserialized.value, true);
|
||||
});
|
||||
});
|
||||
|
||||
group('ConfigNumericValue', () {
|
||||
test('serialize and deserialize works', () {
|
||||
final value = ConfigNumericValue(value: 42);
|
||||
final serialized = value.serialize();
|
||||
expect(serialized, '42');
|
||||
|
||||
final deserialized = ConfigNumericValue.deserialize('42');
|
||||
expect(deserialized.value, 42);
|
||||
|
||||
final nullValue = ConfigNumericValue.deserialize('not_a_number');
|
||||
expect(nullValue.value, null);
|
||||
});
|
||||
});
|
||||
|
||||
group('ConfigSliderValue', () {
|
||||
test('serialize and deserialize works', () {
|
||||
final value = ConfigSliderValue(value: (0.0, 0.5, 1.0));
|
||||
final serialized = value.serialize();
|
||||
expect(serialized, jsonEncode([0.0, 0.5, 1.0]));
|
||||
|
||||
final deserialized = ConfigSliderValue.deserialize(serialized);
|
||||
expect(deserialized.value, (0.0, 0.5, 1.0));
|
||||
});
|
||||
|
||||
test('getPayloadValue returns middle element', () {
|
||||
final slider = ConfigSliderValue(value: (0.0, 0.5, 1.0));
|
||||
expect(slider.getPayloadValue(), 0.5);
|
||||
});
|
||||
});
|
||||
|
||||
group('ConfigTextValue', () {
|
||||
test('serialize and deserialize works', () {
|
||||
final value = ConfigTextValue(value: 'hello');
|
||||
final serialized = value.serialize();
|
||||
expect(serialized, 'hello');
|
||||
|
||||
final deserialized = ConfigTextValue.deserialize('world');
|
||||
expect(deserialized.value, 'world');
|
||||
});
|
||||
});
|
||||
|
||||
group('checkTypeValue', () {
|
||||
test('validates correct type/value matches', () {
|
||||
expect(
|
||||
checkTypeValue(ConfigType.boolean, ConfigBooleanValue(value: true)),
|
||||
true,
|
||||
);
|
||||
expect(
|
||||
checkTypeValue(ConfigType.numeric, ConfigNumericValue(value: 3)),
|
||||
true,
|
||||
);
|
||||
expect(
|
||||
checkTypeValue(
|
||||
ConfigType.slider,
|
||||
ConfigSliderValue(value: (0, 0.5, 1)),
|
||||
),
|
||||
true,
|
||||
);
|
||||
expect(
|
||||
checkTypeValue(ConfigType.text, ConfigTextValue(value: 'hi')),
|
||||
true,
|
||||
);
|
||||
});
|
||||
|
||||
test('returns false for mismatched type/value', () {
|
||||
expect(
|
||||
checkTypeValue(ConfigType.boolean, ConfigNumericValue(value: 1)),
|
||||
false,
|
||||
);
|
||||
expect(
|
||||
checkTypeValue(ConfigType.numeric, ConfigTextValue(value: 'x')),
|
||||
false,
|
||||
);
|
||||
expect(
|
||||
checkTypeValue(ConfigType.slider, ConfigBooleanValue(value: true)),
|
||||
false,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import 'package:genai/interface/consts.dart';
|
||||
import 'package:genai/utils/ai_request_utils.dart';
|
||||
import 'package:better_networking/better_networking.dart';
|
||||
|
||||
const kTestingAPIKey = "AIzaSyAtmGxNxlbh_MokoDbMjHKDSW-gU6GCMOU";
|
||||
const kTestingAPIKey = "XXXXXXXXXXXX";
|
||||
|
||||
void main() {
|
||||
group('ai_request_utils', () {
|
||||
|
||||
74
packages/genai/test/utils.dart/available_models_test.dart
Normal file
74
packages/genai/test/utils.dart/available_models_test.dart
Normal file
@@ -0,0 +1,74 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:genai/models/available_models.dart';
|
||||
import 'package:genai/interface/interface.dart';
|
||||
|
||||
void main() {
|
||||
group('AvailableModels', () {
|
||||
test('can parse from JSON and back', () {
|
||||
const jsonString = '''
|
||||
{
|
||||
"version": 1.0,
|
||||
"model_providers": [
|
||||
{
|
||||
"provider_id": "openai",
|
||||
"provider_name": "OpenAI",
|
||||
"source_url": "https://api.openai.com",
|
||||
"models": [
|
||||
{"id": "gpt-4", "name": "GPT-4"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
''';
|
||||
|
||||
final models = availableModelsFromJson(jsonString);
|
||||
expect(models.version, 1.0);
|
||||
expect(models.modelProviders.length, 1);
|
||||
expect(models.modelProviders.first.providerName, "OpenAI");
|
||||
|
||||
final backToJson = availableModelsToJson(models);
|
||||
expect(backToJson.contains("GPT-4"), true);
|
||||
});
|
||||
|
||||
test('map getter returns map of providers', () {
|
||||
final provider = AIModelProvider(
|
||||
providerId: ModelAPIProvider.openai,
|
||||
providerName: "OpenAI",
|
||||
models: [const Model(id: "gpt-4", name: "GPT-4")],
|
||||
);
|
||||
|
||||
final available = AvailableModels(
|
||||
version: 1.0,
|
||||
modelProviders: [provider],
|
||||
);
|
||||
|
||||
expect(available.map.containsKey(ModelAPIProvider.openai), true);
|
||||
expect(available.map[ModelAPIProvider.openai]?.providerName, "OpenAI");
|
||||
});
|
||||
});
|
||||
|
||||
group('AIModelProvider', () {
|
||||
test(
|
||||
'toAiRequestModel returns default AIRequestModel with model override',
|
||||
() {
|
||||
const provider = AIModelProvider(
|
||||
providerId: ModelAPIProvider.openai,
|
||||
providerName: "OpenAI",
|
||||
);
|
||||
|
||||
const model = const Model(id: "gpt-4", name: "GPT-4");
|
||||
final req = provider.toAiRequestModel(model: model);
|
||||
|
||||
expect(req?.model, "gpt-4");
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
group('Model', () {
|
||||
test('fromJson works', () {
|
||||
final model = Model.fromJson({"id": "mistral", "name": "Mistral"});
|
||||
expect(model.id, "mistral");
|
||||
expect(model.name, "Mistral");
|
||||
});
|
||||
});
|
||||
}
|
||||
24
packages/genai/test/utils.dart/model_manager_test.dart
Normal file
24
packages/genai/test/utils.dart/model_manager_test.dart
Normal file
@@ -0,0 +1,24 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:genai/models/available_models.dart';
|
||||
import 'package:genai/utils/model_manager.dart';
|
||||
|
||||
void main() {
|
||||
group('ModelManager', () {
|
||||
test('fetchModelsFromRemote returns parsed models', () async {
|
||||
final result = await ModelManager.fetchModelsFromRemote();
|
||||
expect(result, isA<AvailableModels>());
|
||||
});
|
||||
|
||||
test('fetchInstalledOllamaModels parses response', () async {
|
||||
final body = jsonEncode({
|
||||
"models": [
|
||||
{"model": "mistral", "name": "Mistral"},
|
||||
{"model": "llama2", "name": "LLaMA 2"},
|
||||
],
|
||||
});
|
||||
final result = await ModelManager.fetchInstalledOllamaModels();
|
||||
expect(result, isNotNull);
|
||||
});
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user