Skip to content

Commit 6e5357e

Browse files
committed
- Test cleanup
- Updated comment for testTrainingDataPage
1 parent e405b08 commit 6e5357e

1 file changed

Lines changed: 39 additions & 46 deletions

File tree

testresults/test/src/org/labkey/test/tests/testresults/TestResultsTest.java

Lines changed: 39 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616
package org.labkey.test.tests.testresults;
1717

18+
import org.apache.hc.client5.http.classic.methods.HttpGet;
1819
import org.apache.hc.client5.http.classic.methods.HttpPost;
1920
import org.apache.hc.client5.http.entity.mime.MultipartEntityBuilder;
2021
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
@@ -49,6 +50,7 @@
4950
import java.util.Map;
5051

5152
import static org.junit.Assert.assertEquals;
53+
import static org.junit.Assert.assertFalse;
5254
import static org.junit.Assert.assertTrue;
5355

5456
@Category({External.class, MacCossLabModules.class})
@@ -59,6 +61,13 @@ public class TestResultsTest extends BaseWebDriverTest implements PostgresOnlyTe
5961
static final String COMPUTER_NAME_1 = "TEST-PC-1";
6062
static final String COMPUTER_NAME_2 = "TEST-PC-2";
6163

64+
private static final Locator SUBMIT_BUTTON = Locator.css("input[type='submit'][value='Submit']");
65+
66+
// XPath for the problems matrix table (header cell contains "Fail: | Leak: | Hang:")
67+
private static final String PROBLEMS_TABLE_XPATH =
68+
"//table[contains(@class,'decoratedtable')]" +
69+
"[.//td[contains(.,'Fail:') and contains(.,'Leak:') and contains(.,'Hang:')]]";
70+
6271
// Run IDs populated in @BeforeClass, used across test methods
6372
private static int _disposableRunId = -1;
6473
private static int _cleanRunId = -1;
@@ -164,12 +173,6 @@ public void navigateToProject()
164173
// Tests
165174
// -------------------------------------------------------------------------
166175

