fix e2e for script runner ui

dependabot/npm_and_yarn/esbuild-0.25.0
Joseph Izang 1 week ago committed by yann300
parent f7abd37b6e
commit 5870d3e5e2
  1. 188
      apps/remix-ide-e2e/src/tests/script-runner.test.ts
  2. 3
      apps/remix-ide/src/app/tabs/locales/en/scriptrunnerui.json
  3. 137
      libs/remix-ui/scriptrunner/src/lib/components/config-section.tsx
  4. 24
      libs/remix-ui/scriptrunner/src/lib/script-runner-ui.tsx
  5. 14
      libs/remix-ui/scriptrunner/src/lib/scriptrunner.css

@ -4,98 +4,106 @@ import init from '../helpers/init'
const tests = {
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, 'http://127.0.0.1:8080', false)
},
'Should activate plugins': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="remixIdeSidePanel"]')
.waitForElementVisible('*[plugin="pluginManager"]')
.click('*[plugin="pluginManager"]')
.waitForElementVisible('*[data-id="pluginManagerComponentPluginManager"]')
.click('*[data-id="pluginManagerComponentPluginManager"]')
.scrollAndClick('*[data-id="pluginManagerComponentActivateButtonUIScriptRunner"]')
},
'Should load default script runner': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('[data-id="sr-loaded-default"]')
.waitForElementVisible('[data-id="dependency-ethers-^5"]')
.waitForElementVisible('[data-id="sr-toggle-ethers6"]')
},
'Should load script runner ethers6': function (browser: NightwatchBrowser) {
browser
.click('[data-id="sr-toggle-ethers6"]')
.waitForElementVisible('[data-id="sr-loaded-ethers6"]')
.waitForElementPresent('[data-id="dependency-ethers-^6"]')
},
'Should have config file in .remix/script.config.json': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('filePanel')
.waitForElementVisible('[data-path=".remix"]')
.waitForElementVisible('[data-id="treeViewDivDraggableItem.remix/script.config.json"]')
.openFile('.remix/script.config.json')
},
'check config file content': function (browser: NightwatchBrowser) {
browser
.getEditorValue((content) => {
console.log(JSON.parse(content))
const parsed = JSON.parse(content)
browser.assert.ok(parsed.defaultConfig === 'ethers6', 'config file content is correct')
})
},
'execute ethers6 script': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="treeViewUltreeViewMenu"]') // make sure we create the file at the root folder
.addFile('deployWithEthersJs.js', { content: deployWithEthersJs })
.pause(1000)
.click('[data-id="treeViewDivtreeViewItemcontracts"]')
.openFile('contracts/2_Owner.sol')
.clickLaunchIcon('solidity')
.click('*[data-id="compilerContainerCompileBtn"]')
.executeScriptInTerminal('remix.execute(\'deployWithEthersJs.js\')')
.waitForElementContainsText('*[data-id="terminalJournal"]', '0xd9145CCE52D386f254917e481eB44e9943F39138', 60000)
},
'switch workspace it should be default again': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('filePanel')
.pause(2000)
.waitForElementVisible('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-semaphore"]')
.scrollAndClick('*[data-id="create-semaphore"]')
.modalFooterOKClick('TemplatesSelection')
.waitForElementVisible({
locateStrategy: 'xpath',
selector: "//li[@data-id='UIScriptRunner' and @role='tab']"
})
.click({
locateStrategy: 'xpath',
selector: "//li[@data-id='UIScriptRunner' and @role='tab']"
})
.waitForElementVisible('[data-id="sr-loaded-default"]')
.waitForElementVisible('[data-id="dependency-ethers-^5"]')
.waitForElementVisible('[data-id="sr-toggle-ethers6"]')
},
'switch to default workspace that should be on ethers6': function (browser: NightwatchBrowser) {
browser
.switchWorkspace('default_workspace')
.waitForElementVisible({
locateStrategy: 'xpath',
selector: "//li[@data-id='UIScriptRunner' and @role='tab']"
})
.click({
locateStrategy: 'xpath',
selector: "//li[@data-id='UIScriptRunner' and @role='tab']"
})
.waitForElementVisible('[data-id="sr-loaded-ethers6"]')
.waitForElementPresent('[data-id="dependency-ethers-^6"]')
}
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, 'http://127.0.0.1:8080', false)
},
'Should activate plugins': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="remixIdeSidePanel"]')
.waitForElementVisible('*[plugin="pluginManager"]')
.click('*[plugin="pluginManager"]')
.waitForElementVisible('*[data-id="pluginManagerComponentPluginManager"]')
.click('*[data-id="pluginManagerComponentPluginManager"]')
.scrollAndClick('*[data-id="pluginManagerComponentActivateButtonUIScriptRunner"]')
},
'Should load default script runner': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="verticalIconsKindfilePanel"]')
.click('*[data-id="verticalIconsKindfilePanel"]')
.waitForElementVisible('*[data-id="treeViewDivtreeViewItemscripts"]')
.click('*[data-id="treeViewDivtreeViewItemscripts"]')
.waitForElementVisible('*[data-id="treeViewDivtreeViewItemscripts/deploy_with_ethers.ts"]')
.click('*[data-id="treeViewDivtreeViewItemscripts/deploy_with_ethers.ts"]')
.waitForElementVisible('button[data-id="script-config"]')
.click('button[data-id="script-config"]')
.waitForElementVisible('[data-id="sr-loaded-default"]')
.waitForElementVisible('[data-id="dependency-ethers-^5"]')
.waitForElementVisible('[data-id="sr-load-ethers6"]')
},
'Should load script runner ethers6': function (browser: NightwatchBrowser) {
browser
.click('[data-id="sr-load-ethers6"]')
.waitForElementVisible('[data-id="sr-loaded-ethers6"]')
.waitForElementPresent('[data-id="dependency-ethers-^6"]')
},
'Should have config file in .remix/script.config.json': function (browser: NightwatchBrowser) {
browser
.frameParent()
// .clickLaunchIcon('filePanel')
.waitForElementVisible('[data-path=".remix"]')
.waitForElementVisible('[data-id="treeViewDivDraggableItem.remix/script.config.json"]')
.openFile('.remix/script.config.json')
},
'check config file content': function (browser: NightwatchBrowser) {
browser
.getEditorValue((content) => {
console.log(JSON.parse(content))
const parsed = JSON.parse(content)
browser.assert.ok(parsed.defaultConfig === 'ethers6', 'config file content is correct')
})
},
'execute ethers6 script': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="treeViewUltreeViewMenu"]') // make sure we create the file at the root folder
.addFile('deployWithEthersJs.js', { content: deployWithEthersJs })
.pause(1000)
.click('[data-id="treeViewDivtreeViewItemcontracts"]')
.openFile('contracts/2_Owner.sol')
.clickLaunchIcon('solidity')
.click('*[data-id="compilerContainerCompileBtn"]')
.executeScriptInTerminal('remix.execute(\'deployWithEthersJs.js\')')
.waitForElementContainsText('*[data-id="terminalJournal"]', '0xd9145CCE52D386f254917e481eB44e9943F39138', 60000)
},
'switch workspace it should be default again': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('filePanel')
.pause(2000)
.waitForElementVisible('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacesMenuDropdown"]')
.click('*[data-id="workspacecreate"]')
.waitForElementPresent('*[data-id="create-semaphore"]')
.scrollAndClick('*[data-id="create-semaphore"]')
.modalFooterOKClick('TemplatesSelection')
.waitForElementVisible({
locateStrategy: 'xpath',
selector: "//li[@data-id='UIScriptRunner' and @role='tab']"
})
.click({
locateStrategy: 'xpath',
selector: "//li[@data-id='UIScriptRunner' and @role='tab']"
})
.waitForElementVisible('[data-id="sr-load-default"]')
.waitForElementVisible('[data-id="dependency-ethers-^5"]')
.waitForElementVisible('[data-id="sr-load-zksyncv6"]')
},
'switch to default workspace that should be on ethers6': function (browser: NightwatchBrowser) {
browser
.switchWorkspace('default_workspace')
.waitForElementVisible({
locateStrategy: 'xpath',
selector: "//li[@data-id='UIScriptRunner' and @role='tab']"
})
.click({
locateStrategy: 'xpath',
selector: "//li[@data-id='UIScriptRunner' and @role='tab']"
})
.waitForElementVisible('[data-id="sr-loaded-ethers6"]')
.waitForElementPresent('[data-id="dependency-ethers-^6"]')
}
}
module.exports = tests
const deployWithEthersJs = `
import { ethers } from 'ethers'
@ -105,7 +113,7 @@ import { ethers } from 'ethers'
* @param {Array<any>} args list of constructor' parameters
* @param {Number} accountIndex account index from the exposed account
* @return {Contract} deployed contract
*
*
*/
const deploy = async (contractName: string, args: Array<any>, accountIndex?: number): Promise<ethers.Contract> => {
@ -136,4 +144,4 @@ const deploy = async (contractName: string, args: Array<any>, accountIndex?: num
} catch (e) {
console.log(e.message)
}
})()`
})()`

@ -0,0 +1,3 @@
{
"scriptrunnerui.defaultSection": "{{configName}}"
}

@ -0,0 +1,137 @@
import React, { useEffect, useRef, useState } from 'react'
import { FormattedMessage } from 'react-intl'
import { ProjectConfiguration } from '../../types';
import { faCheck, faExclamationCircle, faRedoAlt, faToggleOn, faCaretDown, faCaretUp } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { CustomTooltip } from '@remix-ui/helper';
export interface ConfigSectionProps {
_paq: any;
activeKey: string
setActiveKey: (key: string) => void
config: ProjectConfiguration
key: number
loadScriptRunner: (config: ProjectConfiguration) => void
activeConfig: ProjectConfiguration
}
export default function ConfigSection(props: ConfigSectionProps) {
const [isVisible, setIsVisible] = useState(true)
const handleAnimationEnd = () => {
setIsVisible(false);
}
const SectionHeader = () => {
return (
<section className="mr-1">
<div className="custom-control custom-radio">
<input
className="custom-control-input"
type="radio"
name="scriptrunner-config-radio"
value={props.config.name}
id={props.config.title || props.config.name}
onChange={() => {
props.setActiveKey(props.config.name)
props.loadScriptRunner(props.config)
props._paq.push(['trackEvent', 'scriptRunnerPlugin', 'loadScriptRunnerConfig', props.config.name])
}}
checked={props.activeKey === props.config.name}
/>
<label className="form-check-label custom-control-label" htmlFor={`${props.config.title || props.config.name}`}
data-id={`sr-load-${props.config.name}`}>
<div data-id={`sr-loaded-${props.config.name}`} className="pl-2">{props.config.title || props.config.name}</div>
</label>
</div>
</section>
)
}
const Dependencies = () => {
const [showAll, setShowAll] = useState(false);
const visibleDeps = showAll ? props.config.dependencies : props.config.dependencies.slice(0, 4);
const hasMore = props.config.dependencies.length > 4;
return (
<>
{visibleDeps.map((dep, depIndex) => (
<li className="p-1 text-secondary" data-id={`dependency-${dep.name}-${dep.version}`} key={depIndex}>
{dep.name} (v{dep.version})
</li>
))}
{hasMore && (
<li>
<a
href="#"
className="text-primary text-decoration-none"
onClick={(e) => {
e.preventDefault();
setShowAll(!showAll);
}}
>
{showAll ? 'Show less' : 'Show more'}
<FontAwesomeIcon icon={showAll ? faCaretUp : faCaretDown} className="ml-1" />
</a>
</li>
)}
</>
)
}
return (
<section className="mb-4">
<section className="d-flex flex-row ">
<SectionHeader />
<div className="d-flex flex-row ml-3">
{props.config.isLoading && <div className="d-flex flex-row pb-1 align-items-center justify-content-center">
<span>Loading config</span><i className="fas fa-spinner fa-spin ml-1"></i>
</div>}
</div>
<>
{!props.config.isLoading && !props.config.errorStatus && !props.config.error &&
<div onClick={() => props.loadScriptRunner(props.config)} className="pointer px-2 pb-1">
{ props.activeConfig && props.activeConfig.name === props.config.name &&
<div className={`${!isVisible ? 'd-flex flex-row align-items-center justify-content-center pt-1' : 'd-flex flex-row pb-1 align-items-center justify-content-center'}`}>
{isVisible && <span onAnimationEnd={handleAnimationEnd} className="text-success" style={{ animation: 'fadeOut 5s forwards', animationFillMode: 'forwards' }}>Config loaded</span>}
<FontAwesomeIcon data-id={`sr-loaded-${props.config.name}`} className="text-success ml-3" icon={faCheck}></FontAwesomeIcon>
</div>
}
</div>
}
<div className="w-25"></div>
</>
</section>
<section id="errorSection">
{props.config.errorStatus && props.config.error && <div className="text-danger">
<CustomTooltip tooltipText={props.config.error}>
<FontAwesomeIcon data-id={`sr-error-${props.config.name}`} icon={faExclamationCircle}></FontAwesomeIcon>
</CustomTooltip>
</div>}
{!props.config.isLoading && props.config.errorStatus && props.config.error &&
<div
onClick={() => {
props.loadScriptRunner(props.config)
props._paq.push(['trackEvent', 'scriptRunnerPlugin', 'loadScriptRunnerConfig', props.config.name])
}}
className="pointer px-2"
>
<FontAwesomeIcon data-id={`sr-reload-${props.config.name}`} icon={faRedoAlt}></FontAwesomeIcon>
</div>
}
</section>
<section className="d-flex flex-column" style={{ width: '100%' }} >
<div className="mt-4 bg-light p-3 ">
<p className="text-dark text-monospace">{props.config.description}</p>
<p className="text-dark">Dependencies</p>
<ul className="list-unstyled ">
<Dependencies />
</ul>
</div>
</section>
</section>
)
}

@ -5,6 +5,7 @@ import { faCaretDown, faCaretRight, faCheck, faExclamationCircle, faRedoAlt, faT
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { CustomScriptRunner } from "./custom-script-runner";
import { CustomTooltip } from "@remix-ui/helper";
import ConfigSection from "./components/config-section";
const _paq = (window._paq = window._paq || []) // eslint-disable-line
export interface ScriptRunnerUIProps {
@ -33,8 +34,25 @@ export const ScriptRunnerUI = (props: ScriptRunnerUIProps) => {
}
return (
<div className="px-1 pt-2">
<Accordion activeKey={activeKey} defaultActiveKey="default">
<div className="px-5">
<div className="d-flex flex-column justify-content-between mt-4">
<div className="text-uppercase mb-3 text-dark h2" style={{ fontSize: 'x-large' }}>script configuration</div>
<div className="text-uppercase text-dark h3" style={{ fontSize: 'large' }}>choose a specific configuration for your script</div>
</div>
<div className="mt-5 d-flex flex-column gap-3 mb-4">
{configurations.filter((config) => config.publish).map((config: ProjectConfiguration, index) => (
<ConfigSection
activeKey={activeKey}
setActiveKey={setActiveKey}
config={config}
key={index}
loadScriptRunner={loadScriptRunner}
_paq={_paq}
activeConfig={activeConfig}
/>
))}
</div>
{/* <Accordion activeKey={activeKey} defaultActiveKey="default">
{configurations.filter((config) => config.publish).map((config: ProjectConfiguration, index) => (
<div key={index}>
<div className="d-flex align-items-baseline justify-content-between">
@ -97,7 +115,7 @@ export const ScriptRunnerUI = (props: ScriptRunnerUIProps) => {
</Accordion.Collapse>
</div>))
}
</Accordion>
</Accordion> */}
{enableCustomScriptRunner &&
<CustomScriptRunner
customConfig={props.customConfig}

@ -0,0 +1,14 @@
.remixui_spanfade {
opacity: 1;
animation: fadeOut 3s forwards;
}
@keyframes fadeOut {
from {
opacity: 1;
}
to {
opacity: 0;
}
}
Loading…
Cancel
Save