Skip to content

Commit 2934430

Browse files
committed
save work
Signed-off-by: fayi-da <[email protected]>
1 parent 772e570 commit 2934430

File tree

14 files changed

+264
-13
lines changed

14 files changed

+264
-13
lines changed

apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/FrontendIntegrationTest.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ trait FrontendTestCommon extends TestCommon with WebBrowser with CustomMatchers
177177
val options: FirefoxOptions =
178178
new FirefoxOptions()
179179
.setLogLevel(FirefoxDriverLogLevel.DEBUG)
180-
.addArguments("-headless")
180+
// .addArguments("-headless")
181181
options.setCapability("webSocketUrl", true: Any);
182182

183183
protected val webDrivers: mutable.Map[String, WebDriverType] = mutable.Map.empty
@@ -300,6 +300,7 @@ trait FrontendTestCommon extends TestCommon with WebBrowser with CustomMatchers
300300
// We process all browsers in parallel, for faster test termination.
301301
webDrivers.values.toList.parTraverse { webDriver =>
302302
Future {
303+
com.digitalasset.canton.concurrent.Threading.sleep(30000)
303304
webDriver.quit()
304305
}
305306
}.futureValue

apps/app/src/test/scala/org/lfdecentralizedtrust/splice/integration/tests/SvFrontendIntegrationTest.scala

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import org.openqa.selenium.By
2424
import org.openqa.selenium.support.ui.Select
2525
import org.slf4j.event.Level
2626

27+
import scala.jdk.CollectionConverters.*
2728
import java.util.Optional
2829

2930
class SvFrontendIntegrationTest
@@ -308,6 +309,171 @@ class SvFrontendIntegrationTest
308309
}
309310
}
310311

