def testListFlowLogsRaisesIfFlowWasNotCreatedBySameUser(self): flow_id = flow_test_lib.StartFlow(file_finder.FileFinder, self.client_id, creator=self.another_username) router = self._CreateRouter( list_flow_logs=rr.RobotRouterListFlowLogsParams(enabled=True)) with self.assertRaises(access_control.UnauthorizedAccess): router.ListFlowLogs(api_flow.ApiListFlowLogsArgs( client_id=self.client_id, flow_id=flow_id), context=self.context)
def testListFlowsFromClientRef(self): client_id = self.SetupClient(0) flow_id = flow_test_lib.StartFlow(processes.ListProcesses, client_id=client_id) flows = list(self.api.Client(client_id=client_id).ListFlows()) self.assertLen(flows, 1) self.assertEqual(flows[0].client_id, client_id) self.assertEqual(flows[0].flow_id, flow_id) self.assertEqual(flows[0].data.flow_id, flow_id)
def testGetFlowRaisesIfFlowWasNotCreatedBySameUser(self): flow_id = flow_test_lib.StartFlow(file_finder.FileFinder, self.client_id, creator=self.another_username) router = self._CreateRouter(get_flow=rr.RobotRouterGetFlowParams( enabled=True)) with self.assertRaises(access_control.UnauthorizedAccess): router.GetFlow(api_flow.ApiGetFlowArgs(client_id=self.client_id, flow_id=flow_id), token=self.token)
def testGetOsqueryResultsRefusesAccessIfPartOfHuntButWrongFlow(self): client_id = self.SetupClient(0) hunt_id = self.CreateHunt() flow_id = flow_test_lib.StartFlow(flow_test_lib.DummyFlow, client_id=client_id, parent_hunt_id=hunt_id) args = api_osquery.ApiGetOsqueryResultsArgs(client_id=client_id, flow_id=flow_id) with self.assertRaises(ValueError): self.router.GetOsqueryResults(args=args, context=self.context)
def testPaginationSize(self): flow_id = flow_test_lib.StartFlow( filesystem.ListDirectory, creator=self.test_username, client_id=self.client_id, pathspec=rdf_paths.PathSpec.OS(path="/path")) with flow_test_lib.FlowResultMetadataOverride( filesystem.ListDirectory, rdf_flow_objects.FlowResultMetadata( is_metadata_set=True, num_results_per_type_tag=[ rdf_flow_objects.FlowResultCount( type=rdf_client_fs.StatEntry.__name__, count=1) ])): self.Open(f"/v2/clients/{self.client_id}") self.WaitUntil(self.IsElementPresent, "css=.flow-title:contains('ListDirectory')") flow_test_lib.AddResultsToFlow(self.client_id, flow_id, [ rdf_client_fs.StatEntry(pathspec=rdf_paths.PathSpec.OS( path=f"file{i}")) for i in range(15) ]) self.Click("css=result-accordion .title:contains('/path')") for i in range(10): self.WaitUntil(self.IsElementPresent, f"css=td:contains('file{i}')") self.assertEqual(self.GetCssCount("css=td.path:contains('file')"), 10) # Select one paginator updates the other paginator as well as the # displayed rows. self.MatSelect("css=.bottom-paginator mat-select", "50") self.WaitUntilContains("50", self.GetText, "css=.top-paginator mat-select") self.WaitUntilContains("50", self.GetText, "css=.bottom-paginator mat-select") for i in range(15): self.WaitUntil(self.IsElementPresent, f"css=td:contains('file{i}')") self.assertEqual(self.GetCssCount("css=td.path:contains('file')"), 15) self.MatSelect("css=.top-paginator mat-select", "10") self.WaitUntilContains("10", self.GetText, "css=.top-paginator mat-select") self.WaitUntilContains("10", self.GetText, "css=.bottom-paginator mat-select") for i in range(10): self.WaitUntil(self.IsElementPresent, f"css=td:contains('file{i}')") self.assertEqual(self.GetCssCount("css=td.path:contains('file')"), 10)
def testGetCollectedTimelineRefusesAccessIfPartOfHuntButWrongFlow(self): client_id = self.SetupClient(0) hunt_id = self.CreateHunt() flow_id = flow_test_lib.StartFlow(flow_test_lib.DummyFlow, client_id=client_id, parent_hunt_id=hunt_id) args = api_timeline.ApiGetCollectedTimelineArgs(client_id=client_id, flow_id=flow_id) with self.assertRaises(ValueError): self.router.GetCollectedTimeline(args=args, context=self.context)
def testGetCollectedTimelineGrantsAccessIfPartOfHunt(self): client_id = self.SetupClient(0) hunt_id = self.CreateHunt() flow_id = flow_test_lib.StartFlow(timeline.TimelineFlow, client_id=client_id, parent_hunt_id=hunt_id) args = api_timeline.ApiGetCollectedTimelineArgs(client_id=client_id, flow_id=flow_id) self.CheckMethodIsNotAccessChecked(self.router.GetCollectedTimeline, args=args)
def testWaitUntilDoneRasiesWhenItTimesOut(self): client_urn = self.SetupClient(0) flow_id = flow_test_lib.StartFlow(processes.ListProcesses, client_id=client_urn) result_flow = self.api.Client( client_id=client_urn.Basename()).Flow(flow_id).Get() with self.assertRaises(grr_api_errors.PollTimeoutError): with utils.Stubber(grr_api_utils, "DEFAULT_POLL_TIMEOUT", 1): result_flow.WaitUntilDone()
def testGetOsqueryResultsGrantsAccessIfPartOfHunt(self): client_id = self.SetupClient(0) hunt_id = self.CreateHunt() flow_id = flow_test_lib.StartFlow(osquery.OsqueryFlow, client_id=client_id, parent_hunt_id=hunt_id) args = api_osquery.ApiGetOsqueryResultsArgs(client_id=client_id, flow_id=flow_id) self.CheckMethodIsNotAccessChecked(self.router.GetOsqueryResults, args=args)
def GenerateNotifications(cls, client_id, token): """Generates fake notifications of different notification types.""" session_id = flow_test_lib.StartFlow(discovery.Interrogate, client_id=client_id, creator=token.username) notification.Notify( token.username, rdf_objects.UserNotification.Type.TYPE_CLIENT_INTERROGATED, "Fake discovery message", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.CLIENT, client=rdf_objects.ClientReference( client_id=client_id.Basename()))) # ViewObject: VirtualFileSystem notification.Notify( token.username, rdf_objects.UserNotification.Type.TYPE_VFS_FILE_COLLECTED, "File fetch completed", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.VFS_FILE, vfs_file=rdf_objects.VfsFileReference( client_id=client_id.Basename(), path_type=rdf_objects.PathInfo.PathType.OS, path_components=["proc", "10", "exe"]))) gui_test_lib.CreateFileVersion(client_id, "fs/os/proc/10/exe", b"", timestamp=gui_test_lib.TIME_0, token=token) # ViewObject: Flow notification.Notify( token.username, rdf_objects.UserNotification.Type.TYPE_FLOW_RUN_COMPLETED, "Fake view flow message", rdf_objects.ObjectReference( reference_type=rdf_objects.ObjectReference.Type.FLOW, flow=rdf_objects.FlowReference(client_id=client_id.Basename(), flow_id=session_id))) # FlowError if data_store.RelationalDBEnabled(): flow_base.TerminateFlow(client_id.Basename(), session_id, "Fake flow error") else: with aff4.FACTORY.Open(client_id.Add("flows").Add(session_id), mode="rw", token=token) as flow_obj: flow_obj.GetRunner().Error("Fake flow error") return session_id
def testLogsCanBeOpenedByClickingOnLogsTab(self): flow_test_lib.StartFlow(gui_test_lib.FlowWithOneLogStatement, self.client_id, creator=self.token.username) self.Open("/#/clients/%s" % self.client_id) self.Click("css=a[grrtarget='client.flows']") self.Click("css=td:contains('FlowWithOneLogStatement')") self.Click("css=li[heading=Log]") self.WaitUntil(self.IsTextPresent, "I do log.")
def testListFlowsFromClientObject(self): client_urn = self.SetupClient(0) flow_id = flow_test_lib.StartFlow(processes.ListProcesses, client_id=client_urn) client = self.api.Client(client_id=client_urn.Basename()).Get() flows = list(client.ListFlows()) self.assertLen(flows, 1) self.assertEqual(flows[0].client_id, client_urn.Basename()) self.assertEqual(flows[0].flow_id, flow_id) self.assertEqual(flows[0].data.flow_id, flow_id)
def testLogTimestampsArePresentedInUTC(self): with test_lib.FakeTime(42): flow_test_lib.StartFlow(gui_test_lib.FlowWithOneLogStatement, self.client_id, creator=self.test_username) self.Open("/#/clients/%s" % self.client_id) self.Click("css=a[grrtarget='client.flows']") self.Click("css=td:contains('FlowWithOneLogStatement')") self.Click("css=li[heading=Log]") self.WaitUntil(self.IsTextPresent, "1970-01-01 00:00:42 UTC")
def testResultsAreDisplayedInResultsTab(self): flow_test_lib.StartFlow(gui_test_lib.FlowWithOneStatEntryResult, self.client_id, creator=self.test_username) self.Open("/#/clients/%s" % self.client_id) self.Click("css=a[grrtarget='client.flows']") self.Click("css=td:contains('FlowWithOneStatEntryResult')") self.Click("css=li[heading=Results]") self.WaitUntil(self.IsTextPresent, "aff4:/%s/fs/os/some/unique/path" % self.client_id)
def testDisplaysDownloadButtonAndArgs(self): flow_args = rdf_read_low_level.ReadLowLevelArgs( path="/path", length="789", offset="987") flow_id = flow_test_lib.StartFlow( read_low_level.ReadLowLevel, creator=self.test_username, client_id=self.client_id, flow_args=flow_args) print("flow_id", flow_id) self.Open(f"/v2/clients/{self.client_id}") self.WaitUntil(self.IsElementPresent, f"css=.flow-id span:contains('{flow_id}')") self.ScrollToBottom() self.WaitUntil(self.IsElementPresent, "css=result-accordion .title:contains('/path')") self.WaitUntil(self.IsElementPresent, "css=result-accordion .title:contains('789')") self.WaitUntil(self.IsElementPresent, "css=result-accordion .title:contains('987')") self.WaitUntilNot(self.IsElementPresent, "css=a[mat-stroked-button]:contains('Download')") flow_test_lib.MarkFlowAsFinished(client_id=self.client_id, flow_id=flow_id) with flow_test_lib.FlowResultMetadataOverride( read_low_level.ReadLowLevel, rdf_flow_objects.FlowResultMetadata( is_metadata_set=True, num_results_per_type_tag=[ rdf_flow_objects.FlowResultCount( type=rdf_read_low_level.ReadLowLevelFlowResult.__name__, count=1) ])): self.WaitUntil(self.IsElementPresent, "css=a[mat-stroked-button]:contains('Download')") self.WaitUntil( self.IsElementPresent, f"css=a[href='/api/v2/clients/{self.client_id}/vfs-blob/temp/" f"{self.client_id}_{flow_id}_path']") self.Click("css=result-accordion .title:contains('/path')") self.WaitUntil(self.IsElementPresent, "css=result-accordion:contains('Path: /path')") self.WaitUntil(self.IsElementPresent, "css=result-accordion:contains('Length: 789')") self.WaitUntil(self.IsElementPresent, "css=result-accordion:contains('Offset: 987')")
def testDisplaysMultipleResultsForSingleBrowser(self): flow_args = webhistory.CollectBrowserHistoryArgs( browsers=[webhistory.CollectBrowserHistoryArgs.Browser.CHROME]) flow_id = flow_test_lib.StartFlow(webhistory.CollectBrowserHistory, creator=self.test_username, client_id=self.client_id, flow_args=flow_args) flow_test_lib.AddResultsToFlow( self.client_id, flow_id, [_GenResults(webhistory.Browser.CHROME, i) for i in range(200)], tag="CHROME") with flow_test_lib.FlowProgressOverride( webhistory.CollectBrowserHistory, webhistory.CollectBrowserHistoryProgress(browsers=[ webhistory.BrowserProgress( browser=webhistory.Browser.CHROME, status=webhistory.BrowserProgress.Status.SUCCESS, num_collected_files=200, ), ])): self.Open(f"/v2/clients/{self.client_id}") # Expand the flow. self.Click("css=.flow-title:contains('Browser History')") # Expand the browser. self.Click("css=div.title:contains('Chrome')") # Check that only first 100 results are visible. First row is the table # header, so we start with 1. self.WaitUntil(self.IsElementPresent, "css=.results tr:nth(1)") self.WaitUntilNot( self.IsElementPresent, "css=.results tr:nth(101):contains('/home/foo/chrome-100')") # Check that clicking Load More loads the rest. The button can be hidden # under the approval bottom sheet, so for now we workaround by clicking it # programmatically and not with a mouse event. self.WaitUntil(self.IsElementPresent, "css=button:contains('Load More')") self.driver.execute_script( """$("button:contains('Load More')").click();""") self.WaitUntil( self.IsElementPresent, "css=.results tr:nth(200):contains('/home/foo/chrome-199')") self.WaitUntilNot(self.IsElementPresent, "css=.results tr:nth(201)") # Check that the "load more" button disappears when everything is loaded. self.WaitUntilNot(self.IsElementPresent, "css=button:contains('Load More')")
def testListErrors(self): hunt_id = self.StartHunt() client_ids = self.SetupClients(2) with test_lib.FakeTime(52): flow_id = flow_test_lib.StartFlow( flows_processes.ListProcesses, client_id=client_ids[0], parent=flow.FlowParent.FromHuntID(hunt_id)) flow_obj = data_store.REL_DB.ReadFlowObject(client_ids[0], flow_id) flow_obj.flow_state = flow_obj.FlowState.ERROR flow_obj.error_message = "Error foo." data_store.REL_DB.UpdateFlow(client_ids[0], flow_id, flow_obj=flow_obj) with test_lib.FakeTime(55): flow_id = flow_test_lib.StartFlow( flows_processes.ListProcesses, client_id=client_ids[1], parent=flow.FlowParent.FromHuntID(hunt_id)) flow_obj = data_store.REL_DB.ReadFlowObject(client_ids[1], flow_id) flow_obj.flow_state = flow_obj.FlowState.ERROR flow_obj.error_message = "Error bar." flow_obj.backtrace = "<some backtrace>" data_store.REL_DB.UpdateFlow(client_ids[1], flow_id, flow_obj=flow_obj) errors = list(self.api.Hunt(hunt_id).ListErrors()) self.assertLen(errors, 2) self.assertEqual(errors[0].log_message, "Error foo.") self.assertEqual(errors[0].client.client_id, client_ids[0]) self.assertEqual(errors[0].backtrace, "") self.assertEqual(errors[1].log_message, "Error bar.") self.assertEqual(errors[1].client.client_id, client_ids[1]) self.assertEqual(errors[1].backtrace, "<some backtrace>")
def testFlowReprContainsMetadata(self): client_id = self.SetupClient(0) flow_id = flow_test_lib.StartFlow(processes.ListProcesses, client_id=client_id) flow_ref = self.api.Client(client_id=client_id).Flow(flow_id) self.assertIn(client_id, repr(flow_ref)) self.assertIn(flow_id, repr(flow_ref)) flow = flow_ref.Get() self.assertIn(client_id, repr(flow)) self.assertIn(flow_id, repr(flow)) self.assertIn("ListProcesses", repr(flow))
def testPassesNoConditionsToClientFileFinderWhenNoConditionsSpecified(self): flow_id = flow_test_lib.StartFlow( file.CollectMultipleFiles, client_id=self.client_id, path_expressions=["/some/path"]) children = data_store.REL_DB.ReadChildFlowObjects(self.client_id, flow_id) self.assertLen(children, 1) child = children[0] self.assertEqual(child.flow_class_name, file_finder.ClientFileFinder.__name__) self.assertEmpty(child.args.conditions)
def testEmptyTableIsDisplayedInResultsWhenNoResults(self): flow_test_lib.StartFlow( gui_test_lib.FlowWithOneStatEntryResult, self.client_id, creator=self.token.username) self.Open("/#/clients/%s" % self.client_id) self.Click("css=a[grrtarget='client.flows']") self.Click("css=td:contains('FlowWithOneStatEntryResult')") self.Click("css=li[heading=Results]") self.WaitUntil(self.IsElementPresent, "css=#main_bottomPane table thead " "th:contains('Value')")
def testFlowError(self): flow_args = rdf_file_finder.CollectFilesByKnownPathArgs( paths=["/file0", "/file1"]) flow_id = flow_test_lib.StartFlow(file.CollectFilesByKnownPath, creator=self.test_username, client_id=self.client_id, flow_args=flow_args) flow_test_lib.MarkFlowAsFailed(self.client_id, flow_id) self.Open(f"/v2/clients/{self.client_id}") self.WaitUntil(self.IsElementPresent, "css=flow-details mat-icon.error")
def testShowsDownloadButtonOnFlowCompletion(self): flow_args = webhistory.CollectBrowserHistoryArgs( browsers=[webhistory.CollectBrowserHistoryArgs.Browser.CHROME]) flow_id = flow_test_lib.StartFlow(webhistory.CollectBrowserHistory, creator=self.test_username, client_id=self.client_id, flow_args=flow_args) with flow_test_lib.FlowProgressOverride( webhistory.CollectBrowserHistory, webhistory.CollectBrowserHistoryProgress(browsers=[ webhistory.BrowserProgress( browser=webhistory.Browser.CHROME, status=webhistory.BrowserProgress.Status.IN_PROGRESS, num_collected_files=0, ), ])): self.Open(f"/v2/clients/{self.client_id}") # Make sure that the flow panel is already displayed... self.WaitUntil(self.IsElementPresent, "css=.flow-title:contains('Browser History')") # ...and then check for the presence of the 'Download all' button. self.WaitUntilNot( self.IsElementPresent, "css=a[mat-stroked-button]:contains('Download all')") flow_test_lib.MarkFlowAsFinished(self.client_id, flow_id) with flow_test_lib.FlowProgressOverride( webhistory.CollectBrowserHistory, webhistory.CollectBrowserHistoryProgress(browsers=[ webhistory.BrowserProgress( browser=webhistory.Browser.CHROME, status=webhistory.BrowserProgress.Status.IN_PROGRESS, num_collected_files=1, ), ])): with flow_test_lib.FlowResultMetadataOverride( webhistory.CollectBrowserHistory, rdf_flow_objects.FlowResultMetadata( is_metadata_set=True, num_results_per_type_tag=[ rdf_flow_objects.FlowResultCount( type=webhistory.CollectBrowserHistoryResult. __name__, count=1) ])): # The flow details view should get updated automatically. self.WaitUntil( self.IsElementPresent, "css=a[mat-stroked-button]:contains('Download')")
def testIllegalGlob(self): """Test that illegal globs raise.""" paths = ["Test/%%Weird_illegal_attribute%%"] # Run the flow - we expect an AttributeError error to be raised from the # flow since Weird_illegal_attribute is not a valid client attribute. error_cls = artifact_utils.KbInterpolationUnknownAttributesError with self.assertRaises(error_cls) as context: flow_test_lib.StartFlow(filesystem.Glob, paths=paths, client_id=self.client_id) self.assertEqual(context.exception.attrs, ["weird_illegal_attribute"])
def testFlowListGetsUpdatedWithNewFlows(self): flow_1 = flow_test_lib.StartFlow(gui_test_lib.RecursiveTestFlow, self.client_id, creator=self.test_username) self.Open("/#/clients/%s" % self.client_id) # Ensure auto-refresh updates happen every second. self.GetJavaScriptValue( "grrUi.flow.flowsListDirective.setAutoRefreshInterval(1000);") # Go to the flows page without refreshing the page, so that # AUTO_REFRESH_INTERVAL_MS setting is not reset. self.Click("css=a[grrtarget='client.flows']") # Check that the flow list is correctly loaded. self.WaitUntil(self.IsElementPresent, "css=tr:contains('%s')" % flow_1) flow_2 = flow_test_lib.StartFlow(gui_test_lib.FlowWithOneLogStatement, self.client_id, creator=self.test_username) # Check that the flow we started in the background appears in the list. self.WaitUntil(self.IsElementPresent, "css=tr:contains('%s')" % flow_2)
def Run(self): acl_test_lib.CreateUser(self.token.username) with test_lib.FakeTime(42): client_id = self.SetupClient(0) with test_lib.FakeTime(43): flow_id_1 = flow_test_lib.StartFlow( discovery.Interrogate, client_id, creator=self.token.username) with test_lib.FakeTime(44): flow_id_2 = flow_test_lib.StartFlow( processes.ListProcesses, client_id, creator=self.token.username) replace = api_regression_test_lib.GetFlowTestReplaceDict( client_id, flow_id_1, "F:ABCDEF10") replace.update( api_regression_test_lib.GetFlowTestReplaceDict(client_id, flow_id_2, "F:ABCDEF11")) self.Check( "ListFlows", args=flow_plugin.ApiListFlowsArgs(client_id=client_id), replace=replace)
def testApprovalIndicatesThatHuntWasCopiedFromFlow(self): email_descriptor = rdf_output_plugin.OutputPluginDescriptor( plugin_name=compatibility.GetName(email_plugin.EmailOutputPlugin), plugin_args=email_plugin.EmailOutputPluginArgs( email_address="test@localhost", emails_limit=42)) args = flows_processes.ListProcessesArgs( filename_regex="test[a-z]*", fetch_binaries=True) flow_test_lib.StartFlow( flows_processes.ListProcesses, flow_args=args, client_id=self.client_id, output_plugins=[email_descriptor]) self.Open("/#/clients/%s" % self.client_id) self.Click("css=a[grrtarget='client.flows']") self.Click("css=td:contains('ListProcesses')") # Open the wizard. self.Click("css=button[name=create_hunt]") # Go to the hunt parameters page. self.Click("css=grr-new-hunt-wizard-form button.Next") # Go to the output plugins page. self.Click("css=grr-new-hunt-wizard-form button.Next") # Go to the rules page. self.Click("css=grr-new-hunt-wizard-form button.Next") # Go to the review page. self.Click("css=grr-new-hunt-wizard-form button.Next") # Create the hunt. self.Click("css=button:contains('Create Hunt')") self.Click("css=button:contains('Done')") # Request an approval. hunts = data_store.REL_DB.ListHuntObjects(offset=0, count=1) h = hunts[0] approval_id = self.RequestHuntApproval( h.hunt_id, requestor=self.token.username, reason="reason", approver=self.token.username) # Open the approval page. self.Open("/#/users/%s/approvals/hunt/%s/%s" % (self.token.username, h.hunt_id, approval_id)) self.WaitUntil(self.IsElementPresent, "css=div.panel-body:contains('This hunt was created from')")
def testDisplaysArgumentsPopup(self): flow_test_lib.StartFlow(filesystem.ListDirectory, creator=self.test_username, client_id=self.client_id, pathspec=rdf_paths.PathSpec.OS(path="/path")) self.Open(f"/v2/clients/{self.client_id}") self.WaitUntil(self.IsElementPresent, "css=.flow-title:contains('ListDirectory')") self.Click("css=result-accordion .title:contains('Flow arguments')") self.WaitUntil(self.IsElementPresent, "css=input.path-input") path_input = self.GetElement("css=input.path-input") self.assertEqual("/path", path_input.get_attribute("value"))
def testIllegalGlob(self): """Test that illegal globs raise.""" paths = ["Test/%%Weird_illegal_attribute%%"] # Run the flow - we expect an AttributeError error to be raised from the # flow since Weird_illegal_attribute is not a valid client attribute. flow_id = flow_test_lib.StartFlow( filesystem.Glob, paths=paths, client_id=self.client_id) flow_obj = data_store.REL_DB.ReadFlowObject(self.client_id, flow_id) self.assertEqual( flow_obj.error_message, "Some attributes are not part of the knowledgebase: " "weird_illegal_attribute") self.assertIn("KbInterpolationUnknownAttributesError", flow_obj.backtrace)
def testDisplaysSuccessAndFailedResultAndWarning(self): flow_args = rdf_file_finder.CollectFilesByKnownPathArgs( paths=["/file0", "/file1"]) flow_id = flow_test_lib.StartFlow(file.CollectFilesByKnownPath, creator=self.test_username, client_id=self.client_id, flow_args=flow_args) flow_test_lib.AddResultsToFlow(self.client_id, flow_id, [ self._GenFailedResult(0), self._GenCollectedResult(1), ]) with flow_test_lib.FlowProgressOverride( file.CollectFilesByKnownPath, rdf_file_finder.CollectFilesByKnownPathProgress( num_collected=1, num_raw_fs_access_retries=1, num_failed=1)): self.Open(f"/v2/clients/{self.client_id}") self.Click( "css=collect-files-by-known-path-details result-accordion:contains('/file0 + 1 more')" ) self.WaitUntil( self.IsElementPresent, "css=collect-files-by-known-path-details .results:contains('1 file fetched by parsing the raw disk image with libtsk or libfsntfs.')" ) self.WaitUntil( self.IsElementPresent, "css=collect-files-by-known-path-details .mat-tab-label-content:contains('1 successful file collection')" ) self.WaitUntil( self.IsElementPresent, "css=collect-files-by-known-path-details .results:contains('1 B')" ) self.WaitUntil( self.IsElementPresent, "css=collect-files-by-known-path-details .mat-tab-label-content:contains('1 error')" ) self.Click( "css=collect-files-by-known-path-details .mat-tab-label-content:contains('1 error')" ) self.WaitUntil( self.IsElementPresent, "css=collect-files-by-known-path-details .results:contains('errormsg0')" )
def testApiExampleIsShown(self): flow_id = flow_test_lib.StartFlow( gui_test_lib.FlowWithOneStatEntryResult, self.client_id, creator=self.token.username) self.Open("/#/clients/%s/flows/%s/api" % (self.client_id, flow_id)) self.WaitUntil(self.IsTextPresent, "HTTP (authentication details are omitted)") self.WaitUntil(self.IsTextPresent, 'curl -X POST -H "Content-Type: application/json"') self.WaitUntil(self.IsTextPresent, '"@type": "type.googleapis.com/') self.WaitUntil( self.IsTextPresent, '"name": "%s"' % gui_test_lib.FlowWithOneStatEntryResult.__name__)