Merge pull request #4747 from ethereum/vyper-patch-007

Vyper-patch-007
pull/4734/merge
Joseph Izang 7 months ago committed by GitHub
commit e59f1bdaa7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 74
      apps/remix-ide-e2e/src/commands/addFileSnekmate.ts
  2. 12
      apps/remix-ide-e2e/src/commands/openFile.ts
  3. 58
      apps/remix-ide-e2e/src/tests/pinned_contracts.test.ts
  4. 54
      apps/remix-ide-e2e/src/tests/vyper_api.test.ts
  5. 1
      apps/remix-ide-e2e/src/types/index.d.ts
  6. 4
      apps/vyper/src/app/app.tsx
  7. 8
      apps/vyper/src/app/utils/compiler.tsx
  8. 8
      apps/vyper/src/app/utils/remix-client.tsx

@ -0,0 +1,74 @@
import EventEmitter from 'events'
import { NightwatchBrowser, NightwatchContractContent } from 'nightwatch'
class AddFileSnekmate extends EventEmitter {
command(this: NightwatchBrowser, name: string, content: NightwatchContractContent): NightwatchBrowser {
this.api.perform((done) => {
addFileSnekmate(this.api, name, content, () => {
done()
this.emit('complete')
})
})
return this
}
}
function addFileSnekmate(browser: NightwatchBrowser, name: string, content: NightwatchContractContent, done: VoidFunction) {
browser
.isVisible({
selector: "//*[@data-id='sidePanelSwapitTitle' and contains(.,'File explorer')]",
locateStrategy: 'xpath',
suppressNotFoundErrors: true,
timeout: 1000
}, (okVisible) => {
if (!okVisible.value) {
browser.clickLaunchIcon('filePanel')
}
})
.scrollInto('li[data-id="treeViewLitreeViewItemREADME.txt"]')
.waitForElementVisible('li[data-id="treeViewLitreeViewItemLICENSE"]')
.click('li[data-id="treeViewLitreeViewItemLICENSE"]').pause(1000) // focus on root directory
.isVisible({
selector: `//*[@data-id="treeViewLitreeViewItem${name}"]`,
locateStrategy: 'xpath',
abortOnFailure: false,
suppressNotFoundErrors: true,
timeout: 2000
}, (okVisible) => {
// @ts-ignore
// status === -1 means the element is not visible, 0 means it is visible.
if (okVisible.status === 0) {
browser.openFile(name)
.perform(function () {
done()
})
} else {
browser.click('[data-id="fileExplorerNewFilecreateNewFile"]')
.waitForElementContainsText('*[data-id$="fileExplorerTreeItemInput"]', '', 60000)
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', name)
.sendKeys('*[data-id$="fileExplorerTreeItemInput"]', browser.Keys.ENTER)
// isvisible is protocol action called isDisplayed https://www.selenium.dev/selenium/docs/api/java/org/openqa/selenium/WebElement.html#isDisplayed--
.isVisible({
selector: `li[data-id="treeViewLitreeViewItem${name}"]`,
abortOnFailure: false,
suppressNotFoundErrors: true,
timeout: 60000
})
.waitForElementVisible({
selector: `//*[@data-id='tab-active' and contains(@data-path, "${name}")]`,
locateStrategy: 'xpath'
})
.setEditorValue(content.content)
.getEditorValue((result) => {
if(result != content.content) {
browser.setEditorValue(content.content)
}
})
.perform(function () {
done()
})
}
})
}
module.exports = AddFileSnekmate

@ -34,12 +34,12 @@ function openFile (browser: NightwatchBrowser, name: string, done: VoidFunction)
})
})
.waitForElementVisible('li[data-id="treeViewLitreeViewItem' + name + '"', 60000)
.click('li[data-id="treeViewLitreeViewItem' + name + '"')
.pause(2000)
.perform(() => {
done()
})
.waitForElementVisible('li[data-id="treeViewLitreeViewItem' + name + '"', 60000)
.click('li[data-id="treeViewLitreeViewItem' + name + '"')
.pause(2000)
.perform(() => {
done()
})
}
module.exports = OpenFile

