Skip to content

Commit d106be6

Browse files
authored
Merge branch 'master' into starkNet
2 parents 9a7bbd4 + 13473ff commit d106be6

File tree

28 files changed

+488
-106
lines changed

28 files changed

+488
-106
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { NightwatchBrowser } from 'nightwatch'
2+
import EventEmitter from 'events'
3+
4+
class CurrentSelectedFileIs extends EventEmitter {
5+
command (this: NightwatchBrowser, value: string): NightwatchBrowser {
6+
this.api
7+
.waitForElementContainsText('*[data-id="tabs-component"] *[data-id="tab-active"]', value)
8+
.perform(() => {
9+
this.emit('complete')
10+
})
11+
return this
12+
}
13+
}
14+
15+
module.exports = CurrentSelectedFileIs

apps/remix-ide-e2e/src/tests/editor.test.ts

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,33 +147,98 @@ module.exports = {
147147
.waitForElementContainsText('.contextview .type', 'uint256')
148148
.waitForElementContainsText('.contextview .name', 'number')
149149
.click('.contextview [data-action="previous"]') // declaration
150+
.pause(1000)
150151
.execute(() => {
151152
return (document.getElementById('editorView') as any).getCursorPosition()
152153
}, [], (result) => {
153154
console.log('result', result)
154155
browser.assert.equal(result.value, '180')
155156
})
156157
.click('.contextview [data-action="next"]') // back to the initial state
158+
.pause(1000)
157159
.execute(() => {
158160
return (document.getElementById('editorView') as any).getCursorPosition()
159161
}, [], (result) => {
160162
console.log('result', result)
161163
browser.assert.equal(result.value, '323')
162164
})
163165
.click('.contextview [data-action="next"]') // next reference
166+
.pause(1000)
164167
.execute(() => {
165168
return (document.getElementById('editorView') as any).getCursorPosition()
166169
}, [], (result) => {
167170
console.log('result', result)
168171
browser.assert.equal(result.value, '489')
169172
})
170173
.click('.contextview [data-action="gotoref"]') // back to the declaration
174+
.pause(1000)
171175
.execute(() => {
172176
return (document.getElementById('editorView') as any).getCursorPosition()
173177
}, [], (result) => {
174178
console.log('result', result)
175179
browser.assert.equal(result.value, '180')
176180
})
181+
},
182+
183+
'Should display the context view, loop over "Owner" by switching file #group2': function (browser: NightwatchBrowser) {
184+
browser
185+
.clickLaunchIcon('solidity')
186+
.click('[for="autoCompile"]') // disable auto compile
187+
.openFile('contracts')
188+
.openFile('contracts/3_Ballot.sol')
189+
.waitForElementVisible('#editorView')
190+
.setEditorValue(BallotWithARefToOwner)
191+
.clickLaunchIcon('solidity')
192+
.click('*[data-id="compilerContainerCompileBtn"]') // compile
193+
.pause(2000)
194+
.execute(() => {
195+
(document.getElementById('editorView') as any).gotoLine(14, 6)
196+
}, [], () => {})
197+
.waitForElementVisible('.contextview')
198+
.waitForElementContainsText('.contextview .type', 'ContractDefinition')
199+
.waitForElementContainsText('.contextview .name', 'Owner')
200+
.click('.contextview [data-action="next"]')
201+
.pause(1000)
202+
.execute(() => {
203+
return (document.getElementById('editorView') as any).getCursorPosition()
204+
}, [], (result) => {
205+
console.log('result', result)
206+
browser.assert.equal(result.value, '1061')
207+
})
208+
.click('.contextview [data-action="next"]')
209+
.pause(1000)
210+
.execute(() => {
211+
return (document.getElementById('editorView') as any).getCursorPosition()
212+
}, [], (result) => {
213+
console.log('result', result)
214+
browser.assert.equal(result.value, '122')
215+
})
216+
.currentSelectedFileIs('2_Owner.sol') // make sure the current file has been properly changed
217+
.click('.contextview [data-action="next"]')
218+
.pause(1000)
219+
.execute(() => {
220+
return (document.getElementById('editorView') as any).getCursorPosition()
221+
}, [], (result) => {
222+
console.log('result', result)
223+
browser.assert.equal(result.value, '211')
224+
})
225+
.click('.contextview [data-action="next"]')
226+
.currentSelectedFileIs('3_Ballot.sol')
227+
.pause(1000)
228+
.execute(() => {
229+
return (document.getElementById('editorView') as any).getCursorPosition()
230+
}, [], (result) => {
231+
console.log('result', result)
232+
browser.assert.equal(result.value, '1061')
233+
})
234+
.click('.contextview [data-action="gotoref"]') // go to the declaration
235+
.pause(1000)
236+
.execute(() => {
237+
return (document.getElementById('editorView') as any).getCursorPosition()
238+
}, [], (result) => {
239+
console.log('result', result)
240+
browser.assert.equal(result.value, '122')
241+
})
177242
.end()
178243
}
179244
}
@@ -281,3 +346,149 @@ contract Storage {
281346
return number;
282347
}
283348
}`
349+
350+
const BallotWithARefToOwner = `
351+
352+
353+
// SPDX-License-Identifier: GPL-3.0
354+
355+
pragma solidity >=0.7.0 <0.9.0;
356+
357+
import "./2_Owner.sol";
358+
359+
/**
360+
* @title Ballot
361+
* @dev Implements voting process along with vote delegation
362+
*/
363+
contract Ballot {
364+
Owner c;
365+
struct Voter {
366+
uint weight; // weight is accumulated by delegation
367+
bool voted; // if true, that person already voted
368+
address delegate; // person delegated to
369+
uint vote; // index of the voted proposal
370+
}
371+
372+
struct Proposal {
373+
// If you can limit the length to a certain number of bytes,
374+
// always use one of bytes1 to bytes32 because they are much cheaper
375+
bytes32 name; // short name (up to 32 bytes)
376+
uint voteCount; // number of accumulated votes
377+
}
378+
379+
address public chairperson;
380+
381+
mapping(address => Voter) public voters;
382+
383+
Proposal[] public proposals;
384+
385+
/**
386+
* @dev Create a new ballot to choose one of 'proposalNames'.
387+
* @param proposalNames names of proposals
388+
*/
389+
constructor(bytes32[] memory proposalNames) {
390+
c = new Owner();
391+
chairperson = msg.sender;
392+
voters[chairperson].weight = 1;
393+
394+
for (uint i = 0; i < proposalNames.length; i++) {
395+
// 'Proposal({...})' creates a temporary
396+
// Proposal object and 'proposals.push(...)'
397+
// appends it to the end of 'proposals'.
398+
proposals.push(Proposal({
399+
name: proposalNames[i],
400+
voteCount: 0
401+
}));
402+
}
403+
}
404+
405+
/**
406+
* @dev Give 'voter' the right to vote on this ballot. May only be called by 'chairperson'.
407+
* @param voter address of voter
408+
*/
409+
function giveRightToVote(address voter) public {
410+
require(
411+
msg.sender == chairperson,
412+
"Only chairperson can give right to vote."
413+
);
414+
require(
415+
!voters[voter].voted,
416+
"The voter already voted."
417+
);
418+
require(voters[voter].weight == 0);
419+
voters[voter].weight = 1;
420+
}
421+
422+
/**
423+
* @dev Delegate your vote to the voter 'to'.
424+
* @param to address to which vote is delegated
425+
*/
426+
function delegate(address to) public {
427+
Voter storage sender = voters[msg.sender];
428+
require(!sender.voted, "You already voted.");
429+
require(to != msg.sender, "Self-delegation is disallowed.");
430+
431+
while (voters[to].delegate != address(0)) {
432+
to = voters[to].delegate;
433+
434+
// We found a loop in the delegation, not allowed.
435+
require(to != msg.sender, "Found loop in delegation.");
436+
}
437+
sender.voted = true;
438+
sender.delegate = to;
439+
Voter storage delegate_ = voters[to];
440+
if (delegate_.voted) {
441+
// If the delegate already voted,
442+
// directly add to the number of votes
443+
proposals[delegate_.vote].voteCount += sender.weight;
444+
} else {
445+
// If the delegate did not vote yet,
446+
// add to her weight.
447+
delegate_.weight += sender.weight;
448+
}
449+
}
450+
451+
/**
452+
* @dev Give your vote (including votes delegated to you) to proposal 'proposals[proposal].name'.
453+
* @param proposal index of proposal in the proposals array
454+
*/
455+
function vote(uint proposal) public {
456+
Voter storage sender = voters[msg.sender];
457+
require(sender.weight != 0, "Has no right to vote");
458+
require(!sender.voted, "Already voted.");
459+
sender.voted = true;
460+
sender.vote = proposal;
461+
462+
// If 'proposal' is out of the range of the array,
463+
// this will throw automatically and revert all
464+
// changes.
465+
proposals[proposal].voteCount += sender.weight;
466+
}
467+
468+
/**
469+
* @dev Computes the winning proposal taking all previous votes into account.
470+
* @return winningProposal_ index of winning proposal in the proposals array
471+
*/
472+
function winningProposal() public view
473+
returns (uint winningProposal_)
474+
{
475+
uint winningVoteCount = 0;
476+
for (uint p = 0; p < proposals.length; p++) {
477+
if (proposals[p].voteCount > winningVoteCount) {
478+
winningVoteCount = proposals[p].voteCount;
479+
winningProposal_ = p;
480+
}
481+
}
482+
}
483+
484+
/**
485+
* @dev Calls winningProposal() function to get the index of the winner contained in the proposals array and then
486+
* @return winnerName_ the name of the winner
487+
*/
488+
function winnerName() public view
489+
returns (bytes32 winnerName_)
490+
{
491+
winnerName_ = proposals[winningProposal()].name;
492+
}
493+
}
494+
`

apps/remix-ide-e2e/src/tests/plugin_api.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,18 @@ module.exports = {
149149
await clickAndCheckLog(browser, 'udapp:getAccounts', '0x5B38Da6a701c568545dCfcB03FcB875f56beddC4', null, null)
150150
},
151151

152+
'Should select another provider #group1': async function (browser: NightwatchBrowser) {
153+
await clickAndCheckLog(browser, 'udapp:setEnvironmentMode', null, null, { context: 'vm', fork: 'berlin' })
154+
await browser
155+
.frameParent()
156+
.useCss()
157+
.clickLaunchIcon('udapp')
158+
.waitForElementContainsText('#selectExEnvOptions option:checked', 'JavaScript VM (Berlin)')
159+
.clickLaunchIcon('localPlugin')
160+
.useXpath()
161+
// @ts-ignore
162+
.frame(0)
163+
},
152164
// context menu item
153165

154166
'Should create context menu item #group1': async function (browser: NightwatchBrowser) {

apps/remix-ide-e2e/src/tests/url.spec.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,13 @@ module.exports = {
7777
'Should load using URL compiler params': function (browser: NightwatchBrowser) {
7878
browser
7979
.pause(5000)
80-
.url('http://127.0.0.1:8080/#optimize=true&runs=300&autoCompile=true&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js')
80+
.url('http://127.0.0.1:8080/#optimize=true&runs=300&autoCompile=true&evmVersion=istanbul&version=soljson-v0.7.4+commit.3f05b770.js&language=Yul')
8181
.refresh()
8282
.pause(5000)
8383
.clickLaunchIcon('solidity')
8484
.assert.containsText('#versionSelector option[data-id="selected"]', '0.7.4+commit.3f05b770')
8585
.assert.containsText('#evmVersionSelector option[data-id="selected"]', 'istanbul')
86+
.assert.containsText('#compilierLanguageSelector option[data-id="selected"]', 'Yul')
8687
.verify.elementPresent('#optimize:checked')
8788
.verify.elementPresent('#autoCompile:checked')
8889
.verify.attributeEquals('#runs', 'value', '300')

apps/remix-ide-e2e/src/types/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ declare module 'nightwatch' {
6161
acceptAndRemember (this: NightwatchBrowser, remember: boolean, accept: boolean): NightwatchBrowser
6262
clearConsole (this: NightwatchBrowser): NightwatchBrowser
6363
clearTransactions (this: NightwatchBrowser): NightwatchBrowser
64+
currentSelectedFileIs (name: string): NightwatchBrowser
6465
}
6566

6667
export interface NightwatchBrowser {

apps/remix-ide/src/app/editor/editor.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -438,7 +438,7 @@ class Editor extends Plugin {
438438
if (!filePath) return
439439
filePath = await this.call('fileManager', 'getPathFromUrl', filePath)
440440
filePath = filePath.file
441-
if (!this.sessions[filePath]) throw new Error('file not found' + filePath)
441+
if (!this.sessions[filePath]) return
442442
const path = filePath || this.currentFile
443443

444444
const { from } = this.currentRequest

apps/remix-ide/src/app/files/fileManager.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ class FileManager extends Plugin {
470470
}
471471

472472
currentFile () {
473-
return this._deps.config.get('currentFile')
473+
return this.editor.current()
474474
}
475475

476476
async closeAllFiles () {

apps/remix-ide/src/app/plugins/remixd-handle.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,11 +142,11 @@ function remixdDialog () {
142142
</div>
143143
<div className='mb-2 text-break'>
144144
If you are just looking for the remixd command, here it is:
145-
<br></br><br></br><b>${commandText}</b>
145+
<br></br><br></br><b>{commandText}</b>
146146
<CopyToClipboard data-id='remixdCopyCommand' content={commandText}></CopyToClipboard>
147147
</div>
148148
<div className='mb-2 text-break'>
149-
When connected, a session will be started between <em>${window.location.origin}</em> and your local file system at <i>ws://127.0.0.1:65520</i>.
149+
When connected, a session will be started between <em>{window.location.origin}</em> and your local file system at <i>ws://127.0.0.1:65520</i>.
150150
The shared folder will be in the "File Explorers" workspace named "localhost".
151151
<br/>Read more about other <a target="_blank" href="https://remix-ide.readthedocs.io/en/latest/remixd.html#ports-usage">Remixd ports usage</a>
152152
</div>
@@ -155,7 +155,7 @@ function remixdDialog () {
155155
</div>
156156
<div className='mb-2 text-break'>
157157
<h6 className="text-danger">
158-
Before using, make sure remixd version is latest i.e. <b>${remixdVersion}</b>
158+
Before using, make sure remixd version is latest i.e. <b>v{remixdVersion}</b>
159159
<br></br><a target="_blank" href="https://remix-ide.readthedocs.io/en/latest/remixd.html#update-to-the-latest-remixd">Read here how to update it</a>
160160
</h6>
161161
</div>

libs/remix-core-plugin/src/lib/editor-context-listener.ts

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,6 @@ export class EditorContextListener extends Plugin {
8484

8585
async _highlightItems (cursorPosition, compilationResult, file) {
8686
if (this.currentPosition === cursorPosition) return
87-
if (this.currentFile !== file) {
88-
this.currentFile = file
89-
this.currentPosition = cursorPosition
90-
return
91-
}
9287
this._stopHighlighting()
9388
this.currentPosition = cursorPosition
9489
this.currentFile = file
@@ -122,9 +117,13 @@ export class EditorContextListener extends Plugin {
122117
async _highlight (node, compilationResult) {
123118
if (!node) return
124119
const position = sourceMappingDecoder.decode(node.src)
120+
const fileTarget = compilationResult.getSourceName(position.file)
121+
const nodeFound = this._activeHighlights.find((el) => el.fileTarget === fileTarget && el.position.file === position.file && el.position.length === position.length && el.position.start === position.start)
122+
if (nodeFound) return // if the content is already highlighted, do nothing.
123+
125124
await this._highlightInternal(position, node, compilationResult)
126125
if (compilationResult && compilationResult.languageversion.indexOf('soljson') === 0) {
127-
this._activeHighlights.push({ position, fileTarget: compilationResult.getSourceName(position.file), nodeId: node.id })
126+
this._activeHighlights.push({ position, fileTarget, nodeId: node.id })
128127
}
129128
}
130129

@@ -204,13 +203,16 @@ export class EditorContextListener extends Plugin {
204203
}
205204

206205
_loadContractInfos (node) {
206+
const path = (this.nodes.length && this.nodes[0].absolutePath) || this.results.source.target
207207
for (const i in this.nodes) {
208208
if (this.nodes[i].id === node.scope) {
209209
const contract = this.nodes[i]
210-
this.contract = this.results.data.contracts[this.results.source.target][contract.name]
211-
this.estimationObj = this.contract.evm.gasEstimates
212-
this.creationCost = this.estimationObj === null ? '-' : this.estimationObj.creation.totalCost
213-
this.codeDepositCost = this.estimationObj === null ? '-' : this.estimationObj.creation.codeDepositCost
210+
this.contract = this.results.data.contracts[path][contract.name]
211+
if (contract) {
212+
this.estimationObj = this.contract.evm.gasEstimates
213+
this.creationCost = this.estimationObj === null ? '-' : this.estimationObj.creation.totalCost
214+
this.codeDepositCost = this.estimationObj === null ? '-' : this.estimationObj.creation.codeDepositCost
215+
}
214216
}
215217
}
216218
}

0 commit comments

Comments
 (0)