312+
def createProposal(action: String, effectiveAtThreshold: Boolean = true)(
313+
extraFormOps: WebDriverType => Unit
314+
)(implicit
315+
env: SpliceTestConsoleEnvironment
316+
) = {
317+
val requestReasonUrl = "https://new-proposal-url.com/"
318+
val requestReasonBody = "This is a summary of the proposal"
319+
val thresholdDeadline = "2034-07-12 00:12"
320+
val effectiveDate = "2034-07-13 00:12"
321+
322+
withFrontEnd("sv1") { implicit webDriver =>
323+
val previousInflightProposalsSize = getInflightProposals().size
324+
previousInflightProposalsSize shouldBe 0
325+
// logger.debug(s"tesco at definition previousInflightProposalsSize: $previousInflightProposalsSize")
326+
327+
actAndCheck(
328+
"sv1 operator can login and browse to the governance tab", {
329+
go to s"http://localhost:$sv1UIPort/governance-beta"
330+
loginOnCurrentPage(sv1UIPort, sv1Backend.config.ledgerApiUser)
331+
},
332+
)(
333+
"sv1 can navigate to the create proposal page",
334+
_ => {
335+
val initiateProposalButton = find(id("initiate-proposal-button"))
336+
clue("initiate proposal button is visible") {
337+
// eventuallySucceeds() {
338+
initiateProposalButton should not be empty
339+
340+
click on id("initiate-proposal-button")
341+
// }
342+
}
343+
344+
clue("Select an Action page is visible") {
345+
find(id("select-action")) should not be empty
346+
}
347+
348+
clickOn(id("select-action"))
349+
350+
eventually() {
351+
val actionItem = webDriver.findElement(By.cssSelector(s"[data-testid='$action']"))
352+
actionItem.click()
353+
}
354+
355+
webDriver.findElement(By.tagName("body")).click()
356+
357+
val nextButton = webDriver.findElement(By.cssSelector(s"[data-testid='next-button']"))
358+
nextButton.click()
359+
360+
find(id("offboard-sv-action")) should not be empty
361+
362+
},
363+
)
364+
365+
actAndCheck(
366+
"sv1 operator can create a new proposal", {
367+
368+
setThresholdDeadline("sv1", thresholdDeadline, "offboard-sv-expiry-date-field")
369+
370+
if (effectiveAtThreshold) {
371+
inside(find(id("effective-at-threshold-radio"))) { case Some(element) =>
372+
element.underlying.click()
373+
}
374+
} else {
375+
setEffectiveDate2("sv1", effectiveDate)
376+
}
377+
378+
inside(find(id("offboard-sv-summary"))) { case Some(element) =>
379+
element.underlying.sendKeys(requestReasonBody)
380+
}
381+
382+
inside(find(id("offboard-sv-url"))) { case Some(element) =>
383+
element.underlying.sendKeys(requestReasonUrl)
384+
}
385+
386+
extraFormOps(webDriver)
387+
388+
clickVoteRequestSubmitButtonOnceEnabled2()
389+
},
390+
)(
391+
"sv1 can see the new proposal",
392+
_ => {
393+
// find(id("inflight-proposals-section-title")) should not be empty
394+
395+
val currentInflightProposals = getInflightProposals()
396+
currentInflightProposals.size shouldBe previousInflightProposalsSize + 1
397+
398+
clue("click the new proposal") {
399+
// println(s"tesco currentinflight: ${currentInflightProposals.asScala.head}")
400+
val link = webDriver
401+
.findElement(By.cssSelector("[data-testid='inflight-proposals-row-link']"))
402+
// webDriver.executeScript("arguments[0].scrollIntoView(true);", link)
403+
// Not sure why this is the only way to make it work but hewre we are.
404+
webDriver.executeScript("arguments[0].click();", link)
405+
406+
// link.click()
407+
// webDriver.executeScript("arguments[0].click();", link)
408+
// currentInflightProposals.asScala.head.click()
409+
}
410+
},
411+
)
412+
413+
}
414+
415+
withFrontEnd("sv2") { implicit webDriver =>
416+
val (_, reviewButton) = actAndCheck(
417+
"sv2 operator can login and browse to the governance page", {
418+
go to s"http://localhost:$sv2UIPort/governance-beta"
419+
loginOnCurrentPage(sv2UIPort, sv2Backend.config.ledgerApiUser)
420+
},
421+
)(
422+
"sv2 can see the new vote request",
423+
_ => {
424+
eventuallySucceeds() {
425+
val actionsRequired = getActionRequiredElems()
426+
actionsRequired.size shouldBe 1
427+
428+
webDriver.executeScript("arguments[0].click();", actionsRequired.asScala.head)
429+
}
430+
// actionsRequired.asScala.head.click()
431+
432+
inside(find(id("your-vote-reason-input"))) { case Some(element) =>
433+
element.underlying.sendKeys("A sample reason")
434+
}
435+
436+
inside(find(id("your-vote-url-input"))) { case Some(element) =>
437+
element.underlying.sendKeys("https://my-splice-vote-url.com")
438+
}
439+
440+
webDriver.findElement(By.cssSelector(s"[data-testid='your-vote-accept']")).click()
441+
442+
eventuallyClickOn(id("submit-vote-button"))
443+
444+
clue("wait for the vote submission success message") {
445+
eventuallySucceeds() {
446+
inside(find(xpath("//*[@data-testid='vote-submission-success']"))) {
447+
case Some(element) =>
448+
element.text shouldBe "Vote successfully updated!"
449+
}
450+
}
451+
}
452+
},
453+
)
454+
}
455+
456+
withFrontEnd("sv1") { implicit webDriver =>
457+
clue("sv1 operator can see the new vote from sv2") {
458+
val sv2PartyId = sv2Backend.getDsoInfo().svParty.toProtoPrimitive
459+
val votes =
460+
webDriver.findElements(By.cssSelector("[data-testid='proposal-details-vote']"))
461+
votes.size shouldBe 1
462+
463+
val voterInput = votes.asScala.head
464+
.findElement(
465+
By.cssSelector("[data-testid='proposal-details-voter-party-id-input']")
466+
)
467+
voterInput.getAttribute("value") shouldBe sv2PartyId
468+
}
469+
470+
// actAndCheck(
471+
// "sv1 operator can see the vote request detail", {
472+
// },
473+
// )("", _ => {})
474+
}
475+
}
476+
311477
def testCreateAndVoteDsoRulesAction(action: String, effectiveAtThreshold: Boolean = true)(
312478
fillUpForm: WebDriverType => Unit
313479
)(validateRequestedActionInModal: WebDriverType => Unit)(implicit
@@ -564,6 +730,24 @@ class SvFrontendIntegrationTest
564730
}
565731
}
566732

