Skip to content

Commit 64e2f38

Browse files
committed
Merge remote-tracking branch 'origin/develop' into fb_move_limit_logins
2 parents 8091b8e + 3309266 commit 64e2f38

7 files changed

Lines changed: 190 additions & 64 deletions

File tree

build.gradle

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,6 @@ project.tasks.named("uiTests").configure {
182182
project.parent.parent.tasks.named("ijConfigure").configure {
183183
dependsOn(initPropertiesTask)
184184
}
185-
project.tasks.withType(RunTestSuite).configureEach { it ->
186-
scanForTestClasses = true // Required for Gradle 9.3
187-
}
188185

189186
if (project.hasProperty('doPublishing'))
190187
{

src/org/labkey/test/Runner.java

Lines changed: 86 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -129,21 +129,24 @@ private void updateRemainingTests(Test test, boolean failed, boolean errored)
129129
Class<?> testClass = getTestClass(test);
130130
_remainingTests.remove(testClass);
131131
if (failed)
132-
_failedTests.add(test.toString());
132+
_failedTests.add(getTestName(test));
133133
else if (errored)
134-
_erroredTests.add(test.toString());
134+
_erroredTests.add(getTestName(test));
135135
else
136-
_passedTests.add(test.toString());
136+
_passedTests.add(getTestName(test));
137137
}
138138

139139
private static void writeRemainingTests()
140140
{
141-
ArrayList<String> failedAndRemaining = new ArrayList<>();
142-
failedAndRemaining.addAll(_failedTests);
143-
failedAndRemaining.addAll(_erroredTests);
144-
for (Class<?> clazz : _remainingTests)
145-
failedAndRemaining.add(clazz.getName());
146-
writeClasses(failedAndRemaining, getRemainingTestsFile());
141+
if (!TestProperties.isTestRunningOnTeamCity()) // Not useful on TeamCity
142+
{
143+
ArrayList<String> failedAndRemaining = new ArrayList<>();
144+
failedAndRemaining.addAll(_failedTests);
145+
failedAndRemaining.addAll(_erroredTests);
146+
for (Class<?> clazz : _remainingTests)
147+
failedAndRemaining.add(clazz.getName());
148+
writeClasses(failedAndRemaining, getRemainingTestsFile());
149+
}
147150
}
148151

149152
private static void writeClasses(List<String> tests, File file)
@@ -203,7 +206,7 @@ private static Class<?>[] readClasses(File recentlyFailedTestsFile, List<Class<?
203206
filteredRecentlyFailedTests.add(item);
204207
}
205208
}
206-
209+
207210
return filteredRecentlyFailedTests.toArray(new Class[0]);
208211
}
209212

@@ -273,8 +276,7 @@ else if (test instanceof JUnit4TestAdapter adapter)
273276