167-
private static final Locator SUBMIT_BUTTON = Locator.css("input[type='submit'][value='Submit']");
168-
// XPath for the problems matrix table (header cell contains "Fail: | Leak: | Hang:")
169-
private static final String PROBLEMS_TABLE_XPATH =
170-
"//table[contains(@class,'decoratedtable')]" +
171-
"[.//td[contains(.,'Fail:') and contains(.,'Leak:') and contains(.,'Hang:')]]";
172-
173176
@Test
174177
public void testBeginPage()
175178
{
@@ -324,7 +327,7 @@ public void testShowFailuresPage()
324327
// 08:01 via setToEightAM, but the start wall-clock time can shift
325328
// across DST boundaries (e.g. start 07:01 PST, end 08:01 PDT when
326329
// the window crosses spring-forward), so asserting just the dates
327-
// keeps the test stable year-round.
330+
// keeps the test stable.
328331

329332
// --- Path 1: navigate via runDetail.jsp ---
330333
// The "TestFailOne" link on runDetail.jsp does NOT set the `end`
@@ -356,17 +359,11 @@ public void testShowFailuresPage()
356359
// --- Path 2: navigate via the Fail/Leak/Hang table on rundown.jsp ---
357360
// The link in this table sets `end` to the begin page's selected
358361
// date but does not set `viewType`, so the controller defaults to
359-
// ViewType.DAY → start = end - 1 day. (The Top Failures table
360-
// link also passes `viewType`, which preserves rundown's current
361-
// view and produces a 30-day window — not what we want here.)
362-
// Anchoring to a fixed sample-data date (01/17/2026) keeps this
363-
// assertion stable regardless of when the test runs. The link
362+
// ViewType.DAY → start = end - 1 day. The link
364363
// opens in a new browser tab via target="_blank".
365364
beginAt(WebTestHelper.buildRelativeUrl("testresults", PROJECT_NAME, "begin",
366365
Map.of("end", "01/17/2026")));
367-
Locator failLeakHangLink = Locator.xpath(
368-
"//table[contains(@class,'decoratedtable')][.//td[contains(., 'Fail:') and contains(., 'Leak:') and contains(., 'Hang:')]]" +
369-
"//a[text()='TestFailOne']");
366+
Locator failLeakHangLink = Locator.xpath(PROBLEMS_TABLE_XPATH + "//a[text()='TestFailOne']");
370367
click(failLeakHangLink);
371368
switchToWindow(1); // Link opens in a new tab
372369
try
@@ -396,8 +393,7 @@ public void testShowFlaggedPage()
396393
// Verify the Flags page now shows the flagged run. Each flagged row is
397394
// rendered (in flagged.jsp) as a link with text:
398395
// "id: <runId> / <userId> / <postTime>"
399-
// Match by the runId prefix — userId and postTime are baked into the
400-
// sample XML and aren't worth duplicating in the test.
396+
// Match by the runId prefix
401397
clickAndWait(Locator.linkWithText("Flags"));
402398
assertTextNotPresent("There are currently no flagged runs.");
403399
assertTextPresent("Flagged Runs");
@@ -420,18 +416,14 @@ public void testTrainingDataPage()
420416
// rows with Date | Duration | Tests Run | Failure Count | Mean Memory
421417
// | Remove, and a `.stats-row` with "RunCount:N"). Users WITHOUT
422418
// training runs are listed in a separate <table> below, under a
423-
// "No Training Data --" header — that header is always present, so
424-
// it can't be used as an empty-state indicator.
419+
// "No Training Data --" header
425420
Locator.XPathLocator trainingTable = Locator.tagWithId("table", "trainingdata");
426421
Locator removeLink = trainingTable.descendant(Locator.tagWithClass("a", "removedata"));
427422
Locator statsRow = trainingTable.descendant(Locator.tagWithClass("tr", "stats-row"));
428423

429424
// Initial state: no run has been added to the training set yet, so
430425
// the clean run's date should not appear in the training table and
431-
// no Remove link should be present. (We can't assert the stats-row
432-
// is absent — users may already have non-zero mean memory / mean
433-
// tests-run from the imported sample data, which causes a stats-row
434-
// to render before any run is explicitly added.)
426+
// no Remove link should be present.
435427
goToProjectHome(PROJECT_NAME);
436428
clickAndWait(Locator.linkWithText("Training Data"));
437429
assertElementNotPresent(removeLink);
@@ -445,8 +437,7 @@ public void testTrainingDataPage()
445437
assertTextPresent("Remove from training set");
446438

447439
// Verify the Training Data page now shows the run for COMPUTER_NAME_1.
448-
// Scope assertions to <table id="trainingdata"> so we don't accidentally
449-
// match the same text in the "No Training Data" section below.
440+
// Scope assertions to <table id="trainingdata">
450441
clickAndWait(Locator.linkWithText("Training Data"));
451442
assertElementPresent(trainingTable.descendant(
452443
Locator.tagWithId("tr", "user-anchor-" + COMPUTER_NAME_1)));
@@ -464,12 +455,14 @@ public void testTrainingDataPage()
464455
toggleTrainingSet();
465456
assertTextPresent("Add to training set");
466457

467-
// After removal: the Remove link and the run's data row are gone, but
468-
// TEST-PC-1's section stays in the training table because the user's
469-
// meanmemory / meantestsrun are persisted on the User row (not derived
470-
// from current training rows). The stats row now shows "RunCount:0".
471-
// See trainingdata.jsp:158 — users only move to the "No Training Data"
472-
// section when both meanmemory and meantestsrun are 0.
458+
// After removal: the Remove link and the run's data row are gone, and
459+
// the stats row now shows "RunCount:0". TEST-PC-1's section is still
460+
// rendered in the training table though, because of a known bug in
461+
// TrainRunAction: when the user's last training run is removed, the
462+
// the stale UserData row (non-zero meanmemory / meantestsrun) is
463+
// never cleared. trainingdata.jsp:158 only moves users to the
464+
// "No Training Data --" list when both fields are 0, so the section
465+
// stays. See TODO-LK-20260403_testresults-bugs.md.
473466
clickAndWait(Locator.linkWithText("Training Data"));
474467
assertElementNotPresent(removeLink);
475468
assertElementNotPresent(trainingTable.containing("2026-01-16 06:00"));
@@ -481,7 +474,7 @@ public void testTrainingDataPage()
481474
public void testViewLog()
482475
{
483476
// The clean run has a <Log> element — ViewLogAction should return it
484-
String logContent = getApiString("testresults", "viewLog", _cleanRunId, "log");
477+
String logContent = getApiString("viewLog", _cleanRunId, "log");
485478
assertTrue("ViewLog should return log content", logContent != null && !logContent.isEmpty());
486479
// Spot-check the nightly header and test entries from the beginning,
487480
// middle, and end of the log (see pc1-run-0115-clean.xml).
@@ -498,11 +491,11 @@ public void testViewLog()
498491
public void testViewXml()
499492
{
500493
// ViewXmlAction should return the stored XML (without the <Log> element)
501-
String xmlContent = getApiString("testresults", "viewXml", _cleanRunId, "xml");
494+
String xmlContent = getApiString("viewXml", _cleanRunId, "xml");
502495
assertTrue("ViewXml should return XML content", xmlContent != null && !xmlContent.isEmpty());
503496
assertTrue("XML should contain nightly element", xmlContent.contains("nightly"));
504497
assertTrue("XML should contain test data", xmlContent.contains("TestAlpha"));
505-
assertTrue("XML should not contain Log element (stripped before storage)", !xmlContent.contains("<Log>"));
498+
assertFalse("XML should not contain Log element (stripped before storage)", xmlContent.contains("<Log>"));
506499
}
507500

508501
@Test
@@ -579,19 +572,19 @@ public void testApiErrorResponses()
579572
{
580573
// TrainRunAction: missing runId
581574
JSONObject noRunId = postApi("trainRun", Map.of("train", "true"));
582-
assertEquals(false, noRunId.optBoolean("Success", true));
575+
assertFalse(noRunId.optBoolean("Success", true));
583576
assertEquals("runId is required", noRunId.optString("error"));
584577

585578
// TrainRunAction: invalid train value
586579
JSONObject badTrain = postApi("trainRun",
587580
Map.of("runId", String.valueOf(_cleanRunId), "train", "garbage"));
588-
assertEquals(false, badTrain.optBoolean("Success", true));
581+
assertFalse(badTrain.optBoolean("Success", true));
589582
assertEquals("train must be one of: true, false, force", badTrain.optString("error"));
590583

591584
// TrainRunAction: nonexistent runId
592585
JSONObject missingRun = postApi("trainRun",
593586
Map.of("runId", "999999", "train", "true"));
594-
assertEquals(false, missingRun.optBoolean("Success", true));
587+
assertFalse(missingRun.optBoolean("Success", true));
595588
assertEquals("run does not exist: 999999", missingRun.optString("error"));
596589

597590
// SetUserActive: missing userId
@@ -605,12 +598,12 @@ public void testApiErrorResponses()
605598

606599
// DeleteRunAction: missing runId
607600
JSONObject noDeleteRunId = postApi("deleteRun", Map.of());
608-
assertEquals(false, noDeleteRunId.optBoolean("Success", true));
601+
assertFalse(noDeleteRunId.optBoolean("Success", true));
609602
assertEquals("runId is required", noDeleteRunId.optString("error"));
610603

611604
// FlagRunAction: missing runId
612605
JSONObject noFlagRunId = postApi("flagRun", Map.of("flag", "true"));
613-
assertEquals(false, noFlagRunId.optBoolean("Success", true));
606+
assertFalse(noFlagRunId.optBoolean("Success", true));
614607
assertEquals("runId is required", noFlagRunId.optString("error"));
615608
}
616609

@@ -735,7 +728,7 @@ private void assertProblemIconCount(String testName, String iconFile, int expect
735728
Locator icons = Locator.xpath(PROBLEMS_TABLE_XPATH +
736729
"//tr[.//a[text()='" + testName + "']]//img[contains(@src,'" + iconFile + "')]");
737730
assertEquals("Expected " + expectedCount + " " + iconFile + " icon(s) for " + testName,
738-
expectedCount, getElementCount(icons));
731+
expectedCount, icons.findElements(getDriver()).size());
739732
}
740733

741734
/**
@@ -816,18 +809,18 @@ private void goToPrevDay(int count)
816809
}
817810

818811
/**
819-
* Makes an API GET request and returns the value of the specified field from the JSON response.
812+
* Makes an API GET request to a testresults action and returns the value
813+
* of the specified field from the JSON response.
820814
*/
821-
private String getApiString(String controller, String action, int runId, String field)
815+
private String getApiString(String action, int runId, String field)
822816
{
823-
String url = WebTestHelper.buildURL(controller, PROJECT_NAME, action) + "?runId=" + runId;
817+
String url = WebTestHelper.buildURL("testresults", PROJECT_NAME, action) + "?runId=" + runId;
824818
try (CloseableHttpClient httpClient = WebTestHelper.getHttpClient())
825819
{
826-
var request = new org.apache.hc.client5.http.classic.methods.HttpGet(url);
820+
HttpGet request = new HttpGet(url);
827821
APITestHelper.injectCookies(request);
828822
return httpClient.execute(request, response -> {
829-
String body = EntityUtils.toString(response.getEntity());
830-
org.json.JSONObject json = new org.json.JSONObject(body);
823+
JSONObject json = new JSONObject(EntityUtils.toString(response.getEntity()));
831824
return json.optString(field, null);
832825
});
833826
}

0 commit comments

Comments
 (0)