diff --git a/apps/remix-ide-e2e/src/commands/clickElementAtPosition.ts b/apps/remix-ide-e2e/src/commands/clickElementAtPosition.ts index 7fb12e8dfe..7cf22cbabc 100644 --- a/apps/remix-ide-e2e/src/commands/clickElementAtPosition.ts +++ b/apps/remix-ide-e2e/src/commands/clickElementAtPosition.ts @@ -14,7 +14,7 @@ class ClickElement extends EventEmitter { } function _clickElement (browser: NightwatchBrowser, cssSelector: string, index: number, forceSelectIfUnselected: boolean, cb: VoidFunction) { - browser.waitForElementPresent(cssSelector) + browser.waitForElementPresent(cssSelector, 5000) .execute(function (cssSelector: string, index: number, forceSelectIfUnselected: boolean) { const elem = document.querySelectorAll(cssSelector)[index] as HTMLElement if (forceSelectIfUnselected) { diff --git a/apps/remix-ide-e2e/src/tests/editorAutoComplete.test.ts b/apps/remix-ide-e2e/src/tests/editorAutoComplete.test.ts index 9e09df0e8b..5a23048b59 100644 --- a/apps/remix-ide-e2e/src/tests/editorAutoComplete.test.ts +++ b/apps/remix-ide-e2e/src/tests/editorAutoComplete.test.ts @@ -216,7 +216,7 @@ module.exports = { .waitForElementVisible(autoCompleteLineElement('importedbook')) .waitForElementVisible(autoCompleteLineElement('importpublicstring')) .waitForElementVisible(autoCompleteLineElement('publicimport')) - // no private + // no private .waitForElementNotPresent(autoCompleteLineElement('importprivatestring')) .waitForElementNotPresent(autoCompleteLineElement('privateimport')) // no internal @@ -523,4 +523,4 @@ module.exports = { .sendKeys(this.Keys.ENTER) }) } -} \ No newline at end of file +} diff --git a/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts b/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts index 5e7284368a..6a7840c6cd 100644 --- a/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts +++ b/apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts @@ -152,9 +152,12 @@ module.exports = { .waitForElementPresent('*[data-id="verticalIconsKindfilePanel"]') .addFile('myTests/simple_storage_test.sol', sources[0]['tests/simple_storage_test.sol']) .clickLaunchIcon('solidityUnitTesting') - .clearValue('*[data-id="uiPathInput"]') - .setValue('*[data-id="uiPathInput"]', 'myTests') + .execute(() => { + const myQuery: any = document.getElementById('utPath') + myQuery.value = 'myTests' + }) .click('*[data-id="testTabGenerateTestFolder"]') + .saveScreenshot('./reports/screenshots/changeCurrentPathg3.png') .clickElementAtPosition('.singleTest', 0, { forceSelectIfUnselected: true }) .scrollAndClick('*[data-id="testTabRunTestsTabRunAction"]') .waitForElementPresent('*[data-id="testTabSolidityUnitTestsOutputheader"]', 60000) @@ -359,15 +362,15 @@ const sources = [ contract SimpleStorage { uint public storedData; - + constructor() { storedData = 100; } - + function set(uint x) public { storedData = x; } - + function get() public view returns (uint retVal) { return storedData; } @@ -408,7 +411,7 @@ const sources = [ pragma solidity >=0.4.22 <0.9.0; contract Kickstarter { enum State { Started, Completed } - + struct Project { address owner; string name; @@ -420,10 +423,10 @@ const sources = [ } uint numProjects; Project[] public projects; - + constructor() { } - + function createProject(string memory name, uint goal) public { projects.push(); // new line Project storage project = projects[projects.length - 1]; @@ -432,28 +435,28 @@ const sources = [ project.owner = msg.sender; project.state = State.Started; } - + function fundProject(uint projectId) payable public { Project storage project = projects[projectId]; // require project exists // PLEASE CHECK / or erase // not this: require(projects[projectId].exists, "the project must exist to be funded"); - + // require for... underflow/overflow protection project.funders[msg.sender] += msg.value; project.amountContributed += msg.value; project.fundsAvailable += msg.value; - + if (project.amountContributed >= project.goal) { project.state = State.Completed; } } - + // this function is here because we can't use web3 when using the VM function getContractBalance() public view returns(uint balance) { return address(this).balance; } - + } ` }, @@ -470,13 +473,13 @@ const sources = [ enum State { Started, Completed } Kickstarter kickstarter; - + function beforeAll () public { kickstarter = new Kickstarter(); kickstarter.createProject("ProjectA", 123000); kickstarter.createProject("ProjectB", 100); } - + /// #sender: account-1 /// #value: 10000000 function checkProjectExists () public payable { @@ -512,14 +515,14 @@ const sources = [ (address owner, string memory name, uint goal, uint fundsAvailable, uint amountContributed, Kickstarter.State state) = kickstarter.projects(0); Assert.equal(amountContributed, 120000, "contributed amount is incorrect"); } - + } ` }, 'compilationError_test.sol': { content: ` pragma solidity ^0.8.0; - + contract failOnCompilation { fallback() { @@ -547,7 +550,7 @@ const sources = [ uint c = a+b; Assert.equal(a+b, c, "wrong value"); } - } + } ` }, 'tests/ballotFailedDebug_test.sol': { @@ -556,31 +559,31 @@ const sources = [ pragma solidity >=0.7.0 <0.9.0; import "remix_tests.sol"; // this import is automatically injected by Remix. import "../contracts/3_Ballot.sol"; - + contract BallotTest { - + bytes32[] proposalNames; - + Ballot ballotToTest; function beforeAll () public { proposalNames.push(bytes32("candidate1")); ballotToTest = new Ballot(proposalNames); } - + function checkWinningProposalFailed () public { ballotToTest.vote(1); Assert.equal(ballotToTest.winningProposal(), uint(0), "proposal at index 0 should be the winning proposal"); } - + function checkWinningProposalPassed () public { ballotToTest.vote(0); Assert.equal(ballotToTest.winningProposal(), uint(0), "proposal at index 0 should be the winning proposal"); } - + function checkWinningProposalAgain () public { Assert.equal(ballotToTest.winningProposal(), uint(1), "proposal at index 0 should be the winning proposal"); } - + function checkWinninProposalWithReturnValue () public view returns (bool) { return ballotToTest.winningProposal() == 0; } @@ -594,17 +597,17 @@ const sources = [ import "../contracts/3_Ballot.sol"; import "hardhat/console.sol"; - + contract BallotTest { - + bytes32[] proposalNames; - + Ballot ballotToTest; function beforeAll () public { proposalNames.push(bytes32("candidate1")); ballotToTest = new Ballot(proposalNames); } - + function checkWinningProposal () public { console.log("Inside checkWinningProposal"); ballotToTest.vote(1); // This will revert the transaction @@ -617,13 +620,13 @@ const sources = [ pragma solidity >=0.7.0 <0.9.0; import "remix_tests.sol"; // this import is automatically injected by Remix. import "hardhat/console.sol"; - + contract hhLogs { - + function beforeAll () public { console.log('Inside beforeAll'); } - + function checkSender () public { console.log('msg.sender is %s', msg.sender); Assert.ok(true, "should be true"); diff --git a/libs/remix-ui/checkbox/src/lib/remix-ui-checkbox.tsx b/libs/remix-ui/checkbox/src/lib/remix-ui-checkbox.tsx index 4b0d4fa9be..a10da271ec 100644 --- a/libs/remix-ui/checkbox/src/lib/remix-ui-checkbox.tsx +++ b/libs/remix-ui/checkbox/src/lib/remix-ui-checkbox.tsx @@ -1,5 +1,8 @@ import React, { CSSProperties } from 'react' //eslint-disable-line +import { OverlayProps, OverlayTrigger, OverlayTriggerProps, Tooltip } from 'react-bootstrap'// eslint-disable-line import './remix-ui-checkbox.css' +type Placement = import('react-overlays/usePopper').Placement; + /* eslint-disable-next-line */ export interface RemixUiCheckboxProps { @@ -15,6 +18,7 @@ export interface RemixUiCheckboxProps { title?: string visibility?: string display?: string + tooltipPlacement?: Placement } export const RemixUiCheckbox = ({ @@ -29,24 +33,34 @@ export const RemixUiCheckbox = ({ categoryId, title, visibility, - display = 'flex' + display = 'flex', + tooltipPlacement = 'right-start' }: RemixUiCheckboxProps) => { return ( -
- - -
+ + {title} + + } + > +
+ + +
+
) } diff --git a/libs/remix-ui/panel/src/lib/plugins/panel-header.tsx b/libs/remix-ui/panel/src/lib/plugins/panel-header.tsx index 835d08f1d4..a2dabd7523 100644 --- a/libs/remix-ui/panel/src/lib/plugins/panel-header.tsx +++ b/libs/remix-ui/panel/src/lib/plugins/panel-header.tsx @@ -3,6 +3,7 @@ import React, { useEffect, useRef, useState } from 'react' // eslint-disable-lin import { FormattedMessage } from 'react-intl' import { PluginRecord } from '../types' import './panel.css' +import { OverlayTrigger, Tooltip } from 'react-bootstrap' export interface RemixPanelProps { plugins: Record; @@ -35,9 +36,15 @@ const RemixUIPanelHeader = (props: RemixPanelProps) => {
{plugin?.profile?.maintainedBy?.toLowerCase() === "remix" && ()}
-
- -
+ + Plugin info + + } placement={'right-end'}> +
+ +
+
diff --git a/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx b/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx index 1f4f2bac9a..2dedc06ce9 100644 --- a/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx +++ b/libs/remix-ui/solidity-compiler/src/lib/compiler-container.tsx @@ -742,15 +742,26 @@ export const CompilerContainer = (props: CompilerContainerProps) => { - promptCompiler()} - title={intl.formatMessage({ - id: 'solidity.addACustomCompilerWithURL', - defaultMessage: "Add a custom compiler with URL", - })} - > - showCompilerLicense()} title="See compiler license"> + + + + } + > + promptCompiler()}> + + + {"See compiler license"} + + } + > + showCompilerLicense()}> + handleLanguageChange(e.target.value)} disabled={state.useFileConfiguration} value={state.language} className="custom-select" id="compilierLanguageSelector" title="Language specification available from Compiler >= v0.5.7"> - - - + + {'Language specification available from Compiler >= v0.5.7'} + + } + > + +
- {(!showFilePathInput && state.useFileConfiguration) && { } : async () => { await openFile() }} - className="py-2 remixui_compilerConfigPath" - >{configFilePath === '' ? 'No file selected.' : configFilePath}} + {(!showFilePathInput && state.useFileConfiguration) && + + Click to open the config file + + + } + > + { } : async () => { await openFile() }} + className="py-2 remixui_compilerConfigPath" + >{configFilePath === '' ? 'No file selected.' : configFilePath} + } {(!showFilePathInput && !state.useFileConfiguration) && {configFilePath}} { const { api, compiledFileName, contractsDetails, contractList, modal } = props @@ -198,16 +199,56 @@ export const ContractSelection = (props: ContractSelectionProps) => {
- - - {/* Copy to Clipboard */}
diff --git a/libs/remix-ui/solidity-unit-testing/src/lib/solidity-unit-testing.tsx b/libs/remix-ui/solidity-unit-testing/src/lib/solidity-unit-testing.tsx index 947eae4dac..0396ba7932 100644 --- a/libs/remix-ui/solidity-unit-testing/src/lib/solidity-unit-testing.tsx +++ b/libs/remix-ui/solidity-unit-testing/src/lib/solidity-unit-testing.tsx @@ -2,6 +2,7 @@ import React, { useState, useRef, useEffect, ReactElement } from 'react' // esli import * as semver from 'semver' import { eachOfSeries } from 'async' // eslint-disable-line import type Web3 from 'web3' +import { OverlayTrigger, Tooltip } from 'react-bootstrap' import { canUseWorker, urlFromVersion } from '@remix-project/remix-solidity' import { Renderer } from '@remix-ui/renderer' // eslint-disable-line import { Toaster } from '@remix-ui/toaster' // eslint-disable-line @@ -198,7 +199,7 @@ export const SolidityUnitTesting = (props: Record) => { // eslint-d if (await testTabLogic.pathExists(testDirInput)) { setDisableCreateButton(true) setDisableGenerateButton(false) - + } else { // Enable Create button setDisableCreateButton(false) @@ -296,20 +297,26 @@ export const SolidityUnitTesting = (props: Record) => { // eslint-d let label if (index > -1) { const className = "alert-danger d-inline-block mb-1 mr-1 p-1 failed_" + runningTestFileName - label = (
+ At least one contract test failed + + }>
FAIL -
) +
) } else { const className = "alert-success d-inline-block mb-1 mr-1 p-1 passed_" + runningTestFileName - label = (
+ All contract tests passed + + }>
PASS -
) +
) } // show contract and file name with label const ContractCard: ReactElement = ( @@ -335,8 +342,12 @@ export const SolidityUnitTesting = (props: Record) => { // eslint-d if (test.debugTxHash) { const { web3, debugTxHash } = test debugBtn = ( -
startDebug(debugTxHash, web3)}> - +
startDebug(debugTxHash, web3)}> + + Start debugging + + }>
) } @@ -663,57 +674,102 @@ export const SolidityUnitTesting = (props: Record) => { // eslint-d }) } - { if (inputPathValue === '/') setInputPathValue('')} } - onChange={handleTestDirInput} - onClick = {() => { if (inputPathValue === '/') setInputPathValue('')} } - /> - + { if (inputPathValue === '/') setInputPathValue('')} } + onChange={handleTestDirInput} + onClick = {() => { if (inputPathValue === '/') setInputPathValue('')} } + /> + + + Create a test folder + + } + > + +
- - + + Generate a sample test file + + } placement={'bottom-start'}> + + + + Check out documentation. + + } placement={'bottom-start'}> + +
- - + +
@@ -730,7 +786,7 @@ export const SolidityUnitTesting = (props: Record) => { // eslint-d const elemId = `singleTest${testFileObj.fileName}` return (
- toggleCheckbox(e.target.checked, index)} type="checkbox" checked={testFileObj.checked} /> + toggleCheckbox(e.target.checked, index)} type="checkbox" checked={testFileObj.checked} />
) diff --git a/libs/remix-ui/static-analyser/src/lib/Button/StaticAnalyserButton.tsx b/libs/remix-ui/static-analyser/src/lib/Button/StaticAnalyserButton.tsx index 62876bc1c0..787aa4483d 100644 --- a/libs/remix-ui/static-analyser/src/lib/Button/StaticAnalyserButton.tsx +++ b/libs/remix-ui/static-analyser/src/lib/Button/StaticAnalyserButton.tsx @@ -1,4 +1,5 @@ import React from 'react' //eslint-disable-line +import { OverlayTrigger, Tooltip } from 'react-bootstrap' interface StaticAnalyserButtonProps { onClick: (event) => void @@ -14,10 +15,21 @@ const StaticAnalyserButton = ({ title }: StaticAnalyserButtonProps) => { let classList = "btn btn-sm w-25 btn-primary" - classList += disabled ? " disabled" : "" + classList += disabled ? " disabled" : "" return ( - ) } diff --git a/libs/remix-ui/static-analyser/src/lib/remix-ui-static-analyser.tsx b/libs/remix-ui/static-analyser/src/lib/remix-ui-static-analyser.tsx index e0379d1b11..f10e7baddf 100644 --- a/libs/remix-ui/static-analyser/src/lib/remix-ui-static-analyser.tsx +++ b/libs/remix-ui/static-analyser/src/lib/remix-ui-static-analyser.tsx @@ -255,7 +255,7 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { if(fileName !== currentFile) { const {file, provider} = await props.analysisModule.call('fileManager', 'getPathFromUrl', fileName) if (file.startsWith('.deps') || (provider.type === 'localhost' && file.startsWith('localhost/node_modules'))) isLibrary = true - } + } const msg = message(result.name, item.warning, item.more, fileName, locationString) const options = { type: 'warning', @@ -321,7 +321,7 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { if(fileName !== currentFile) { const {file, provider} = await props.analysisModule.call('fileManager', 'getPathFromUrl', fileName) if (file.startsWith('.deps') || (provider.type === 'localhost' && file.startsWith('localhost/node_modules'))) isLibrary = true - } + } const msg = message(item.title, item.description, item.more, fileName, locationString) const options = { type: 'warning', @@ -490,6 +490,7 @@ export const RemixUiStaticAnalyser = (props: RemixUiStaticAnalyserProps) => { label="Select all" onClick={() => handleCheckAllModules(groupedModules)} onChange={() => {}} + tooltipPlacement={'top-start'} /> { checked={autoRun} label="Autorun" onChange={() => {}} + tooltipPlacement={'bottom-start'} />