@ -29,7 +29,7 @@ module.exports = {
.assert.textContains('*[data-id="deployAndRunNoInstanceText"]', 'Currently you have no unpinned contracts to interact with.')
.assert.not.elementPresent('*[data-id="NoPinnedInstanceText"]')
.assert.elementPresent('*[data-id="pinnedInstance0xd9145CCE52D386f254917e481eB44e9943F39138"]')
},
},
'Test pinned contract loading on environment change #group1': function (browser: NightwatchBrowser) {
browser
.switchEnvironment('vm-shanghai')
@ -41,7 +41,7 @@ module.exports = {
.assert.textContains('*[data-id="pinnedContractsSublabel"]', '(network: vm-cancun)')
.assert.not.elementPresent('*[data-id="NoPinnedInstanceText"]')
.assert.elementPresent('*[data-id="pinnedInstance0xd9145CCE52D386f254917e481eB44e9943F39138"]')
},
},
'Interact with pinned contract #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="universalDappUiTitleExpander0"]')
@ -51,23 +51,23 @@ module.exports = {
.assert.textContains('*[data-id="instanceContractFilePath"]', 'default_workspace/contracts/1_Storage.sol')
.clickFunction('retrieve - call')
.testFunction('last',
{
to: 'Storage.retrieve() 0xd9145CCE52D386f254917e481eB44e9943F39138',
'decoded output': { "0": "uint256: 0" }
})
{
to: 'Storage.retrieve() 0xd9145CCE52D386f254917e481eB44e9943F39138',
'decoded output': { "0": "uint256: 0" }
})
.clickFunction('store - transact (not payable)', { types: 'uint256 num', values: '35' })
.testFunction('last',
{
status: '0x1 Transaction mined and execution succeed',
'decoded input': { "uint256 num": "35" }
})
{
status: '0x1 Transaction mined and execution succeed',
'decoded input': { "uint256 num": "35" }
})
.clickFunction('retrieve - call')
.testFunction('last',
{
to: 'Storage.retrieve() 0xd9145CCE52D386f254917e481eB44e9943F39138',
'decoded output': { "0": "uint256: 35" }
})
},
{
to: 'Storage.retrieve() 0xd9145CCE52D386f254917e481eB44e9943F39138',
'decoded output': { "0": "uint256: 35" }
})
},
'Unpin & interact #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="universalDappUiUdappUnpin"]')
@ -78,23 +78,23 @@ module.exports = {
.assert.not.elementPresent('*[data-id="instanceContractFilePath"]')
.clickFunction('retrieve - call')
.testFunction('last',
{
to: 'Storage.retrieve() 0xd9145CCE52D386f254917e481eB44e9943F39138',
'decoded output': { "0": "uint256: 35" }
})
{
to: 'Storage.retrieve() 0xd9145CCE52D386f254917e481eB44e9943F39138',
'decoded output': { "0": "uint256: 35" }
})
.clickFunction('store - transact (not payable)', { types: 'uint256 num', values: '55' })
.testFunction('last',
{
status: '0x1 Transaction mined and execution succeed',
'decoded input': { "uint256 num": "55" }
})
{
status: '0x1 Transaction mined and execution succeed',
'decoded input': { "uint256 num": "55" }
})
.clickFunction('retrieve - call')
.testFunction('last',
{
to: 'Storage.retrieve() 0xd9145CCE52D386f254917e481eB44e9943F39138',
'decoded output': { "0": "uint256: 55" }
})
},
{
to: 'Storage.retrieve() 0xd9145CCE52D386f254917e481eB44e9943F39138',
'decoded output': { "0": "uint256: 55" }
})
},
'Re-pin & delete immediately #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="universalDappUiUdappPin"]')
@ -102,5 +102,5 @@ module.exports = {
.click('*[data-id="universalDappUiUdappDelete"]')
.assert.textContains('*[data-id="NoPinnedInstanceText"]', 'No pinned contracts found for selected workspace & network')
.assert.textContains('*[data-id="deployAndRunNoInstanceText"]', 'Currently you have no unpinned contracts to interact with.')
},
},
}

