mirror of
https://github.com/foss42/apidash.git
synced 2025-12-02 18:57:05 +08:00
tests: add authentication unit tests
This commit is contained in:
@@ -0,0 +1,338 @@
|
||||
import 'package:better_networking/better_networking.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('Authentication Handling Tests', () {
|
||||
test(
|
||||
'given sendHttpRequest when no authentication is provided then it should not throw any error',
|
||||
() async {
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
);
|
||||
|
||||
final result = await sendHttpRequest(
|
||||
'test-request',
|
||||
APIType.rest,
|
||||
null,
|
||||
httpRequestModel,
|
||||
);
|
||||
|
||||
expect(
|
||||
result.$1?.request?.url.toString(),
|
||||
equals('https://api.apidash.dev/users'),
|
||||
);
|
||||
},
|
||||
);
|
||||
test(
|
||||
'given handleAuth when no authentication is provided then it should return the same httpRequestModel',
|
||||
() async {
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
);
|
||||
|
||||
final result = await handleAuth(httpRequestModel, null);
|
||||
|
||||
expect(result.headers, isNull);
|
||||
expect(result.url, equals('https://api.apidash.dev/users'));
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'given handleAuth when none authentication type is provided then it should add any headers or throw errors',
|
||||
() async {
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
);
|
||||
|
||||
const authModel = AuthModel(type: APIAuthType.none);
|
||||
|
||||
final result = await handleAuth(httpRequestModel, authModel);
|
||||
|
||||
expect(result.headers, isEmpty);
|
||||
expect(result.url, equals('https://api.apidash.dev/users'));
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'given handleAuth when basic authentication fields are provided then it should add an authorization header',
|
||||
() async {
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
);
|
||||
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: 'testuser',
|
||||
password: 'testpass',
|
||||
);
|
||||
const authModel = AuthModel(type: APIAuthType.basic, basic: basicAuth);
|
||||
|
||||
final result = await handleAuth(httpRequestModel, authModel);
|
||||
|
||||
expect(result.headers, isNotEmpty);
|
||||
expect(
|
||||
result.headers?.any((h) => h.name.toLowerCase() == 'authorization'),
|
||||
isTrue,
|
||||
);
|
||||
expect(result.url, equals('https://api.apidash.dev/users'));
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'given handleAuth when handle bearer authentication fields are provided then it should add an authorization header',
|
||||
() async {
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
);
|
||||
|
||||
const bearerAuth = AuthBearerModel(token: 'bearer-token-123');
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.bearer,
|
||||
bearer: bearerAuth,
|
||||
);
|
||||
|
||||
final result = await handleAuth(httpRequestModel, authModel);
|
||||
|
||||
expect(result.headers, isNotEmpty);
|
||||
expect(
|
||||
result.headers?.any((h) => h.name.toLowerCase() == 'authorization'),
|
||||
isTrue,
|
||||
);
|
||||
expect(result.url, equals('https://api.apidash.dev/users'));
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'given handleAuth when API key authentication fields are provided then it should add an authorization header',
|
||||
() async {
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
);
|
||||
|
||||
const apiKeyAuth = AuthApiKeyModel(
|
||||
key: 'api-key-123',
|
||||
location: 'header',
|
||||
name: 'X-API-Key',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.apiKey,
|
||||
apikey: apiKeyAuth,
|
||||
);
|
||||
|
||||
final result = await handleAuth(httpRequestModel, authModel);
|
||||
|
||||
expect(result.headers, isNotEmpty);
|
||||
expect(
|
||||
result.headers?.any((h) => h.name.toLowerCase() == 'x-api-key'),
|
||||
isTrue,
|
||||
);
|
||||
expect(result.url, equals('https://api.apidash.dev/users'));
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'given handleAuth when API key authentication fields are provided then it should add an authorization query',
|
||||
() async {
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
);
|
||||
|
||||
const apiKeyAuth = AuthApiKeyModel(
|
||||
key: 'api-key-123',
|
||||
location: 'query',
|
||||
name: 'apikey',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.apiKey,
|
||||
apikey: apiKeyAuth,
|
||||
);
|
||||
|
||||
final result = await handleAuth(httpRequestModel, authModel);
|
||||
|
||||
expect(result.params, isNotEmpty);
|
||||
expect(result.params?.any((p) => p.name == 'apikey'), isTrue);
|
||||
expect(result.url, equals('https://api.apidash.dev/users'));
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'given handleAuth when JWT authentication fields are provided then it should add an authorization header',
|
||||
() async {
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
);
|
||||
|
||||
const jwtAuth = AuthJwtModel(
|
||||
secret: 'jwt-secret',
|
||||
payload: '{"sub": "1234567890"}',
|
||||
addTokenTo: 'header',
|
||||
algorithm: 'HS256',
|
||||
isSecretBase64Encoded: false,
|
||||
headerPrefix: 'Bearer',
|
||||
queryParamKey: 'token',
|
||||
header: 'Authorization',
|
||||
);
|
||||
const authModel = AuthModel(type: APIAuthType.jwt, jwt: jwtAuth);
|
||||
|
||||
final result = await handleAuth(httpRequestModel, authModel);
|
||||
|
||||
expect(result.headers, isNotEmpty);
|
||||
expect(
|
||||
result.headers?.any((h) => h.name.toLowerCase() == 'authorization'),
|
||||
isTrue,
|
||||
);
|
||||
expect(result.url, equals('https://api.apidash.dev/users'));
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'given handleAuth when digest authentication fields are provided then it should add an authorization header',
|
||||
() async {
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
);
|
||||
|
||||
const digestAuth = AuthDigestModel(
|
||||
username: 'digestuser',
|
||||
password: 'digestpass',
|
||||
realm: 'test-realm',
|
||||
nonce: 'test-nonce',
|
||||
algorithm: 'MD5',
|
||||
qop: 'auth',
|
||||
opaque: 'test-opaque',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.digest,
|
||||
digest: digestAuth,
|
||||
);
|
||||
|
||||
final result = await handleAuth(httpRequestModel, authModel);
|
||||
|
||||
expect(result.headers, isNotEmpty);
|
||||
expect(
|
||||
result.headers?.any((h) => h.name.toLowerCase() == 'authorization'),
|
||||
isTrue,
|
||||
);
|
||||
expect(result.url, equals('https://api.apidash.dev/users'));
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'given handleAuth when multiple headers are provided then it should add an authorization header to the existing headers',
|
||||
() async {
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
headers: [
|
||||
NameValueModel(name: 'Content-Type', value: 'application/json'),
|
||||
NameValueModel(name: 'Accept', value: 'application/json'),
|
||||
],
|
||||
);
|
||||
|
||||
const bearerAuth = AuthBearerModel(token: 'bearer-token-123');
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.bearer,
|
||||
bearer: bearerAuth,
|
||||
);
|
||||
|
||||
final result = await handleAuth(httpRequestModel, authModel);
|
||||
|
||||
expect(result.headers, isNotEmpty);
|
||||
expect(result.headers?.any((h) => h.name == 'Content-Type'), isTrue);
|
||||
expect(result.headers?.any((h) => h.name == 'Accept'), isTrue);
|
||||
expect(
|
||||
result.headers?.any((h) => h.name.toLowerCase() == 'authorization'),
|
||||
isTrue,
|
||||
);
|
||||
expect(result.url, equals('https://api.apidash.dev/users'));
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'given handleAuth when multiple params are provided then it should add it to the existing params',
|
||||
() async {
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
params: [
|
||||
NameValueModel(name: 'limit', value: '10'),
|
||||
NameValueModel(name: 'offset', value: '0'),
|
||||
],
|
||||
);
|
||||
|
||||
const apiKeyAuth = AuthApiKeyModel(
|
||||
key: 'api-key-123',
|
||||
location: 'query',
|
||||
name: 'apikey',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.apiKey,
|
||||
apikey: apiKeyAuth,
|
||||
);
|
||||
|
||||
final result = await handleAuth(httpRequestModel, authModel);
|
||||
|
||||
expect(result.params, isNotEmpty);
|
||||
expect(result.params?.any((p) => p.name == 'limit'), isTrue);
|
||||
expect(result.params?.any((p) => p.name == 'offset'), isTrue);
|
||||
expect(result.params?.any((p) => p.name == 'apikey'), isTrue);
|
||||
expect(result.url, equals('https://api.apidash.dev/users'));
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'given handleAuth when special characters are provided it should not throw an error',
|
||||
() async {
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
);
|
||||
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: 'user@domain.com',
|
||||
password: r'P@ssw0rd!@#$%^&*()',
|
||||
);
|
||||
const authModel = AuthModel(type: APIAuthType.basic, basic: basicAuth);
|
||||
|
||||
final result = await handleAuth(httpRequestModel, authModel);
|
||||
|
||||
expect(result.headers, isNotEmpty);
|
||||
expect(
|
||||
result.headers?.any((h) => h.name.toLowerCase() == 'authorization'),
|
||||
isTrue,
|
||||
);
|
||||
expect(result.url, equals('https://api.apidash.dev/users'));
|
||||
},
|
||||
);
|
||||
|
||||
test(
|
||||
'given handleAuth when no values are provided it should not throw an error',
|
||||
() async {
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
);
|
||||
|
||||
const basicAuth = AuthBasicAuthModel(username: '', password: '');
|
||||
const authModel = AuthModel(type: APIAuthType.basic, basic: basicAuth);
|
||||
|
||||
final result = await handleAuth(httpRequestModel, authModel);
|
||||
|
||||
expect(result.headers, isNotEmpty);
|
||||
expect(
|
||||
result.headers?.any((h) => h.name.toLowerCase() == 'authorization'),
|
||||
isTrue,
|
||||
);
|
||||
expect(result.url, equals('https://api.apidash.dev/users'));
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
340
packages/better_networking/test/utils/auth/auth_models_test.dart
Normal file
340
packages/better_networking/test/utils/auth/auth_models_test.dart
Normal file
@@ -0,0 +1,340 @@
|
||||
import 'package:better_networking/better_networking.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
void main() {
|
||||
group('AuthModel Tests', () {
|
||||
test('should create AuthModel with none type', () {
|
||||
const authModel = AuthModel(type: APIAuthType.none);
|
||||
|
||||
expect(authModel.type, APIAuthType.none);
|
||||
expect(authModel.basic, isNull);
|
||||
expect(authModel.bearer, isNull);
|
||||
expect(authModel.apikey, isNull);
|
||||
expect(authModel.jwt, isNull);
|
||||
expect(authModel.digest, isNull);
|
||||
});
|
||||
|
||||
test('should create AuthModel with basic authentication', () {
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: 'testuser',
|
||||
password: 'testpass',
|
||||
);
|
||||
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: basicAuth,
|
||||
);
|
||||
|
||||
expect(authModel.type, APIAuthType.basic);
|
||||
expect(authModel.basic, isNotNull);
|
||||
expect(authModel.basic?.username, 'testuser');
|
||||
expect(authModel.basic?.password, 'testpass');
|
||||
});
|
||||
|
||||
test('should create AuthModel with bearer token', () {
|
||||
const bearerAuth = AuthBearerModel(token: 'bearer-token-123');
|
||||
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.bearer,
|
||||
bearer: bearerAuth,
|
||||
);
|
||||
|
||||
expect(authModel.type, APIAuthType.bearer);
|
||||
expect(authModel.bearer, isNotNull);
|
||||
expect(authModel.bearer?.token, 'bearer-token-123');
|
||||
});
|
||||
|
||||
test('should create AuthModel with API key authentication', () {
|
||||
const apiKeyAuth = AuthApiKeyModel(
|
||||
key: 'api-key-123',
|
||||
location: 'header',
|
||||
name: 'X-API-Key',
|
||||
);
|
||||
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.apiKey,
|
||||
apikey: apiKeyAuth,
|
||||
);
|
||||
|
||||
expect(authModel.type, APIAuthType.apiKey);
|
||||
expect(authModel.apikey, isNotNull);
|
||||
expect(authModel.apikey?.key, 'api-key-123');
|
||||
expect(authModel.apikey?.location, 'header');
|
||||
expect(authModel.apikey?.name, 'X-API-Key');
|
||||
});
|
||||
|
||||
test('should create AuthModel with JWT authentication', () {
|
||||
const jwtAuth = AuthJwtModel(
|
||||
secret: 'jwt-secret',
|
||||
payload: '{"sub": "1234567890"}',
|
||||
addTokenTo: 'header',
|
||||
algorithm: 'HS256',
|
||||
isSecretBase64Encoded: false,
|
||||
headerPrefix: 'Bearer',
|
||||
queryParamKey: 'token',
|
||||
header: 'Authorization',
|
||||
);
|
||||
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.jwt,
|
||||
jwt: jwtAuth,
|
||||
);
|
||||
|
||||
expect(authModel.type, APIAuthType.jwt);
|
||||
expect(authModel.jwt, isNotNull);
|
||||
expect(authModel.jwt?.secret, 'jwt-secret');
|
||||
expect(authModel.jwt?.algorithm, 'HS256');
|
||||
expect(authModel.jwt?.isSecretBase64Encoded, false);
|
||||
});
|
||||
|
||||
test('should create AuthModel with digest authentication', () {
|
||||
const digestAuth = AuthDigestModel(
|
||||
username: 'digestuser',
|
||||
password: 'digestpass',
|
||||
realm: 'test-realm',
|
||||
nonce: 'test-nonce',
|
||||
algorithm: 'MD5',
|
||||
qop: 'auth',
|
||||
opaque: 'test-opaque',
|
||||
);
|
||||
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.digest,
|
||||
digest: digestAuth,
|
||||
);
|
||||
|
||||
expect(authModel.type, APIAuthType.digest);
|
||||
expect(authModel.digest, isNotNull);
|
||||
expect(authModel.digest?.username, 'digestuser');
|
||||
expect(authModel.digest?.realm, 'test-realm');
|
||||
expect(authModel.digest?.algorithm, 'MD5');
|
||||
});
|
||||
|
||||
test('should serialize and deserialize AuthModel correctly', () {
|
||||
const originalModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: AuthBasicAuthModel(
|
||||
username: 'testuser',
|
||||
password: 'testpass',
|
||||
),
|
||||
);
|
||||
|
||||
final json = originalModel.toJson();
|
||||
final deserializedModel = AuthModel.fromJson(json);
|
||||
|
||||
expect(deserializedModel.type, originalModel.type);
|
||||
expect(deserializedModel.basic?.username, originalModel.basic?.username);
|
||||
expect(deserializedModel.basic?.password, originalModel.basic?.password);
|
||||
});
|
||||
|
||||
test('should handle copyWith for AuthModel', () {
|
||||
const originalModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: AuthBasicAuthModel(
|
||||
username: 'testuser',
|
||||
password: 'testpass',
|
||||
),
|
||||
);
|
||||
|
||||
const newBasicAuth = AuthBasicAuthModel(
|
||||
username: 'newuser',
|
||||
password: 'newpass',
|
||||
);
|
||||
|
||||
final copiedModel = originalModel.copyWith(
|
||||
type: APIAuthType.basic,
|
||||
basic: newBasicAuth,
|
||||
);
|
||||
|
||||
expect(copiedModel.type, APIAuthType.basic);
|
||||
expect(copiedModel.basic?.username, 'newuser');
|
||||
expect(copiedModel.basic?.password, 'newpass');
|
||||
});
|
||||
|
||||
test('should handle API key with default values', () {
|
||||
const apiKeyAuth = AuthApiKeyModel(key: 'test-key');
|
||||
|
||||
expect(apiKeyAuth.key, 'test-key');
|
||||
expect(apiKeyAuth.location, 'header');
|
||||
expect(apiKeyAuth.name, 'x-api-key');
|
||||
});
|
||||
|
||||
test('should handle API key with custom values', () {
|
||||
const apiKeyAuth = AuthApiKeyModel(
|
||||
key: 'custom-key',
|
||||
location: 'query',
|
||||
name: 'api_key',
|
||||
);
|
||||
|
||||
expect(apiKeyAuth.key, 'custom-key');
|
||||
expect(apiKeyAuth.location, 'query');
|
||||
expect(apiKeyAuth.name, 'api_key');
|
||||
});
|
||||
|
||||
test('should handle JWT with private key', () {
|
||||
const jwtAuth = AuthJwtModel(
|
||||
secret: 'jwt-secret',
|
||||
privateKey: 'private-key-content',
|
||||
payload: '{"sub": "1234567890"}',
|
||||
addTokenTo: 'header',
|
||||
algorithm: 'RS256',
|
||||
isSecretBase64Encoded: true,
|
||||
headerPrefix: 'Bearer',
|
||||
queryParamKey: 'token',
|
||||
header: 'Authorization',
|
||||
);
|
||||
|
||||
expect(jwtAuth.secret, 'jwt-secret');
|
||||
expect(jwtAuth.privateKey, 'private-key-content');
|
||||
expect(jwtAuth.algorithm, 'RS256');
|
||||
expect(jwtAuth.isSecretBase64Encoded, true);
|
||||
});
|
||||
|
||||
test('should handle edge cases with empty strings', () {
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: '',
|
||||
password: '',
|
||||
);
|
||||
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: basicAuth,
|
||||
);
|
||||
|
||||
expect(authModel.basic?.username, '');
|
||||
expect(authModel.basic?.password, '');
|
||||
});
|
||||
|
||||
test('should handle JSON serialization with null values', () {
|
||||
const authModel = AuthModel(type: APIAuthType.none);
|
||||
|
||||
final json = authModel.toJson();
|
||||
final deserializedModel = AuthModel.fromJson(json);
|
||||
|
||||
expect(deserializedModel.type, APIAuthType.none);
|
||||
expect(deserializedModel.basic, isNull);
|
||||
expect(deserializedModel.bearer, isNull);
|
||||
expect(deserializedModel.apikey, isNull);
|
||||
expect(deserializedModel.jwt, isNull);
|
||||
expect(deserializedModel.digest, isNull);
|
||||
});
|
||||
|
||||
test('should handle complex JWT payload', () {
|
||||
const complexPayload = '''
|
||||
{
|
||||
"sub": "1234567890",
|
||||
"name": "John Doe",
|
||||
"iat": 1516239022,
|
||||
"exp": 1516242622,
|
||||
"roles": ["admin", "user"],
|
||||
"permissions": {
|
||||
"read": true,
|
||||
"write": false
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
||||
const jwtAuth = AuthJwtModel(
|
||||
secret: 'complex-secret',
|
||||
payload: complexPayload,
|
||||
addTokenTo: 'header',
|
||||
algorithm: 'HS512',
|
||||
isSecretBase64Encoded: false,
|
||||
headerPrefix: 'JWT',
|
||||
queryParamKey: 'jwt_token',
|
||||
header: 'X-JWT-Token',
|
||||
);
|
||||
|
||||
expect(jwtAuth.payload, complexPayload);
|
||||
expect(jwtAuth.headerPrefix, 'JWT');
|
||||
expect(jwtAuth.queryParamKey, 'jwt_token');
|
||||
expect(jwtAuth.header, 'X-JWT-Token');
|
||||
});
|
||||
|
||||
test('should handle digest auth with all parameters', () {
|
||||
const digestAuth = AuthDigestModel(
|
||||
username: 'digestuser',
|
||||
password: 'digestpass',
|
||||
realm: 'api.example.com',
|
||||
nonce: 'dcd98b7102dd2f0e8b11d0f600bfb0c093',
|
||||
algorithm: 'SHA-256',
|
||||
qop: 'auth-int',
|
||||
opaque: '5ccc069c403ebaf9f0171e9517f40e41',
|
||||
);
|
||||
|
||||
expect(digestAuth.username, 'digestuser');
|
||||
expect(digestAuth.password, 'digestpass');
|
||||
expect(digestAuth.realm, 'api.example.com');
|
||||
expect(digestAuth.nonce, 'dcd98b7102dd2f0e8b11d0f600bfb0c093');
|
||||
expect(digestAuth.algorithm, 'SHA-256');
|
||||
expect(digestAuth.qop, 'auth-int');
|
||||
expect(digestAuth.opaque, '5ccc069c403ebaf9f0171e9517f40e41');
|
||||
});
|
||||
});
|
||||
|
||||
test('should handle type mismatch scenarios', () {
|
||||
// Test when type is basic but bearer data is provided
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
bearer: AuthBearerModel(token: 'token'),
|
||||
);
|
||||
|
||||
expect(authModel.type, APIAuthType.basic);
|
||||
expect(authModel.bearer?.token, 'token');
|
||||
expect(authModel.basic, isNull);
|
||||
});
|
||||
|
||||
test('should handle multiple auth types provided', () {
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.bearer,
|
||||
basic: AuthBasicAuthModel(username: 'user', password: 'pass'),
|
||||
bearer: AuthBearerModel(token: 'token'),
|
||||
apikey: AuthApiKeyModel(key: 'key'),
|
||||
);
|
||||
|
||||
expect(authModel.type, APIAuthType.bearer);
|
||||
expect(authModel.basic, isNotNull);
|
||||
expect(authModel.bearer, isNotNull);
|
||||
expect(authModel.apikey, isNotNull);
|
||||
});
|
||||
|
||||
test('should handle serialization with special characters', () {
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: 'user@domain.com',
|
||||
password: r'P@ssw0rd!@#$%^&*()',
|
||||
);
|
||||
|
||||
const authModel = AuthModel(type: APIAuthType.basic, basic: basicAuth);
|
||||
|
||||
final json = authModel.toJson();
|
||||
final deserializedModel = AuthModel.fromJson(json);
|
||||
|
||||
expect(deserializedModel.basic?.username, 'user@domain.com');
|
||||
expect(deserializedModel.basic?.password, r'P@ssw0rd!@#$%^&*()');
|
||||
});
|
||||
|
||||
test('should handle very long strings', () {
|
||||
final longString = 'a' * 1000;
|
||||
|
||||
final bearerAuth = AuthBearerModel(token: longString);
|
||||
final authModel = AuthModel(type: APIAuthType.bearer, bearer: bearerAuth);
|
||||
|
||||
expect(authModel.bearer?.token, longString);
|
||||
expect(authModel.bearer?.token.length, 1000);
|
||||
});
|
||||
|
||||
test('should handle Unicode characters', () {
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: 'user_测试_тест_テスト',
|
||||
password: 'password_🔑_🚀_💻',
|
||||
);
|
||||
|
||||
const authModel = AuthModel(type: APIAuthType.basic, basic: basicAuth);
|
||||
|
||||
final json = authModel.toJson();
|
||||
final deserializedModel = AuthModel.fromJson(json);
|
||||
|
||||
expect(deserializedModel.basic?.username, 'user_测试_тест_テスト');
|
||||
expect(deserializedModel.basic?.password, 'password_🔑_🚀_💻');
|
||||
});
|
||||
}
|
||||
32
pubspec.lock
32
pubspec.lock
@@ -9,6 +9,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "82.0.0"
|
||||
adaptive_number:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: adaptive_number
|
||||
sha256: "3a567544e9b5c9c803006f51140ad544aedc79604fd4f3f2c1380003f97c1d77"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -349,6 +357,14 @@ packages:
|
||||
relative: true
|
||||
source: path
|
||||
version: "0.1.3"
|
||||
dart_jsonwebtoken:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_jsonwebtoken
|
||||
sha256: "21ce9f8a8712f741e8d6876a9c82c0f8a257fe928c4378a91d8527b92a3fd413"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.0"
|
||||
dart_style:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -381,6 +397,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.0"
|
||||
ed25519_edwards:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: ed25519_edwards
|
||||
sha256: "6ce0112d131327ec6d42beede1e5dfd526069b18ad45dcf654f15074ad9276cd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.1"
|
||||
equatable:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1246,6 +1270,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
pointycastle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pointycastle
|
||||
sha256: "92aa3841d083cc4b0f4709b5c74fd6409a3e6ba833ffc7dc6a8fee096366acf5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -22,7 +22,7 @@ final historyRequestModel1 = HistoryRequestModel(
|
||||
metaData: historyMetaModel1,
|
||||
httpRequestModel: httpRequestModelGet4,
|
||||
httpResponseModel: responseModel,
|
||||
);
|
||||
authModel: AuthModel(type: APIAuthType.none));
|
||||
|
||||
final historyMetaModel2 = HistoryMetaModel(
|
||||
historyId: 'historyId2',
|
||||
@@ -39,7 +39,7 @@ final historyRequestModel2 = HistoryRequestModel(
|
||||
metaData: historyMetaModel2,
|
||||
httpRequestModel: httpRequestModelPost10,
|
||||
httpResponseModel: responseModel,
|
||||
);
|
||||
authModel: AuthModel(type: APIAuthType.none));
|
||||
|
||||
/// JSONs
|
||||
final Map<String, dynamic> historyMetaModelJson1 = {
|
||||
@@ -59,7 +59,15 @@ final Map<String, dynamic> historyRequestModelJson1 = {
|
||||
"httpRequestModel": httpRequestModelGet4Json,
|
||||
"httpResponseModel": responseModelJson,
|
||||
'preRequestScript': null,
|
||||
'postRequestScript': null
|
||||
'postRequestScript': null,
|
||||
'authModel': {
|
||||
'type': 'none',
|
||||
'apikey': null,
|
||||
'bearer': null,
|
||||
'basic': null,
|
||||
'jwt': null,
|
||||
'digest': null
|
||||
}
|
||||
};
|
||||
|
||||
final Map<String, dynamic> historyMetaModelJson2 = {
|
||||
|
||||
@@ -83,4 +83,325 @@ void main() {
|
||||
var httpRequestModel3 = httpRequestModel.copyWith(headers: null);
|
||||
expect(httpRequestModel3.headers, null);
|
||||
});
|
||||
|
||||
group('HttpRequestModel Auth Tests', () {
|
||||
test('should create HttpRequestModel with no authentication', () {
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
);
|
||||
|
||||
expect(httpRequestModel.authModel?.type, APIAuthType.none);
|
||||
});
|
||||
|
||||
test('should create HttpRequestModel with basic authentication', () {
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: 'testuser',
|
||||
password: 'testpass',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: basicAuth,
|
||||
);
|
||||
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
authModel: authModel,
|
||||
);
|
||||
|
||||
expect(httpRequestModel.authModel, isNotNull);
|
||||
expect(httpRequestModel.authModel?.type, APIAuthType.basic);
|
||||
expect(httpRequestModel.authModel?.basic?.username, 'testuser');
|
||||
expect(httpRequestModel.authModel?.basic?.password, 'testpass');
|
||||
});
|
||||
|
||||
test('should create HttpRequestModel with bearer authentication', () {
|
||||
const bearerAuth = AuthBearerModel(token: 'bearer-token-123');
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.bearer,
|
||||
bearer: bearerAuth,
|
||||
);
|
||||
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.post,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
authModel: authModel,
|
||||
);
|
||||
|
||||
expect(httpRequestModel.authModel?.type, APIAuthType.bearer);
|
||||
expect(httpRequestModel.authModel?.bearer?.token, 'bearer-token-123');
|
||||
});
|
||||
|
||||
test('should create HttpRequestModel with API key authentication', () {
|
||||
const apiKeyAuth = AuthApiKeyModel(
|
||||
key: 'api-key-123',
|
||||
location: 'header',
|
||||
name: 'X-API-Key',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.apiKey,
|
||||
apikey: apiKeyAuth,
|
||||
);
|
||||
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
authModel: authModel,
|
||||
);
|
||||
|
||||
expect(httpRequestModel.authModel?.type, APIAuthType.apiKey);
|
||||
expect(httpRequestModel.authModel?.apikey?.key, 'api-key-123');
|
||||
expect(httpRequestModel.authModel?.apikey?.location, 'header');
|
||||
expect(httpRequestModel.authModel?.apikey?.name, 'X-API-Key');
|
||||
});
|
||||
|
||||
test('should create HttpRequestModel with JWT authentication', () {
|
||||
const jwtAuth = AuthJwtModel(
|
||||
secret: 'jwt-secret',
|
||||
payload: '{"sub": "1234567890"}',
|
||||
addTokenTo: 'header',
|
||||
algorithm: 'HS256',
|
||||
isSecretBase64Encoded: false,
|
||||
headerPrefix: 'Bearer',
|
||||
queryParamKey: 'token',
|
||||
header: 'Authorization',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.jwt,
|
||||
jwt: jwtAuth,
|
||||
);
|
||||
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.patch,
|
||||
url: 'https://api.apidash.dev/users/1',
|
||||
authModel: authModel,
|
||||
);
|
||||
|
||||
expect(httpRequestModel.authModel?.type, APIAuthType.jwt);
|
||||
expect(httpRequestModel.authModel?.jwt?.secret, 'jwt-secret');
|
||||
expect(httpRequestModel.authModel?.jwt?.algorithm, 'HS256');
|
||||
expect(httpRequestModel.authModel?.jwt?.isSecretBase64Encoded, false);
|
||||
});
|
||||
|
||||
test('should create HttpRequestModel with digest authentication', () {
|
||||
const digestAuth = AuthDigestModel(
|
||||
username: 'digestuser',
|
||||
password: 'digestpass',
|
||||
realm: 'test-realm',
|
||||
nonce: 'test-nonce',
|
||||
algorithm: 'MD5',
|
||||
qop: 'auth',
|
||||
opaque: 'test-opaque',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.digest,
|
||||
digest: digestAuth,
|
||||
);
|
||||
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.delete,
|
||||
url: 'https://api.apidash.dev/users/1',
|
||||
authModel: authModel,
|
||||
);
|
||||
|
||||
expect(httpRequestModel.authModel?.type, APIAuthType.digest);
|
||||
expect(httpRequestModel.authModel?.digest?.username, 'digestuser');
|
||||
expect(httpRequestModel.authModel?.digest?.realm, 'test-realm');
|
||||
expect(httpRequestModel.authModel?.digest?.algorithm, 'MD5');
|
||||
});
|
||||
|
||||
test(
|
||||
'should serialize and deserialize HttpRequestModel with auth correctly',
|
||||
() {
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: 'testuser',
|
||||
password: 'testpass',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: basicAuth,
|
||||
);
|
||||
|
||||
const originalModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
authModel: authModel,
|
||||
);
|
||||
|
||||
final json = originalModel.toJson();
|
||||
final deserializedModel = HttpRequestModel.fromJson(json);
|
||||
|
||||
expect(deserializedModel.method, originalModel.method);
|
||||
expect(deserializedModel.url, originalModel.url);
|
||||
expect(deserializedModel.authModel?.type, originalModel.authModel?.type);
|
||||
expect(deserializedModel.authModel?.basic?.username,
|
||||
originalModel.authModel?.basic?.username);
|
||||
expect(deserializedModel.authModel?.basic?.password,
|
||||
originalModel.authModel?.basic?.password);
|
||||
});
|
||||
|
||||
test('should handle copyWith for HttpRequestModel with auth', () {
|
||||
const originalAuth = AuthBasicAuthModel(
|
||||
username: 'testuser',
|
||||
password: 'testpass',
|
||||
);
|
||||
const originalAuthModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: originalAuth,
|
||||
);
|
||||
|
||||
const originalModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
authModel: originalAuthModel,
|
||||
);
|
||||
|
||||
const newAuth = AuthBearerModel(token: 'new-bearer-token');
|
||||
const newAuthModel = AuthModel(
|
||||
type: APIAuthType.bearer,
|
||||
bearer: newAuth,
|
||||
);
|
||||
|
||||
final copiedModel = originalModel.copyWith(
|
||||
authModel: newAuthModel,
|
||||
);
|
||||
|
||||
expect(copiedModel.method, originalModel.method);
|
||||
expect(copiedModel.url, originalModel.url);
|
||||
expect(copiedModel.authModel?.type, APIAuthType.bearer);
|
||||
expect(copiedModel.authModel?.bearer?.token, 'new-bearer-token');
|
||||
});
|
||||
|
||||
test('should handle HttpRequestModel with complex auth scenarios', () {
|
||||
const complexPayload = '''
|
||||
{
|
||||
"sub": "1234567890",
|
||||
"name": "John Doe",
|
||||
"iat": 1516239022,
|
||||
"exp": 1516242622,
|
||||
"roles": ["admin", "user"],
|
||||
"permissions": {
|
||||
"read": true,
|
||||
"write": false
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
||||
const jwtAuth = AuthJwtModel(
|
||||
secret: 'complex-secret',
|
||||
privateKey: 'private-key-content',
|
||||
payload: complexPayload,
|
||||
addTokenTo: 'query',
|
||||
algorithm: 'RS256',
|
||||
isSecretBase64Encoded: true,
|
||||
headerPrefix: 'JWT',
|
||||
queryParamKey: 'jwt_token',
|
||||
header: 'X-JWT-Token',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.jwt,
|
||||
jwt: jwtAuth,
|
||||
);
|
||||
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.post,
|
||||
url: 'https://api.apidash.dev/secure-endpoint',
|
||||
authModel: authModel,
|
||||
headers: [
|
||||
NameValueModel(name: 'Content-Type', value: 'application/json'),
|
||||
NameValueModel(name: 'Accept', value: 'application/json'),
|
||||
],
|
||||
);
|
||||
|
||||
expect(httpRequestModel.authModel?.jwt?.payload, complexPayload);
|
||||
expect(
|
||||
httpRequestModel.authModel?.jwt?.privateKey, 'private-key-content');
|
||||
expect(httpRequestModel.authModel?.jwt?.algorithm, 'RS256');
|
||||
expect(httpRequestModel.authModel?.jwt?.isSecretBase64Encoded, true);
|
||||
expect(httpRequestModel.authModel?.jwt?.addTokenTo, 'query');
|
||||
});
|
||||
|
||||
test('should handle HttpRequestModel with auth and other fields', () {
|
||||
const apiKeyAuth = AuthApiKeyModel(
|
||||
key: 'api-key-123',
|
||||
location: 'header',
|
||||
name: 'X-API-Key',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.apiKey,
|
||||
apikey: apiKeyAuth,
|
||||
);
|
||||
|
||||
const httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.post,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
authModel: authModel,
|
||||
headers: [
|
||||
NameValueModel(name: 'Content-Type', value: 'application/json'),
|
||||
NameValueModel(name: 'Accept', value: 'application/json'),
|
||||
],
|
||||
params: [
|
||||
NameValueModel(name: 'limit', value: '10'),
|
||||
NameValueModel(name: 'offset', value: '0'),
|
||||
],
|
||||
body: '{"name": "John Doe", "email": "john@example.com"}',
|
||||
bodyContentType: ContentType.json,
|
||||
);
|
||||
|
||||
expect(httpRequestModel.authModel?.type, APIAuthType.apiKey);
|
||||
expect(httpRequestModel.authModel?.apikey?.key, 'api-key-123');
|
||||
expect(httpRequestModel.headers?.length, 2);
|
||||
expect(httpRequestModel.params?.length, 2);
|
||||
expect(httpRequestModel.body,
|
||||
'{"name": "John Doe", "email": "john@example.com"}');
|
||||
expect(httpRequestModel.bodyContentType, ContentType.json);
|
||||
});
|
||||
|
||||
test('should handle HttpRequestModel with multiple auth types in sequence',
|
||||
() {
|
||||
const originalAuth = AuthBasicAuthModel(
|
||||
username: 'testuser',
|
||||
password: 'testpass',
|
||||
);
|
||||
const originalAuthModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: originalAuth,
|
||||
);
|
||||
|
||||
var httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.apidash.dev/users',
|
||||
authModel: originalAuthModel,
|
||||
);
|
||||
|
||||
expect(httpRequestModel.authModel?.type, APIAuthType.basic);
|
||||
|
||||
// Change to bearer
|
||||
const bearerAuth = AuthBearerModel(token: 'bearer-token');
|
||||
const bearerAuthModel = AuthModel(
|
||||
type: APIAuthType.bearer,
|
||||
bearer: bearerAuth,
|
||||
);
|
||||
|
||||
httpRequestModel = httpRequestModel.copyWith(authModel: bearerAuthModel);
|
||||
expect(httpRequestModel.authModel?.type, APIAuthType.bearer);
|
||||
|
||||
// Change to API key
|
||||
const apiKeyAuth = AuthApiKeyModel(
|
||||
key: 'api-key',
|
||||
location: 'query',
|
||||
name: 'key',
|
||||
);
|
||||
const apiKeyAuthModel = AuthModel(
|
||||
type: APIAuthType.apiKey,
|
||||
apikey: apiKeyAuth,
|
||||
);
|
||||
|
||||
httpRequestModel = httpRequestModel.copyWith(authModel: apiKeyAuthModel);
|
||||
expect(httpRequestModel.authModel?.type, APIAuthType.apiKey);
|
||||
expect(httpRequestModel.authModel?.apikey?.location, 'query');
|
||||
expect(httpRequestModel.authModel?.apikey?.name, 'key');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -384,6 +384,14 @@ const httpRequestModelGet4Json = <String, dynamic>{
|
||||
{'name': 'add_space', 'value': 'true'},
|
||||
{'name': 'trailing_zeros', 'value': 'true'}
|
||||
],
|
||||
'authModel': {
|
||||
'type': 'none',
|
||||
'apikey': null,
|
||||
'bearer': null,
|
||||
'basic': null,
|
||||
'jwt': null,
|
||||
'digest': null
|
||||
},
|
||||
"isHeaderEnabledList": null,
|
||||
"isParamEnabledList": null,
|
||||
"bodyContentType": "json",
|
||||
@@ -403,6 +411,14 @@ const httpRequestModelPost10Json = <String, dynamic>{
|
||||
{'name': 'size', 'value': '2'},
|
||||
{'name': 'len', 'value': '3'}
|
||||
],
|
||||
'authModel': {
|
||||
'type': 'none',
|
||||
'apikey': null,
|
||||
'bearer': null,
|
||||
'basic': null,
|
||||
'jwt': null,
|
||||
'digest': null
|
||||
},
|
||||
'isHeaderEnabledList': [false, true],
|
||||
'isParamEnabledList': null,
|
||||
"bodyContentType": 'json',
|
||||
|
||||
@@ -7,7 +7,6 @@ import 'http_response_models.dart';
|
||||
const requestModelGet1 = RequestModel(
|
||||
id: 'get1',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelGet1,
|
||||
);
|
||||
|
||||
@@ -15,7 +14,6 @@ const requestModelGet1 = RequestModel(
|
||||
const requestModelGet2 = RequestModel(
|
||||
id: 'get2',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelGet2,
|
||||
);
|
||||
|
||||
@@ -23,7 +21,6 @@ const requestModelGet2 = RequestModel(
|
||||
const requestModelGet3 = RequestModel(
|
||||
id: 'get3',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelGet3,
|
||||
);
|
||||
|
||||
@@ -31,7 +28,6 @@ const requestModelGet3 = RequestModel(
|
||||
const requestModelGet4 = RequestModel(
|
||||
id: 'get4',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelGet4,
|
||||
);
|
||||
|
||||
@@ -39,7 +35,6 @@ const requestModelGet4 = RequestModel(
|
||||
const requestModelGet5 = RequestModel(
|
||||
id: 'get5',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelGet5,
|
||||
);
|
||||
|
||||
@@ -47,7 +42,6 @@ const requestModelGet5 = RequestModel(
|
||||
const requestModelGet6 = RequestModel(
|
||||
id: 'get6',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelGet6,
|
||||
);
|
||||
|
||||
@@ -55,7 +49,6 @@ const requestModelGet6 = RequestModel(
|
||||
const requestModelGet7 = RequestModel(
|
||||
id: 'get7',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelGet7,
|
||||
);
|
||||
|
||||
@@ -63,7 +56,6 @@ const requestModelGet7 = RequestModel(
|
||||
const requestModelGet8 = RequestModel(
|
||||
id: 'get8',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelGet8,
|
||||
);
|
||||
|
||||
@@ -71,7 +63,6 @@ const requestModelGet8 = RequestModel(
|
||||
const requestModelGet9 = RequestModel(
|
||||
id: 'get9',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelGet9,
|
||||
);
|
||||
|
||||
@@ -79,7 +70,6 @@ const requestModelGet9 = RequestModel(
|
||||
const requestModelGet10 = RequestModel(
|
||||
id: 'get10',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelGet10,
|
||||
);
|
||||
|
||||
@@ -87,7 +77,6 @@ const requestModelGet10 = RequestModel(
|
||||
const requestModelGet11 = RequestModel(
|
||||
id: 'get11',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelGet11,
|
||||
);
|
||||
|
||||
@@ -95,7 +84,6 @@ const requestModelGet11 = RequestModel(
|
||||
const requestModelGet12 = RequestModel(
|
||||
id: 'get12',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelGet12,
|
||||
);
|
||||
|
||||
@@ -103,7 +91,6 @@ const requestModelGet12 = RequestModel(
|
||||
const requestModelHead1 = RequestModel(
|
||||
id: 'head1',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelHead1,
|
||||
);
|
||||
|
||||
@@ -111,7 +98,6 @@ const requestModelHead1 = RequestModel(
|
||||
const requestModelHead2 = RequestModel(
|
||||
id: 'head2',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelHead2,
|
||||
);
|
||||
|
||||
@@ -119,7 +105,6 @@ const requestModelHead2 = RequestModel(
|
||||
const requestModelPost1 = RequestModel(
|
||||
id: 'post1',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPost1,
|
||||
);
|
||||
|
||||
@@ -127,7 +112,6 @@ const requestModelPost1 = RequestModel(
|
||||
const requestModelPost2 = RequestModel(
|
||||
id: 'post2',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPost2,
|
||||
);
|
||||
|
||||
@@ -135,7 +119,6 @@ const requestModelPost2 = RequestModel(
|
||||
const requestModelPost3 = RequestModel(
|
||||
id: 'post3',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPost3,
|
||||
);
|
||||
|
||||
@@ -143,7 +126,6 @@ const requestModelPost3 = RequestModel(
|
||||
const requestModelPost4 = RequestModel(
|
||||
id: 'post4',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPost4,
|
||||
);
|
||||
|
||||
@@ -151,7 +133,6 @@ const requestModelPost4 = RequestModel(
|
||||
const requestModelPost5 = RequestModel(
|
||||
id: 'post5',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPost5,
|
||||
);
|
||||
|
||||
@@ -159,7 +140,6 @@ const requestModelPost5 = RequestModel(
|
||||
const requestModelPost6 = RequestModel(
|
||||
id: 'post6',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPost6,
|
||||
);
|
||||
|
||||
@@ -167,7 +147,6 @@ const requestModelPost6 = RequestModel(
|
||||
const requestModelPost7 = RequestModel(
|
||||
id: 'post7',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPost7,
|
||||
);
|
||||
|
||||
@@ -175,7 +154,6 @@ const requestModelPost7 = RequestModel(
|
||||
const requestModelPost8 = RequestModel(
|
||||
id: 'post8',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPost8,
|
||||
);
|
||||
|
||||
@@ -183,14 +161,12 @@ const requestModelPost8 = RequestModel(
|
||||
const requestModelPost9 = RequestModel(
|
||||
id: 'post9',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPost9,
|
||||
);
|
||||
|
||||
const requestModelPost10 = RequestModel(
|
||||
id: 'post9',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPost10,
|
||||
);
|
||||
|
||||
@@ -198,7 +174,6 @@ const requestModelPost10 = RequestModel(
|
||||
const requestModelPut1 = RequestModel(
|
||||
id: 'put1',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPut1,
|
||||
);
|
||||
|
||||
@@ -206,7 +181,6 @@ const requestModelPut1 = RequestModel(
|
||||
const requestModelPatch1 = RequestModel(
|
||||
id: 'patch1',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPatch1,
|
||||
);
|
||||
|
||||
@@ -214,7 +188,6 @@ const requestModelPatch1 = RequestModel(
|
||||
const requestModelDelete1 = RequestModel(
|
||||
id: 'delete1',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelDelete1,
|
||||
);
|
||||
|
||||
@@ -222,7 +195,6 @@ const requestModelDelete1 = RequestModel(
|
||||
const requestModelDelete2 = RequestModel(
|
||||
id: 'delete2',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelDelete2,
|
||||
);
|
||||
|
||||
@@ -230,7 +202,6 @@ const requestModelDelete2 = RequestModel(
|
||||
RequestModel testRequestModel = RequestModel(
|
||||
id: '1',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPost10,
|
||||
responseStatus: 200,
|
||||
httpResponseModel: responseModel,
|
||||
@@ -241,7 +212,6 @@ Map<String, dynamic> requestModelJson = {
|
||||
'id': '1',
|
||||
'apiType': 'rest',
|
||||
'name': '',
|
||||
'authModel': '',
|
||||
'description': '',
|
||||
'httpRequestModel': httpRequestModelPost10Json,
|
||||
'responseStatus': 200,
|
||||
@@ -255,7 +225,6 @@ Map<String, dynamic> requestModelJson = {
|
||||
const requestModelGet13 = RequestModel(
|
||||
id: 'get13',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelGet13,
|
||||
);
|
||||
|
||||
@@ -263,7 +232,6 @@ const requestModelGet13 = RequestModel(
|
||||
const requestModelGetBadSSL = RequestModel(
|
||||
id: 'badSSL',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelGetBadSSL,
|
||||
);
|
||||
|
||||
@@ -271,7 +239,6 @@ const requestModelGetBadSSL = RequestModel(
|
||||
const requestModelPost11 = RequestModel(
|
||||
id: 'post11',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPost11,
|
||||
);
|
||||
|
||||
@@ -279,7 +246,6 @@ const requestModelPost11 = RequestModel(
|
||||
const requestModelPost12 = RequestModel(
|
||||
id: 'post12',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPost12,
|
||||
);
|
||||
|
||||
@@ -287,13 +253,11 @@ const requestModelPost12 = RequestModel(
|
||||
const requestModelPost13 = RequestModel(
|
||||
id: 'post13',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelPost13,
|
||||
);
|
||||
|
||||
const requestModelOptions1 = RequestModel(
|
||||
id: 'options1',
|
||||
apiType: APIType.rest,
|
||||
authModel: AuthModel(type: APIAuthType.none),
|
||||
httpRequestModel: httpRequestModelOptions1,
|
||||
);
|
||||
|
||||
@@ -17,7 +17,7 @@ void main() {
|
||||
var responseRec = await sendHttpRequest(
|
||||
requestModelGet1.id,
|
||||
requestModelGet1.apiType,
|
||||
requestModelGet1.authModel,
|
||||
AuthModel(type: APIAuthType.none),
|
||||
requestModelGet1.httpRequestModel!,
|
||||
defaultUriScheme: kDefaultUriScheme,
|
||||
noSSL: false,
|
||||
@@ -36,7 +36,7 @@ void main() {
|
||||
var responseRec = await sendHttpRequest(
|
||||
requestModelGet13.id,
|
||||
requestModelGet13.apiType,
|
||||
requestModelGet13.authModel,
|
||||
AuthModel(type: APIAuthType.none),
|
||||
requestModelGet13.httpRequestModel!,
|
||||
defaultUriScheme: kDefaultUriScheme,
|
||||
noSSL: false,
|
||||
@@ -54,7 +54,7 @@ void main() {
|
||||
var responseRec = await sendHttpRequest(
|
||||
requestModelPost11.id,
|
||||
requestModelPost11.apiType,
|
||||
requestModelPost11.authModel,
|
||||
AuthModel(type: APIAuthType.none),
|
||||
requestModelPost11.httpRequestModel!,
|
||||
);
|
||||
|
||||
@@ -69,7 +69,7 @@ void main() {
|
||||
var responseRec = await sendHttpRequest(
|
||||
requestModelPost12.id,
|
||||
requestModelPost12.apiType,
|
||||
requestModelPost12.authModel,
|
||||
AuthModel(type: APIAuthType.none),
|
||||
requestModelPost12.httpRequestModel!,
|
||||
);
|
||||
|
||||
@@ -83,7 +83,7 @@ void main() {
|
||||
var responseRec = await sendHttpRequest(
|
||||
requestModelPost13.id,
|
||||
requestModelPost13.apiType,
|
||||
requestModelPost13.authModel,
|
||||
AuthModel(type: APIAuthType.none),
|
||||
requestModelPost13.httpRequestModel!,
|
||||
);
|
||||
|
||||
@@ -97,7 +97,7 @@ void main() {
|
||||
var responseRec = await sendHttpRequest(
|
||||
requestModelGetBadSSL.id,
|
||||
requestModelGetBadSSL.apiType,
|
||||
requestModelGetBadSSL.authModel,
|
||||
AuthModel(type: APIAuthType.none),
|
||||
requestModelGetBadSSL.httpRequestModel!,
|
||||
defaultUriScheme: kDefaultUriScheme,
|
||||
noSSL: false,
|
||||
@@ -110,7 +110,7 @@ void main() {
|
||||
var responseRec = await sendHttpRequest(
|
||||
requestModelGetBadSSL.id,
|
||||
requestModelGetBadSSL.apiType,
|
||||
requestModelGetBadSSL.authModel,
|
||||
AuthModel(type: APIAuthType.none),
|
||||
requestModelGetBadSSL.httpRequestModel!,
|
||||
defaultUriScheme: kDefaultUriScheme,
|
||||
noSSL: true,
|
||||
@@ -131,7 +131,7 @@ void main() {
|
||||
var responseRec = await sendHttpRequest(
|
||||
requestModelOptions1.id,
|
||||
requestModelOptions1.apiType,
|
||||
requestModelOptions1.authModel,
|
||||
AuthModel(type: APIAuthType.none),
|
||||
requestModelOptions1.httpRequestModel!,
|
||||
defaultUriScheme: kDefaultUriScheme,
|
||||
noSSL: false,
|
||||
@@ -139,9 +139,14 @@ void main() {
|
||||
|
||||
final responseData = responseModel.fromResponse(response: responseRec.$1!);
|
||||
expect(responseData.statusCode, 200);
|
||||
expect(responseData.headers?['access-control-allow-methods'], 'GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS');
|
||||
expect(responseData.headers?['access-control-allow-methods']?.contains("OPTIONS"), true);
|
||||
expect(responseData.headers?['allow'], 'GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS');
|
||||
expect(responseData.headers?['access-control-allow-methods'],
|
||||
'GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS');
|
||||
expect(
|
||||
responseData.headers?['access-control-allow-methods']
|
||||
?.contains("OPTIONS"),
|
||||
true);
|
||||
expect(responseData.headers?['allow'],
|
||||
'GET,POST,PUT,PATCH,DELETE,HEAD,OPTIONS');
|
||||
expect(responseData.headers?['allow']?.contains("OPTIONS"), true);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -51,4 +51,580 @@ void main() async {
|
||||
// Verify that the Snackbar is shown
|
||||
expect(find.text('Switched to POST method'), findsOneWidget);
|
||||
}, skip: true);
|
||||
|
||||
group('CollectionStateNotifier Auth Tests', () {
|
||||
late ProviderContainer container;
|
||||
late CollectionStateNotifier notifier;
|
||||
|
||||
setUp(() {
|
||||
container = createContainer();
|
||||
notifier = container.read(collectionStateNotifierProvider.notifier);
|
||||
});
|
||||
|
||||
test('should update request with basic authentication', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: 'testuser',
|
||||
password: 'testpass',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: basicAuth,
|
||||
);
|
||||
|
||||
notifier.update(id: id, authModel: authModel);
|
||||
|
||||
final updatedRequest = notifier.getRequestModel(id);
|
||||
expect(
|
||||
updatedRequest?.httpRequestModel?.authModel?.type, APIAuthType.basic);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.basic?.username,
|
||||
'testuser');
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.basic?.password,
|
||||
'testpass');
|
||||
});
|
||||
|
||||
test('should update request with bearer authentication', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
const bearerAuth = AuthBearerModel(token: 'bearer-token-123');
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.bearer,
|
||||
bearer: bearerAuth,
|
||||
);
|
||||
|
||||
notifier.update(id: id, authModel: authModel);
|
||||
|
||||
final updatedRequest = notifier.getRequestModel(id);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.type,
|
||||
APIAuthType.bearer);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.bearer?.token,
|
||||
'bearer-token-123');
|
||||
});
|
||||
|
||||
test('should update request with API key authentication', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
const apiKeyAuth = AuthApiKeyModel(
|
||||
key: 'api-key-123',
|
||||
location: 'header',
|
||||
name: 'X-API-Key',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.apiKey,
|
||||
apikey: apiKeyAuth,
|
||||
);
|
||||
|
||||
notifier.update(id: id, authModel: authModel);
|
||||
|
||||
final updatedRequest = notifier.getRequestModel(id);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.type,
|
||||
APIAuthType.apiKey);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.apikey?.key,
|
||||
'api-key-123');
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.apikey?.location,
|
||||
'header');
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.apikey?.name,
|
||||
'X-API-Key');
|
||||
});
|
||||
|
||||
test('should update request with JWT authentication', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
const jwtAuth = AuthJwtModel(
|
||||
secret: 'jwt-secret',
|
||||
payload: '{"sub": "1234567890"}',
|
||||
addTokenTo: 'header',
|
||||
algorithm: 'HS256',
|
||||
isSecretBase64Encoded: false,
|
||||
headerPrefix: 'Bearer',
|
||||
queryParamKey: 'token',
|
||||
header: 'Authorization',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.jwt,
|
||||
jwt: jwtAuth,
|
||||
);
|
||||
|
||||
notifier.update(id: id, authModel: authModel);
|
||||
|
||||
final updatedRequest = notifier.getRequestModel(id);
|
||||
expect(
|
||||
updatedRequest?.httpRequestModel?.authModel?.type, APIAuthType.jwt);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.jwt?.secret,
|
||||
'jwt-secret');
|
||||
expect(
|
||||
updatedRequest?.httpRequestModel?.authModel?.jwt?.algorithm, 'HS256');
|
||||
expect(
|
||||
updatedRequest
|
||||
?.httpRequestModel?.authModel?.jwt?.isSecretBase64Encoded,
|
||||
false);
|
||||
});
|
||||
|
||||
test('should update request with digest authentication', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
const digestAuth = AuthDigestModel(
|
||||
username: 'digestuser',
|
||||
password: 'digestpass',
|
||||
realm: 'test-realm',
|
||||
nonce: 'test-nonce',
|
||||
algorithm: 'MD5',
|
||||
qop: 'auth',
|
||||
opaque: 'test-opaque',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.digest,
|
||||
digest: digestAuth,
|
||||
);
|
||||
|
||||
notifier.update(id: id, authModel: authModel);
|
||||
|
||||
final updatedRequest = notifier.getRequestModel(id);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.type,
|
||||
APIAuthType.digest);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.digest?.username,
|
||||
'digestuser');
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.digest?.realm,
|
||||
'test-realm');
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.digest?.algorithm,
|
||||
'MD5');
|
||||
});
|
||||
|
||||
test('should remove authentication when set to none', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
|
||||
// First add auth
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: 'testuser',
|
||||
password: 'testpass',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: basicAuth,
|
||||
);
|
||||
notifier.update(id: id, authModel: authModel);
|
||||
|
||||
// Then remove auth
|
||||
const noAuthModel = AuthModel(type: APIAuthType.none);
|
||||
notifier.update(id: id, authModel: noAuthModel);
|
||||
|
||||
final updatedRequest = notifier.getRequestModel(id);
|
||||
expect(
|
||||
updatedRequest?.httpRequestModel?.authModel?.type, APIAuthType.none);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.basic, isNull);
|
||||
});
|
||||
|
||||
test('should preserve auth when duplicating request', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: 'testuser',
|
||||
password: 'testpass',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: basicAuth,
|
||||
);
|
||||
|
||||
notifier.update(id: id, authModel: authModel);
|
||||
notifier.duplicate(id: id);
|
||||
|
||||
final sequence = container.read(requestSequenceProvider);
|
||||
final duplicatedId = sequence.firstWhere((element) => element != id);
|
||||
final duplicatedRequest = notifier.getRequestModel(duplicatedId);
|
||||
|
||||
expect(duplicatedRequest?.httpRequestModel?.authModel?.type,
|
||||
APIAuthType.basic);
|
||||
expect(duplicatedRequest?.httpRequestModel?.authModel?.basic?.username,
|
||||
'testuser');
|
||||
expect(duplicatedRequest?.httpRequestModel?.authModel?.basic?.password,
|
||||
'testpass');
|
||||
});
|
||||
|
||||
test('should not clear auth when clearing response', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
const bearerAuth = AuthBearerModel(token: 'bearer-token-123');
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.bearer,
|
||||
bearer: bearerAuth,
|
||||
);
|
||||
|
||||
notifier.update(id: id, authModel: authModel);
|
||||
notifier.clearResponse(id: id);
|
||||
|
||||
final updatedRequest = notifier.getRequestModel(id);
|
||||
// Auth should be preserved when clearing response
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.type,
|
||||
APIAuthType.bearer);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.bearer?.token,
|
||||
'bearer-token-123');
|
||||
});
|
||||
|
||||
test('should handle auth with special characters', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: 'user@domain.com',
|
||||
password: r'P@ssw0rd!@#$%^&*()',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: basicAuth,
|
||||
);
|
||||
|
||||
notifier.update(id: id, authModel: authModel);
|
||||
|
||||
final updatedRequest = notifier.getRequestModel(id);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.basic?.username,
|
||||
'user@domain.com');
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.basic?.password,
|
||||
r'P@ssw0rd!@#$%^&*()');
|
||||
});
|
||||
|
||||
test('should handle multiple auth type changes', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
|
||||
// Start with basic auth
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: 'testuser',
|
||||
password: 'testpass',
|
||||
);
|
||||
const basicAuthModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: basicAuth,
|
||||
);
|
||||
notifier.update(id: id, authModel: basicAuthModel);
|
||||
|
||||
// Switch to bearer
|
||||
const bearerAuth = AuthBearerModel(token: 'bearer-token-123');
|
||||
const bearerAuthModel = AuthModel(
|
||||
type: APIAuthType.bearer,
|
||||
bearer: bearerAuth,
|
||||
);
|
||||
notifier.update(id: id, authModel: bearerAuthModel);
|
||||
|
||||
// Switch to API key
|
||||
const apiKeyAuth = AuthApiKeyModel(
|
||||
key: 'api-key-123',
|
||||
location: 'query',
|
||||
name: 'apikey',
|
||||
);
|
||||
const apiKeyAuthModel = AuthModel(
|
||||
type: APIAuthType.apiKey,
|
||||
apikey: apiKeyAuth,
|
||||
);
|
||||
notifier.update(id: id, authModel: apiKeyAuthModel);
|
||||
|
||||
final updatedRequest = notifier.getRequestModel(id);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.type,
|
||||
APIAuthType.apiKey);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.apikey?.key,
|
||||
'api-key-123');
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.apikey?.location,
|
||||
'query');
|
||||
expect(
|
||||
updatedRequest?.httpRequestModel?.authModel?.apikey?.name, 'apikey');
|
||||
});
|
||||
|
||||
test('should handle empty auth values', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: '',
|
||||
password: '',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: basicAuth,
|
||||
);
|
||||
|
||||
notifier.update(id: id, authModel: authModel);
|
||||
|
||||
final updatedRequest = notifier.getRequestModel(id);
|
||||
expect(
|
||||
updatedRequest?.httpRequestModel?.authModel?.type, APIAuthType.basic);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.basic?.username, '');
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.basic?.password, '');
|
||||
});
|
||||
|
||||
test('should save and load auth data correctly', () async {
|
||||
final notifier = container.read(collectionStateNotifierProvider.notifier);
|
||||
|
||||
final id = notifier.state!.entries.first.key;
|
||||
const jwtAuth = AuthJwtModel(
|
||||
secret: 'jwt-secret',
|
||||
payload: '{"sub": "1234567890"}',
|
||||
addTokenTo: 'header',
|
||||
algorithm: 'HS256',
|
||||
isSecretBase64Encoded: false,
|
||||
headerPrefix: 'Bearer',
|
||||
queryParamKey: 'token',
|
||||
header: 'Authorization',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.jwt,
|
||||
jwt: jwtAuth,
|
||||
);
|
||||
|
||||
notifier.update(id: id, authModel: authModel);
|
||||
await notifier.saveData();
|
||||
|
||||
// Create new container and load data
|
||||
late ProviderContainer newContainer;
|
||||
try {
|
||||
newContainer = ProviderContainer();
|
||||
|
||||
// Wait for the container to initialize by accessing the provider
|
||||
final newNotifier =
|
||||
newContainer.read(collectionStateNotifierProvider.notifier);
|
||||
|
||||
// Give some time for the microtask in the constructor to complete
|
||||
await Future.delayed(const Duration(milliseconds: 10));
|
||||
|
||||
final loadedRequest = newNotifier.getRequestModel(id);
|
||||
|
||||
expect(
|
||||
loadedRequest?.httpRequestModel?.authModel?.type, APIAuthType.jwt);
|
||||
expect(loadedRequest?.httpRequestModel?.authModel?.jwt?.secret,
|
||||
'jwt-secret');
|
||||
expect(loadedRequest?.httpRequestModel?.authModel?.jwt?.algorithm,
|
||||
'HS256');
|
||||
} finally {
|
||||
newContainer.dispose();
|
||||
}
|
||||
});
|
||||
|
||||
test('should handle auth in addRequestModel', () {
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: 'testuser',
|
||||
password: 'testpass',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: basicAuth,
|
||||
);
|
||||
|
||||
final httpRequestModel = HttpRequestModel(
|
||||
method: HTTPVerb.get,
|
||||
url: 'https://api.example.com/users',
|
||||
authModel: authModel,
|
||||
);
|
||||
|
||||
notifier.addRequestModel(httpRequestModel, name: 'Test Request');
|
||||
|
||||
final sequence = container.read(requestSequenceProvider);
|
||||
final addedRequest = notifier.getRequestModel(sequence.first);
|
||||
|
||||
expect(
|
||||
addedRequest?.httpRequestModel?.authModel?.type, APIAuthType.basic);
|
||||
expect(addedRequest?.httpRequestModel?.authModel?.basic?.username,
|
||||
'testuser');
|
||||
expect(addedRequest?.httpRequestModel?.authModel?.basic?.password,
|
||||
'testpass');
|
||||
});
|
||||
|
||||
test('should handle complex JWT configuration', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
const complexPayload = '''
|
||||
{
|
||||
"sub": "1234567890",
|
||||
"name": "John Doe",
|
||||
"iat": 1516239022,
|
||||
"exp": 1516242622,
|
||||
"roles": ["admin", "user"],
|
||||
"permissions": {
|
||||
"read": true,
|
||||
"write": false
|
||||
}
|
||||
}
|
||||
''';
|
||||
|
||||
const jwtAuth = AuthJwtModel(
|
||||
secret: 'complex-secret',
|
||||
privateKey: 'private-key-content',
|
||||
payload: complexPayload,
|
||||
addTokenTo: 'query',
|
||||
algorithm: 'RS256',
|
||||
isSecretBase64Encoded: true,
|
||||
headerPrefix: 'JWT',
|
||||
queryParamKey: 'jwt_token',
|
||||
header: 'X-JWT-Token',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.jwt,
|
||||
jwt: jwtAuth,
|
||||
);
|
||||
|
||||
notifier.update(id: id, authModel: authModel);
|
||||
|
||||
final updatedRequest = notifier.getRequestModel(id);
|
||||
expect(
|
||||
updatedRequest?.httpRequestModel?.authModel?.type, APIAuthType.jwt);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.jwt?.payload,
|
||||
complexPayload);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.jwt?.privateKey,
|
||||
'private-key-content');
|
||||
expect(
|
||||
updatedRequest?.httpRequestModel?.authModel?.jwt?.algorithm, 'RS256');
|
||||
expect(
|
||||
updatedRequest
|
||||
?.httpRequestModel?.authModel?.jwt?.isSecretBase64Encoded,
|
||||
true);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.jwt?.addTokenTo,
|
||||
'query');
|
||||
});
|
||||
|
||||
test('should handle API key in different locations', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
|
||||
// Test header location
|
||||
const headerApiKey = AuthApiKeyModel(
|
||||
key: 'header-key',
|
||||
location: 'header',
|
||||
name: 'X-API-Key',
|
||||
);
|
||||
const headerAuthModel = AuthModel(
|
||||
type: APIAuthType.apiKey,
|
||||
apikey: headerApiKey,
|
||||
);
|
||||
notifier.update(id: id, authModel: headerAuthModel);
|
||||
|
||||
var updatedRequest = notifier.getRequestModel(id);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.apikey?.location,
|
||||
'header');
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.apikey?.name,
|
||||
'X-API-Key');
|
||||
|
||||
// Test query location
|
||||
const queryApiKey = AuthApiKeyModel(
|
||||
key: 'query-key',
|
||||
location: 'query',
|
||||
name: 'apikey',
|
||||
);
|
||||
const queryAuthModel = AuthModel(
|
||||
type: APIAuthType.apiKey,
|
||||
apikey: queryApiKey,
|
||||
);
|
||||
notifier.update(id: id, authModel: queryAuthModel);
|
||||
|
||||
updatedRequest = notifier.getRequestModel(id);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.apikey?.location,
|
||||
'query');
|
||||
expect(
|
||||
updatedRequest?.httpRequestModel?.authModel?.apikey?.name, 'apikey');
|
||||
});
|
||||
|
||||
test('should handle digest auth with different algorithms', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
|
||||
// Test MD5 algorithm
|
||||
const md5DigestAuth = AuthDigestModel(
|
||||
username: 'digestuser',
|
||||
password: 'digestpass',
|
||||
realm: 'test-realm',
|
||||
nonce: 'test-nonce',
|
||||
algorithm: 'MD5',
|
||||
qop: 'auth',
|
||||
opaque: 'test-opaque',
|
||||
);
|
||||
const md5AuthModel = AuthModel(
|
||||
type: APIAuthType.digest,
|
||||
digest: md5DigestAuth,
|
||||
);
|
||||
notifier.update(id: id, authModel: md5AuthModel);
|
||||
|
||||
var updatedRequest = notifier.getRequestModel(id);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.digest?.algorithm,
|
||||
'MD5');
|
||||
|
||||
// Test SHA-256 algorithm
|
||||
const sha256DigestAuth = AuthDigestModel(
|
||||
username: 'digestuser',
|
||||
password: 'digestpass',
|
||||
realm: 'test-realm',
|
||||
nonce: 'test-nonce',
|
||||
algorithm: 'SHA-256',
|
||||
qop: 'auth-int',
|
||||
opaque: 'test-opaque',
|
||||
);
|
||||
const sha256AuthModel = AuthModel(
|
||||
type: APIAuthType.digest,
|
||||
digest: sha256DigestAuth,
|
||||
);
|
||||
notifier.update(id: id, authModel: sha256AuthModel);
|
||||
|
||||
updatedRequest = notifier.getRequestModel(id);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.digest?.algorithm,
|
||||
'SHA-256');
|
||||
expect(
|
||||
updatedRequest?.httpRequestModel?.authModel?.digest?.qop, 'auth-int');
|
||||
});
|
||||
|
||||
test('should handle auth model copyWith functionality', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
const originalAuth = AuthBasicAuthModel(
|
||||
username: 'original',
|
||||
password: 'original',
|
||||
);
|
||||
const originalAuthModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: originalAuth,
|
||||
);
|
||||
|
||||
notifier.update(id: id, authModel: originalAuthModel);
|
||||
|
||||
// Update with copyWith
|
||||
const updatedAuth = AuthBasicAuthModel(
|
||||
username: 'updated',
|
||||
password: 'updated',
|
||||
);
|
||||
final updatedAuthModel = originalAuthModel.copyWith(
|
||||
basic: updatedAuth,
|
||||
);
|
||||
|
||||
notifier.update(id: id, authModel: updatedAuthModel);
|
||||
|
||||
final updatedRequest = notifier.getRequestModel(id);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.basic?.username,
|
||||
'updated');
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.basic?.password,
|
||||
'updated');
|
||||
});
|
||||
|
||||
test('should handle auth with very long tokens', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
final longToken = 'a' * 5000; // Very long token
|
||||
|
||||
final bearerAuth = AuthBearerModel(token: longToken);
|
||||
final authModel = AuthModel(
|
||||
type: APIAuthType.bearer,
|
||||
bearer: bearerAuth,
|
||||
);
|
||||
|
||||
notifier.update(id: id, authModel: authModel);
|
||||
|
||||
final updatedRequest = notifier.getRequestModel(id);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.bearer?.token,
|
||||
longToken);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.bearer?.token.length,
|
||||
5000);
|
||||
});
|
||||
|
||||
test('should handle auth with Unicode characters', () {
|
||||
final id = notifier.state!.entries.first.key;
|
||||
const basicAuth = AuthBasicAuthModel(
|
||||
username: 'user_测试_тест_テスト',
|
||||
password: 'password_🔑_🚀_💻',
|
||||
);
|
||||
const authModel = AuthModel(
|
||||
type: APIAuthType.basic,
|
||||
basic: basicAuth,
|
||||
);
|
||||
|
||||
notifier.update(id: id, authModel: authModel);
|
||||
|
||||
final updatedRequest = notifier.getRequestModel(id);
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.basic?.username,
|
||||
'user_测试_тест_テスト');
|
||||
expect(updatedRequest?.httpRequestModel?.authModel?.basic?.password,
|
||||
'password_🔑_🚀_💻');
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
container.dispose();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user