diff --git a/.circleci/config.yml b/.circleci/config.yml index 7fcd0cd3d1..acc9a0ffb8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -221,7 +221,7 @@ jobs: - store_artifacts: path: ./reports/screenshots - remix-ide-plugin-manager: + remix-ide-plugin-api: docker: # specify the version you desire here - image: circleci/node:14.17.6-browsers @@ -249,13 +249,11 @@ jobs: name: Start Selenium command: ./node_modules/.bin/selenium-standalone start --drivers.chrome.version=2.39 --drivers.chrome.baseURL=https://chromedriver.storage.googleapis.com background: true - - run: ./apps/remix-ide/ci/browser_tests_plugin_manager.sh + - run: ./apps/remix-ide/ci/browser_tests_plugin_api.sh - store_test_results: path: ./reports/tests - store_artifacts: path: ./reports/screenshots - - deploy-remix-live: docker: # specify the version you desire here @@ -375,6 +373,9 @@ workflows: - remix-libs: requires: - lint + - remix-ide-plugin-api: + requires: + - lint - remix-ide-chrome-1: requires: - lint @@ -390,9 +391,6 @@ workflows: - remix-ide-run-deploy: requires: - lint - - remix-ide-plugin-manager: - requires: - - lint - publish: requires: - lint @@ -403,7 +401,7 @@ workflows: - remix-ide-firefox-1 - remix-ide-firefox-2 - remix-ide-run-deploy - - remix-ide-plugin-manager + - remix-ide-plugin-api filters: branches: only: remix_live @@ -414,7 +412,7 @@ workflows: - remix-ide-firefox-1 - remix-ide-firefox-2 - remix-ide-run-deploy - - remix-ide-plugin-manager + - remix-ide-plugin-api filters: branches: only: master @@ -425,7 +423,7 @@ workflows: - remix-ide-firefox-1 - remix-ide-firefox-2 - remix-ide-run-deploy - - remix-ide-plugin-manager + - remix-ide-plugin-api filters: branches: only: remix_beta diff --git a/.gitignore b/.gitignore index d35a9539a0..a79e0a0920 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,5 @@ testem.log # System Files .DS_Store +.vscode/settings.json +.vscode/launch.json diff --git a/apps/remix-ide-e2e/src/commands/acceptAndRemember.ts b/apps/remix-ide-e2e/src/commands/acceptAndRemember.ts new file mode 100644 index 0000000000..987a6fbe7e --- /dev/null +++ b/apps/remix-ide-e2e/src/commands/acceptAndRemember.ts @@ -0,0 +1,30 @@ +import { NightwatchBrowser } from 'nightwatch' +import EventEmitter from 'events' + +class AcceptAndRemember extends EventEmitter { + command (this: NightwatchBrowser, remember:boolean, accept: boolean): NightwatchBrowser { + this.api.perform((done) => { + acceptAndRemember(this.api, remember, accept, () => { + done() + this.emit('complete') + }) + }) + return this + } +} + +function acceptAndRemember (browser: NightwatchBrowser, remember: boolean, accept: boolean, callback: VoidFunction) { + browser.useXpath().waitForElementVisible('//*[@data-id="modalDialogModalBody"]') + if (remember) { + browser.click('//*[@id="remember"]', () => { + if (accept) { + browser.click('//*[@id="modal-footer-ok"]') + } else { + browser.click('//*[@id="modal-footer-cancel"]') + } + browser.perform(function () { callback() }) + }) + } +} + +module.exports = AcceptAndRemember diff --git a/apps/remix-ide-e2e/src/commands/addLocalPlugin.ts b/apps/remix-ide-e2e/src/commands/addLocalPlugin.ts new file mode 100644 index 0000000000..06f4b25cdc --- /dev/null +++ b/apps/remix-ide-e2e/src/commands/addLocalPlugin.ts @@ -0,0 +1,46 @@ +import { NightwatchBrowser } from 'nightwatch' +import EventEmitter from 'events' +import { ExternalProfile, LocationProfile, Profile } from '@remixproject/plugin-utils' + +class AddLocalPlugin extends EventEmitter { + command (this: NightwatchBrowser, profile: Profile & LocationProfile & ExternalProfile): NightwatchBrowser { + this.api.perform((done) => { + addLocalPlugin(this.api, profile, () => { + done() + this.emit('complete') + }) + }) + return this + } +} + +function addLocalPlugin (browser: NightwatchBrowser, profile: Profile & LocationProfile & ExternalProfile, callback: VoidFunction) { + browser.waitForElementVisible('*[data-id="remixIdeSidePanel"]') + .pause(3000).element('css selector', '*[data-id="pluginManagerComponentPluginManager"]', function (result) { + if (result.status === 0) { + browser.click('*[plugin="pluginManager"]') + } + }) + + browser.waitForElementVisible('*[data-id="pluginManagerComponentPluginManager"]') + .execute(function () { + window.testmode = true + }) + .click('*[data-id="pluginManagerComponentPluginSearchButton"]') + .waitForElementVisible('*[data-id="pluginManagerLocalPluginModalDialogModalDialogContainer-react"]') + .click('*[data-id="pluginManagerLocalPluginModalDialogModalDialogModalBody-react"]') + .waitForElementVisible('*[data-id="localPluginName"]') + .clearValue('*[data-id="localPluginName"]').setValue('*[data-id="localPluginName"]', profile.name) + .clearValue('*[data-id="localPluginDisplayName"]').setValue('*[data-id="localPluginDisplayName"]', profile.displayName) + .clearValue('*[data-id="localPluginUrl"]').setValue('*[data-id="localPluginUrl"]', profile.url) + .clearValue('*[data-id="localPluginCanActivate"]').setValue('*[data-id="localPluginCanActivate"]', profile.canActivate ? profile.canActivate.join(',') : '') + .click('*[data-id="localPluginRadioButtoniframe"]') + .click(profile.location === 'sidePanel' ? '*[data-id="localPluginRadioButtonsidePanel"]' : '*[data-id="localPluginRadioButtonmainPanel"]') + .click('*[data-id="pluginManagerLocalPluginModalDialogModalDialogModalFooter-react"]') + .click('*[data-id="pluginManagerLocalPluginModalDialog-modal-footer-ok-react') + .waitForElementVisible('[data-id="verticalIconsKindlocalPlugin"]') + .click('[data-id="verticalIconsKindlocalPlugin"]') + .perform(function () { callback() }) +} + +module.exports = AddLocalPlugin diff --git a/apps/remix-ide-e2e/src/local-plugin/src/app/Client.ts b/apps/remix-ide-e2e/src/local-plugin/src/app/Client.ts new file mode 100644 index 0000000000..488b109db6 --- /dev/null +++ b/apps/remix-ide-e2e/src/local-plugin/src/app/Client.ts @@ -0,0 +1,13 @@ +import { PluginClient } from '@remixproject/plugin' +import { createClient } from '@remixproject/plugin-webview' +export class RemixPlugin extends PluginClient { + constructor () { + super() + this.methods = ['testCommand'] + createClient(this) + } + + async testCommand (data: any) { + + } +} diff --git a/apps/remix-ide-e2e/src/local-plugin/src/app/app.css b/apps/remix-ide-e2e/src/local-plugin/src/app/app.css index 5d5777c1cb..ce033a9bb1 100644 --- a/apps/remix-ide-e2e/src/local-plugin/src/app/app.css +++ b/apps/remix-ide-e2e/src/local-plugin/src/app/app.css @@ -1,128 +1,3 @@ -.app { - font-family: sans-serif; - min-width: 300px; - max-width: 600px; - margin: 50px auto; -} - -.app .gutter-left { - margin-left: 9px; -} - -.app .col-span-2 { - grid-column: span 2; -} - -.app .flex { - display: flex; - align-items: center; - justify-content: center; -} - -.app header { - background-color: #143055; - color: white; - padding: 5px; - border-radius: 3px; -} - -.app main { - padding: 0 36px; -} - -.app p { - text-align: center; -} - -.app h1 { - text-align: center; - margin-left: 18px; - font-size: 24px; -} - -.app h2 { - text-align: center; - font-size: 20px; - margin: 40px 0 10px 0; -} - -.app .resources { - text-align: center; - list-style: none; - padding: 0; - display: grid; - grid-gap: 9px; - grid-template-columns: 1fr 1fr; -} - -.app .resource { - color: #0094ba; - height: 36px; - background-color: rgba(0, 0, 0, 0); - border: 1px solid rgba(0, 0, 0, 0.12); - border-radius: 4px; - padding: 3px 9px; - text-decoration: none; -} - -.app .resource:hover { - background-color: rgba(68, 138, 255, 0.04); -} - -.app pre { - padding: 9px; - border-radius: 4px; - background-color: black; - color: #eee; -} - -.app details { - border-radius: 4px; - color: #333; - background-color: rgba(0, 0, 0, 0); - border: 1px solid rgba(0, 0, 0, 0.12); - padding: 3px 9px; - margin-bottom: 9px; -} - -.app summary { - outline: none; - height: 36px; - line-height: 36px; -} - -.app .github-star-container { - margin-top: 12px; - line-height: 20px; -} - -.app .github-star-container a { - display: flex; - align-items: center; - text-decoration: none; - color: #333; -} - -.app .github-star-badge { - color: #24292e; - display: flex; - align-items: center; - font-size: 12px; - padding: 3px 10px; - border: 1px solid rgba(27, 31, 35, 0.2); - border-radius: 3px; - background-image: linear-gradient(-180deg, #fafbfc, #eff3f6 90%); - margin-left: 4px; - font-weight: 600; -} - -.app .github-star-badge:hover { - background-image: linear-gradient(-180deg, #f0f3f6, #e6ebf1 90%); - border-color: rgba(27, 31, 35, 0.35); - background-position: -0.5em; -} -.app .github-star-badge .material-icons { - height: 16px; - width: 16px; - margin-right: 4px; -} +.jumbotron { + max-height: 25vh; +} \ No newline at end of file diff --git a/apps/remix-ide-e2e/src/local-plugin/src/app/app.tsx b/apps/remix-ide-e2e/src/local-plugin/src/app/app.tsx index 60f4f024df..50c4699997 100644 --- a/apps/remix-ide-e2e/src/local-plugin/src/app/app.tsx +++ b/apps/remix-ide-e2e/src/local-plugin/src/app/app.tsx @@ -1,37 +1,126 @@ + import React, { useEffect, useState } from 'react' -import { PluginClient } from '@remixproject/plugin' -import { createClient } from '@remixproject/plugin-webview' +import { RemixPlugin } from './Client' +import { Logger } from './logger' +import { filePanelProfile } from '@remixproject/plugin-api/lib/file-system/file-panel/profile' +import { filSystemProfile } from '@remixproject/plugin-api/lib/file-system/file-manager/profile' +import { dGitProfile } from '@remixproject/plugin-api/lib/dgit/profile' +import { editorProfile } from '@remixproject/plugin-api/lib/editor/profile' +import { settingsProfile } from '@remixproject/plugin-api/lib/settings/profile' +import { networkProfile } from '@remixproject/plugin-api/lib/network/profile' +import { terminalProfile } from '@remixproject/plugin-api/lib/terminal/profile' +import { udappProfile } from '@remixproject/plugin-api/lib/udapp' +import { compilerProfile } from '@remixproject/plugin-api/lib/compiler' +import { contentImportProfile } from '@remixproject/plugin-api/lib/content-import' +import { windowProfile } from '@remixproject/plugin-api/lib/window' +import { pluginManagerProfile } from '@remixproject/plugin-api/lib/plugin-manager' +import { Profile } from '@remixproject/plugin-utils' import './app.css' -import { ReactComponent as Logo } from './logo.svg' +const client = new RemixPlugin() + +function App () { + const [payload, setPayload] = useState('') + const [log, setLog] = useState() + const [started, setStarted] = useState(false) + const [events, setEvents] = useState() + const [profiles, setProfiles] = useState([pluginManagerProfile, filePanelProfile, filSystemProfile, dGitProfile, networkProfile, settingsProfile, editorProfile, terminalProfile, compilerProfile, udappProfile, contentImportProfile, windowProfile]) -export const App = () => { - const [remixClient, setRemixClient] = useState(null) + const handleChange = ({ target }: any) => { + setPayload(target.value) + } useEffect(() => { - (async () => { - const client = createClient(new PluginClient()) + client.onload(async () => { + const customProfiles = ['menuicons', 'tabs', 'solidityUnitTesting'] + + client.testCommand = async (data: any) => { + console.log(data) + methodLog(data) + } + + let addProfiles = [] + for (const name of customProfiles) { + const p = await client.call('manager', 'getProfile', name) + addProfiles = [...addProfiles, p] + } + setProfiles(profiles => [...profiles, ...addProfiles]) - await client.onload() - console.log('Local plugin loaded') - setRemixClient(client) - })() + profiles.map((profile: Profile) => { + if (profile.events) { + profile.events.map((event: string) => { + client.on(profile.name as any, event, (...args: any) => { + console.log('event :', event, args) + eventLog({ + event: event, + args: args + }) + }) + }) + } + }) + }) }, []) - const handleClick = () => { - remixClient.call('manager', 'activatePlugin', 'LearnEth') + const methodLog = (log: any) => { + const addValue = typeof log === 'string' ? log : JSON.stringify(log) + setLog((value) => `${value} ${addValue}`) + } + + const eventLog = (log: any) => { + const addValue = typeof log === 'string' ? log : JSON.stringify(log) + setEvents((value) => `${value} ${addValue}`) + } + + const clientMethod = async (profile: Profile, method: string) => { + try { + let ob: any = null + try { + ob = JSON.parse(payload) + if (ob && !Array.isArray(ob)) { ob = [ob] } + } catch (e) { } + const args = ob || [payload] + setStarted(true) + setLog('') + setEvents('') + console.log('calling :', profile.name, method, ...args) + await client.call('manager', 'activatePlugin', profile.name) + const result = await client.call(profile.name as any, method, ...args) + console.log('result :', result) + methodLog(result) + } catch (e) { + methodLog(e.message) + } + setStarted(false) } return ( -
-
- -