@ -27,28 +27,30 @@ module.exports = {
.frameParent()
.clickLaunchIcon('filePanel')
.waitForElementVisible({
selector: "//*[@data-id='workspacesSelect' and contains(.,'vyper-lang')]",
selector: "//*[@data-id='workspacesSelect' and contains(.,'snekmate')]",
locateStrategy: 'xpath',
timeout: 60000
})
.currentWorkspaceIs('vyper-lang')
.currentWorkspaceIs('snekmate')
.waitForElementVisible({
selector: "//*[@data-id='treeViewLitreeViewItemexamples' and contains(.,'examples')]",
selector: "//*[@data-id='treeViewLitreeViewItemsrc' and contains(.,'src')]",
locateStrategy: 'xpath',
timeout: 60000
})
.openFile('examples')
.openFile('examples/auctions')
.openFile('examples/auctions/blind_auction.vy')
.openFile('src')
.openFile('src/snekmate')
.openFile('src/snekmate/tokens')
.openFile('src/snekmate/tokens/ERC721.vy')
},
// 'Add vyper file to run tests #group1': function (browser: NightwatchBrowser) {
// browser.addFile('TestBallot.sol', sources[0]['TestBallot.sol'])
// },
'@sources': () => sources,
'Context menu click to compile blind_auction should succeed #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="treeViewLitreeViewItemexamples/auctions/blind_auction.vy"]')
.rightClick('*[data-id="treeViewLitreeViewItemexamples/auctions/blind_auction.vy"]')
.addFileSnekmate('blind_auction.vy', sources[0]['blindAuction'])
.click('*[data-id="treeViewLitreeViewItemblind_auction.vy"]')
.rightClick('*[data-id="treeViewLitreeViewItemblind_auction.vy"]')
.waitForElementPresent('[data-id="contextMenuItemvyper"]')
.click('[data-id="contextMenuItemvyper"]')
.clickLaunchIcon('vyper')
@ -145,6 +147,33 @@ module.exports = {
browser.verifyCallReturnValue(contractAddress, ['0:uint256: 0'])
.perform(() => done())
})
},
'Compile Ownable contract from snekmate #group1': function (browser: NightwatchBrowser) {
let contractAddress
browser
.frameParent()
.clickLaunchIcon('filePanel')
.switchWorkspace('snekmate')
.openFile('src')
.openFile('src/snekmate')
.openFile('src/snekmate/auth')
.openFile('src/snekmate/auth/Ownable.vy')
.rightClick('*[data-id="treeViewLitreeViewItemsrc/snekmate/auth/Ownable.vy"]')
.waitForElementVisible('*[data-id="contextMenuItemvyper"]')
.click('*[data-id="contextMenuItemvyper"]')
.clickLaunchIcon('vyper')
// @ts-ignore
.frame(0)
.click('[data-id="compile"]')
.waitForElementVisible({
selector:'[data-id="compilation-details"]',
timeout: 60000
})
.click('[data-id="compilation-details"]')
.frameParent()
.waitForElementVisible('[data-id="copy-abi"]')
.end()
}
}
@ -180,8 +209,9 @@ def _createPokemon(_name: String[32], _dna: uint256, _HP: uint256):
wins: 0
})
self.totalPokemonCount += 1`
const sources = [{
const blindAuction = `
'blindAuction' : { content: `
# Blind Auction. Adapted to Vyper from [Solidity by Example](https://github.com/ethereum/solidity/blob/develop/docs/solidity-by-example.rst#blind-auction-1)
#pragma version ^0.3.10
@ -358,4 +388,6 @@ def auctionEnd():
# Transfer funds to beneficiary
send(self.beneficiary, self.highestBid)
`
`}
}
]

@ -73,6 +73,7 @@ declare module 'nightwatch' {
waitForElementNotContainsText: (id: string, value: string, timeout: number = 10000) => NightwatchBrowser
hideToolTips: (this: NightwatchBrowser) => NightwatchBrowser
enableClipBoard: () => NightwatchBrowser
addFileSnekmate: (name: string, content: NightwatchContractContent) => NightwatchBrowser
}
export interface NightwatchBrowser {

@ -117,9 +117,9 @@ const App = () => {
<main id="vyper-plugin">
<section>
<div className="px-3 pt-3 mb-3 w-100">
<CustomTooltip placement="bottom" tooltipText="Clone Vyper examples. Switch to the File Explorer to see the examples.">
<CustomTooltip placement="bottom" tooltipText="Clone a repo of Vyper examples. Switch to the File Explorer to see the examples.">
<Button data-id="add-repository" className="w-100 btn btn-secondary" onClick={() => remixClient.cloneVyperRepo()}>
Clone Vyper examples repository
Clone a repo of Vyper examples
</Button>
</CustomTooltip>
</div>

@ -144,14 +144,18 @@ const compileReturnType = (output, contract) => {
const fixContractContent = (content: string) => {
if (content.length === 0) return
const pragmaFound = content.includes('#pragma version ^0.3.10')
const wrongpragmaFound = content.includes('# pragma version ^0.3.10')
const evmVerFound = content.includes('#pragma evm-version shanghai')
const pragma = '#pragma version ^0.3.10'
const evmVer = '#pragma evm-version shanghai'
if (!evmVerFound) {
if (evmVerFound === false) {
content = `${evmVer}\n${content}`
}
if (!pragmaFound) {
if (wrongpragmaFound === true) {
content = content.replace('# pragma version ^0.3.10', '')
}
if (pragmaFound === false ) {
content = `${pragma}\n${content}`
}
return content

@ -80,20 +80,20 @@ export class RemixClient extends PluginClient {
async cloneVyperRepo() {
try {
// @ts-ignore
this.call('notification', 'toast', 'cloning Vyper repository...')
this.call('notification', 'toast', 'cloning Snekmate Vyper repository...')
await this.call('manager', 'activatePlugin', 'dGitProvider')
await this.call(
'dGitProvider',
'clone',
{url: 'https://github.com/vyperlang/vyper', token: null, branch: 'v0.3.10'},
{url: 'https://github.com/pcaversaccio/snekmate', token: null, branch: 'v0.0.5'},
// @ts-ignore
'vyper-lang'
'snekmate'
)
this.call(
// @ts-ignore
'notification',
'toast',
'Vyper repository cloned, the workspace Vyper has been created.'
'Snekmate Vyper repository cloned, the workspace snekmate has been created.'
)
} catch (e) {
// @ts-ignore

Loading…
Cancel
Save