Skip to content

Commit 74b2244

Browse files
authored
Merge branch 'master' into ethskills
2 parents 2ec6c66 + 94fb4b0 commit 74b2244

File tree

169 files changed

+11160
-3969
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

169 files changed

+11160
-3969
lines changed

apps/remix-dapp/src/locales/en/udapp.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,11 @@
5454
"udapp.forkVmStateDesc1":"Forking state will create a new environment with same state as selected environment",
5555
"udapp.forkVmStateDesc2":"New environment will be pinned, which can be unpinned or deleted using Environment Explorer",
5656
"udapp.fork": "Fork",
57-
"udapp.resetVmStateTitle": "Reset VM state",
57+
"udapp.resetVmStateTitle": "Environment state reset",
5858
"udapp.resetVmStateDesc1": "Resetting the state of this VM will delete the associated transaction details in this Workspace.",
5959
"udapp.resetVmStateDesc2": "It will also delete the data of contracts deployed and pinned in this Workspace.",
6060
"udapp.resetVmStateDesc3": "Do you want to continue?",
61-
"udapp.reset": "Reset",
61+
"udapp.reset": "Yes reset",
6262
"udapp.delete": "Delete",
6363
"udapp.injectedTitle": "Unfortunately it's not possible to create an account using injected provider. Please create the account directly from your provider (i.e metamask or other of the same type).",
6464
"udapp.createSmartAccount": "Create a Safe Smart Account",
@@ -88,6 +88,8 @@
8888

8989
"udapp._comment_instanceContainerUI.tsx": "libs/remix-ui/run-tab/src/lib/components/instanceContainerUI.tsx",
9090
"udapp.deployedContracts": "Deployed Contracts",
91+
"udapp.noDeployedContracts": "There is no contract to show.",
92+
"udapp.deployFirstContract": "Deploy your first contract, or learn how to do it following our in-app tutorials.",
9193
"udapp.deployAndRunClearInstances": "Clear instances list and reset recorder",
9294
"udapp.deployAndRunNoInstanceText": "Currently you have no contract instances to interact with.",
9395
"udapp.tooltipText6": "Autogenerated generic user interfaces for interaction with deployed contracts",