Welcome to local-plugin!

-
-
- -
+
+
PLUGIN API TESTER
+

+ + + + + + {profiles.map((profile: Profile) => { + const methods = profile.methods.map((method: string) => { + return + }) + const events = profile.events ? profile.events.map((event: string) => { + return + }) : null + return


{methods}

{events ? : null}{events}
+ })} +
) } diff --git a/apps/remix-ide-e2e/src/local-plugin/src/app/logger.tsx b/apps/remix-ide-e2e/src/local-plugin/src/app/logger.tsx new file mode 100644 index 0000000000..92033e264b --- /dev/null +++ b/apps/remix-ide-e2e/src/local-plugin/src/app/logger.tsx @@ -0,0 +1,9 @@ +import React from 'react' +interface loggerProps { + log: any, + id: string +} + +export const Logger: React.FC = (props) => { + return (
{props.log}
) +} diff --git a/apps/remix-ide-e2e/src/local-plugin/src/app/logo.svg b/apps/remix-ide-e2e/src/local-plugin/src/app/logo.svg deleted file mode 100644 index 8fa84ab509..0000000000 --- a/apps/remix-ide-e2e/src/local-plugin/src/app/logo.svg +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/apps/remix-ide-e2e/src/local-plugin/src/app/star.svg b/apps/remix-ide-e2e/src/local-plugin/src/app/star.svg deleted file mode 100644 index 901053d385..0000000000 --- a/apps/remix-ide-e2e/src/local-plugin/src/app/star.svg +++ /dev/null @@ -1,11 +0,0 @@ - - - - - diff --git a/apps/remix-ide-e2e/src/local-plugin/src/index.html b/apps/remix-ide-e2e/src/local-plugin/src/index.html index e8058b50b5..b1a45c177c 100644 --- a/apps/remix-ide-e2e/src/local-plugin/src/index.html +++ b/apps/remix-ide-e2e/src/local-plugin/src/index.html @@ -1,10 +1,9 @@ - - LocalPlugin - + + Remix Plugin API Tester diff --git a/apps/remix-ide-e2e/src/tests/pluginManager.ts b/apps/remix-ide-e2e/src/tests/pluginManager.test.ts similarity index 62% rename from apps/remix-ide-e2e/src/tests/pluginManager.ts rename to apps/remix-ide-e2e/src/tests/pluginManager.test.ts index f1c35100b5..48f3ae29d8 100644 --- a/apps/remix-ide-e2e/src/tests/pluginManager.ts +++ b/apps/remix-ide-e2e/src/tests/pluginManager.test.ts @@ -12,13 +12,6 @@ const testData = { pluginUrl: 'https://zokrates.github.io/zokrates-remix-plugin/' } -const localPluginData = { - pluginName: 'localPlugin', - pluginDisplayName: 'Local Plugin', - pluginCanActivate: 'LearnEth', - pluginUrl: 'http://localhost:2020' -} - module.exports = { before: function (browser: NightwatchBrowser, done: VoidFunction) { init(browser, done, 'http://127.0.0.1:8080', false) @@ -76,44 +69,6 @@ module.exports = { .waitForElementVisible('*[data-id="pluginManagerComponentActivateButtonvyper"]', 60000) }, - /* - 'Should grant plugin permission (ZOKRATES)': function (browser) { - browser.waitForElementVisible('*[data-id="pluginManagerComponentPluginManager"]') - .click('*[data-id="pluginManagerPermissionsButton"]') - .waitForElementVisible('*[data-id="pluginManagerSettingsPermissionForm"]') - .assert.containsText('*[data-id="pluginManagerSettingsPermissionForm"]', 'No Permission requested yet') - .modalFooterOKClick() - .click('*[data-id="verticalIconsFileExplorerIcons"]') - .openFile('3_Ballot.sol') - .click('*[plugin="ZoKrates"]') - .pause(5000) - .frame(0) - .useXpath().click("//span[text()='Compile']") - .pause(2000) - .frameParent() - .useCss().waitForElementVisible('*[data-id="modalDialogContainer"]') - .assert.containsText('*[data-id="permissionHandlerMessage"]', 'ZOKRATES" WOULD LIKE TO ACCESS "FILE MANAGER" :') - .pause(2000) - .click('*[data-id="permissionHandlerRememberChoice"]') - .pause(2000) - .modalFooterOKClick() - }, - - 'Should revert plugin permission (ZOKRATES)': function (browser) { - browser.waitForElementVisible('*[data-id="verticalIconsSettingsIcons"]') - .click('*[data-id="verticalIconsSettingsIcons"]') - .waitForElementVisible('*[data-id="pluginManagerPermissionsButton"]') - .click('*[data-id="pluginManagerPermissionsButton"]') - .waitForElementVisible('*[data-id="modalDialogContainer"]') - .click('*[data-id="pluginManagerSettingsPermissionForm"]') - .pause(2000) - .click('*[data-id="pluginManagerSettingsClearAllPermission"]') - .pause(2000) - .assert.containsText('*[data-id="pluginManagerSettingsPermissionForm"]', 'No Permission requested yet') - .modalFooterOKClick() - }, - */ - 'Should connect a local plugin': function (browser: NightwatchBrowser) { browser.waitForElementVisible('*[data-id="pluginManagerComponentPluginManager"]') .execute(function () { @@ -130,8 +85,6 @@ module.exports = { .click('*[data-id="localPluginRadioButtonsidePanel"]') .click('*[data-id="pluginManagerLocalPluginModalDialogModalDialogModalFooter-react"]') .click('*[data-id="pluginManagerLocalPluginModalDialog-modal-footer-ok-react') - // .modalFooterOKClick() - // .waitForElementVisible('*[data-id="pluginManagerComponentDeactivateButtonremixIde"]', 60000) }, 'Should display error message for creating already existing plugin': function (browser: NightwatchBrowser) { @@ -154,46 +107,17 @@ module.exports = { .assert.containsText('*[data-shared="tooltipPopup"]', 'Cannot create Plugin : This name has already been used') }, - 'Local plugin should activate LearnEth plugin': function (browser: NightwatchBrowser) { - browser - .waitForElementVisible('*[data-id="pluginManagerComponentPluginManager"]') - .click('*[data-id="pluginManagerComponentPluginSearchButton"]') - .waitForElementVisible('*[data-id="pluginManagerLocalPluginModalDialogModalDialogContainer-react"]') - .click('*[data-id="pluginManagerLocalPluginModalDialogModalDialogModalBody-react"]') - .waitForElementVisible('*[data-id="localPluginName"]') - .clearValue('*[data-id="localPluginName"]').setValue('*[data-id="localPluginName"]', localPluginData.pluginName) - .clearValue('*[data-id="localPluginDisplayName"]').setValue('*[data-id="localPluginDisplayName"]', localPluginData.pluginDisplayName) - .clearValue('*[data-id="localPluginCanActivate"]').setValue('*[data-id="localPluginCanActivate"]', localPluginData.pluginCanActivate) - .clearValue('*[data-id="localPluginUrl"]').setValue('*[data-id="localPluginUrl"]', localPluginData.pluginUrl) - .click('*[data-id="localPluginRadioButtoniframe"]') - .click('*[data-id="localPluginRadioButtonsidePanel"]') - .click('*[data-id="pluginManagerLocalPluginModalDialogModalDialogModalFooter-react"]') - .click('*[data-id="pluginManagerLocalPluginModalDialog-modal-footer-ok-react') - .waitForElementVisible('[data-id="verticalIconsKindlocalPlugin"]') - .click('[data-id="verticalIconsKindlocalPlugin"]') - .waitForElementNotPresent('[data-id="verticalIconsKindLearnEth"]') - .pause(2000) - // @ts-ignore - .frame('plugin-localPlugin') - .useXpath().click("//button[text()='Activate Learneth']") - .pause(2000) - .frameParent() - .useCss().waitForElementPresent('[data-id="verticalIconsKindLearnEth"]') - }, - 'Should load back installed plugins after reload': function (browser: NightwatchBrowser) { browser .waitForElementVisible('*[data-id="remixIdeSidePanel"]') - .click('*[plugin="pluginManager"]') .waitForElementVisible('*[data-id="pluginManagerComponentPluginManager"]') .getInstalledPlugins((plugins) => { browser.refresh() .waitForElementVisible('*[data-id="remixIdeSidePanel"]') .pause(3000) .perform((done) => { - // const filtered = plugins.filter(plugin => plugin !== 'testremixIde') // remove this when localplugin bug is resolved plugins.forEach(plugin => { - if ((plugin !== testData.pluginName) && plugin !== localPluginData.pluginName) { + if (plugin !== testData.pluginName) { browser.waitForElementVisible(`[plugin="${plugin}"`) } }) diff --git a/apps/remix-ide-e2e/src/tests/plugin_api.ts b/apps/remix-ide-e2e/src/tests/plugin_api.ts new file mode 100644 index 0000000000..9eae1f8c4f --- /dev/null +++ b/apps/remix-ide-e2e/src/tests/plugin_api.ts @@ -0,0 +1,327 @@ +'use strict' +import { ExternalProfile, LocationProfile, Profile } from '@remixproject/plugin-utils' +import { NightwatchBrowser } from 'nightwatch' +import init from '../helpers/init' + +declare global { + interface Window { testmode: boolean; } +} + +const localPluginData: Profile & LocationProfile & ExternalProfile = { + name: 'localPlugin', + displayName: 'Local Plugin', + canActivate: ['dGitProvider', 'flattener', 'solidityUnitTesting'], + url: 'http://localhost:2020', + location: 'sidePanel' +} + +const getBrowserLogs = async function (browser: NightwatchBrowser) { + browser.getLog('browser', (logEntries) => { + if (logEntries && logEntries.length > 0) { + console.log('Browser log:') + console.log(logEntries) + } + }) +} + +const debugValues = async function (browser: NightwatchBrowser, field: string, expected: any) { + return new Promise((resolve) => { + if (!expected) { + resolve(true) + return + } + browser.waitForElementVisible(`//*[@id="${field}"]`).getText(`//*[@id="${field}"]`, (result) => { + console.log(result) + if (!result.value.toString().includes(expected)) { + console.log('Actual result:') + console.log(result.value.toString()) + console.log('Expected result:') + console.log(expected) + getBrowserLogs(browser) + browser.assert.ok(false, 'Returned value from call does not match expected value.') + } else { + browser.assert.ok(true) + } + resolve(true) + }) + }) +} + +const setPayload = async (browser: NightwatchBrowser, payload: any) => { + return new Promise((resolve) => { + if (typeof payload !== 'string') payload = JSON.stringify(payload) + browser.clearValue('//*[@id="payload"]').setValue('//*[@id="payload"]', payload, (result) => { + resolve(result) + }) + }) +} + +const clearPayLoad = async (browser: NightwatchBrowser) => { + return new Promise((resolve) => { + browser.clearValue('//*[@id="payload"]', () => { + resolve(true) + }) + }) +} + +const clickButton = async (browser: NightwatchBrowser, buttonText: string) => { + return new Promise((resolve) => { + browser.useXpath().waitForElementVisible(`//*[@data-id='${buttonText}']`).pause(100) + .click(`//*[@data-id='${buttonText}']`, async () => { + await checkForAcceptAndRemember(browser) + browser.waitForElementContainsText('//*[@id="callStatus"]', 'stop').perform(() => resolve(true)) + }) + }) +} + +const checkForAcceptAndRemember = async function (browser: NightwatchBrowser) { + return new Promise((resolve) => { + browser.frameParent(() => { + browser.pause(1000).element('xpath', '//*[@data-id="permissionHandlerRememberUnchecked"]', (visible:any) => { + if (visible.status && visible.status === -1) { + // @ts-ignore + browser.frame(0, () => { resolve(true) }) + } else { + browser.waitForElementVisible('//*[@data-id="permissionHandlerRememberUnchecked"]').click('//*[@data-id="permissionHandlerRememberUnchecked"]').waitForElementVisible('//*[@id="modal-footer-ok"]').click('//*[@id="modal-footer-ok"]', () => { + // @ts-ignore + browser.frame(0, () => { resolve(true) }) + }) + } + }) + }) + }) +} + +/** + * performs an action on the test local plugin calling a method on a plugin + * + * @param {NightwatchBrowser} browser + * @param {string} buttonText the button which needs to be clicked formatted as pluginname:methodname, ie 'fileManager:writeFile' + * @param {any} methodResult can be a string expected or an object. it is the result of the method called. + * @param {any} eventResult can be a string expected or an object. it is the event generated by the method called. + * @param {any} payload can be a string expected or an object. it is the payload passed to the call + * @return {Promise} + */ + +const clickAndCheckLog = async (browser: NightwatchBrowser, buttonText: string, methodResult: any, eventResult: any, payload: any) => { + if (payload) { + await setPayload(browser, payload) + } else { + await clearPayLoad(browser) + } + if (methodResult && typeof methodResult !== 'string') { methodResult = JSON.stringify(methodResult) } + if (eventResult && typeof eventResult !== 'string') { eventResult = JSON.stringify(eventResult) } + if (buttonText) { + await clickButton(browser, buttonText) + } + await debugValues(browser, 'methods', methodResult) + await debugValues(browser, 'events', eventResult) +} + +const assertPluginIsActive = function (browser: NightwatchBrowser, id: string, shouldBeVisible: boolean) { + if (shouldBeVisible) { + browser.waitForElementVisible(`//*[@data-id="verticalIconsKind${id}"]`) + } else { + browser.waitForElementNotPresent(`//*[@data-id="verticalIconsKind${id}"]`) + } +} + +module.exports = { + before: function (browser: NightwatchBrowser, done: VoidFunction) { + init(browser, done, 'http://127.0.0.1:8080', false) + }, + + afterEach: function (browser: NightwatchBrowser) { + browser.getLog('browser', (logEntries) => { + console.log(logEntries) + }) + }, + + 'Should connect a local plugin': function (browser: NightwatchBrowser) { + browser.addLocalPlugin(localPluginData) + // @ts-ignore + .frame(0).useXpath() + }, + + // UDAPP + 'Should get accounts': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'udapp:getAccounts', '0x5B38Da6a701c568545dCfcB03FcB875f56beddC4', null, null) + }, + + // context menu item + + 'Should create context menu item': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'filePanel:registerContextMenuItem', null, null, { + id: 'localPlugin', + name: 'testCommand', + label: 'testCommand', + type: [], + extension: ['.sol'], + path: [], + pattern: [] + }) + await browser.useXpath().frameParent(async () => { + browser.useCss().clickLaunchIcon('filePanel') + .waitForElementVisible('[data-id="treeViewLitreeViewItemcontracts"]').element('css selector', '[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]', (visible: any) => { + if (visible.status && visible.status === -1) { + browser.click('[data-id="treeViewLitreeViewItemcontracts"]') + } + }) + .waitForElementVisible('[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]') + .rightClick('[data-id="treeViewLitreeViewItemcontracts/1_Storage.sol"]').useXpath().waitForElementVisible('//*[@id="menuitemtestcommand"]').click('//*[@id="menuitemtestcommand"]', async () => { + // @ts-ignore + browser.click('//*[@data-id="verticalIconsKindlocalPlugin"]').frame(0, async () => { + await clickAndCheckLog(browser, null, { id: 'localPlugin', name: 'testCommand', label: 'testCommand', type: [], extension: ['.sol'], path: ['contracts/1_Storage.sol'], pattern: [] }, null, null) + }) + }) + }) + }, + + // FILESYSTEM + + 'Should get current workspace': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'filePanel:getCurrentWorkspace', { name: 'default_workspace', isLocalhost: false, absolutePath: '.workspaces/default_workspace' }, null, null) + }, + + 'Should get current files': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'fileManager:readdir', { contracts: { isDirectory: true }, scripts: { isDirectory: true }, tests: { isDirectory: true }, 'README.txt': { isDirectory: false } }, null, '/') + }, + 'Should throw error on current file': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'fileManager:getCurrentFile', 'Error from IDE : Error: No such file or directory No file selected', null, null) + }, + 'Should open readme.txt': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'fileManager:open', null, { event: 'currentFileChanged', args: ['README.txt'] }, 'README.txt') + }, + 'Should have current file': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'fileManager:getCurrentFile', 'README.txt', null, null) + }, + 'Should create dir': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'fileManager:mkdir', null, null, 'testdir') + await clickAndCheckLog(browser, 'fileManager:readdir', 'testdir', null, '/') + }, + 'Should get file': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'fileManager:getFile', 'REMIX EXAMPLE PROJECT', null, 'README.txt') + }, + 'Should close all files': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'fileManager:closeAllFiles', null, { event: 'noFileSelected', args: [] }, null) + }, + + 'Should switch to file': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'fileManager:switchFile', null, { event: 'currentFileChanged', args: ['contracts/1_Storage.sol'] }, 'contracts/1_Storage.sol') + await clickAndCheckLog(browser, 'fileManager:getCurrentFile', 'contracts/1_Storage.sol', null, null) + await clickAndCheckLog(browser, 'fileManager:switchFile', null, { event: 'currentFileChanged', args: ['README.txt'] }, 'README.txt') + await clickAndCheckLog(browser, 'fileManager:getCurrentFile', 'README.txt', null, null) + }, + 'Should write to file': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'fileManager:writeFile', null, { event: 'fileSaved', args: ['README.txt'] }, ['README.txt', 'test']) + await clickAndCheckLog(browser, 'fileManager:readFile', 'test', null, 'README.txt') + }, + 'Should set file': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'fileManager:setFile', null, { event: 'fileAdded', args: ['new.sol'] }, ['new.sol', 'test']) + await clickAndCheckLog(browser, 'fileManager:readFile', 'test', null, 'new.sol') + }, + 'Should write to new file': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'fileManager:writeFile', null, { event: 'fileAdded', args: ['testing.txt'] }, ['testing.txt', 'test']) + await clickAndCheckLog(browser, 'fileManager:readFile', 'test', null, 'testing.txt') + }, + 'Should rename file': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'fileManager:rename', null, null, ['testing.txt', 'testrename.txt']) + await clickAndCheckLog(browser, 'fileManager:readFile', 'test', null, 'testrename.txt') + }, + + 'Should create empty workspace': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'filePanel:createWorkspace', null, null, ['emptyworkspace', true]) + await clickAndCheckLog(browser, 'filePanel:getCurrentWorkspace', { name: 'emptyworkspace', isLocalhost: false, absolutePath: '.workspaces/emptyworkspace' }, null, null) + await clickAndCheckLog(browser, 'fileManager:readdir', {}, null, '/') + }, + 'Should create workspace': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'filePanel:createWorkspace', null, null, 'testspace') + await clickAndCheckLog(browser, 'filePanel:getCurrentWorkspace', { name: 'testspace', isLocalhost: false, absolutePath: '.workspaces/testspace' }, null, null) + await clickAndCheckLog(browser, 'fileManager:readdir', { contracts: { isDirectory: true }, scripts: { isDirectory: true }, tests: { isDirectory: true }, 'README.txt': { isDirectory: false } }, null, null) + }, + 'Should get all workspaces': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'filePanel:getWorkspaces', ['default_workspace', 'emptyworkspace', 'testspace'], null, null) + }, + 'Should have set workspace event': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'filePanel:createWorkspace', null, { event: 'setWorkspace', args: [{ name: 'newspace', isLocalhost: false }] }, 'newspace') + }, + 'Should have event when switching workspace': async function (browser: NightwatchBrowser) { + // @ts-ignore + browser.frameParent().useCss().clickLaunchIcon('filePanel').click('*[data-id="workspacesSelect"] option[value="default_workspace"]').useXpath().click('//*[@data-id="verticalIconsKindlocalPlugin"]').frame(0, async () => { + await clickAndCheckLog(browser, null, null, { event: 'setWorkspace', args: [{ name: 'default_workspace', isLocalhost: false }] }, null) + }) + }, + + 'Should rename workspace': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'filePanel:renameWorkspace', null, null, ['default_workspace', 'renamed']) + await clickAndCheckLog(browser, 'filePanel:getWorkspaces', ['emptyworkspace', 'testspace', 'newspace', 'renamed'], null, null) + }, + 'Should delete workspace': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'filePanel:deleteWorkspace', null, null, ['testspace']) + await clickAndCheckLog(browser, 'filePanel:getWorkspaces', ['emptyworkspace', 'newspace', 'renamed'], null, null) + }, + // DGIT + 'Should have changes on new workspace': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'filePanel:createWorkspace', null, null, 'dgit') + await clickAndCheckLog(browser, 'dGitProvider:status', [['README.txt', 0, 2, 0], ['contracts/1_Storage.sol', 0, 2, 0], ['contracts/2_Owner.sol', 0, 2, 0], ['contracts/3_Ballot.sol', 0, 2, 0], ['scripts/deploy_ethers.js', 0, 2, 0], ['scripts/deploy_web3.js', 0, 2, 0], ['tests/4_Ballot_test.sol', 0, 2, 0]], null, null) + }, + + 'Should stage contract': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'dGitProvider:add', null, null, { + filepath: 'contracts/1_Storage.sol' + }) + await clickAndCheckLog(browser, 'dGitProvider:status', [['README.txt', 0, 2, 0], ['contracts/1_Storage.sol', 0, 2, 2], ['contracts/2_Owner.sol', 0, 2, 0], ['contracts/3_Ballot.sol', 0, 2, 0], ['scripts/deploy_ethers.js', 0, 2, 0], ['scripts/deploy_web3.js', 0, 2, 0], ['tests/4_Ballot_test.sol', 0, 2, 0]], null, null) + }, + 'Should commit changes': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'dGitProvider:commit', null, null, { author: { name: 'Remix', email: 'Remix' }, message: 'commit-message' }) + await clickAndCheckLog(browser, 'dGitProvider:log', 'commit-message', null, null) + }, + 'Should have git log': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'dGitProvider:log', 'commit-message', null, null) + }, + 'Should have branches': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'dGitProvider:branches', [{ name: 'main' }], null, null) + }, + // resolver + 'Should resolve url': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'contentImport:resolve', '# Remix Project', null, 'https://github.com/ethereum/remix-project/blob/master/README.md') + }, + 'Should resolve and save url': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'contentImport:resolveAndSave', '# Remix Project', { event: 'fileAdded', args: ['.deps/github/ethereum/remix-project/README.md'] }, 'https://github.com/ethereum/remix-project/blob/master/README.md') + }, + // UNIT TESTING + 'Should activate solidityUnitTesting': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'manager:activatePlugin', null, null, 'solidityUnitTesting') + browser.frameParent() + assertPluginIsActive(browser, 'solidityUnitTesting', true) + // @ts-ignore + browser.frame(0) + await clickAndCheckLog(browser, 'manager:isActive', true, null, 'solidityUnitTesting') + }, + + 'Should test from path with solidityUnitTesting': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'solidityUnitTesting:testFromPath', '"totalPassing":2,"totalFailing":0', null, 'tests/4_Ballot_test.sol') + }, + + 'Should deactivate solidityUnitTesting': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'manager:deactivatePlugin', null, null, 'solidityUnitTesting') + browser.frameParent() + assertPluginIsActive(browser, 'solidityUnitTesting', false) + // @ts-ignore + browser.frame(0) + await clickAndCheckLog(browser, 'manager:isActive', false, null, 'solidityUnitTesting') + }, + + // COMPILER + + 'Should compile a file': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'solidity:compile', null, null, 'contracts/1_Storage.sol') + browser.pause(5000, async () => { + await clickAndCheckLog(browser, 'solidity:compile', null, 'compilationFinished', null) + }) + }, + + 'Should get compilationresults': async function (browser: NightwatchBrowser) { + await clickAndCheckLog(browser, 'solidity:getCompilationResult', 'contracts/1_Storage.sol', null, null) + } +} diff --git a/apps/remix-ide-e2e/src/types/index.d.ts b/apps/remix-ide-e2e/src/types/index.d.ts index 634fcf7e98..7033bf2057 100644 --- a/apps/remix-ide-e2e/src/types/index.d.ts +++ b/apps/remix-ide-e2e/src/types/index.d.ts @@ -57,6 +57,8 @@ declare module 'nightwatch' { checkAnnotationsNotPresent(type: string): NightwatchBrowser getLastTransactionHash(callback: (hash: string) => void) currentWorkspaceIs(name: string): NightwatchBrowser + addLocalPlugin(this: NightwatchBrowser, profile: Profile & LocationProfile & ExternalProfile): NightwatchBrowser + acceptAndRemember (this: NightwatchBrowser, remember: boolean, accept: boolean): NightwatchBrowser } export interface NightwatchBrowser { diff --git a/apps/remix-ide/ci/browser_tests_plugin_manager.sh b/apps/remix-ide/ci/browser_tests_plugin_api.sh similarity index 82% rename from apps/remix-ide/ci/browser_tests_plugin_manager.sh rename to apps/remix-ide/ci/browser_tests_plugin_api.sh index 4f856292c6..8b3ef4eeb3 100755 --- a/apps/remix-ide/ci/browser_tests_plugin_manager.sh +++ b/apps/remix-ide/ci/browser_tests_plugin_api.sh @@ -12,7 +12,7 @@ npx nx serve remix-ide-e2e-src-local-plugin & sleep 5 npm run build:e2e -npm run nightwatch_local_pluginManager || TEST_EXITCODE=1 +npm run nightwatch_local_pluginApi || TEST_EXITCODE=1 echo "$TEST_EXITCODE" if [ "$TEST_EXITCODE" -eq 1 ] diff --git a/apps/remix-ide/src/assets/css/intro.js/2.7.0/introjs.min.css b/apps/remix-ide/src/assets/css/intro.js/2.7.0/introjs.min.css new file mode 100644 index 0000000000..4f508ed90c --- /dev/null +++ b/apps/remix-ide/src/assets/css/intro.js/2.7.0/introjs.min.css @@ -0,0 +1 @@ +.introjs-overlay{position:absolute;box-sizing:content-box;z-index:999999;background-color:#000;opacity:0;background:-moz-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:-webkit-gradient(radial,center center,0px,center center,100%,color-stop(0%,rgba(0,0,0,0.4)),color-stop(100%,rgba(0,0,0,0.9)));background:-webkit-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:-o-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:-ms-radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);background:radial-gradient(center,ellipse cover,rgba(0,0,0,0.4) 0,rgba(0,0,0,0.9) 100%);filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr='#66000000',endColorstr='#e6000000',GradientType=1)";-ms-filter:"alpha(opacity=50)";filter:alpha(opacity=50);-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-ms-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-fixParent{z-index:auto!important;opacity:1.0!important;-webkit-transform:none!important;-moz-transform:none!important;-ms-transform:none!important;-o-transform:none!important;transform:none!important}.introjs-showElement,tr.introjs-showElement>td,tr.introjs-showElement>th{z-index:9999999!important}.introjs-disableInteraction{z-index:99999999!important;position:absolute;background-color:white;opacity:0;filter:alpha(opacity=0)}.introjs-relativePosition,tr.introjs-showElement>td,tr.introjs-showElement>th{position:relative}.introjs-helperLayer{box-sizing:content-box;position:absolute;z-index:9999998;background-color:#FFF;background-color:rgba(255,255,255,.9);border:1px solid #777;border:1px solid rgba(0,0,0,.5);border-radius:4px;box-shadow:0 2px 15px rgba(0,0,0,.4);-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-ms-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-tooltipReferenceLayer{box-sizing:content-box;position:absolute;visibility:hidden;z-index:10000000;background-color:transparent;-webkit-transition:all .3s ease-out;-moz-transition:all .3s ease-out;-ms-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-helperLayer *,.introjs-helperLayer *:before,.introjs-helperLayer *:after{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;-ms-box-sizing:content-box;-o-box-sizing:content-box;box-sizing:content-box}.introjs-helperNumberLayer{box-sizing:content-box;position:absolute;visibility:visible;top:-16px;left:-16px;z-index:9999999999!important;padding:2px;font-family:Arial,verdana,tahoma;font-size:13px;font-weight:bold;color:white;text-align:center;text-shadow:1px 1px 1px rgba(0,0,0,.3);background:#ff3019;background:-webkit-linear-gradient(top,#ff3019 0,#cf0404 100%);background:-webkit-gradient(linear,left top,left bottom,color-stop(0%,#ff3019),color-stop(100%,#cf0404));background:-moz-linear-gradient(top,#ff3019 0,#cf0404 100%);background:-ms-linear-gradient(top,#ff3019 0,#cf0404 100%);background:-o-linear-gradient(top,#ff3019 0,#cf0404 100%);background:linear-gradient(to bottom,#ff3019 0,#cf0404 100%);width:20px;height:20px;line-height:20px;border:3px solid white;border-radius:50%;filter:"progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3019', endColorstr='#cf0404', GradientType=0)";filter:"progid:DXImageTransform.Microsoft.Shadow(direction=135, strength=2, color=ff0000)";box-shadow:0 2px 5px rgba(0,0,0,.4)}.introjs-arrow{border:5px solid white;content:'';position:absolute}.introjs-arrow.top{top:-10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:white;border-left-color:transparent}.introjs-arrow.top-right{top:-10px;right:10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:white;border-left-color:transparent}.introjs-arrow.top-middle{top:-10px;left:50%;margin-left:-5px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:white;border-left-color:transparent}.introjs-arrow.right{right:-10px;top:10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:transparent;border-left-color:white}.introjs-arrow.right-bottom{bottom:10px;right:-10px;border-top-color:transparent;border-right-color:transparent;border-bottom-color:transparent;border-left-color:white}.introjs-arrow.bottom{bottom:-10px;border-top-color:white;border-right-color:transparent;border-bottom-color:transparent;border-left-color:transparent}.introjs-arrow.left{left:-10px;top:10px;border-top-color:transparent;border-right-color:white;border-bottom-color:transparent;border-left-color:transparent}.introjs-arrow.left-bottom{left:-10px;bottom:10px;border-top-color:transparent;border-right-color:white;border-bottom-color:transparent;border-left-color:transparent}.introjs-tooltip{box-sizing:content-box;position:absolute;visibility:visible;padding:10px;background-color:white;min-width:200px;max-width:300px;border-radius:3px;box-shadow:0 1px 10px rgba(0,0,0,.4);-webkit-transition:opacity .1s ease-out;-moz-transition:opacity .1s ease-out;-ms-transition:opacity .1s ease-out;-o-transition:opacity .1s ease-out;transition:opacity .1s ease-out}.introjs-tooltipbuttons{text-align:right;white-space:nowrap}.introjs-button{box-sizing:content-box;position:relative;overflow:visible;display:inline-block;padding:.3em .8em;border:1px solid #d4d4d4;margin:0;text-decoration:none;text-shadow:1px 1px 0 #fff;font:11px/normal sans-serif;color:#333;white-space:nowrap;cursor:pointer;outline:0;background-color:#ececec;background-image:-webkit-gradient(linear,0 0,0 100%,from(#f4f4f4),to(#ececec));background-image:-moz-linear-gradient(#f4f4f4,#ececec);background-image:-o-linear-gradient(#f4f4f4,#ececec);background-image:linear-gradient(#f4f4f4,#ececec);-webkit-background-clip:padding;-moz-background-clip:padding;-o-background-clip:padding-box;-webkit-border-radius:.2em;-moz-border-radius:.2em;border-radius:.2em;zoom:1;*display:inline;margin-top:10px}.introjs-button:hover{border-color:#bcbcbc;text-decoration:none;box-shadow:0 1px 1px #e3e3e3}.introjs-button:focus,.introjs-button:active{background-image:-webkit-gradient(linear,0 0,0 100%,from(#ececec),to(#f4f4f4));background-image:-moz-linear-gradient(#ececec,#f4f4f4);background-image:-o-linear-gradient(#ececec,#f4f4f4);background-image:linear-gradient(#ececec,#f4f4f4)}.introjs-button::-moz-focus-inner{padding:0;border:0}.introjs-skipbutton{box-sizing:content-box;margin-right:5px;color:#7a7a7a}.introjs-prevbutton{-webkit-border-radius:.2em 0 0 .2em;-moz-border-radius:.2em 0 0 .2em;border-radius:.2em 0 0 .2em;border-right:0}.introjs-prevbutton.introjs-fullbutton{border:1px solid #d4d4d4;-webkit-border-radius:.2em;-moz-border-radius:.2em;border-radius:.2em}.introjs-nextbutton{-webkit-border-radius:0 .2em .2em 0;-moz-border-radius:0 .2em .2em 0;border-radius:0 .2em .2em 0}.introjs-nextbutton.introjs-fullbutton{-webkit-border-radius:.2em;-moz-border-radius:.2em;border-radius:.2em}.introjs-disabled,.introjs-disabled:hover,.introjs-disabled:focus{color:#9a9a9a;border-color:#d4d4d4;box-shadow:none;cursor:default;background-color:#f4f4f4;background-image:none;text-decoration:none}.introjs-hidden{display:none}.introjs-bullets{text-align:center}.introjs-bullets ul{box-sizing:content-box;clear:both;margin:15px auto 0;padding:0;display:inline-block}.introjs-bullets ul li{box-sizing:content-box;list-style:none;float:left;margin:0 2px}.introjs-bullets ul li a{box-sizing:content-box;display:block;width:6px;height:6px;background:#ccc;border-radius:10px;-moz-border-radius:10px;-webkit-border-radius:10px;text-decoration:none;cursor:pointer}.introjs-bullets ul li a:hover{background:#999}.introjs-bullets ul li a.active{background:#999}.introjs-progress{box-sizing:content-box;overflow:hidden;height:10px;margin:10px 0 5px 0;border-radius:4px;background-color:#ecf0f1}.introjs-progressbar{box-sizing:content-box;float:left;width:0;height:100%;font-size:10px;line-height:10px;text-align:center;background-color:#08c}.introjsFloatingElement{position:absolute;height:0;width:0;left:50%;top:50%}.introjs-fixedTooltip{position:fixed}.introjs-hint{box-sizing:content-box;position:absolute;background:transparent;width:20px;height:15px;cursor:pointer}.introjs-hint:focus{border:0;outline:0}.introjs-hidehint{display:none}.introjs-fixedhint{position:fixed}.introjs-hint:hover>.introjs-hint-pulse{border:5px solid rgba(60,60,60,0.57)}.introjs-hint-pulse{box-sizing:content-box;width:10px;height:10px;border:5px solid rgba(60,60,60,0.27);-webkit-border-radius:30px;-moz-border-radius:30px;border-radius:30px;background-color:rgba(136,136,136,0.24);z-index:10;position:absolute;-webkit-transition:all .2s ease-out;-moz-transition:all .2s ease-out;-ms-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}.introjs-hint-no-anim .introjs-hint-dot{-webkit-animation:none;-moz-animation:none;animation:none}.introjs-hint-dot{box-sizing:content-box;border:10px solid rgba(146,146,146,0.36);background:transparent;-webkit-border-radius:60px;-moz-border-radius:60px;border-radius:60px;height:50px;width:50px;-webkit-animation:introjspulse 3s ease-out;-moz-animation:introjspulse 3s ease-out;animation:introjspulse 3s ease-out;-webkit-animation-iteration-count:infinite;-moz-animation-iteration-count:infinite;animation-iteration-count:infinite;position:absolute;top:-25px;left:-25px;z-index:1;opacity:0}@-webkit-keyframes introjspulse{0%{-webkit-transform:scale(0);opacity:.0}25%{-webkit-transform:scale(0);opacity:.1}50%{-webkit-transform:scale(0.1);opacity:.3}75%{-webkit-transform:scale(0.5);opacity:.5}100%{-webkit-transform:scale(1);opacity:.0}}@-moz-keyframes introjspulse{0%{-moz-transform:scale(0);opacity:.0}25%{-moz-transform:scale(0);opacity:.1}50%{-moz-transform:scale(0.1);opacity:.3}75%{-moz-transform:scale(0.5);opacity:.5}100%{-moz-transform:scale(1);opacity:.0}}@keyframes introjspulse{0%{transform:scale(0);opacity:.0}25%{transform:scale(0);opacity:.1}50%{transform:scale(0.1);opacity:.3}75%{transform:scale(0.5);opacity:.5}100%{transform:scale(1);opacity:.0}} \ No newline at end of file diff --git a/apps/remix-ide/src/assets/css/intro.js/4.1.0/introjs.min.css b/apps/remix-ide/src/assets/css/intro.js/4.1.0/introjs.min.css new file mode 100644 index 0000000000..d8b1714797 --- /dev/null +++ b/apps/remix-ide/src/assets/css/intro.js/4.1.0/introjs.min.css @@ -0,0 +1,2 @@ +@-webkit-keyframes introjspulse{0%{-webkit-transform:scale(0);transform:scale(0);opacity:0}25%{-webkit-transform:scale(0);transform:scale(0);opacity:.1}50%{-webkit-transform:scale(.1);transform:scale(.1);opacity:.3}75%{-webkit-transform:scale(.5);transform:scale(.5);opacity:.5}100%{-webkit-transform:scale(1);transform:scale(1);opacity:0}}@keyframes introjspulse{0%{-webkit-transform:scale(0);transform:scale(0);opacity:0}25%{-webkit-transform:scale(0);transform:scale(0);opacity:.1}50%{-webkit-transform:scale(.1);transform:scale(.1);opacity:.3}75%{-webkit-transform:scale(.5);transform:scale(.5);opacity:.5}100%{-webkit-transform:scale(1);transform:scale(1);opacity:0}}.introjs-overlay{position:absolute;-webkit-box-sizing:content-box;box-sizing:content-box;z-index:999999;opacity:0;-webkit-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-showElement{z-index:9999999!important}tr.introjs-showElement>td{z-index:9999999!important;position:relative}tr.introjs-showElement>th{z-index:9999999!important;position:relative}.introjs-disableInteraction{z-index:99999999!important;position:absolute;background-color:#fff;opacity:0}.introjs-relativePosition{position:relative}.introjs-helperLayer{-webkit-box-sizing:content-box;box-sizing:content-box;position:absolute;z-index:9999998;border-radius:4px;-webkit-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-helperLayer *{-webkit-box-sizing:content-box;box-sizing:content-box}.introjs-helperLayer :before{-webkit-box-sizing:content-box;box-sizing:content-box}.introjs-helperLayer :after{-webkit-box-sizing:content-box;box-sizing:content-box}.introjs-tooltipReferenceLayer{font-family:"Helvetica Neue",Inter,ui-sans-serif,"Apple Color Emoji",Helvetica,Arial,sans-serif;-webkit-box-sizing:content-box;box-sizing:content-box;position:absolute;visibility:hidden;z-index:100000000;background-color:transparent;-webkit-transition:all .3s ease-out;-o-transition:all .3s ease-out;transition:all .3s ease-out}.introjs-tooltipReferenceLayer *{font-family:"Helvetica Neue",Inter,ui-sans-serif,"Apple Color Emoji",Helvetica,Arial,sans-serif}.introjs-helperNumberLayer{font-family:"Helvetica Neue",Inter,ui-sans-serif,"Apple Color Emoji",Helvetica,Arial,sans-serif;color:#9e9e9e;text-align:center;padding-top:10px;padding-bottom:10px}.introjs-arrow{border:5px solid transparent;content:"";position:absolute}.introjs-arrow.top{top:-10px;left:10px;border-bottom-color:#fff}.introjs-arrow.top-right{top:-10px;right:10px;border-bottom-color:#fff}.introjs-arrow.top-middle{top:-10px;left:50%;margin-left:-5px;border-bottom-color:#fff}.introjs-arrow.right{right:-10px;top:10px;border-left-color:#fff}.introjs-arrow.right-bottom{bottom:10px;right:-10px;border-left-color:#fff}.introjs-arrow.bottom{bottom:-10px;left:10px;border-top-color:#fff}.introjs-arrow.bottom-right{bottom:-10px;right:10px;border-top-color:#fff}.introjs-arrow.bottom-middle{bottom:-10px;left:50%;margin-left:-5px;border-top-color:#fff}.introjs-arrow.left{left:-10px;top:10px;border-right-color:#fff}.introjs-arrow.left-bottom{left:-10px;bottom:10px;border-right-color:#fff}.introjs-tooltip{-webkit-box-sizing:content-box;box-sizing:content-box;position:absolute;visibility:visible;background-color:#fff;min-width:250px;max-width:300px;border-radius:5px;-webkit-box-shadow:0 3px 30px rgba(33,33,33,.3);box-shadow:0 3px 30px rgba(33,33,33,.3);-webkit-transition:opacity .1s ease-out;-o-transition:opacity .1s ease-out;transition:opacity .1s ease-out}.introjs-tooltiptext{padding:20px}.introjs-tooltip-title{font-size:18px;margin:0;padding:0;font-weight:700;float:left;line-height:32px}.introjs-tooltip-header{padding-left:20px;padding-right:20px;padding-top:10px}.introjs-tooltip-header:after{content:".";visibility:hidden;display:block;height:0;clear:both}.introjs-tooltipbuttons{border-top:1px solid #e0e0e0;padding:10px;text-align:right;white-space:nowrap}.introjs-tooltipbuttons:after{content:"";visibility:hidden;display:block;height:0;clear:both}.introjs-button{-webkit-box-sizing:content-box;box-sizing:content-box;position:relative;overflow:visible;display:inline-block;padding:.5rem 1rem;border:1px solid #bdbdbd;text-decoration:none;text-shadow:1px 1px 0 #fff;font-size:14px;color:#424242;white-space:nowrap;cursor:pointer;outline:0;background-color:#f4f4f4;border-radius:.2em;zoom:1}.introjs-button:hover{outline:0;text-decoration:none;border-color:#9e9e9e;background-color:#e0e0e0;color:#212121}.introjs-button:focus{outline:0;text-decoration:none;background-color:#eee;-webkit-box-shadow:0 0 0 .2rem rgba(158,158,158,.5);box-shadow:0 0 0 .2rem rgba(158,158,158,.5);border:1px solid #616161;color:#212121}.introjs-button:active{outline:0;text-decoration:none;background-color:#e0e0e0;border-color:#9e9e9e;color:#212121}.introjs-button::-moz-focus-inner{padding:0;border:0}.introjs-skipbutton{-webkit-box-sizing:content-box;box-sizing:content-box;color:#616161;float:right;font-size:20px;cursor:pointer;font-weight:700;line-height:1;text-align:center;padding:7px 10px}.introjs-skipbutton:focus,.introjs-skipbutton:hover{color:#212121;outline:0;text-decoration:none}.introjs-prevbutton{float:left}.introjs-nextbutton{float:right}.introjs-disabled{color:#9e9e9e;border-color:#bdbdbd;-webkit-box-shadow:none;box-shadow:none;cursor:default;background-color:#f4f4f4;background-image:none;text-decoration:none}.introjs-disabled:focus,.introjs-disabled:hover{color:#9e9e9e;border-color:#bdbdbd;-webkit-box-shadow:none;box-shadow:none;cursor:default;background-color:#f4f4f4;background-image:none;text-decoration:none}.introjs-hidden{display:none}.introjs-bullets{text-align:center;padding-top:10px;padding-bottom:10px}.introjs-bullets ul{-webkit-box-sizing:content-box;box-sizing:content-box;clear:both;margin:0 auto 0;padding:0;display:inline-block}.introjs-bullets ul li{-webkit-box-sizing:content-box;box-sizing:content-box;list-style:none;float:left;margin:0 2px}.introjs-bullets ul li a{-webkit-transition:width .1s ease-in;-o-transition:width .1s ease-in;transition:width .1s ease-in;-webkit-box-sizing:content-box;box-sizing:content-box;display:block;width:6px;height:6px;background:#ccc;border-radius:10px;text-decoration:none;cursor:pointer}.introjs-bullets ul li a:focus,.introjs-bullets ul li a:hover{width:15px;background:#999;text-decoration:none;outline:0}.introjs-bullets ul li a.active{width:15px;background:#999}.introjs-progress{-webkit-box-sizing:content-box;box-sizing:content-box;overflow:hidden;height:10px;margin:10px;border-radius:4px;background-color:#e0e0e0}.introjs-progressbar{-webkit-box-sizing:content-box;box-sizing:content-box;float:left;width:0%;height:100%;font-size:10px;line-height:10px;text-align:center;background-color:#08c}.introjsFloatingElement{position:absolute;height:0;width:0;left:50%;top:50%}.introjs-fixedTooltip{position:fixed}.introjs-hint{-webkit-box-sizing:content-box;box-sizing:content-box;position:absolute;background:0 0;width:20px;height:15px;cursor:pointer}.introjs-hint:focus{border:0;outline:0}.introjs-hint:hover>.introjs-hint-pulse{border:5px solid rgba(60,60,60,.57)}.introjs-hidehint{display:none}.introjs-fixedhint{position:fixed}.introjs-hint-pulse{-webkit-box-sizing:content-box;box-sizing:content-box;width:10px;height:10px;border:5px solid rgba(60,60,60,.27);border-radius:30px;background-color:rgba(136,136,136,.24);z-index:10;position:absolute;-webkit-transition:all .2s ease-out;-o-transition:all .2s ease-out;transition:all .2s ease-out}.introjs-hint-no-anim .introjs-hint-dot{-webkit-animation:none;animation:none}.introjs-hint-dot{-webkit-box-sizing:content-box;box-sizing:content-box;border:10px solid rgba(146,146,146,.36);background:0 0;border-radius:60px;height:50px;width:50px;-webkit-animation:introjspulse 3s ease-out;animation:introjspulse 3s ease-out;-webkit-animation-iteration-count:infinite;animation-iteration-count:infinite;position:absolute;top:-25px;left:-25px;z-index:1;opacity:0} +/*# sourceMappingURL=introjs.min.css.map */ \ No newline at end of file diff --git a/apps/remix-ide/src/remixEngine.js b/apps/remix-ide/src/remixEngine.js index e7c358e576..1ad385146b 100644 --- a/apps/remix-ide/src/remixEngine.js +++ b/apps/remix-ide/src/remixEngine.js @@ -13,6 +13,7 @@ export class RemixEngine extends Engine { if (name === 'dGitProvider') return { queueTimeout: 60000 * 4 } if (name === 'slither') return { queueTimeout: 60000 * 4 } // Requires when a solc version is installed if (name === 'hardhat') return { queueTimeout: 60000 * 4 } + if (name === 'localPlugin') return { queueTimeout: 60000 * 4 } return { queueTimeout: 10000 } } diff --git a/package-lock.json b/package-lock.json index 87b6da39fe..5fcf108368 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9251,46 +9251,46 @@ "integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==" }, "@remixproject/engine": { - "version": "0.3.208", - "resolved": "https://registry.npmjs.org/@remixproject/engine/-/engine-0.3.208.tgz", - "integrity": "sha512-kEWHrkQZUbik4uAVotFRVWA1+Za5m1EUYsKYaFLdroQHIUzuiWZjgYfxDixFb/hGYUZy2GPLzwTkNfJnRmSSaQ==", + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/@remixproject/engine/-/engine-0.3.24.tgz", + "integrity": "sha512-XVPaRIAwxTxEmc+u+bq9nIqUcP1NDdQFTm/8xmw8HcZicgagUW/y0RuLEMBj5GTGXF+EsljY27t6bPy7fmVHWQ==", "requires": { - "@remixproject/plugin-api": "0.3.208", - "@remixproject/plugin-utils": "0.3.208" + "@remixproject/plugin-api": "0.3.24", + "@remixproject/plugin-utils": "0.3.24" } }, "@remixproject/engine-web": { - "version": "0.3.208", - "resolved": "https://registry.npmjs.org/@remixproject/engine-web/-/engine-web-0.3.208.tgz", - "integrity": "sha512-3/OqsTKub5J374GoNo3H/889BdfL+khfj9uyKiyWMVK+hCQ5acdpLa+H7CPdUBbqk/Gt1HjjD+iV2zzRw/vdWg==", + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/@remixproject/engine-web/-/engine-web-0.3.24.tgz", + "integrity": "sha512-6P2NLoL9KSa/84FumEM3QxvOW4g/hIEsq8NcbBA+/PHz9VnIRoxRg2K/jGJUHHqKw+dfoSdk5lQ+LkFQHcrp+w==", "requires": { - "@remixproject/engine": "0.3.208", - "@remixproject/plugin-api": "0.3.208", - "@remixproject/plugin-utils": "0.3.208" + "@remixproject/engine": "0.3.24", + "@remixproject/plugin-api": "0.3.24", + "@remixproject/plugin-utils": "0.3.24" } }, "@remixproject/plugin": { - "version": "0.3.208", - "resolved": "https://registry.npmjs.org/@remixproject/plugin/-/plugin-0.3.208.tgz", - "integrity": "sha512-6bA8823xaRYn+dYf1a1AObiCgSf6Q4tlSmVvcS/KYWQmi2upDmfGCILxAVaKD6CWCTP/3bdeXeH/q766NdpLcQ==", + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/@remixproject/plugin/-/plugin-0.3.24.tgz", + "integrity": "sha512-nGtt3IZA5X2kcXauu5h5P8EEoMtHbVGm5wWnv0c7aYYWbffhQdK8dqtNNEAtQavWrsp5TL61zekqpkFzgxVv9w==", "requires": { - "@remixproject/plugin-api": "0.3.208", - "@remixproject/plugin-utils": "0.3.208", + "@remixproject/plugin-api": "0.3.24", + "@remixproject/plugin-utils": "0.3.24", "events": "3.2.0" } }, "@remixproject/plugin-api": { - "version": "0.3.208", - "resolved": "https://registry.npmjs.org/@remixproject/plugin-api/-/plugin-api-0.3.208.tgz", - "integrity": "sha512-11hFxABBrEzE4fgcDblWqxLAh5ARH2tBADgh9KNk+y7LUV7aQ7OZf4KiZ2US+uKiSC6497iu/uLHbWBTeRqlVA==", + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/@remixproject/plugin-api/-/plugin-api-0.3.24.tgz", + "integrity": "sha512-mBxou9OSsQt7ggMmKTJR433jJaSAckBmVj82Ek7i/+EGxEAxSqKhPfRlh5sFiTgvUmzHQzuvqa8ndyw0Bbcq4w==", "requires": { - "@remixproject/plugin-utils": "0.3.208" + "@remixproject/plugin-utils": "0.3.24" } }, "@remixproject/plugin-utils": { - "version": "0.3.208", - "resolved": "https://registry.npmjs.org/@remixproject/plugin-utils/-/plugin-utils-0.3.208.tgz", - "integrity": "sha512-PjEK+ty6X14ud3h2U/XH8BBbqwLF3CwduOxHCXfCG0KarR4FwuSfocWQfGlASeDFmPzyV1aMGn//U6xZ03O42Q==", + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/@remixproject/plugin-utils/-/plugin-utils-0.3.24.tgz", + "integrity": "sha512-nMXGCgs6filbgUc/Zvh1gReGG5HN2Bq+AI4Q7Ao08Thhg5ALj1UsbzQf86Ya/L7Q+EF6Em1CbgPT0VhcGlP66A==", "requires": { "tslib": "2.0.1" }, @@ -9303,13 +9303,13 @@ } }, "@remixproject/plugin-webview": { - "version": "0.3.208", - "resolved": "https://registry.npmjs.org/@remixproject/plugin-webview/-/plugin-webview-0.3.208.tgz", - "integrity": "sha512-nbcWq7xYqNQXu4G84B68fzNWsafpO9NHcmLiVOFqel6xl7gp4X9hpY5dm4Cs7WY+9YY0IdLWRNfqA6pbT2qsgw==", + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/@remixproject/plugin-webview/-/plugin-webview-0.3.24.tgz", + "integrity": "sha512-Wcyi+gGq1AYprE58vhQS181swAKZpoLAfKlKuHJ+ezbysUDuX8jgsEiQ6u1c17nQfy8Hp9sntK6VcCcDddn8gg==", "requires": { - "@remixproject/plugin": "0.3.208", - "@remixproject/plugin-api": "0.3.208", - "@remixproject/plugin-utils": "0.3.208", + "@remixproject/plugin": "0.3.24", + "@remixproject/plugin-api": "0.3.24", + "@remixproject/plugin-utils": "0.3.24", "axios": "^0.21.1" }, "dependencies": { @@ -9324,13 +9324,13 @@ } }, "@remixproject/plugin-ws": { - "version": "0.3.208", - "resolved": "https://registry.npmjs.org/@remixproject/plugin-ws/-/plugin-ws-0.3.208.tgz", - "integrity": "sha512-7GH18UXSO8TZ9khKPvJQESGMVDSnPhDj42j4ENjK+Td6qpYutfTmqMD1YMW3TL2KgY89irytPHCMuCiUtEDoBQ==", + "version": "0.3.24", + "resolved": "https://registry.npmjs.org/@remixproject/plugin-ws/-/plugin-ws-0.3.24.tgz", + "integrity": "sha512-COIROJX61vS2TRH82MflIUlScxLauNtLkMRY7vzncVOIvufApvNc84Ua8Vr6vhSb2tZeWX+u4UTiFnpFDRL7xw==", "requires": { - "@remixproject/plugin": "0.3.208", - "@remixproject/plugin-api": "0.3.208", - "@remixproject/plugin-utils": "0.3.208" + "@remixproject/plugin": "0.3.24", + "@remixproject/plugin-api": "0.3.24", + "@remixproject/plugin-utils": "0.3.24" } }, "@restart/context": { @@ -24063,6 +24063,12 @@ "isobject": "^3.0.1" } }, + "is-port-reachable": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-port-reachable/-/is-port-reachable-3.1.0.tgz", + "integrity": "sha512-vjc0SSRNZ32s9SbZBzGaiP6YVB+xglLShhgZD/FHMZUXBvQWaV9CtzgeVhjccFJrI6RAMV+LX7NYxueW/A8W5A==", + "dev": true + }, "is-posix-bracket": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", @@ -41555,15 +41561,17 @@ "integrity": "sha1-9RWxoWLek8LM7y/AyjPztVQ+OMg=" }, "selenium-standalone": { - "version": "6.24.0", - "resolved": "https://registry.npmjs.org/selenium-standalone/-/selenium-standalone-6.24.0.tgz", - "integrity": "sha512-Dun2XgNAgCfJNrrSzuv7Z7Wj7QTvBKpqx0VXFz7bW9T9FUe5ytzgzoCEEshwDVMh0Dv6sCgdZg7VDhM/q2yPPQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/selenium-standalone/-/selenium-standalone-7.1.0.tgz", + "integrity": "sha512-Pc7U48qwB4LVy/XczBrPPXwUhEPl3XQSik8SjLfj2qzBEtZqrjyzOlnnXq4aVCdr5wH9FiFJm8LwheJbK2+/oQ==", "dev": true, "requires": { - "commander": "^2.20.3", + "commander": "^7.2.0", "cross-spawn": "^7.0.3", "debug": "^4.3.1", + "fs-extra": "^10.0.0", "got": "^11.8.2", + "is-port-reachable": "^3.0.0", "lodash.mapvalues": "^4.6.0", "lodash.merge": "^4.6.2", "minimist": "^1.2.5", @@ -41604,6 +41612,12 @@ "responselike": "^2.0.0" } }, + "commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "dev": true + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -41639,6 +41653,17 @@ "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "dev": true }, + "fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, "get-stream": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", @@ -41673,6 +41698,16 @@ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, "keyv": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.0.3.tgz", @@ -41748,6 +41783,12 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index b0412172a1..b6d99a91d7 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ "nightwatch_local_gist": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/gist.spec.js --env=chrome", "nightwatch_local_workspace": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/workspace.test.js --env=chrome", "nightwatch_local_defaultLayout": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/defaultLayout.test.js --env=chrome", - "nightwatch_local_pluginManager": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/pluginManager.js --env=chrome", + "nightwatch_local_pluginManager": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/pluginManager.test.js --env=chrome", "nightwatch_local_publishContract": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/publishContract.test.js --env=chrome", "nightwatch_local_generalSettings": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/generalSettings.test.js --env=chrome", "nightwatch_local_fileExplorer": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/fileExplorer.test.js --env=chrome", @@ -90,6 +90,7 @@ "nightwatch_local_runAndDeploy": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/runAndDeploy.js --env=chrome-runAndDeploy", "nightwatch_local_url": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/url.spec.js --env=chrome", "nightwatch_local_verticalIconscontextmenu": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/verticalIconsPanel.spec.js --env=chrome", + "nightwatch_local_pluginApi": "npm run build:e2e && nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js dist/apps/remix-ide-e2e/src/tests/plugin_api.js --env=chrome", "onchange": "onchange apps/remix-ide/build/app.js -- npm-run-all lint", "remixd": "nx build remixd && nx serve remixd --folder=./apps/remix-ide/contracts --remixide=http://127.0.0.1:8080", "selenium": "selenium-standalone start", @@ -141,13 +142,13 @@ "@ethereumjs/tx": "^3.3.2", "@ethereumjs/vm": "^5.5.3", "@monaco-editor/react": "^4.3.1", - "@remixproject/engine": "^0.3.20", - "@remixproject/engine-web": "^0.3.20", - "@remixproject/plugin": "^0.3.20", - "@remixproject/plugin-api": "^0.3.20", - "@remixproject/plugin-utils": "^0.3.20", - "@remixproject/plugin-webview": "^0.3.20", - "@remixproject/plugin-ws": "^0.3.20", + "@remixproject/engine": "^0.3.24", + "@remixproject/engine-web": "^0.3.24", + "@remixproject/plugin": "^0.3.24", + "@remixproject/plugin-api": "^0.3.24", + "@remixproject/plugin-utils": "^0.3.24", + "@remixproject/plugin-webview": "^0.3.24", + "@remixproject/plugin-ws": "^0.3.24", "ansi-gray": "^0.1.1", "async": "^2.6.2", "axios": ">=0.21.1", @@ -218,7 +219,7 @@ "@types/jest": "^27.0.2", "@types/lodash": "^4.14.172", "@types/mocha": "^7.0.2", - "@types/nightwatch": "^1.1.6", + "@types/nightwatch": "1.3.4", "@types/node": "~8.9.4", "@types/react": "^17.0.24", "@types/react-beautiful-dnd": "^13.1.2", @@ -279,7 +280,7 @@ "mkdirp": "^0.5.1", "mocha": "^8.0.1", "nanohtml": "^1.6.3", - "nightwatch": "^1.5.1", + "nightwatch": "^1.7.11", "nodemon": "^2.0.4", "notify-error": "^1.2.0", "npm-link-local": "^1.1.0", @@ -291,7 +292,7 @@ "remix-tabs": "1.1.3", "request": "^2.83.0", "rimraf": "^2.6.1", - "selenium-standalone": "^6.17.0", + "selenium-standalone": "^7.1.0", "semver": "^6.3.0", "solc": "0.7.4", "swarmgw": "^0.3.1",