274277
if (_failedTests.size() + _erroredTests.size() < _maxTestFailures || _maxTestFailures <= 0)
275278
{
276-
final Class<?> currentTestClass = getTestClass(test);
277-
final String currentTestName = currentTestClass.getSimpleName();
279+
final String currentTestName = getTestName(test);
278280

279281
TestListener classFailListener = new TestListener()
280282
{
@@ -298,13 +300,16 @@ public void endTest(Test _test) { }
298300
};
299301
testResult.addListener(classFailListener);
300302

301-
logToServer("=== Starting " + currentTestName + getProgress() + " ===");
302-
LOG.info("=============== Starting " + currentTestName + getProgress() + " =================");
303+
if (!(test instanceof JUnitTest.RemoteTest))
304+
{
305+
logToServer("=== Starting " + currentTestName + getProgress() + " ===");
306+
LOG.info("=============== Starting " + currentTestName + getProgress() + " =================");
307+
}
303308

304309
// This stub matches the failure generated by JUnit when it fails during static setup/teardown (e.g. @BeforeClass)
305310
// Without this TeamCity has no way of knowing when a setup/teardown failure has been resolved
306-
final Test loggingStub = test instanceof JUnit4TestAdapter ?
307-
new TestSuite(currentTestClass) :
311+
final Test loggingStub = test instanceof JUnit4TestAdapter jUnit4TestAdapter ?
312+
new TestSuite(jUnit4TestAdapter.getTestClass()) :
308313
null;
309314

310315
if (loggingStub != null)
@@ -317,10 +322,13 @@ public void endTest(Test _test) { }
317322

318323
testResult.removeListener(classFailListener);
319324

320-
String result = failed.booleanValue() || errored.booleanValue() ? "Failed " : "Completed ";
321-
TestLogger.resetLogger();
322-
LOG.info("=============== " + result + currentTestName + getProgress() + " =================");
323-
logToServer("=== " + result + currentTestName + getProgress() + " ===");
325+
if (!(test instanceof JUnitTest.RemoteTest))
326+
{
327+
String result = failed.booleanValue() || errored.booleanValue() ? "Failed " : "Completed ";
328+
TestLogger.resetLogger();
329+
LOG.info("=============== " + result + currentTestName + getProgress() + " =================");
330+
logToServer("=== " + result + currentTestName + getProgress() + " ===");
331+
}
324332

325333
}
326334
else
@@ -547,7 +555,7 @@ public String describe()
547555
}
548556
else if (test.countTestCases() > 0)
549557
{
550-
suite.addTest(test);
558+
flattenSuiteInto(suite, (TestSuite) test);
551559
foundServerSideTest = true;
552560
}
553561
}
@@ -570,7 +578,7 @@ else if (specifiedSuite.startsWith("?") && specifiedSuite.length() > 1)
570578
}
571579
TestSuite dynamicSuite = JUnitTest.dynamicSuite(requestedSuites, excludedSuites);
572580
if (dynamicSuite.countTestCases() > 0)
573-
suite.addTest(dynamicSuite);
581+
flattenSuiteInto(suite, dynamicSuite);
574582
}
575583
}
576584

@@ -603,9 +611,9 @@ public void run(TestResult testResult)
603611

604612
private static void writeTimeReport()
605613
{
606-
int width = 60;
614+
int width = 64;
607615
long total = 0;
608-
LOG.info("======================= Time Report ========================");
616+
LOG.info(getCenteredText("Time Report", '=', width));
609617

610618
Duration totalCrawlTime = Duration.ZERO;
611619
int totalUniquePages = 0;
@@ -619,7 +627,7 @@ private static void writeTimeReport()
619627
}
620628
for (Map.Entry<Test, Long> entry : _testStats.entrySet())
621629
{
622-
String testName = entry.getKey().toString();
630+
String testName = getTestName(entry.getKey());
623631
long duration = entry.getValue();
624632

625633
long percent = Math.round(100.0 * (duration / (double) total));
@@ -630,7 +638,6 @@ private static void writeTimeReport()
630638
(_erroredTests.contains(testName) ? "ERROR" : "not run"))) +
631639
" - " +
632640
formatDuration(duration) + " " + percentStr;
633-
testName = testName.substring(testName.lastIndexOf('.') + 1);
634641

635642
LOG.info(getFixedWidthString(testName, durationAndPercent, width));
636643

