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);
|
final kAvailableModels = AvailableModels.fromJson(kModelsData);
|
||||||
|
|
||||||
const kModelRemoteUrl =
|
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';
|
const kBaseOllamaUrl = 'http://localhost:11434';
|
||||||
|
|||||||
@@ -25,4 +25,3 @@ dev_dependencies:
|
|||||||
freezed: ^2.5.7
|
freezed: ^2.5.7
|
||||||
json_serializable: ^6.7.1
|
json_serializable: ^6.7.1
|
||||||
test: ^1.25.2
|
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:genai/utils/ai_request_utils.dart';
|
||||||
import 'package:better_networking/better_networking.dart';
|
import 'package:better_networking/better_networking.dart';
|
||||||
|
|
||||||
const kTestingAPIKey = "AIzaSyAtmGxNxlbh_MokoDbMjHKDSW-gU6GCMOU";
|
const kTestingAPIKey = "XXXXXXXXXXXX";
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
group('ai_request_utils', () {
|
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