init
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:kickkings_support/models/account.dart';
|
||||
|
||||
void main() {
|
||||
test('admins can read and write support', () {
|
||||
const account = Account(
|
||||
id: '1',
|
||||
username: 'ada',
|
||||
isAdmin: true,
|
||||
permissions: {},
|
||||
);
|
||||
|
||||
expect(account.canReadSupport, isTrue);
|
||||
expect(account.canWriteSupport, isTrue);
|
||||
});
|
||||
|
||||
test('support read does not grant write', () {
|
||||
final account = Account.fromJson({
|
||||
'id': '1',
|
||||
'username': 'ada',
|
||||
'isAdmin': false,
|
||||
'permissions': {
|
||||
'support': {'read': true, 'write': false},
|
||||
},
|
||||
});
|
||||
|
||||
expect(account.canReadSupport, isTrue);
|
||||
expect(account.canWriteSupport, isFalse);
|
||||
});
|
||||
|
||||
test('missing support permission cannot enter the inbox', () {
|
||||
final account = Account.fromJson({
|
||||
'id': '1',
|
||||
'username': 'ada',
|
||||
'isAdmin': false,
|
||||
'permissions': {
|
||||
'players': {'read': true},
|
||||
},
|
||||
});
|
||||
|
||||
expect(account.canReadSupport, isFalse);
|
||||
expect(account.canWriteSupport, isFalse);
|
||||
});
|
||||
|
||||
test('account json round trip keeps support flags', () {
|
||||
final account = Account.fromJson({
|
||||
'id': 'acct',
|
||||
'username': 'ada',
|
||||
'isAdmin': false,
|
||||
'permissions': {
|
||||
'support': {'read': true, 'write': true},
|
||||
},
|
||||
});
|
||||
|
||||
final restored = Account.fromJson(account.toJson());
|
||||
expect(restored.canReadSupport, isTrue);
|
||||
expect(restored.canWriteSupport, isTrue);
|
||||
expect(restored.username, 'ada');
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:kickkings_support/models/api_exception.dart';
|
||||
|
||||
void main() {
|
||||
test('reads the error string', () {
|
||||
final error = ApiException.fromBody(
|
||||
statusCode: 401,
|
||||
body: {'error': 'Invalid credentials'},
|
||||
);
|
||||
|
||||
expect(error.statusCode, 401);
|
||||
expect(error.message, 'Invalid credentials');
|
||||
expect(error.isUnauthorized, isTrue);
|
||||
});
|
||||
|
||||
test('appends retryAfterSeconds', () {
|
||||
final error = ApiException.fromBody(
|
||||
statusCode: 429,
|
||||
body: {
|
||||
'error': 'Too many failed login attempts. Try again later.',
|
||||
'retryAfterSeconds': 900,
|
||||
},
|
||||
);
|
||||
|
||||
expect(error.retryAfterSeconds, 900);
|
||||
expect(
|
||||
error.message,
|
||||
'Too many failed login attempts. Try again later. Retry after 900 seconds.',
|
||||
);
|
||||
});
|
||||
|
||||
test('uses the fallback when the body has no error', () {
|
||||
final error = ApiException.fromBody(
|
||||
statusCode: 503,
|
||||
body: 'unavailable',
|
||||
fallback: 'Could not reach the server.',
|
||||
);
|
||||
|
||||
expect(error.message, 'Could not reach the server.');
|
||||
expect(error.retryAfterSeconds, isNull);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:kickkings_support/config.dart';
|
||||
import 'package:kickkings_support/models/login_result.dart';
|
||||
import 'package:kickkings_support/models/support_message.dart';
|
||||
import 'package:kickkings_support/models/support_ticket.dart';
|
||||
|
||||
void main() {
|
||||
test('normalizes a base url', () {
|
||||
expect(
|
||||
normalizeBaseUrl('https://kickkings.playpoolstudios.com/'),
|
||||
'https://kickkings.playpoolstudios.com',
|
||||
);
|
||||
expect(normalizeBaseUrl(' https://example.com/// '), 'https://example.com');
|
||||
});
|
||||
|
||||
test('ticket query omits empty filters', () {
|
||||
expect(ticketListQuery(status: 'open'), {'status': 'open'});
|
||||
expect(ticketListQuery(status: 'closed', category: 'bug'), {
|
||||
'status': 'closed',
|
||||
'category': 'bug',
|
||||
});
|
||||
expect(ticketListQuery(), isEmpty);
|
||||
});
|
||||
|
||||
test('parses a ticket and a thread', () {
|
||||
final ticket = SupportTicket.fromJson({
|
||||
'id': 'ticket-1',
|
||||
'userId': 42,
|
||||
'username': 'playername',
|
||||
'category': 'bug',
|
||||
'categoryLabel': 'Report Bug',
|
||||
'status': 'open',
|
||||
'createdAt': '2026-10-15T12:00:00.000Z',
|
||||
'updatedAt': '2026-10-15T12:00:00.000Z',
|
||||
'lastMessageAt': '2026-10-15T12:05:00.000Z',
|
||||
'lastMessagePreview': 'The match froze',
|
||||
});
|
||||
|
||||
expect(ticket.userId, 42);
|
||||
expect(ticket.displayCategory, 'Report Bug');
|
||||
expect(ticket.isClosed, isFalse);
|
||||
expect(
|
||||
ticket.lastMessageAt.toUtc().toIso8601String(),
|
||||
'2026-10-15T12:05:00.000Z',
|
||||
);
|
||||
|
||||
final thread = SupportThread.fromJson({
|
||||
'ticket': {
|
||||
'id': 'ticket-1',
|
||||
'userId': 42,
|
||||
'username': 'playername',
|
||||
'category': 'bug',
|
||||
'categoryLabel': 'Report Bug',
|
||||
'status': 'closed',
|
||||
'createdAt': '2026-10-15T12:00:00.000Z',
|
||||
'updatedAt': '2026-10-15T12:10:00.000Z',
|
||||
'lastMessageAt': '2026-10-15T12:10:00.000Z',
|
||||
'lastMessagePreview': 'We are looking into this.',
|
||||
},
|
||||
'messages': [
|
||||
{
|
||||
'id': 'message-1',
|
||||
'ticketId': 'ticket-1',
|
||||
'authorKind': 'player',
|
||||
'authorName': 'playername',
|
||||
'body': 'The match froze',
|
||||
'createdAt': '2026-10-15T12:00:00.000Z',
|
||||
},
|
||||
{
|
||||
'id': 'message-2',
|
||||
'ticketId': 'ticket-1',
|
||||
'authorKind': 'staff',
|
||||
'authorName': 'ada',
|
||||
'body': 'We are looking into this.',
|
||||
'createdAt': '2026-10-15T12:10:00.000Z',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
expect(thread.ticket.isClosed, isTrue);
|
||||
expect(thread.messages, hasLength(2));
|
||||
expect(thread.messages.first.isStaff, isFalse);
|
||||
expect(thread.messages.last.isStaff, isTrue);
|
||||
});
|
||||
|
||||
test('parses a login result', () {
|
||||
final result = LoginResult.fromJson({
|
||||
'ok': true,
|
||||
'token': 'session-token',
|
||||
'account': {
|
||||
'id': 'acct',
|
||||
'username': 'ada',
|
||||
'isAdmin': false,
|
||||
'permissions': {
|
||||
'support': {'read': true, 'write': true},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.token, 'session-token');
|
||||
expect(result.account.canWriteSupport, isTrue);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:kickkings_support/models/support_message.dart';
|
||||
|
||||
void main() {
|
||||
test('rejects an empty reply', () {
|
||||
expect(validateReplyBody(' '), 'Enter a message.');
|
||||
});
|
||||
|
||||
test('accepts a trimmed reply up to 4000 characters', () {
|
||||
expect(validateReplyBody(' hello '), isNull);
|
||||
expect(validateReplyBody('a' * maxReplyLength), isNull);
|
||||
});
|
||||
|
||||
test('rejects a reply over 4000 characters', () {
|
||||
expect(
|
||||
validateReplyBody('a' * (maxReplyLength + 1)),
|
||||
'Message must be 4000 characters or fewer.',
|
||||
);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user