Merge pull request #2925 from ethereum/custom-tooltips-sut

Add custom tooltip to SUT
pull/2989/head
Joseph Izang 2 years ago committed by GitHub
commit b00aad2e44
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      apps/remix-ide-e2e/src/commands/clickElementAtPosition.ts
  2. 4
      apps/remix-ide-e2e/src/tests/editorAutoComplete.test.ts
  3. 67
      apps/remix-ide-e2e/src/tests/solidityUnittests.test.ts
  4. 15
      libs/remix-ui/panel/src/lib/plugins/panel-header.tsx
  5. 158
      libs/remix-ui/solidity-unit-testing/src/lib/solidity-unit-testing.tsx

@ -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) {

@ -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)
})
}
}
}

@ -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");

@ -2,6 +2,7 @@
import React, { useEffect, useRef, useState } from 'react' // eslint-disable-line
import { PluginRecord } from '../types'
import './panel.css'
import { OverlayTrigger, Tooltip } from 'react-bootstrap'
export interface RemixPanelProps {
plugins: Record<string, PluginRecord>;
@ -32,9 +33,15 @@ const RemixUIPanelHeader = (props: RemixPanelProps) => {
<div className="d-flex flex-row">
{plugin?.profile?.maintainedBy?.toLowerCase() === "remix" && (<i aria-hidden="true" className="text-success mt-1 px-1 fas fa-check" title="Maintained by Remix"></i>)}
</div>
<div className="swapitHeaderInfoSection d-flex justify-content-between" data-id='swapitHeaderInfoSectionId' onClick={toggleClass} title="Plugin info">
<i className={`px-2 ml-2 pt-1 pb-4 ${!toggleExpander ? 'fas fa-angle-right' : 'fas fa-angle-down bg-light'}`} aria-hidden="true"></i>
</div>
<OverlayTrigger overlay={
<Tooltip className="text-nowrap" id="pluginInfoTooltip">
<span>Plugin info</span>
</Tooltip>
} placement={'right-end'}>
<div className="swapitHeaderInfoSection d-flex justify-content-between" data-id='swapitHeaderInfoSectionId' onClick={toggleClass}>
<i className={`px-2 ml-2 pt-1 pb-4 ${!toggleExpander ? 'fas fa-angle-right' : 'fas fa-angle-down bg-light'}`} aria-hidden="true"></i>
</div>
</OverlayTrigger>
</div>
</div>
<div className={`bg-light mx-3 mb-2 p-3 pt-1 border-bottom flex-column ${toggleExpander ? "d-flex" : "d-none"}`}>
@ -57,7 +64,7 @@ const RemixUIPanelHeader = (props: RemixPanelProps) => {
<span> { plugin?.profile.description } </span>
</span>}
{plugin?.profile?.repo && <span className="d-flex flex-row align-items-center">
<a href={plugin?.profile?.repo} target="_blank" rel="noreferrer">
<a href={plugin?.profile?.repo} target="_blank" rel="noreferrer">
Make an issue</a>
</span>}
</div>

@ -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<string, any>) => { // 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<string, any>) => { // eslint-d
let label
if (index > -1) {
const className = "alert-danger d-inline-block mb-1 mr-1 p-1 failed_" + runningTestFileName
label = (<div
label = (<OverlayTrigger placement={'right'} overlay={
<Tooltip className="text-nowrap" id="info-recorder">
<span>At least one contract test failed</span>
</Tooltip>
}><div
className={className}
title="At least one contract test failed"
>
FAIL
</div>)
</div></OverlayTrigger>)
} else {
const className = "alert-success d-inline-block mb-1 mr-1 p-1 passed_" + runningTestFileName
label = (<div
label = (<OverlayTrigger placement={'top-end'} overlay={
<Tooltip className="text-nowrap" id="info-recorder">
<span>All contract tests passed</span>
</Tooltip>
}><div
className={className}
title="All contract tests passed"
>
PASS
</div>)
</div></OverlayTrigger>)
}
// show contract and file name with label
const ContractCard: ReactElement = (
@ -335,8 +342,12 @@ export const SolidityUnitTesting = (props: Record<string, any>) => { // eslint-d
if (test.debugTxHash) {
const { web3, debugTxHash } = test
debugBtn = (
<div id={test.value.replaceAll(' ', '_')} className="btn border btn btn-sm ml-1" style={{ cursor: 'pointer' }} title="Start debugging" onClick={() => startDebug(debugTxHash, web3)}>
<i className="fas fa-bug"></i>
<div id={test.value.replaceAll(' ', '_')} className="btn border btn btn-sm ml-1" style={{ cursor: 'pointer' }} onClick={() => startDebug(debugTxHash, web3)}>
<OverlayTrigger placement={'top-start'} overlay={
<Tooltip className="text-nowrap" id="info-recorder">
<span>Start debugging</span>
</Tooltip>
}><i className="fas fa-bug"></i></OverlayTrigger>
</div>
)
}
@ -663,57 +674,102 @@ export const SolidityUnitTesting = (props: Record<string, any>) => { // eslint-d
})
}
</datalist>
<input
list="utPathList"
className="inputFolder custom-select"
id="utPath"
data-id="uiPathInput"
name="utPath"
value={inputPathValue}
title="Press 'Enter' to change the path for test files."
style={{ backgroundImage: "var(--primary)" }}
onKeyDown={() => { if (inputPathValue === '/') setInputPathValue('')} }
onChange={handleTestDirInput}
onClick = {() => { if (inputPathValue === '/') setInputPathValue('')} }
/>
<button
className="btn border ml-2"
data-id="testTabGenerateTestFolder"
title="Create a test folder"
disabled={disableCreateButton}
onClick={handleCreateFolder}
<OverlayTrigger
placement="top-end"
overlay={
<Tooltip className="text-nowrap" id="uiPathInputtooltip">
<span>{"Press 'Enter' to change the path for test files."}</span>
</Tooltip>
}
>
Create
</button>
<input
list="utPathList"
className="inputFolder custom-select"
id="utPath"
data-id="uiPathInput"
name="utPath"
value={inputPathValue}
style={{ backgroundImage: "var(--primary)" }}
onKeyDown={() => { if (inputPathValue === '/') setInputPathValue('')} }
onChange={handleTestDirInput}
onClick = {() => { if (inputPathValue === '/') setInputPathValue('')} }
/>
</OverlayTrigger>
<OverlayTrigger
placement="top-end"
overlay={
<Tooltip className="text-nowrap" id="uiPathInputButtontooltip">
<span>Create a test folder</span>
</Tooltip>
}
>
<button
className="btn border ml-2"
data-id="testTabGenerateTestFolder"
disabled={disableCreateButton}
onClick={handleCreateFolder}
>
Create
</button>
</OverlayTrigger>
</div>
</div>
</div>
<div>
<div className="d-flex p-2">
<button
className="btn border w-50"
data-id="testTabGenerateTestFile"
title="Generate a sample test file"
disabled={disableGenerateButton}
onClick={async () => {
await testTabLogic.generateTestFile((err:any) => { if (err) setToasterMsg(err)}) // eslint-disable-line @typescript-eslint/no-explicit-any
await updateForNewCurrent()
}}
>
Generate
</button>
<a className="btn border text-decoration-none pr-0 d-flex w-50 ml-2" title="Check out documentation." target="__blank" href="https://remix-ide.readthedocs.io/en/latest/unittesting.html#test-directory">
<OverlayTrigger overlay={
<Tooltip id="generateTestsButtontooltip" className="text-nowrap">
<span>Generate a sample test file</span>
</Tooltip>
} placement={'bottom-start'}>
<button
className="btn border w-50"
data-id="testTabGenerateTestFile"
disabled={disableGenerateButton}
onClick={async () => {
await testTabLogic.generateTestFile((err:any) => { if (err) setToasterMsg(err)}) // eslint-disable-line @typescript-eslint/no-explicit-any
await updateForNewCurrent()
}}
>
Generate
</button>
</OverlayTrigger>
<OverlayTrigger overlay={
<Tooltip id="generateTestsLinktooltip" className="text-nowrap">
<span>Check out documentation.</span>
</Tooltip>
} placement={'bottom-start'}>
<a className="btn border text-decoration-none pr-0 d-flex w-50 ml-2" target="__blank" href="https://remix-ide.readthedocs.io/en/latest/unittesting.html#test-directory">
<label className="btn p-1 ml-2 m-0">How to use...</label>
</a>
</OverlayTrigger>
</div>
<div className="d-flex p-2">
<button id="runTestsTabRunAction" title={runButtonTitle} data-id="testTabRunTestsTabRunAction" className="w-50 btn btn-primary" disabled={disableRunButton} onClick={runTests}>
<span className="fas fa-play ml-2"></span>
<label className="labelOnBtn btn btn-primary p-1 ml-2 m-0">Run</label>
</button>
<button id="runTestsTabStopAction" data-id="testTabRunTestsTabStopAction" className="w-50 pl-2 ml-2 btn btn-secondary" disabled={disableStopButton} title="Stop running tests" onClick={stopTests}>
<span className="fas fa-stop ml-2"></span>
<label className="labelOnBtn btn btn-secondary p-1 ml-2 m-0" id="runTestsTabStopActionLabel">{stopButtonLabel}</label>
<OverlayTrigger placement={'top-start'} overlay={
<Tooltip className="text-nowrap" id="info-recorder">
<span>
{runButtonTitle}
</span>
</Tooltip>
}>
<button id="runTestsTabRunAction"data-id="testTabRunTestsTabRunAction" className="w-50 btn btn-primary" disabled={disableRunButton} onClick={runTests}>
<span className="fas fa-play ml-2"></span>
<label className="labelOnBtn btn btn-primary p-1 ml-2 m-0">Run</label>
</button>
</OverlayTrigger>
<button id="runTestsTabStopAction" data-id="testTabRunTestsTabStopAction" className="w-50 pl-2 ml-2 btn btn-secondary" disabled={disableStopButton} onClick={stopTests}>
<OverlayTrigger placement={'top-start'} overlay={
<Tooltip className="text-nowrap" id="info-recorder">
<span>
Stop running tests
</span>
</Tooltip>
}>
<span>
<span className="fas fa-stop ml-2"></span>
<label className="labelOnBtn btn btn-secondary p-1 ml-2 m-0" id="runTestsTabStopActionLabel">{stopButtonLabel}</label>
</span>
</OverlayTrigger>
</button>
</div>
<div className="d-flex align-items-center mx-3 pb-2 mt-2 border-bottom">
@ -730,7 +786,7 @@ export const SolidityUnitTesting = (props: Record<string, any>) => { // eslint-d
const elemId = `singleTest${testFileObj.fileName}`
return (
<div className="d-flex align-items-center py-1" key={index}>
<input className="singleTest" id={elemId} onChange={(e) => toggleCheckbox(e.target.checked, index)} type="checkbox" checked={testFileObj.checked} />
<input data-id="singleTest" className="singleTest" id={elemId} onChange={(e) => toggleCheckbox(e.target.checked, index)} type="checkbox" checked={testFileObj.checked} />
<label className="singleTestLabel text-nowrap pl-2 mb-0" htmlFor={elemId}>{testFileObj.fileName}</label>
</div>
)

Loading…
Cancel
Save