@@ -686,7 +693,7 @@ private static void writeTimeReport()
686693
}
687694
if (!TeamCityUtils.getBuildStatistics().isEmpty())
688695
{
689-
LOG.info("--------------------- Build Statistics ---------------------");
696+
LOG.info(getCenteredText("Build Statistics", '-', width));
690697
for (String stat : TeamCityUtils.getBuildStatistics().keySet())
691698
{
692699
List<Number> values = TeamCityUtils.getBuildStatistics().get(stat);
@@ -702,7 +709,7 @@ private static void writeTimeReport()
702709
Map<String, Collection<String>> actionWarnings = WebDriverWrapper.getActionWarnings();
703710
if (!actionWarnings.isEmpty())
704711
{
705-
LOG.info("---------------------- Test Warnings -----------------------");
712+
LOG.info(getCenteredText("Test Warnings", '-', width));
706713
for (String warning : actionWarnings.keySet())
707714
{
708715
LOG.info(" " + warning + ":");
@@ -714,7 +721,7 @@ private static void writeTimeReport()
714721
}
715722
}
716723
}
717-
LOG.info("------------------------------------------------------------");
724+
LOG.info("-".repeat(width));
718725
LOG.info(getFixedWidthString("Total duration:", formatDuration(total), width) + "\n");
719726
LOG.info("Completed " + FastDateFormat.getInstance("yyyy-MM-dd HH:mm").format(new Date()));
720727
}
@@ -744,10 +751,23 @@ private static String getRowString(String[] list, int columnWidth)
744751
private static String getFixedWidthString(String prefix, String suffix, int length)
745752
{
746753
int contentLength = prefix.length() + suffix.length();
747-
int padding = Math.max(0, length - contentLength);
754+
int padding = Math.max(1, length - contentLength);
748755
return prefix + " ".repeat(padding) + suffix;
749756
}
750757

