def test_week_day(self): start = datetime.now() end = start + timedelta(hours=1) until = datetime.now() + timedelta(weeks=9) data = self.get_outage_data(title='every week day outage', start=start, end=end, tool_name=tool.name, outage=True, frequency='DAILY_WEEKDAYS', interval=1, until=until) login_as_staff(self.client) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEqual(response.status_code, 200) outages = ScheduledOutage.objects.filter(title='every week day outage', tool=tool) for outage in outages: # 0 is Monday, 5 & 6 are Saturday and Sunday self.assertLess( outage.start.astimezone( timezone.get_current_timezone()).weekday(), 5)
def billing_by_attribute(self, attribute_name, attribute_value, result_attribute_name, results_number): data = { 'start': datetime.now().strftime('%m/%d/%Y'), 'end': datetime.now().strftime('%m/%d/%Y'), attribute_name: attribute_value } login_as_staff(self.client) response = self.client.get('/api/billing', data, follow=True) self.assertEqual(response.status_code, 403, "regular user or staff doesn't have permission") staff_user = User.objects.get(username='******') staff_user.user_permissions.add( Permission.objects.get(codename='use_billing_api')) staff_user.save() response = self.client.get('/api/billing', data, follow=True) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data), results_number) date_format = api.date_time_format for billing_item in response.data: start = datetime.strptime(billing_item['start'], date_format) end = datetime.strptime(billing_item['end'], date_format) self.assertEqual(datetime.now().date(), start.date()) self.assertEqual(datetime.now().date(), end.date()) self.assertEqual(billing_item.get(result_attribute_name), attribute_value)
def billing_by_attribute(self, attribute_name, attribute_value, result_attribute_name, results_number): data = { "start": datetime.now().strftime("%m/%d/%Y"), "end": datetime.now().strftime("%m/%d/%Y"), attribute_name: attribute_value, } login_as_staff(self.client) response = self.client.get("/api/billing", data, follow=True) self.assertEqual(response.status_code, 403, "regular user or staff doesn't have permission") staff_user = User.objects.get(username="******") staff_user.user_permissions.add( Permission.objects.get(codename="use_billing_api")) staff_user.save() response = self.client.get("/api/billing", data, follow=True) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data), results_number) date_format = ("%Y-%m-%dT%H:%M:%S.%f%z" if api_settings.DATETIME_FORMAT.lower() == ISO_8601 else api_settings.DATETIME_FORMAT) for billing_item in response.data: start = datetime.strptime(billing_item["start"], date_format) end = datetime.strptime(billing_item["end"], date_format) self.assertEqual(datetime.now().date(), start.date()) self.assertEqual(datetime.now().date(), end.date()) self.assertEqual(billing_item.get(result_attribute_name), attribute_value)
def weekend(self, item_id: int, item_type: ReservationItemType): start = datetime.now() end = start + timedelta(hours=1) until = datetime.now() + timedelta(weeks=9) data = self.get_outage_data(title='every weekend day outage', start=start, end=end, item_id=item_id, item_type=item_type, outage=True, frequency='DAILY_WEEKENDS', interval=1, until=until) login_as_staff(self.client) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEqual(response.status_code, 200) outages = ScheduledOutage.objects.filter( title='every weekend day outage', tool=tool) for outage in outages: # 0 is Monday, 5 & 6 are Saturday and Sunday self.assertGreaterEqual( outage.start.astimezone( timezone.get_current_timezone()).weekday(), 5)
def test_cancel_outage(self): # create outage start = datetime.now() end = start + timedelta(hours=1) data = self.get_outage_data(title="Outage", start=start, end=end, tool_name=tool.name) login_as_staff(self.client) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEquals(response.status_code, 200) outage = ScheduledOutage.objects.get(title="Outage") self.assertTrue(outage.id) # regular user should not be able to delete outage login_as_user(self.client) response = self.client.get(reverse('cancel_outage', kwargs={'outage_id': 999}), {}, follow=True) test_response_is_landing_page(self, response) self.assertTrue(ScheduledOutage.objects.get(pk=outage.id).id, outage.id) login_as_staff(self.client) # get should fail response = self.client.get(reverse('cancel_outage', kwargs={'outage_id': 999}), {}, follow=True) self.assertEquals(response.status_code, 405) # test wrong id response = self.client.post(reverse('cancel_outage', kwargs={'outage_id':999}), {}, follow=True) self.assertEquals(response.status_code, 404) response = self.client.post(reverse('cancel_outage', kwargs={'outage_id': outage.id}), {}, follow=True) self.assertEquals(response.status_code, 200) self.assertEquals(ScheduledOutage.objects.all().count(), 0)
def every_day_for_a_week(self, item_id: int, item_type: ReservationItemType): start = datetime.now() end = start + timedelta(hours=1) until = datetime.now() + timedelta(days=6) data = self.get_outage_data(title='every day outage week', start=start, end=end, item_id=item_id, item_type=item_type, outage=True, frequency='DAILY', interval=1, until=until) login_as_staff(self.client) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEqual(response.status_code, 200) outages = ScheduledOutage.objects.filter(title='every day outage week', tool=tool) self.assertEqual(len(outages), 7)
def every_week_for_a_year(self, item_id: int, item_type: ReservationItemType): start = (datetime.now() + timedelta(days=1)).replace(microsecond=0).replace(hour=7) end = start + timedelta(hours=1) until = datetime.now() + timedelta(days=365) data = self.get_outage_data(title='every day outage year', start=start, end=end, item_id=item_id, item_type=item_type, outage=True, frequency='WEEKLY', interval=1, until=until) login_as_staff(self.client) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEqual(response.status_code, 200) outages = ScheduledOutage.objects.filter( title='every day outage year').filter( **{f'{item_type.value}__id': item_id}) for outage in outages: good_start = outage.start.astimezone( timezone.get_current_timezone()) good_end = outage.end.astimezone(timezone.get_current_timezone()) self.assertEqual(good_start.weekday(), start.weekday()) self.assertEqual(good_end.weekday(), end.weekday()) self.assertEqual(good_start.time(), start.time()) self.assertEqual(good_end.time(), end.time())
def test_every_week_for_a_year(self): start = datetime.now().replace(microsecond=0) end = start + timedelta(hours=1) until = datetime.now() + timedelta(days=365) data = self.get_outage_data(title='every day outage year', start=start, end=end, tool_name=tool.name, outage=True, frequency='WEEKLY', interval=1, until=until) login_as_staff(self.client) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEqual(response.status_code, 200) outages = ScheduledOutage.objects.filter(title='every day outage year', tool=tool) for outage in outages: good_start = outage.start.astimezone( timezone.get_current_timezone()) good_end = outage.end.astimezone(timezone.get_current_timezone()) self.assertEqual(good_start.weekday(), start.weekday()) self.assertEqual(good_end.weekday(), end.weekday()) self.assertEqual(good_start.time(), start.time()) self.assertEqual(good_end.time(), end.time())
def test_area_access_page_by_staff(self): login_as_staff(self.client) response = self.client.post(reverse('area_access'), {}, follow=True) self.assertEqual(response.status_code, 405) # POST isn't accepted, only GET response = self.client.get(reverse('area_access'), {}, follow=True) self.assertTrue("area_access" in response.request['PATH_INFO']) self.assertEqual(response.status_code, 200)
def test_create_outage(self): start = datetime.now() end = start + timedelta(hours=1) data = self.get_outage_data(title="Outage", start=start, end=end, tool_name=tool.name) login_as_staff(self.client) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEquals(response.status_code, 200) self.assertEquals(ScheduledOutage.objects.all().count(), 1) self.assertTrue(ScheduledOutage.objects.get(title="Outage"))
def test_no_tool_name_404(self): start = datetime.now() end = start + timedelta(hours=1) until = datetime.now() + timedelta(days=5) data = self.get_outage_data(start=start, end=end, outage=True, frequency='DAILY', interval=1, until=until) login_as_staff(self.client) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEquals(response.status_code, 404)
def test_resize_outage(self): # create outage start = datetime.now() end = start + timedelta(hours=1) data = self.get_outage_data(title="Outage", start=start, end=end, tool_name=tool.name) login_as_staff(self.client) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEquals(response.status_code, 200) outage = ScheduledOutage.objects.get(title="Outage") self.assertTrue(outage.id) # regular user should not be able to resize outage login_as_user(self.client) response = self.client.get(reverse('resize_outage'), {}, follow=True) test_response_is_landing_page(self, response) self.assertTrue(ScheduledOutage.objects.get(pk=outage.id).id, outage.id) # back to staff mode login_as_staff(self.client) # test wrong delta response = self.client.post(reverse('resize_outage'), {'delta':'asd', 'id': outage.id}, follow=True) self.assertEquals(response.status_code, 400) self.assertEquals(response.content.decode(), "Invalid delta") # test no outage id response = self.client.post(reverse('resize_outage'), {'delta': 10}, follow=True) self.assertEquals(response.status_code, 404) self.assertEquals(response.content.decode(), "The outage that you wish to modify doesn't exist!") # test resize to less than original time response = self.client.post(reverse('resize_outage'), {'delta': -60, 'id': outage.id}, follow=True) self.assertEquals(response.status_code, 400) self.assertTrue('Outage start time' in response.content.decode()) self.assertTrue('must be before the end time' in response.content.decode()) # create a reservation and try to resize outage to overlap reservation start_reservation = end + timedelta(hours=1) end_reservation = start_reservation + timedelta(hours=1) Reservation.objects.create(user=owner, creator=owner, tool=tool, start=start_reservation, end=end_reservation, short_notice=False) response = self.client.post(reverse('resize_outage'), {'delta': 61, 'id': outage.id}, follow=True) self.assertEquals(response.status_code, 400) self.assertEquals(response.content.decode(), "Your scheduled outage coincides with a reservation that already exists. Please choose a different time.") # test reduce outage time by 10 min response = self.client.post(reverse('resize_outage'), {'delta': -10, 'id':outage.id}, follow=True) self.assertEquals(response.status_code, 200) self.assertEquals(ScheduledOutage.objects.get(pk=outage.id).end, outage.end - timedelta(minutes=10)) # test increase outage time by 10 min outage = ScheduledOutage.objects.get(pk=outage.id) response = self.client.post(reverse('resize_outage'), {'delta': 10, 'id': outage.id}, follow=True) self.assertEquals(response.status_code, 200) self.assertEquals(ScheduledOutage.objects.get(pk=outage.id).end, outage.end + timedelta(minutes=10))
def test_create_area_outage(self): start = datetime.now() end = start + timedelta(hours=1) data = self.get_outage_data(title="Outage", start=start, end=end, item_id=area.id, item_type=ReservationItemType.AREA) login_as_staff(self.client) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEqual(response.status_code, 200) self.assertEqual(ScheduledOutage.objects.all().count(), 1) self.assertTrue(ScheduledOutage.objects.get(title="Outage"))
def test_outage_policy_problems(self): start = datetime.now() end = start - timedelta(hours=1) data = self.get_outage_data(start=start, end=end, tool_name=tool.name) # regular user should not be able to create outage login_as_user(self.client) response = self.client.get(reverse('create_outage'), {}, follow=True) test_response_is_landing_page(self, response) # back to staff mode login_as_staff(self.client) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEquals(response.status_code, 400) self.assertEquals(response.content.decode(), "The request parameters have an end time that precedes the start time.") # fix time end = (start + timedelta(hours=1)) # Create a reservation and try to schedule an outage at the same time Reservation.objects.create(user=owner, creator=owner, tool=tool, start=start, end=end, short_notice=False) data = self.get_outage_data(start=start, end=end, tool_name=tool.name) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEquals(response.status_code, 400) self.assertEquals(response.content.decode(), "Your scheduled outage coincides with a reservation that already exists. Please choose a different time.") # try to schedule an outage that starts before but ends slightly after the reservation starts data = self.get_outage_data(start=start-timedelta(hours=1), end=end-timedelta(minutes=59), tool_name=tool.name) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEquals(response.status_code, 400) self.assertEquals(response.content.decode(), "Your scheduled outage coincides with a reservation that already exists. Please choose a different time.") # try to schedule an outage that starts slightly before the reservation ends data = self.get_outage_data(start=start + timedelta(minutes=59), end=end + timedelta(hours=1), tool_name=tool.name) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEquals(response.status_code, 400) self.assertEquals(response.content.decode(), "Your scheduled outage coincides with a reservation that already exists. Please choose a different time.") # no title start = start + timedelta(hours=2) end = end + timedelta(hours=2) data = self.get_outage_data(start=start, end=end, tool_name=tool.name) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEquals(response.status_code, 200) # response code valid but form is sent back. let's make sure the outage was indeed NOT created self.assertEquals(ScheduledOutage.objects.all().count(), 0)
def outage_details(self, item_id: int, item_type: ReservationItemType): # create outage start = datetime.now() end = start + timedelta(hours=1) data = self.get_outage_data(title="Outage", start=start, end=end, item_id=item_id, item_type=item_type) login_as_staff(self.client) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEqual(response.status_code, 200) outage = ScheduledOutage.objects.get(title="Outage") self.assertTrue(outage.id) # anybody that is logged in can see outage details login_as_user(self.client) # post should fail response = self.client.post(reverse('outage_details', kwargs={'outage_id': 999}), {}, follow=True) self.assertEqual(response.status_code, 405) # test wrong id response = self.client.get(reverse('outage_details', kwargs={'outage_id': 999}), {}, follow=True) self.assertEqual(response.status_code, 404) response = self.client.get(reverse('outage_details', kwargs={'outage_id': outage.id}), {}, follow=True) self.assertEqual(response.status_code, 200) outage.delete()
def test_new_area_record_get(self): user = login_as_user(self.client) response = self.client.get(reverse('new_area_access_record'), data={'customer': user.id}, follow=True) test_response_is_landing_page(self, response) staff = login_as_staff(self.client) user.is_active = False user.save() response = self.client.get(reverse('new_area_access_record'), data={'customer': user.id}, follow=True) self.assertEqual(response.status_code, 200) self.assertTrue("Oops! Something went wrong" in str(response.content)) self.assertTrue("is inactive" in str(response.content)) # user is inactive user.is_active = True user.save() response = self.client.get(reverse('new_area_access_record'), data={'customer': user.id}, follow=True) self.assertEqual(response.status_code, 200) self.assertTrue("Oops! Something went wrong" in str(response.content)) self.assertTrue( "does not have any active projects to bill area access" in str(response.content)) # user does not have active projects user.projects.add( Project.objects.create( name="Project1", account=Account.objects.create(name="Account1"))) user.save() response = self.client.get(reverse('new_area_access_record'), data={'customer': user.id}, follow=True) self.assertEqual(response.status_code, 200) self.assertTrue("Oops! Something went wrong" in str(response.content)) self.assertTrue("does not have access to any billable NanoFab areas" in str(response.content)) # user does not have access user.physical_access_levels.add( PhysicalAccessLevel.objects.create( name="cleanroom access", area=area, schedule=PhysicalAccessLevel.Schedule.ALWAYS)) user.save() response = self.client.get(reverse('new_area_access_record'), data={'customer': user.id}, follow=True) self.assertEqual(response.status_code, 200) self.assertFalse("Oops! Something went wrong" in str(response.content))
def move_outage(self, item_id: int, item_type: ReservationItemType): # create outage start = datetime.now() end = start + timedelta(hours=1) data = self.get_outage_data(title="Outage", start=start, end=end, item_id=item_id, item_type=item_type) login_as_staff(self.client) response = self.client.post(reverse('create_outage'), data, follow=True) self.assertEqual(response.status_code, 200) outage = ScheduledOutage.objects.get(title="Outage") self.assertTrue(outage.id) # regular user should not be able to move outage login_as_user(self.client) response = self.client.get(reverse('move_outage'), {}, follow=True) test_response_is_landing_page(self, response) self.assertTrue( ScheduledOutage.objects.get(pk=outage.id).id, outage.id) # back to staff mode login_as_staff(self.client) # test wrong delta response = self.client.post(reverse('move_outage'), { 'delta': 'asd', 'id': outage.id }, follow=True) self.assertEqual(response.status_code, 400) self.assertEqual(response.content.decode(), "Invalid delta") # test no outage id response = self.client.post(reverse('move_outage'), {'delta': 10}, follow=True) self.assertEqual(response.status_code, 404) self.assertEqual(response.content.decode(), "The outage that you wish to modify doesn't exist!") # create a reservation and try to move outage to overlap reservation start_reservation = end + timedelta(hours=1) end_reservation = start_reservation + timedelta(hours=1) if item_type == ReservationItemType.TOOL: Reservation.objects.create(user=owner, creator=owner, tool=tool, start=start_reservation, end=end_reservation, short_notice=False) elif item_type == ReservationItemType.AREA: Reservation.objects.create(user=owner, creator=owner, area=area, start=start_reservation, end=end_reservation, short_notice=False) response = self.client.post(reverse('move_outage'), { 'delta': 61, 'id': outage.id }, follow=True) self.assertEqual(response.status_code, 400) self.assertEqual( response.content.decode(), "Your scheduled outage coincides with a reservation that already exists. Please choose a different time." ) # test move outage 10 min earlier response = self.client.post(reverse('move_outage'), { 'delta': -10, 'id': outage.id }, follow=True) self.assertEqual(response.status_code, 200) self.assertEqual( ScheduledOutage.objects.get(pk=outage.id).end, outage.end - timedelta(minutes=10)) self.assertEqual( ScheduledOutage.objects.get(pk=outage.id).start, outage.start - timedelta(minutes=10)) # test move outage 10 min later outage = ScheduledOutage.objects.get(pk=outage.id) response = self.client.post(reverse('move_outage'), { 'delta': 10, 'id': outage.id }, follow=True) self.assertEqual(response.status_code, 200) self.assertEqual( ScheduledOutage.objects.get(pk=outage.id).end, outage.end + timedelta(minutes=10)) self.assertEqual( ScheduledOutage.objects.get(pk=outage.id).start, outage.start + timedelta(minutes=10)) outage.delete()
def test_staff_login_to_area(self): staff = login_as_staff(self.client) tablet_user = login_as_user_with_permissions(self.client, ['add_areaaccessrecord']) response = self.client.post(reverse('login_to_area', kwargs={'door_id': door.id}), data={'badge_number': staff.badge_number}, follow=True) self.assertEqual(response.status_code, 200) self.assertTrue("You are not a member of any active projects" in str( response.content)) # user does not have active projects staff.projects.add( Project.objects.create( name="Maintenance", account=Account.objects.create(name="Maintenance Account"))) staff.save() response = self.client.post(reverse('login_to_area', kwargs={'door_id': door.id}), data={'badge_number': staff.badge_number}, follow=True) self.assertTrue("Physical access denied" in str(response.content)) # create an area an allow staff access without granting it to them access = PhysicalAccessLevel.objects.create( allow_staff_access=True, name="cleanroom access", area=door.area, schedule=PhysicalAccessLevel.Schedule.ALWAYS) response = self.client.post(reverse('login_to_area', kwargs={'door_id': door.id}), data={'badge_number': staff.badge_number}, follow=True) self.assertEqual(response.status_code, 200) self.assertTrue( f"login_to_area/{door.id}" in response.request['PATH_INFO']) self.assertTrue("You're logged in to the " in str(response.content)) # try to login again response = self.client.post(reverse('login_to_area', kwargs={'door_id': door.id}), data={'badge_number': staff.badge_number}, follow=True) self.assertTrue("already logged into" in str(response.content)) # user already logged in response = self.client.post(reverse('logout_of_area', kwargs={'door_id': door.id}), data={'badge_number': staff.badge_number}, follow=True) self.assertEqual(response.status_code, 200) test_response_is_landing_page( self, response) # tablet user does not have permission to logout tablet_user.user_permissions.add( Permission.objects.get(codename='change_areaaccessrecord')) tablet_user.save() response = self.client.post(reverse('logout_of_area', kwargs={'door_id': door.id}), data={'badge_number': staff.badge_number}, follow=True) self.assertTrue("now logged out of the" in str(response.content)) # now undo access and try explicitly access.allow_staff_access = False access.save() response = self.client.post(reverse('login_to_area', kwargs={'door_id': door.id}), data={'badge_number': staff.badge_number}, follow=True) self.assertTrue("Physical access denied" in str(response.content)) # also work by explicitly giving access to staff staff.physical_access_levels.add(access) staff.save() response = self.client.post(reverse('login_to_area', kwargs={'door_id': door.id}), data={'badge_number': staff.badge_number}, follow=True) self.assertEqual(response.status_code, 200) self.assertTrue( f"login_to_area/{door.id}" in response.request['PATH_INFO']) self.assertTrue("You're logged in to the " in str(response.content)) self.assertTrue( AreaAccessRecord.objects.filter( area=door.area, customer=User.objects.get( badge_number=staff.badge_number)).exists())
def test_staff_login_to_area(self): staff = login_as_staff(self.client) self.client.post(reverse('self_log_in'), data={'area': area.id}, follow=True) self.assertFalse( AreaAccessRecord.objects.filter(area=area, end__isnull=True).exists()) # user does not have active projects project = Project.objects.create( name="Maintenance", account=Account.objects.create(name="Maintenance Account")) staff.projects.add(project) staff.save() self.client.post(reverse('self_log_in'), data={ 'area': area.id, 'project': project.id }, follow=True) self.assertFalse( AreaAccessRecord.objects.filter(area=area, end__isnull=True).exists()) Customization.objects.update_or_create(name='self_log_in', defaults={'value': 'enabled'}) self.client.post(reverse('self_log_in'), data={ 'area': area.id, 'project': project.id }, follow=True) self.assertFalse( AreaAccessRecord.objects.filter(area=area, end__isnull=True).exists()) # create an area an allow staff access without granting it to them access = PhysicalAccessLevel.objects.create( allow_staff_access=True, name="cleanroom access", area=area, schedule=PhysicalAccessLevel.Schedule.ALWAYS) self.client.post(reverse('self_log_in'), data={ 'area': area.id, 'project': project.id }, follow=True) record = AreaAccessRecord.objects.filter(area=area, customer=staff) self.assertTrue(record.exists()) # try to login again self.client.post(reverse('self_log_in'), data={ 'area': area.id, 'project': project.id }, follow=True) # not successful. still only one record self.assertEqual( AreaAccessRecord.objects.filter(area=area, customer=staff, end__isnull=True).count(), 1) self.assertEqual( AreaAccessRecord.objects.filter(area=area, customer=staff, end__isnull=True)[0], record[0]) self.assertTrue(record[0].end is None) # logout Customization.objects.update_or_create(name='self_log_out', defaults={'value': 'enabled'}) self.client.get(reverse('self_log_out', kwargs={'user_id': staff.id}), follow=True) self.assertTrue(record[0].end is not None) # now undo access and try explicitly access.allow_staff_access = False access.save() self.client.post(reverse('self_log_in'), data={ 'area': area.id, 'project': project.id }, follow=True) self.assertFalse( AreaAccessRecord.objects.filter(area=area, customer=staff, end__isnull=True).exists()) # also work by explicitly giving access to staff staff.physical_access_levels.add(access) staff.save() self.client.post(reverse('self_log_in'), data={ 'area': area.id, 'project': project.id }, follow=True) self.assertTrue( AreaAccessRecord.objects.filter(area=area, customer=staff, end__isnull=True).exists())