apps/remix-ide-e2e/src/commands/addAtAddressInstance.ts

Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,31 +15,34 @@ class addAtAddressInstance extends EventEmitter {
1515

1616
function addInstance (browser: NightwatchBrowser, address: string, isValidFormat: boolean, isValidChecksum: boolean, isAbi: boolean, callback: VoidFunction) {
1717
browser
18-
.clickLaunchIcon('udapp')
19-
.waitForElementVisible('.ataddressinput')
20-
.click('.ataddressinput')
21-
.setValue('.ataddressinput', address, function () {
22-
if (!isValidFormat || !isValidChecksum) browser.assert.elementPresent('button[id^="runAndDeployAtAddressButton"]:disabled')
23-
else if (isAbi) {
24-
browser
25-
.click({
26-
selector: '//*[@id="runAndDeployAtAddressButtonContainer"]',
27-
locateStrategy: 'xpath'
28-
})
29-
.waitForElementPresent('[data-id="udappNotify-modal-footer-ok-react"]', 5000)
30-
.execute(function () {
31-
const modal = document.querySelector('[data-id="udappNotify-modal-footer-ok-react"]') as any
18+
.clickLaunchIcon('udapp')
19+
.waitForElementVisible('[data-id="addDeployedContract"]')
20+
.pause(500) // Wait for any UI transitions to complete
21+
.execute(function () {
22+
// Use JavaScript to click the button, avoiding sticky header issues
23+
const button = document.querySelector('[data-id="addDeployedContract"]') as HTMLElement
24+
if (button) {
25+
button.scrollIntoView({ behavior: 'auto', block: 'center' })
26+
button.click()
27+
}
28+
})
29+
.waitForElementVisible('[data-id="deployedContractAddressInput"]')
30+
.setValue('[data-id="deployedContractAddressInput"]', address, function () {
31+
if (!isValidFormat || !isValidChecksum) browser.assert.elementPresent('[data-id="addDeployedContractButton"]:disabled')
32+
else if (isAbi) {
33+
browser
34+
.click('[data-id="addDeployedContractButton"]') // Click Add button in dialog
35+
.waitForElementPresent('[data-id="deployedContractsAtAddress-modal-footer-ok-react"]', 5000)
36+
.execute(function () {
37+
const modal = document.querySelector('[data-id="deployedContractsAtAddress-modal-footer-ok-react"]') as any
3238

33-
modal.click()
34-
})
35-
} else {
36-
browser.click({
37-
selector: '//*[@id="runAndDeployAtAddressButtonContainer"]',
38-
locateStrategy: 'xpath'
39-
})
40-
}
41-
callback()
42-
})
39+
modal.click()
40+
})
41+
} else {
42+
browser.click('[data-id="addDeployedContractButton"]') // Click Add button in dialog
43+
}
44+
callback()
45+
})
4346
}
4447

4548
module.exports = addAtAddressInstance

apps/remix-ide-e2e/src/commands/addFile.ts

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ class AddFile extends EventEmitter {
1717

1818
function addFile(browser: NightwatchBrowser, name: string, content: NightwatchContractContent, readMeFile:string, done: VoidFunction) {
1919
const readmeSelector = `li[data-id="treeViewLitreeViewItem${readMeFile}"]`
20+
const anyTreeItemSelector = 'li[data-id^="treeViewLitreeViewItem"]' // Any item in tree
21+
2022
browser
2123
.isVisible({
2224
selector: "//*[@data-id='sidePanelSwapitTitle' and contains(.,'File explorer')]",
@@ -28,12 +30,39 @@ function addFile(browser: NightwatchBrowser, name: string, content: NightwatchCo
2830
browser.clickLaunchIcon('filePanel')
2931
}
3032
})
33+
.waitForElementPresent('[data-test-id="virtuoso-scroller"]', 10000)
34+
.pause(500)
35+
// Ensure file tree is loaded by waiting for at least one tree item
36+
.waitForElementPresent(anyTreeItemSelector, 10000)
37+
.pause(500)
38+
// Force virtuoso to render all items by scrolling to bottom and back
3139
.execute(function () {
3240
const container = document.querySelector('[data-test-id="virtuoso-scroller"]');
33-
container.scrollTop = container.scrollHeight;
41+
if (container) {
42+
// Scroll to bottom to force rendering
43+
container.scrollTop = container.scrollHeight;
44+
}
3445
})
35-
.scrollInto(readmeSelector)
36-
.waitForElementVisible(readmeSelector)
46+
.pause(1000) // Give time for virtuoso to render items
47+
.execute(function () {
48+
const container = document.querySelector('[data-test-id="virtuoso-scroller"]');
49+
if (container) {
50+
// Scroll back to top
51+
container.scrollTop = 0;
52+
}
53+
})
54+
.pause(1000)
55+
// Now wait for README to be present in DOM
56+
.waitForElementPresent(readmeSelector, 10000)
57+
// Use scrollIntoView to make it visible
58+
.execute(function (selector) {
59+
const element = document.querySelector(selector);
60+
if (element) {
61+
element.scrollIntoView({ behavior: 'auto', block: 'center' });
62+
}
63+
}, [readmeSelector])
64+
.pause(500)
65+
.waitForElementVisible(readmeSelector, 10000)
3766
.click(readmeSelector).pause(1000) // focus on root directory
3867
.isVisible({
3968
selector: `//*[@data-id="treeViewLitreeViewItem${name}"]`,
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { NightwatchBrowser } from 'nightwatch'
2+
import EventEmitter from 'events'
3+
4+
class ClearDeployedContract extends EventEmitter {
5+
command (this: NightwatchBrowser, index: number): NightwatchBrowser {
6+
this.api.perform((done: VoidFunction) => {
7+
clearContract(this.api, index, () => {
8+
done()
9+
this.emit('complete')
10+
})
11+
})
12+
return this
13+
}
14+
}
15+
16+
function clearContract (browser: NightwatchBrowser, index: number, callback: VoidFunction) {
17+
browser
18+
.clickLaunchIcon('udapp')
19+
.waitForElementPresent(`[data-id="contractKebabIcon-${index}"]`)
20+
.execute(function (index) {
21+
// Use JavaScript to click the button, avoiding sticky header issues
22+
const optionsMenu = document.querySelector(`[data-id="contractKebabIcon-${index}"]`) as HTMLElement
23+
if (optionsMenu) {
24+
optionsMenu.scrollIntoView({ behavior: 'auto', block: 'center' })
25+
}
26+
}, [index])
27+
.waitForElementVisible(`[data-id="contractKebabIcon-${index}"]`)
28+
.click(`[data-id="contractKebabIcon-${index}"]`) // Click kebab icon
29+
.waitForElementVisible('[data-id="clear"]')
30+
.click('[data-id="clear"]') // Click "Clear" option in kebab menu
31+
.pause(500)
32+
.perform(() => {
33+
callback()
34+
})
35+
}
36+
37+
module.exports = ClearDeployedContract
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { NightwatchBrowser } from 'nightwatch'
2+
import EventEmitter from 'events'
3+
4+
class ClearDeployedContracts extends EventEmitter {
5+
command (this: NightwatchBrowser): NightwatchBrowser {
6+
this.api.perform((done: VoidFunction) => {
7+
clearContracts(this.api, () => {
8+
done()
9+
this.emit('complete')
10+
})
11+
})
12+
return this
13+
}
14+
}
15+
16+
function clearContracts (browser: NightwatchBrowser, callback: VoidFunction) {
17+
browser
18+
.clickLaunchIcon('udapp')
19+
.waitForElementVisible('[data-id="deployedContractsContainer"]')
20+
.waitForElementVisible('[data-id="clearAllDeployedContracts"]')
21+
.pause(500)
22+
.execute(function () {
23+
// Use JavaScript to click the button, avoiding sticky header issues
24+
const clearBtn = document.querySelector('[data-id="clearAllDeployedContracts"]') as HTMLElement
25+
if (clearBtn) {
26+
clearBtn.scrollIntoView({ behavior: 'auto', block: 'center' })
27+
clearBtn.click()
28+
}
29+
})
30+
.waitForElementVisible('[data-id="confirmClearAll"]')
31+
.execute(function () {
32+
// Use JavaScript to click the confirm button
33+
const confirmBtn = document.querySelector('[data-id="confirmClearAll"]') as HTMLElement
34+
if (confirmBtn) {
35+
confirmBtn.scrollIntoView({ behavior: 'auto', block: 'center' })
36+
confirmBtn.click()
37+
}
38+
})
39+
.pause(500)
40+
.perform(() => {
41+
callback()
42+
})
43+
}
44+
45+
module.exports = ClearDeployedContracts

apps/remix-ide-e2e/src/commands/clickFunction.ts

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,31 +7,29 @@ import EventEmitter from 'events'
77
class ClickFunction extends EventEmitter {
88
command(
99
this: NightwatchBrowser,
10-
fnFullName: string,
10+
instanceIndex: number,
11+
functionIndex: number,
1112
expectedInput?: NightwatchClickFunctionExpectedInput
1213
): NightwatchBrowser {
1314
this.api
14-
.waitForElementPresent('.instance *[data-bs-title="' + fnFullName + '"]')
15+
.execute(function (instanceIndex, functionIndex) {
16+
// Use JavaScript to click the button, avoiding sticky header issues
17+
const executeButton = document.querySelector(`[data-id="deployedContractItem-${instanceIndex}-button-${functionIndex}"]`) as HTMLElement
18+
if (executeButton) {
19+
executeButton.scrollIntoView({ behavior: 'auto', block: 'center' })
20+
}
21+
}, [instanceIndex, functionIndex])
1522
.perform(function (client, done) {
16-
client.execute(
17-
function () {
18-
document.querySelector('#runTabView').scrollTop =
19-
document.querySelector('#runTabView').scrollHeight
20-
},
21-
[],
22-
function () {
23-
if (expectedInput) {
24-
client.setValue(
25-
'#runTabView input[data-bs-title="' + expectedInput.types + '"]',
26-
expectedInput.values,
27-
(_) => _
28-
)
29-
}
30-
done()
31-
}
32-
)
23+
if (expectedInput) {
24+
client.setValue(
25+
`[data-id="deployedContractItem-${instanceIndex}-input-${functionIndex}"]`,
26+
expectedInput.values,
27+
(_) => _
28+
)
29+
}
30+
done()
3331
})
34-
.scrollAndClick('.instance *[data-bs-title="' + fnFullName + '"]')
32+
.click(`[data-id="deployedContractItem-${instanceIndex}-button-${functionIndex}"]`)
3533
.pause(2000)
3634
.perform(() => {
3735
this.emit('complete')

apps/remix-ide-e2e/src/commands/clickInstance.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import EventEmitter from 'events'
33

44
class ClickInstance extends EventEmitter {
55
command (this: NightwatchBrowser, index: number): NightwatchBrowser {
6-
const selector = `[data-id="universalDappUiTitleExpander${index}"]`
6+
const selector = `[data-id="deployedContractItem-${index}"]`
77

88
this.api.waitForElementPresent({
99
locateStrategy: 'css selector',

apps/remix-ide-e2e/src/commands/connectToExternalHttpProvider.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,42 @@ class ConnectToExternalHttpProvider extends EventEmitter {
77
(result) => {
88
if (result.status as any === -1) {
99
console.log("No connection to external provider found. Adding one.", url)
10-
browser
10+
this.api
11+
// Close any existing modal
1112
.click({
1213
locateStrategy: 'css selector',
1314
selector: '[data-id="basic-http-provider-modal-footer-ok-react"]',
1415
abortOnFailure: false,
1516
suppressNotFoundErrors: true,
1617
timeout: 5000
1718
})
19+
// Close any open sub-category dropdown first
20+
.click({
21+
locateStrategy: 'css selector',
22+
selector: 'body',
23+
abortOnFailure: false,
24+
suppressNotFoundErrors: true
25+
})
26+
.pause(500)
27+
// Now switch to the provider
1828
.switchEnvironment('basic-http-provider')
19-
.waitForElementPresent('[data-id="basic-http-provider-modal-footer-ok-react"]')
29+
.waitForElementPresent('[data-id="basic-http-provider-modal-footer-ok-react"]', 10000)
30+
.pause(500)
2031
.execute(() => {
21-
(document.querySelector('*[data-id="basic-http-providerModalDialogContainer-react"] input[data-id="modalDialogCustomPromp"]') as any).focus()
32+
const input = document.querySelector('*[data-id="basic-http-providerModalDialogContainer-react"] input[data-id="modalDialogCustomPromp"]') as any
33+
if (input) input.focus()
2234
}, [], () => { })
35+
.clearValue('[data-id="modalDialogCustomPromp"]')
2336
.setValue('[data-id="modalDialogCustomPromp"]', url)
37+
.pause(500)
2438
.modalFooterOKClick('basic-http-provider')
25-
.perform((done) => {
39+
.pause(1000)
40+
.perform((done: VoidFunction) => {
2641
done()
2742
this.emit('complete')
2843
})
2944
} else {
30-
this.api.perform((done) => {
45+
this.api.perform((done: VoidFunction) => {
3146
done()
3247
this.emit('complete')
3348
})

apps/remix-ide-e2e/src/commands/createContract.ts

Lines changed: 43 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,53 @@ class CreateContract extends EventEmitter {
1414
}
1515

1616
function createContract (browser: NightwatchBrowser, inputParams: string, callback: VoidFunction) {
17+
browser.execute(function () {
18+
// Use JavaScript to click the button, avoiding sticky header issues
19+
const deployButton = document.querySelector('[data-id="deployButton"]') as HTMLElement
20+
if (deployButton) {
21+
deployButton.scrollIntoView({ behavior: 'auto', block: 'center' })
22+
}
23+
})
1724
if (inputParams) {
18-
browser.setValue('.udapp_contractActionsContainerSingle > input', inputParams, function () {
19-
browser
20-
.pause(1000) // wait to get the button enabled
21-
.waitForElementVisible('.udapp_contractActionsContainerSingle button')
22-
.click('.udapp_contractActionsContainerSingle button').pause(500).perform(function () { callback() })
25+
const params = inputParams.split(',')
26+
27+
// Get the number of constructor inputs
28+
browser.execute(function () {
29+
const inputs = document.querySelectorAll('input[data-id^="constructorInput"]')
30+
return inputs.length
31+
}, [], function (result: any) {
32+
const inputCount = result.value
33+
34+
// Fill each input sequentially using Nightwatch setValue
35+
const fillInputs = (index: number) => {
36+
if (index >= inputCount) {
37+
// All inputs filled, now deploy
38+
browser
39+
.pause(500) // wait for React to update
40+
.waitForElementVisible('[data-id="deployButton"]')
41+
.click('[data-id="deployButton"]')
42+
.pause(500)
43+
.perform(function () { callback() })
44+
return
45+
}
46+
47+
const selector = `input[data-id="constructorInput${index}"]`
48+
const value = params[index]
49+
50+
browser
51+
.waitForElementVisible(selector, 5000)
52+
.clearValue(selector)
53+
.setValue(selector, value)
54+
.pause(1000)
55+
.perform(() => fillInputs(index + 1))
56+
}
57+
58+
fillInputs(0)
2359
})
2460
} else {
2561
browser
26-
.waitForElementVisible('.udapp_contractActionsContainerSingle button')
27-
.click('.udapp_contractActionsContainerSingle button')
62+
.waitForElementVisible('[data-id="deployButton"]')
63+
.click('[data-id="deployButton"]')
2864
.pause(500)
2965
.perform(function () { callback() })
3066
}

0 commit comments

Comments
 (0)