733+
"NEW UI: Offboard" in { implicit env =>
734+
val sv3PartyId = sv3Backend.getDsoInfo().svParty.toProtoPrimitive
735+
736+
createProposal("SRARC_OffboardSv") { implicit webDriver =>
737+
// eventually() {
738+
find(id("offboard-sv-member-dropdown")) match {
739+
case Some(element) => element.underlying.click()
740+
case None =>
741+
fail("Could not find offboard-sv-member-dropdown")
742+
}
743+
744+
val memberSelect = webDriver.findElement(By.cssSelector(s"[data-value='$sv3PartyId']"))
745+
memberSelect.click()
746+
webDriver.findElement(By.tagName("body")).click()
747+
// }
748+
}
749+
}
750+
567751
"can create a valid SRARC_OffboardSv vote request and cast vote on it" in { implicit env =>
568752
val sv3PartyId = sv3Backend.getDsoInfo().svParty.toProtoPrimitive
569753
testCreateAndVoteDsoRulesAction("SRARC_OffboardSv") { webDriver =>
@@ -1141,6 +1325,14 @@ class SvFrontendIntegrationTest
11411325
.getOrElse(0)
11421326
}
11431327

1328+
def getInflightProposals()(implicit webDriver: WebDriverType) = {
1329+
webDriver.findElements(By.cssSelector("[data-testid='inflight-proposals-row-link']"))
1330+
}
1331+
1332+
def getActionRequiredElems()(implicit webDriver: WebDriverType) = {
1333+
webDriver.findElements(By.cssSelector("[data-testid='action-required-card-link']"))
1334+
}
1335+
11441336
def getVoteRequestsRejectedSize()(implicit webDriver: WebDriverType) = {
11451337
val tbodyRejected = find(id("sv-vote-results-rejected-table-body"))
11461338
tbodyRejected

apps/app/src/test/scala/org/lfdecentralizedtrust/splice/util/SvFrontendTestUtil.scala

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package org.lfdecentralizedtrust.splice.util
22

33
import org.lfdecentralizedtrust.splice.integration.tests.SpliceTests.TestCommon
44
import org.lfdecentralizedtrust.splice.integration.tests.FrontendTestCommon
5+
import org.openqa.selenium.By
56
import scala.concurrent.duration.DurationInt
67

78
trait SvFrontendTestUtil extends TestCommon {
@@ -13,12 +14,24 @@ trait SvFrontendTestUtil extends TestCommon {
1314
setDateTime(party, "datetime-picker-vote-request-expiration", dateTime)
1415
}
1516

17+
def setThresholdDeadline(party: String, dateTime: String, id: String)(implicit
18+
webDriver: WebDriverType
19+
) = {
20+
setDateTime(party, id, dateTime)
21+
}
22+
1623
def setEffectiveDate(party: String, dateTime: String)(implicit
1724
webDriver: WebDriverType
1825
) = {
1926
setDateTime(party, "datetime-picker-vote-request-effectivity", dateTime)
2027
}
2128

29+
def setEffectiveDate2(party: String, dateTime: String)(implicit
30+
webDriver: WebDriverType
31+
) = {
32+
setDateTime(party, "effective-date-field", dateTime)
33+
}
34+
2235
def setAmuletConfigDate(party: String, dateTime: String)(implicit
2336
webDriver: WebDriverType
2437
) = {
@@ -42,4 +55,37 @@ trait SvFrontendTestUtil extends TestCommon {
4255
}
4356
}
4457
}
58+
59+
def clickVoteRequestSubmitButtonOnceEnabled2(
60+
enabled: Boolean = true
61+
)(implicit webDriver: WebDriverType) = {
62+
63+
// ensure all validations on the form are done
64+
webDriver.findElement(By.tagName("body")).click()
65+
66+
def submitButton = find(id("submit-button"))
67+
68+
clue("wait for the review button to become clickable") {
69+
eventually()(
70+
submitButton.value.isEnabled shouldBe enabled
71+
)
72+
}
73+
74+
clue("click the review button and progress to review page") {
75+
inside(find(xpath("//button[contains(text(), 'Review Proposal')]"))) {
76+
case Some(button) =>
77+
button.underlying.click()
78+
case None =>
79+
fail("Could not find review button")
80+
}
81+
}
82+
83+
clue("Submit form") {
84+
eventuallySucceeds() {
85+
val submitButton =
86+
webDriver.findElement(By.xpath("//button[contains(text(), 'Submit Proposal')]"))
87+
submitButton.click()
88+
}
89+
}
90+
}
4591
}

apps/sv/frontend/src/__tests__/governance/governance-page.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ describe.skip('Governance Page', () => {
8080

8181
await navigateToGovernancePage(user);
8282

83-
expect(() => screen.getAllByTestId('inflight-vote-requests-row')).toThrowError(
83+
expect(() => screen.getAllByTestId('inflight-proposals-row')).toThrowError(
8484
/Unable to find an element/
8585
);
8686
});

apps/sv/frontend/src/components/beta/PageSectionHeader.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ const PageSectionHeader: React.FC<PageSectionHeaderProps> = ({
1414
'data-testid': testId,
1515
}) => (
1616
<Box sx={{ display: 'flex', alignItems: 'center', mb: 3 }}>
17-
<Typography variant="h3" fontFamily="lato" fontSize={18} data-testid={`${testId}-title`}>
17+
<Typography variant="h3" fontFamily="lato" fontSize={18} data-testid={`${testId}-title`} id={`${testId}-title`}>
1818
{title}
1919
</Typography>
2020
<Badge

apps/sv/frontend/src/components/form-components/EffectiveDateField.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export const EffectiveDateField: React.FC<EffectiveDateFieldProps> = props => {
8686
textField: {
8787
fullWidth: true,
8888
variant: 'outlined',
89-
id: `${id}-field`,
89+
id: `${id}-field effective-date-field`,
9090
onBlur: field.handleBlur,
9191
error: !field.state.meta.isValid,
9292
helperText: field.state.meta.errors?.[0],
@@ -102,7 +102,7 @@ export const EffectiveDateField: React.FC<EffectiveDateFieldProps> = props => {
102102

103103
<FormControlLabel
104104
value="threshold"
105-
control={<Radio />}
105+
control={<Radio id="effective-at-threshold-radio" />}
106106
label={
107107
<Box>
108108
<Typography>Make effective at threshold</Typography>

apps/sv/frontend/src/components/form-components/FormControls.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ export const FormControls: React.FC<FormControlsProps> = props => {
5252
type={'submit'}
5353
size="large"
5454
disabled={!canSubmit || isSubmitting}
55+
id="submit-button"
5556
data-testid="submit-button"
5657
>
5758
{isSubmitting ? 'Submitting' : submitTitle}

apps/sv/frontend/src/components/form-components/ProposalSummaryField.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export const ProposalSummaryField: React.FC<ProposalSummaryFieldProps> = props =
3838
error={!field.state.meta.isValid}
3939
helperText={field.state.meta.errors?.[0]}
4040
inputProps={{ 'data-testid': id }}
41+
id={id}
4142
/>
4243
<Typography variant="body2" sx={{ mt: 1 }} data-testid={`${id}-subtitle`}>
4344
{subtitle || PROPOSAL_SUMMARY_SUBTITLE}

apps/sv/frontend/src/components/form-components/TextField.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export const TextField: React.FC<TextFieldProps> = props => {
3939
}
4040
onChange={e => field.handleChange(e.target.value)}
4141
inputProps={{ 'data-testid': id }}
42+
id={id}
4243
{...muiTextFieldProps}
4344
/>
4445
{subtitle && (

apps/sv/frontend/src/components/forms/SelectAction.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ export const SelectAction: React.FC = () => {
105105

106106
<Button
107107
variant="contained"
108+
id="next-button"
108109
data-testid="next-button"
109110
type="submit"
110111
disabled={!canSubmit}

0 commit comments

Comments
 (0)