758+
private static String getCenteredText(String text, char paddingChar, int width)
759+
{
760+
text = StringUtils.trimToEmpty(text);
761+
if (text.length() > width)
762+
return text;
763+
764+
text = text.isEmpty() ? "" : " " + text + " ";
765+
int paddingLength = width - text.length();
766+
int leftPadding = paddingLength / 2;
767+
int rightPadding = paddingLength - leftPadding;
768+
return Character.toString(paddingChar).repeat(leftPadding) + text + Character.toString(paddingChar).repeat(rightPadding);
769+
}
770+
751771
private static TestSet getCompositeTestSet(List<String> suitesColl)
752772
{
753773
if (suitesColl.isEmpty())
@@ -1021,7 +1041,7 @@ else if (testNames.isEmpty())
10211041
Test test = e.nextElement();
10221042
Class<?> testClass = getTestClass(test);
10231043
_remainingTests.add(testClass);
1024-
LOG.info(" " + testClass.getSimpleName());
1044+
LOG.info(" " + getTestName(test));
10251045
for (String testMethod : specifiedTestMethods.getOrDefault(testClass, Collections.emptyList()))
10261046
{
10271047
LOG.info(" ." + testMethod);
@@ -1126,10 +1146,43 @@ private static String getModuleNameFromPath(File path)
11261146
return null;
11271147
}
11281148

1149+
private static void flattenSuiteInto(TestSuite destination, TestSuite source)
1150+
{
1151+
if (TestProperties.isTestRunningOnTeamCity())
1152+
{
1153+
// Flatten test suites so that TeamCity will correlate with results from before Gradle 9.3
1154+
Enumeration<Test> tests = source.tests();
1155+
while (tests.hasMoreElements())
1156+
{
1157+
Test t = tests.nextElement();
1158+
if (t instanceof TestSuite nested)
1159+
flattenSuiteInto(destination, nested);
1160+
else
1161+
destination.addTest(t);
1162+
}
1163+
}
1164+
else
1165+
{
1166+
destination.addTest(source);
1167+
}
1168+
}
1169+
1170+
private static String getTestName(Test test)
1171+
{
1172+
if (test instanceof JUnit4TestAdapter testAdapter)
1173+
return testAdapter.getTestClass().getSimpleName();
1174+
else if (test instanceof JUnitTest.RemoteTest remoteTest)
1175+
return remoteTest.getName();
1176+
else
1177+
return test.getClass().getSimpleName();
1178+
}
1179+
11291180
private static Class<?> getTestClass(Test test)
11301181
{
1131-
if (test instanceof JUnit4TestAdapter)
1132-
return ((JUnit4TestAdapter) test).getTestClass();
1182+
if (test instanceof JUnit4TestAdapter testAdapter)
1183+
return testAdapter.getTestClass();
1184+
else if (test instanceof JUnitTest.RemoteTest)
1185+
return JUnitTest.class;
11331186
else
11341187
return test.getClass();
11351188
}

src/org/labkey/test/pages/query/SourceQueryPage.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
package org.labkey.test.pages.query;
22

33
import org.labkey.test.Locator;
4+
import org.labkey.test.Locators;
45
import org.labkey.test.WebDriverWrapper;
56
import org.labkey.test.WebTestHelper;
67
import org.labkey.test.pages.LabKeyPage;
78
import org.labkey.test.util.DataRegion;
89
import org.labkey.test.util.DataRegionTable;
910
import org.labkey.test.util.Ext4Helper;
1011
import org.openqa.selenium.WebDriver;
12+
import org.openqa.selenium.WebElement;
1113
import org.openqa.selenium.support.ui.WebDriverWait;
1214

1315
import java.time.Duration;
@@ -88,7 +90,7 @@ public String getMetadataXml()
8890

8991
public SourceQueryPage clickSave()
9092
{
91-
Ext4Helper.Locators.ext4Button("Save").findElement(getDriver()).click();
93+
elementCache().saveButton.click();
9294
waitForElement(Locator.id("status").withText("Saved"), WAIT_FOR_JAVASCRIPT);
9395
waitForElementToDisappear(Locator.id("status").withText("Saved"), WAIT_FOR_JAVASCRIPT);
9496

@@ -97,16 +99,24 @@ public SourceQueryPage clickSave()
9799

98100
public ExecuteQueryPage clickSaveAndFinish()
99101
{
100-
clickAndWait(Ext4Helper.Locators.ext4Button("Save & Finish").findElement(getDriver()));
102+
clickAndWait(elementCache().saveAndFinishButton);
103+
assertNoLabKeyErrors();
101104
return new ExecuteQueryPage(getDriver());
102105
}
103106

104107
public String clickSaveExpectingError()
105108
{
106-
Ext4Helper.Locators.ext4Button("Save").findElement(getDriver()).click();
109+
elementCache().saveButton.click();
107110
return waitForElement(Locator.tagWithId("div","status")).getText();
108111
}
109112

113+
public String clickSaveAndFinishExpectingError()
114+
{
115+
clickAndWait(elementCache().saveAndFinishButton);
116+
clearCache();
117+
return waitForElement(Locators.labkeyError).getText();
118+
}
119+
110120
@Override
111121
protected ElementCache newElementCache()
112122
{
@@ -115,5 +125,7 @@ protected ElementCache newElementCache()
115125

116126
protected class ElementCache extends LabKeyPage<?>.ElementCache
117127
{
128+
private final WebElement saveButton = Ext4Helper.Locators.ext4Button("Save").findWhenNeeded(this);
129+
private final WebElement saveAndFinishButton = Ext4Helper.Locators.ext4Button("Save & Finish").findWhenNeeded(this);
118130
}
119131
}

src/org/labkey/test/tests/CustomizeViewTest.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -303,14 +303,18 @@ public void saveFilterTest()
303303
FieldKey fieldKey = FieldKey.fromParts(LAST_NAME_COLUMN);
304304
String op = "Starts With";
305305
String value = "J";
306-
String[] viewNames = {TRICKY_CHARACTERS + "view", "AAC", "aaa", "aad", "zzz"};
306+
String[] viewNames = {TRICKY_CHARACTERS + "view", "AAC", "aaa", "aad", "zzz", "view,with,comma"};
307307

308308
setColumns(LAST_NAME_COLUMN);
309309
for(String name : viewNames)
310310
{
311311
_customizeViewsHelper.openCustomizeViewPanel();
312312
_customizeViewsHelper.addFilter(fieldKey, op, value);
313313
_customizeViewsHelper.saveCustomView(name);
314+
_customizeViewsHelper.openCustomizeViewPanel();
315+
// GitHub Issue #936 : ensure custom view can be edited
316+
assertElementNotPresent(Locator.tagWithClass("div", "alert-warning").withText(String.format("Custom Grid View '%s' not found.", name)));
317+
_customizeViewsHelper.closePanel();
314318
}
315319

316320
DataRegionTable drt = new DataRegionTable("query", getDriver());

0 commit comments

Comments
 (0)