Test Cases
This commit is contained in:
@@ -0,0 +1,409 @@
|
||||
// ignore_for_file: deprecated_member_use
|
||||
|
||||
import 'dart:async';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:tasq/models/it_service_request.dart';
|
||||
import 'package:tasq/models/it_service_request_assignment.dart';
|
||||
import 'package:tasq/models/profile.dart';
|
||||
import 'package:tasq/models/ticket.dart';
|
||||
import 'package:tasq/models/task.dart';
|
||||
import 'package:tasq/models/task_assignment.dart';
|
||||
import 'package:tasq/models/ticket_message.dart';
|
||||
import 'package:tasq/models/duty_schedule.dart';
|
||||
import 'package:tasq/models/attendance_log.dart';
|
||||
import 'package:tasq/models/live_position.dart';
|
||||
import 'package:tasq/models/leave_of_absence.dart';
|
||||
import 'package:tasq/models/pass_slip.dart';
|
||||
import 'package:tasq/models/team.dart';
|
||||
import 'package:tasq/models/team_member.dart';
|
||||
import 'package:tasq/screens/dashboard/dashboard_screen.dart';
|
||||
import 'package:tasq/utils/app_time.dart';
|
||||
|
||||
// underlying providers needed by the dashboard metrics logic
|
||||
import 'package:tasq/providers/it_service_request_provider.dart';
|
||||
import 'package:tasq/providers/profile_provider.dart';
|
||||
import 'package:tasq/providers/tickets_provider.dart';
|
||||
import 'package:tasq/providers/tasks_provider.dart';
|
||||
import 'package:tasq/providers/workforce_provider.dart'; // dutySchedulesProvider
|
||||
import 'package:tasq/providers/attendance_provider.dart';
|
||||
import 'package:tasq/providers/whereabouts_provider.dart';
|
||||
import 'package:tasq/providers/leave_provider.dart';
|
||||
import 'package:tasq/providers/pass_slip_provider.dart';
|
||||
import 'package:tasq/providers/teams_provider.dart';
|
||||
|
||||
void main() {
|
||||
group('dashboardMetricsProvider', () {
|
||||
test('service request in progress causes status to become On task', () async {
|
||||
AppTime.initialize();
|
||||
final now = AppTime.now();
|
||||
// create a single IT staff profile
|
||||
final profile = Profile(
|
||||
id: 'u1',
|
||||
fullName: 'Staff One',
|
||||
role: 'it_staff',
|
||||
avatarUrl: null,
|
||||
allowTracking: false,
|
||||
);
|
||||
|
||||
final service = ItServiceRequest(
|
||||
id: 'r1',
|
||||
services: ['wifi'],
|
||||
eventName: 'Event',
|
||||
status: ItServiceRequestStatus.inProgress,
|
||||
outsidePremiseAllowed: false,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
);
|
||||
|
||||
final assignment = ItServiceRequestAssignment(
|
||||
id: 'a1',
|
||||
requestId: 'r1',
|
||||
userId: 'u1',
|
||||
createdAt: now,
|
||||
);
|
||||
|
||||
final container = ProviderContainer(
|
||||
overrides: [
|
||||
profilesProvider.overrideWith((ref) => Stream.value([profile])),
|
||||
itServiceRequestsProvider.overrideWith(
|
||||
(ref) => Stream.value([service]),
|
||||
),
|
||||
itServiceRequestAssignmentsProvider.overrideWith(
|
||||
(ref) => Stream.value([assignment]),
|
||||
),
|
||||
|
||||
// everything else can be empty streams so dashboard metrics doesn't crash
|
||||
ticketsProvider.overrideWith((ref) => Stream.value(const <Ticket>[])),
|
||||
tasksProvider.overrideWith((ref) => Stream.value(const <Task>[])),
|
||||
taskAssignmentsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <TaskAssignment>[]),
|
||||
),
|
||||
ticketMessagesAllProvider.overrideWith(
|
||||
(ref) => Stream.value(const <TicketMessage>[]),
|
||||
),
|
||||
dutySchedulesProvider.overrideWith(
|
||||
(ref) => Stream.value(const <DutySchedule>[]),
|
||||
),
|
||||
attendanceLogsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <AttendanceLog>[]),
|
||||
),
|
||||
livePositionsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <LivePosition>[]),
|
||||
),
|
||||
leavesProvider.overrideWith(
|
||||
(ref) => Stream.value(const <LeaveOfAbsence>[]),
|
||||
),
|
||||
|
||||
passSlipsProvider.overrideWithProvider(
|
||||
StreamProvider<List<PassSlip>>(
|
||||
(ref) => Stream.value(const <PassSlip>[]),
|
||||
),
|
||||
),
|
||||
teamsProvider.overrideWithProvider(
|
||||
StreamProvider<List<Team>>((ref) => Stream.value(const <Team>[])),
|
||||
),
|
||||
teamMembersProvider.overrideWithProvider(
|
||||
StreamProvider<List<TeamMember>>(
|
||||
(ref) => Stream.value(const <TeamMember>[]),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
// wait for the dashboard metrics provider to emit AsyncData
|
||||
final completer = Completer<DashboardMetrics>();
|
||||
container.listen<AsyncValue<DashboardMetrics>>(dashboardMetricsProvider, (
|
||||
prev,
|
||||
next,
|
||||
) {
|
||||
if (next is AsyncData<DashboardMetrics>) {
|
||||
completer.complete(next.value);
|
||||
}
|
||||
}, fireImmediately: true);
|
||||
final data = await completer.future;
|
||||
expect(data.staffRows.length, 1);
|
||||
expect(data.staffRows.first.status, 'On event');
|
||||
});
|
||||
|
||||
test('service request not in progress does not affect status', () async {
|
||||
AppTime.initialize();
|
||||
final now = AppTime.now();
|
||||
final profile = Profile(
|
||||
id: 'u2',
|
||||
fullName: 'Staff Two',
|
||||
role: 'it_staff',
|
||||
avatarUrl: null,
|
||||
allowTracking: false,
|
||||
);
|
||||
|
||||
final service = ItServiceRequest(
|
||||
id: 'r2',
|
||||
services: ['wifi'],
|
||||
eventName: 'Event',
|
||||
status: ItServiceRequestStatus.scheduled,
|
||||
outsidePremiseAllowed: false,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
);
|
||||
|
||||
final assignment = ItServiceRequestAssignment(
|
||||
id: 'a2',
|
||||
requestId: 'r2',
|
||||
userId: 'u2',
|
||||
createdAt: now,
|
||||
);
|
||||
|
||||
final container = ProviderContainer(
|
||||
overrides: [
|
||||
profilesProvider.overrideWith((ref) => Stream.value([profile])),
|
||||
itServiceRequestsProvider.overrideWith(
|
||||
(ref) => Stream.value([service]),
|
||||
),
|
||||
itServiceRequestAssignmentsProvider.overrideWith(
|
||||
(ref) => Stream.value([assignment]),
|
||||
),
|
||||
|
||||
ticketsProvider.overrideWith((ref) => Stream.value(const <Ticket>[])),
|
||||
tasksProvider.overrideWith((ref) => Stream.value(const <Task>[])),
|
||||
taskAssignmentsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <TaskAssignment>[]),
|
||||
),
|
||||
ticketMessagesAllProvider.overrideWith(
|
||||
(ref) => Stream.value(const <TicketMessage>[]),
|
||||
),
|
||||
dutySchedulesProvider.overrideWith(
|
||||
(ref) => Stream.value(const <DutySchedule>[]),
|
||||
),
|
||||
attendanceLogsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <AttendanceLog>[]),
|
||||
),
|
||||
livePositionsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <LivePosition>[]),
|
||||
),
|
||||
leavesProvider.overrideWith(
|
||||
(ref) => Stream.value(const <LeaveOfAbsence>[]),
|
||||
),
|
||||
|
||||
passSlipsProvider.overrideWithProvider(
|
||||
StreamProvider<List<PassSlip>>(
|
||||
(ref) => Stream.value(const <PassSlip>[]),
|
||||
),
|
||||
),
|
||||
teamsProvider.overrideWithProvider(
|
||||
StreamProvider<List<Team>>((ref) => Stream.value(const <Team>[])),
|
||||
),
|
||||
teamMembersProvider.overrideWithProvider(
|
||||
StreamProvider<List<TeamMember>>(
|
||||
(ref) => Stream.value(const <TeamMember>[]),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final completer = Completer<DashboardMetrics>();
|
||||
container.listen<AsyncValue<DashboardMetrics>>(dashboardMetricsProvider, (
|
||||
prev,
|
||||
next,
|
||||
) {
|
||||
if (next is AsyncData<DashboardMetrics>) {
|
||||
completer.complete(next.value);
|
||||
}
|
||||
}, fireImmediately: true);
|
||||
final data = await completer.future;
|
||||
expect(data.staffRows.length, 1);
|
||||
// since user has no attendance or task data they should default to Off duty
|
||||
expect(data.staffRows.first.status.toLowerCase(), contains('off'));
|
||||
});
|
||||
});
|
||||
|
||||
test(
|
||||
'approved leave should force On leave status and not mark Off duty',
|
||||
() async {
|
||||
AppTime.initialize();
|
||||
final now = AppTime.now();
|
||||
final profile = Profile(
|
||||
id: 'u3',
|
||||
fullName: 'Staff Three',
|
||||
role: 'it_staff',
|
||||
avatarUrl: null,
|
||||
allowTracking: false,
|
||||
);
|
||||
|
||||
// create a schedule for today
|
||||
final schedule = DutySchedule(
|
||||
id: 's1',
|
||||
userId: profile.id,
|
||||
shiftType: 'am',
|
||||
startTime: DateTime(now.year, now.month, now.day, 8),
|
||||
endTime: DateTime(now.year, now.month, now.day, 16),
|
||||
status: 'scheduled',
|
||||
createdAt: now,
|
||||
checkInAt: null,
|
||||
checkInLocation: null,
|
||||
relieverIds: [],
|
||||
);
|
||||
|
||||
final leave = LeaveOfAbsence(
|
||||
id: 'l1',
|
||||
userId: profile.id,
|
||||
leaveType: 'sick_leave',
|
||||
justification: 'ill',
|
||||
startTime: now.subtract(const Duration(hours: 1)),
|
||||
endTime: now.add(const Duration(hours: 4)),
|
||||
status: 'approved',
|
||||
filedBy: profile.id,
|
||||
createdAt: now,
|
||||
);
|
||||
|
||||
final container = ProviderContainer(
|
||||
overrides: [
|
||||
profilesProvider.overrideWith((ref) => Stream.value([profile])),
|
||||
dutySchedulesProvider.overrideWith((ref) => Stream.value([schedule])),
|
||||
leavesProvider.overrideWith((ref) => Stream.value([leave])),
|
||||
|
||||
// stub the rest with empties
|
||||
ticketsProvider.overrideWith((ref) => Stream.value(const <Ticket>[])),
|
||||
tasksProvider.overrideWith((ref) => Stream.value(const <Task>[])),
|
||||
taskAssignmentsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <TaskAssignment>[]),
|
||||
),
|
||||
ticketMessagesAllProvider.overrideWith(
|
||||
(ref) => Stream.value(const <TicketMessage>[]),
|
||||
),
|
||||
attendanceLogsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <AttendanceLog>[]),
|
||||
),
|
||||
livePositionsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <LivePosition>[]),
|
||||
),
|
||||
passSlipsProvider.overrideWithProvider(
|
||||
StreamProvider<List<PassSlip>>(
|
||||
(ref) => Stream.value(const <PassSlip>[]),
|
||||
),
|
||||
),
|
||||
teamsProvider.overrideWithProvider(
|
||||
StreamProvider<List<Team>>((ref) => Stream.value(const <Team>[])),
|
||||
),
|
||||
teamMembersProvider.overrideWithProvider(
|
||||
StreamProvider<List<TeamMember>>(
|
||||
(ref) => Stream.value(const <TeamMember>[]),
|
||||
),
|
||||
),
|
||||
itServiceRequestsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <ItServiceRequest>[]),
|
||||
),
|
||||
itServiceRequestAssignmentsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <ItServiceRequestAssignment>[]),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final completer = Completer<DashboardMetrics>();
|
||||
container.listen<AsyncValue<DashboardMetrics>>(dashboardMetricsProvider, (
|
||||
prev,
|
||||
next,
|
||||
) {
|
||||
if (next is AsyncData<DashboardMetrics>) {
|
||||
completer.complete(next.value);
|
||||
}
|
||||
}, fireImmediately: true);
|
||||
final data = await completer.future;
|
||||
expect(data.staffRows.length, 1);
|
||||
expect(data.staffRows.first.status, equals('On leave'));
|
||||
},
|
||||
);
|
||||
|
||||
test('rejected leave should not affect schedule status', () async {
|
||||
AppTime.initialize();
|
||||
final now = AppTime.now();
|
||||
final profile = Profile(
|
||||
id: 'u4',
|
||||
fullName: 'Staff Four',
|
||||
role: 'it_staff',
|
||||
avatarUrl: null,
|
||||
allowTracking: false,
|
||||
);
|
||||
|
||||
final schedule = DutySchedule(
|
||||
id: 's2',
|
||||
userId: profile.id,
|
||||
shiftType: 'am',
|
||||
startTime: DateTime(now.year, now.month, now.day, 8),
|
||||
endTime: DateTime(now.year, now.month, now.day, 16),
|
||||
status: 'scheduled',
|
||||
createdAt: now,
|
||||
checkInAt: null,
|
||||
checkInLocation: null,
|
||||
relieverIds: [],
|
||||
);
|
||||
|
||||
final leave = LeaveOfAbsence(
|
||||
id: 'l2',
|
||||
userId: profile.id,
|
||||
leaveType: 'vacation_leave',
|
||||
justification: 'plans',
|
||||
startTime: now.subtract(const Duration(hours: 1)),
|
||||
endTime: now.add(const Duration(hours: 4)),
|
||||
status: 'rejected',
|
||||
filedBy: profile.id,
|
||||
createdAt: now,
|
||||
);
|
||||
|
||||
final container = ProviderContainer(
|
||||
overrides: [
|
||||
profilesProvider.overrideWith((ref) => Stream.value([profile])),
|
||||
dutySchedulesProvider.overrideWith((ref) => Stream.value([schedule])),
|
||||
leavesProvider.overrideWith((ref) => Stream.value([leave])),
|
||||
ticketsProvider.overrideWith((ref) => Stream.value(const <Ticket>[])),
|
||||
tasksProvider.overrideWith((ref) => Stream.value(const <Task>[])),
|
||||
taskAssignmentsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <TaskAssignment>[]),
|
||||
),
|
||||
ticketMessagesAllProvider.overrideWith(
|
||||
(ref) => Stream.value(const <TicketMessage>[]),
|
||||
),
|
||||
attendanceLogsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <AttendanceLog>[]),
|
||||
),
|
||||
livePositionsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <LivePosition>[]),
|
||||
),
|
||||
passSlipsProvider.overrideWithProvider(
|
||||
StreamProvider<List<PassSlip>>(
|
||||
(ref) => Stream.value(const <PassSlip>[]),
|
||||
),
|
||||
),
|
||||
teamsProvider.overrideWithProvider(
|
||||
StreamProvider<List<Team>>((ref) => Stream.value(const <Team>[])),
|
||||
),
|
||||
teamMembersProvider.overrideWithProvider(
|
||||
StreamProvider<List<TeamMember>>(
|
||||
(ref) => Stream.value(const <TeamMember>[]),
|
||||
),
|
||||
),
|
||||
itServiceRequestsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <ItServiceRequest>[]),
|
||||
),
|
||||
itServiceRequestAssignmentsProvider.overrideWith(
|
||||
(ref) => Stream.value(const <ItServiceRequestAssignment>[]),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
final completer = Completer<DashboardMetrics>();
|
||||
container.listen<AsyncValue<DashboardMetrics>>(dashboardMetricsProvider, (
|
||||
prev,
|
||||
next,
|
||||
) {
|
||||
if (next is AsyncData<DashboardMetrics>) {
|
||||
completer.complete(next.value);
|
||||
}
|
||||
}, fireImmediately: true);
|
||||
final data = await completer.future;
|
||||
expect(data.staffRows.length, 1);
|
||||
// since leave was rejected, status should not be 'On leave' nor 'Off duty'
|
||||
expect(data.staffRows.first.status, isNot('On leave'));
|
||||
expect(data.staffRows.first.status.toLowerCase(), isNot(contains('off')));
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user