Merge branch 'master' into remixd_terminal

pull/1342/head
David Zagi 3 years ago committed by GitHub
commit 046e04f1ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 40
      .circleci/config.yml
  2. 2
      apps/remix-ide-e2e/nightwatch.ts
  3. 4
      apps/remix-ide-e2e/src/local-plugin/.babelrc
  4. 16
      apps/remix-ide-e2e/src/local-plugin/.browserslistrc
  5. 248
      apps/remix-ide-e2e/src/local-plugin/.eslintrc
  6. 128
      apps/remix-ide-e2e/src/local-plugin/src/app/app.css
  7. 39
      apps/remix-ide-e2e/src/local-plugin/src/app/app.tsx
  8. 17
      apps/remix-ide-e2e/src/local-plugin/src/app/logo.svg
  9. 11
      apps/remix-ide-e2e/src/local-plugin/src/app/star.svg
  10. 0
      apps/remix-ide-e2e/src/local-plugin/src/assets/.gitkeep
  11. 3
      apps/remix-ide-e2e/src/local-plugin/src/environments/environment.prod.ts
  12. 6
      apps/remix-ide-e2e/src/local-plugin/src/environments/environment.ts
  13. BIN
      apps/remix-ide-e2e/src/local-plugin/src/favicon.ico
  14. 14
      apps/remix-ide-e2e/src/local-plugin/src/index.html
  15. 11
      apps/remix-ide-e2e/src/local-plugin/src/main.tsx
  16. 7
      apps/remix-ide-e2e/src/local-plugin/src/polyfills.ts
  17. 1
      apps/remix-ide-e2e/src/local-plugin/src/styles.css
  18. 13
      apps/remix-ide-e2e/src/local-plugin/tsconfig.app.json
  19. 16
      apps/remix-ide-e2e/src/local-plugin/tsconfig.json
  20. 41
      apps/remix-ide-e2e/src/tests/pluginManager.ts
  21. 55
      apps/remix-ide-e2e/src/tests/solidityUnittests.spec.ts
  22. 21
      apps/remix-ide/ci/browser_tests_plugin_manager.sh
  23. 14
      apps/remix-ide/src/app/tabs/test-tab.js
  24. 9
      libs/remix-tests/src/testRunner.ts
  25. 5
      nx.json
  26. 2
      package.json
  27. 74
      workspace.json

@ -220,6 +220,40 @@ jobs:
- store_artifacts: - store_artifacts:
path: ./reports/screenshots path: ./reports/screenshots
remix-ide-plugin-manager:
docker:
# specify the version you desire here
- image: circleci/node:10.18.0-browsers
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
resource_class: xlarge
# - image: circleci/mongo:3.4.4
environment:
- COMMIT_AUTHOR_EMAIL: "yann@ethereum.org"
- COMMIT_AUTHOR: "Circle CI"
- FILES_TO_PACKAGE: "dist/apps/remix-ide/assets dist/apps/remix-ide/index.html dist/apps/remix-ide/main.js dist/apps/remix-ide/polyfills.js dist/apps/remix-ide/runtime.js dist/apps/remix-ide/vendor.js dist/apps/remix-ide/favicon.ico"
working_directory: ~/remix-project
steps:
- checkout
- run: npm install
- run: npx nx build remix-ide --with-deps
- run: npx nx build remix-ide-e2e-src-local-plugin
- run:
name: Download Selenium
command: ./node_modules/.bin/selenium-standalone install --drivers.chrome.version=2.39 --drivers.chrome.baseURL=https://chromedriver.storage.googleapis.com
- run:
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
- store_test_results:
path: ./reports/tests
- store_artifacts:
path: ./reports/screenshots
deploy-remix-live: deploy-remix-live:
docker: docker:
@ -355,6 +389,9 @@ workflows:
- remix-ide-run-deploy: - remix-ide-run-deploy:
requires: requires:
- lint - lint
- remix-ide-plugin-manager:
requires:
- lint
- publish: - publish:
requires: requires:
- lint - lint
@ -365,6 +402,7 @@ workflows:
- remix-ide-firefox-1 - remix-ide-firefox-1
- remix-ide-firefox-2 - remix-ide-firefox-2
- remix-ide-run-deploy - remix-ide-run-deploy
- remix-ide-plugin-manager
filters: filters:
branches: branches:
only: remix_live only: remix_live
@ -375,6 +413,7 @@ workflows:
- remix-ide-firefox-1 - remix-ide-firefox-1
- remix-ide-firefox-2 - remix-ide-firefox-2
- remix-ide-run-deploy - remix-ide-run-deploy
- remix-ide-plugin-manager
filters: filters:
branches: branches:
only: master only: master
@ -385,6 +424,7 @@ workflows:
- remix-ide-firefox-1 - remix-ide-firefox-1
- remix-ide-firefox-2 - remix-ide-firefox-2
- remix-ide-run-deploy - remix-ide-run-deploy
- remix-ide-plugin-manager
filters: filters:
branches: branches:
only: remix_beta only: remix_beta

@ -30,7 +30,7 @@ module.exports = {
javascriptEnabled: true, javascriptEnabled: true,
acceptSslCerts: true acceptSslCerts: true
}, },
exclude: ['dist/apps/remix-ide-e2e/src/tests/runAndDeploy.js'] exclude: ['dist/apps/remix-ide-e2e/src/tests/runAndDeploy.js', 'dist/apps/remix-ide-e2e/src/tests/pluginManager.spec.ts']
}, },
chrome: { chrome: {

@ -0,0 +1,4 @@
{
"presets": ["@nrwl/react/babel"],
"plugins": []
}

@ -0,0 +1,16 @@
# This file is used by:
# 1. autoprefixer to adjust CSS to support the below specified browsers
# 2. babel preset-env to adjust included polyfills
#
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
#
# If you need to support different browsers in production, you may tweak the list below.
last 1 Chrome version
last 1 Firefox version
last 2 Edge major versions
last 2 Safari major version
last 2 iOS major versions
Firefox ESR
not IE 9-11 # For IE 9-11 support, remove 'not'.

@ -0,0 +1,248 @@
{
"rules": {
"array-callback-return": "warn",
"dot-location": ["warn", "property"],
"eqeqeq": ["warn", "smart"],
"new-parens": "warn",
"no-caller": "warn",
"no-cond-assign": ["warn", "except-parens"],
"no-const-assign": "warn",
"no-control-regex": "warn",
"no-delete-var": "warn",
"no-dupe-args": "warn",
"no-dupe-keys": "warn",
"no-duplicate-case": "warn",
"no-empty-character-class": "warn",
"no-empty-pattern": "warn",
"no-eval": "warn",
"no-ex-assign": "warn",
"no-extend-native": "warn",
"no-extra-bind": "warn",
"no-extra-label": "warn",
"no-fallthrough": "warn",
"no-func-assign": "warn",
"no-implied-eval": "warn",
"no-invalid-regexp": "warn",
"no-iterator": "warn",
"no-label-var": "warn",
"no-labels": ["warn", { "allowLoop": true, "allowSwitch": false }],
"no-lone-blocks": "warn",
"no-loop-func": "warn",
"no-mixed-operators": [
"warn",
{
"groups": [
["&", "|", "^", "~", "<<", ">>", ">>>"],
["==", "!=", "===", "!==", ">", ">=", "<", "<="],
["&&", "||"],
["in", "instanceof"]
],
"allowSamePrecedence": false
}
],
"no-multi-str": "warn",
"no-native-reassign": "warn",
"no-negated-in-lhs": "warn",
"no-new-func": "warn",
"no-new-object": "warn",
"no-new-symbol": "warn",
"no-new-wrappers": "warn",
"no-obj-calls": "warn",
"no-octal": "warn",
"no-octal-escape": "warn",
"no-redeclare": "warn",
"no-regex-spaces": "warn",
"no-restricted-syntax": ["warn", "WithStatement"],
"no-script-url": "warn",
"no-self-assign": "warn",
"no-self-compare": "warn",
"no-sequences": "warn",
"no-shadow-restricted-names": "warn",
"no-sparse-arrays": "warn",
"no-template-curly-in-string": "warn",
"no-this-before-super": "warn",
"no-throw-literal": "warn",
"no-restricted-globals": [
"error",
"addEventListener",
"blur",
"close",
"closed",
"confirm",
"defaultStatus",
"defaultstatus",
"event",
"external",
"find",
"focus",
"frameElement",
"frames",
"history",
"innerHeight",
"innerWidth",
"length",
"location",
"locationbar",
"menubar",
"moveBy",
"moveTo",
"name",
"onblur",
"onerror",
"onfocus",
"onload",
"onresize",
"onunload",
"open",
"opener",
"opera",
"outerHeight",
"outerWidth",
"pageXOffset",
"pageYOffset",
"parent",
"print",
"removeEventListener",
"resizeBy",
"resizeTo",
"screen",
"screenLeft",
"screenTop",
"screenX",
"screenY",
"scroll",
"scrollbars",
"scrollBy",
"scrollTo",
"scrollX",
"scrollY",
"self",
"status",
"statusbar",
"stop",
"toolbar",
"top"
],
"no-unexpected-multiline": "warn",
"no-unreachable": "warn",
"no-unused-expressions": [
"error",
{
"allowShortCircuit": true,
"allowTernary": true,
"allowTaggedTemplates": true
}
],
"no-unused-labels": "warn",
"no-useless-computed-key": "warn",
"no-useless-concat": "warn",
"no-useless-escape": "warn",
"no-useless-rename": [
"warn",
{
"ignoreDestructuring": false,
"ignoreImport": false,
"ignoreExport": false
}
],
"no-with": "warn",
"no-whitespace-before-property": "warn",
"react-hooks/exhaustive-deps": "warn",
"require-yield": "warn",
"rest-spread-spacing": ["warn", "never"],
"strict": ["warn", "never"],
"unicode-bom": ["warn", "never"],
"use-isnan": "warn",
"valid-typeof": "warn",
"no-restricted-properties": [
"error",
{
"object": "require",
"property": "ensure",
"message": "Please use import() instead. More info: https://facebook.github.io/create-react-app/docs/code-splitting"
},
{
"object": "System",
"property": "import",
"message": "Please use import() instead. More info: https://facebook.github.io/create-react-app/docs/code-splitting"
}
],
"getter-return": "warn",
"import/first": "error",
"import/no-amd": "error",
"import/no-webpack-loader-syntax": "error",
"react/forbid-foreign-prop-types": ["warn", { "allowInPropTypes": true }],
"react/jsx-no-comment-textnodes": "warn",
"react/jsx-no-duplicate-props": "warn",
"react/jsx-no-target-blank": "warn",
"react/jsx-no-undef": "error",
"react/jsx-pascal-case": ["warn", { "allowAllCaps": true, "ignore": [] }],
"react/jsx-uses-react": "warn",
"react/jsx-uses-vars": "warn",
"react/no-danger-with-children": "warn",
"react/no-direct-mutation-state": "warn",
"react/no-is-mounted": "warn",
"react/no-typos": "error",
"react/react-in-jsx-scope": "error",
"react/require-render-return": "error",
"react/style-prop-object": "warn",
"react/jsx-no-useless-fragment": "warn",
"jsx-a11y/accessible-emoji": "warn",
"jsx-a11y/alt-text": "warn",
"jsx-a11y/anchor-has-content": "warn",
"jsx-a11y/anchor-is-valid": [
"warn",
{ "aspects": ["noHref", "invalidHref"] }
],
"jsx-a11y/aria-activedescendant-has-tabindex": "warn",
"jsx-a11y/aria-props": "warn",
"jsx-a11y/aria-proptypes": "warn",
"jsx-a11y/aria-role": "warn",
"jsx-a11y/aria-unsupported-elements": "warn",
"jsx-a11y/heading-has-content": "warn",
"jsx-a11y/iframe-has-title": "warn",
"jsx-a11y/img-redundant-alt": "warn",
"jsx-a11y/no-access-key": "warn",
"jsx-a11y/no-distracting-elements": "warn",
"jsx-a11y/no-redundant-roles": "warn",
"jsx-a11y/role-has-required-aria-props": "warn",
"jsx-a11y/role-supports-aria-props": "warn",
"jsx-a11y/scope": "warn",
"react-hooks/rules-of-hooks": "error",
"default-case": "off",
"no-dupe-class-members": "off",
"no-undef": "off",
"@typescript-eslint/consistent-type-assertions": "warn",
"no-array-constructor": "off",
"@typescript-eslint/no-array-constructor": "warn",
"@typescript-eslint/no-namespace": "error",
"no-use-before-define": "off",
"@typescript-eslint/no-use-before-define": [
"warn",
{
"functions": false,
"classes": false,
"variables": false,
"typedefs": false
}
],
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"warn",
{ "args": "none", "ignoreRestSiblings": true }
],
"no-useless-constructor": "off",
"@typescript-eslint/no-useless-constructor": "warn"
},
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"jest": true,
"node": true
},
"settings": { "react": { "version": "detect" } },
"plugins": ["import", "jsx-a11y", "react", "react-hooks"],
"extends": ["../../../../.eslintrc"],
"ignorePatterns": ["!**/*"]
}

@ -0,0 +1,128 @@
.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;
}

@ -0,0 +1,39 @@
import React, { useEffect, useState } from 'react'
import { PluginClient } from '@remixproject/plugin'
import { createClient } from '@remixproject/plugin-webview'
import './app.css'
import { ReactComponent as Logo } from './logo.svg'
export const App = () => {
const [remixClient, setRemixClient] = useState(null)
useEffect(() => {
(async () => {
const client = createClient(new PluginClient())
await client.onload()
console.log('Local plugin loaded')
setRemixClient(client)
})()
}, [])
const handleClick = () => {
remixClient.call('manager', 'activatePlugin', 'LearnEth')
}
return (
<div className="app">
<header className="flex">
<Logo width="75" height="75" />
<h1>Welcome to local-plugin!</h1>
</header>
<main>
<button data-id="btnActivateRemixd" onClick={handleClick}>Activate Learneth</button>
</main>
</div>
)
}
export default App

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="262px" height="163px" viewBox="0 0 262 163" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="Styles-&amp;-Quick-Wins" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Nx---Quick-Wins" transform="translate(-476.000000, -1284.000000)" fill-rule="nonzero">
<g id="Logos" transform="translate(-11.000000, 782.000000)">
<g id="Nx_Flat_White" transform="translate(487.000000, 502.000000)">
<polygon id="Path" fill="#FFFFFF" points="130.68 104.59 97.49 52.71 97.44 96.3 40.24 0 0 0 0 162.57 39.79 162.57 39.92 66.39 96.53 158.26"></polygon>
<polygon id="Path" fill="#FFFFFF" points="97.5 41.79 137.24 41.79 137.33 41.33 137.33 0 97.54 0 97.49 41.33"></polygon>
<path d="M198.66,86.86 C189.139872,86.6795216 180.538723,92.516445 177.19,101.43 C182.764789,93.0931021 193.379673,89.7432211 202.73,93.37 C207.05,95.13 212.73,97.97 217.23,96.45 C212.950306,90.4438814 206.034895,86.8725952 198.66,86.86 L198.66,86.86 Z" id="Path" fill="#96D8E9"></path>
<path d="M243.75,106.42 C243.75,101.55 241.1,100.42 235.6,98.42 C231.52,97 226.89,95.4 223.52,91 C222.86,90.13 222.25,89.15 221.6,88.11 C220.14382,85.4164099 218.169266,83.037429 215.79,81.11 C212.58,78.75 208.37,77.6 202.91,77.6 C191.954261,77.6076705 182.084192,84.2206169 177.91,94.35 C183.186964,87.0278244 191.956716,83.0605026 200.940147,83.9314609 C209.923578,84.8024193 217.767888,90.3805017 221.54,98.58 C223.424615,101.689762 227.141337,103.174819 230.65,102.22 C236.02,101.07 235.65,106.15 243.76,107.87 L243.75,106.42 Z" id="Path" fill="#48C4E5"></path>
<path d="M261.46,105.38 L261.46,105.27 C261.34,73.03 235.17,45.45 202.91,45.45 C183.207085,45.4363165 164.821777,55.3450614 154,71.81 L153.79,71.45 L137.23,45.45 L97.5,45.4499858 L135.25,104.57 L98.41,162.57 L137,162.57 L153.79,136.78 L170.88,162.57 L209.48,162.57 L174.48,107.49 C173.899005,106.416838 173.583536,105.220114 173.56,104 C173.557346,96.2203871 176.64661,88.7586448 182.147627,83.2576275 C187.648645,77.7566101 195.110387,74.6673462 202.89,74.67 C219.11,74.67 221.82,84.37 225.32,88.93 C232.23,97.93 246.03,93.99 246.03,105.73 L246.03,105.73 C246.071086,108.480945 247.576662,111.001004 249.979593,112.340896 C252.382524,113.680787 255.317747,113.636949 257.679593,112.225896 C260.041438,110.814842 261.471086,108.250945 261.43,105.5 L261.43,105.5 L261.43,105.38 L261.46,105.38 Z" id="Path" fill="#FFFFFF"></path>
<path d="M261.5,113.68 C261.892278,116.421801 261.504116,119.218653 260.38,121.75 C258.18,126.84 254.51,125.14 254.51,125.14 C254.51,125.14 251.35,123.6 253.27,120.65 C255.4,117.36 259.61,117.74 261.5,113.68 Z" id="Path" fill="#FFFFFF"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg
className="material-icons"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path d="M0 0h24v24H0z" fill="none" />
<path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" />
</svg>

After

Width:  |  Height:  |  Size: 347 B

@ -0,0 +1,3 @@
export const environment = {
production: true
}

@ -0,0 +1,6 @@
// This file can be replaced during build by using the `fileReplacements` array.
// When building for production, this file is replaced with `environment.prod.ts`.
export const environment = {
production: false
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>LocalPlugin</title>
<base href="/" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" type="image/x-icon" href="favicon.ico" />
</head>
<body>
<div id="root"></div>
</body>
</html>

@ -0,0 +1,11 @@
import React from 'react'
import ReactDOM from 'react-dom'
import App from './app/app'
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
)

@ -0,0 +1,7 @@
/**
* Polyfill stable language features. These imports will be optimized by `@babel/preset-env`.
*
* See: https://github.com/zloirock/core-js#babel
*/
import 'core-js/stable'
import 'regenerator-runtime/runtime'

@ -0,0 +1 @@
/* You can add global styles to this file, and also import other style files */

@ -0,0 +1,13 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../../../dist/out-tsc",
"types": ["node"]
},
"files": [
"../../../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../../../node_modules/@nrwl/react/typings/image.d.ts"
],
"exclude": ["**/*.spec.ts", "**/*.spec.tsx"],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}

@ -0,0 +1,16 @@
{
"extends": "../../../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.app.json"
}
]
}

@ -12,6 +12,13 @@ const testData = {
pluginUrl: 'https://zokrates.github.io/zokrates-remix-plugin/' pluginUrl: 'https://zokrates.github.io/zokrates-remix-plugin/'
} }
const localPluginData = {
pluginName: 'localPlugin',
pluginDisplayName: 'Local Plugin',
pluginCanActivate: 'LearnEth',
pluginUrl: 'http://localhost:2020'
}
module.exports = { module.exports = {
before: function (browser: NightwatchBrowser, done: VoidFunction) { before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, 'http://127.0.0.1:8080', false) init(browser, done, 'http://127.0.0.1:8080', false)
@ -147,8 +154,38 @@ module.exports = {
.assert.containsText('*[data-shared="tooltipPopup"]', 'Cannot create Plugin : This name has already been used') .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) { 'Should load back installed plugins after reload': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('*[data-id="pluginManagerComponentPluginManager"]') browser
.waitForElementVisible('*[data-id="remixIdeSidePanel"]')
.click('*[plugin="pluginManager"]')
.waitForElementVisible('*[data-id="pluginManagerComponentPluginManager"]')
.getInstalledPlugins((plugins) => { .getInstalledPlugins((plugins) => {
browser.refresh() browser.refresh()
.waitForElementVisible('*[data-id="remixIdeSidePanel"]') .waitForElementVisible('*[data-id="remixIdeSidePanel"]')
@ -156,7 +193,7 @@ module.exports = {
.perform((done) => { .perform((done) => {
// const filtered = plugins.filter(plugin => plugin !== 'testremixIde') // remove this when localplugin bug is resolved // const filtered = plugins.filter(plugin => plugin !== 'testremixIde') // remove this when localplugin bug is resolved
plugins.forEach(plugin => { plugins.forEach(plugin => {
if (plugin !== testData.pluginName && plugin !== 'testremixIde') { if ((plugin !== testData.pluginName) && plugin !== localPluginData.pluginName) {
browser.waitForElementVisible(`[plugin="${plugin}"`) browser.waitForElementVisible(`[plugin="${plugin}"`)
} }
}) })

@ -90,11 +90,10 @@ module.exports = {
.waitForElementContainsText('*[data-id="testTabTestsExecutionStopped"]', 'The test execution has been stopped', 60000) .waitForElementContainsText('*[data-id="testTabTestsExecutionStopped"]', 'The test execution has been stopped', 60000)
}, },
'Should fail on compilation': function (browser: NightwatchBrowser) { 'Should fail on compilation, open file on error click, not disappear error': function (browser: NightwatchBrowser) {
browser.waitForElementPresent('*[data-id="verticalIconsKindfilePanel"]') browser.waitForElementPresent('*[data-id="verticalIconsKindfilePanel"]')
.addFile('tests/compilationError_test.sol', sources[0]['compilationError_test.sol']) .addFile('tests/compilationError_test.sol', sources[0]['compilationError_test.sol'])
.clickLaunchIcon('filePanel') .click('div[title="default_workspace/tests/compilationError_test.sol"] span[class="close"]')
.openFile('tests/compilationError_test.sol')
.clickLaunchIcon('solidityUnitTesting') .clickLaunchIcon('solidityUnitTesting')
.pause(2000) .pause(2000)
.click('*[data-id="testTabCheckAllTests"]') .click('*[data-id="testTabCheckAllTests"]')
@ -102,6 +101,12 @@ module.exports = {
.scrollAndClick('*[data-id="testTabRunTestsTabRunAction"]') .scrollAndClick('*[data-id="testTabRunTestsTabRunAction"]')
.waitForElementContainsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'SyntaxError: No visibility specified', 120000) .waitForElementContainsText('*[data-id="testTabSolidityUnitTestsOutput"]', 'SyntaxError: No visibility specified', 120000)
.waitForElementContainsText('*[data-id="testTabTestsExecutionStoppedError"]', 'The test execution has been stopped because of error(s) in your test file', 120000) .waitForElementContainsText('*[data-id="testTabTestsExecutionStoppedError"]', 'The test execution has been stopped because of error(s) in your test file', 120000)
.click('*[data-id="tests/compilationError_test.sol"]')
.pause(1000)
.getEditorValue((content) => browser.assert.ok(content.indexOf('contract failOnCompilation {') !== -1))
// Verify that compilation error is still present after a file is opened
// usually, tests result is cleared on opening a new file
.verify.elementPresent('*[data-id="tests/compilationError_test.sol"]')
}, },
'Should fail on deploy': function (browser: NightwatchBrowser) { 'Should fail on deploy': function (browser: NightwatchBrowser) {
@ -210,6 +215,23 @@ module.exports = {
.removeFile('tests/hhLogs_test.sol', 'workspace_new') .removeFile('tests/hhLogs_test.sol', 'workspace_new')
}, },
'Solidity Unit tests with hardhat console log for EVM revert': function (browser: NightwatchBrowser) {
browser
.waitForElementPresent('*[data-id="verticalIconsKindfilePanel"]')
.addFile('tests/ballotFailedLog_test.sol', sources[0]['tests/ballotFailedLog_test.sol'])
.clickLaunchIcon('solidityUnitTesting')
.waitForElementVisible('*[id="singleTesttests/4_Ballot_test.sol"]', 60000)
.click('*[id="singleTesttests/4_Ballot_test.sol"]')
.click('#runTestsTabRunAction')
.pause(2000)
.waitForElementVisible('*[data-id="testTabSolidityUnitTestsOutputheader"]', 120000)
.waitForElementContainsText('#solidityUnittestsOutput', 'tests/ballotFailedLog_test.sol', 60000)
.assert.containsText('#journal > div:nth-child(6) > span > div', 'Check winning proposal:')
.assert.containsText('#journal > div:nth-child(6) > span > div', 'Inside checkWinningProposal')
.openFile('tests/ballotFailedLog_test.sol')
.removeFile('tests/ballotFailedLog_test.sol', 'workspace_new')
},
'Debug failed test using debugger': function (browser: NightwatchBrowser) { 'Debug failed test using debugger': function (browser: NightwatchBrowser) {
browser browser
.waitForElementPresent('*[data-id="verticalIconsKindfilePanel"]') .waitForElementPresent('*[data-id="verticalIconsKindfilePanel"]')
@ -428,7 +450,7 @@ const sources = [
}, },
'compilationError_test.sol': { 'compilationError_test.sol': {
content: ` content: `
pragma solidity ^0.7.0; pragma solidity ^0.8.0;
contract failOnCompilation { contract failOnCompilation {
fallback() { fallback() {
@ -487,6 +509,31 @@ const sources = [
} }
}` }`
}, },
'tests/ballotFailedLog_test.sol': {
content: `// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "remix_tests.sol"; // this import is automatically injected by Remix.
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
}
}`
},
'tests/hhLogs_test.sol': { 'tests/hhLogs_test.sol': {
content: `// SPDX-License-Identifier: GPL-3.0 content: `// SPDX-License-Identifier: GPL-3.0

@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -e
BUILD_ID=${CIRCLE_BUILD_NUM:-${TRAVIS_JOB_NUMBER}}
echo "$BUILD_ID"
TEST_EXITCODE=0
npm run serve &
npx nx serve remix-ide-e2e-src-local-plugin &
sleep 5
npm run build:e2e
npm run nightwatch_local_pluginManager || TEST_EXITCODE=1
echo "$TEST_EXITCODE"
if [ "$TEST_EXITCODE" -eq 1 ]
then
exit 1
fi

@ -44,6 +44,7 @@ module.exports = class TestTab extends ViewPlugin {
this.offsetToLineColumnConverter = offsetToLineColumnConverter this.offsetToLineColumnConverter = offsetToLineColumnConverter
this.allFilesInvolved = [] this.allFilesInvolved = []
this.isDebugging = false this.isDebugging = false
this.currentErrors = []
appManager.event.on('activate', (name) => { appManager.event.on('activate', (name) => {
if (name === 'solidity') this.updateRunAction() if (name === 'solidity') this.updateRunAction()
@ -117,6 +118,14 @@ module.exports = class TestTab extends ViewPlugin {
} }
async updateForNewCurrent (file) { async updateForNewCurrent (file) {
// Ensure that when someone clicks on compilation error and that opens a new file
// Test result, which is compilation error in this case, is not cleared
if (this.currentErrors) {
if (Array.isArray(this.currentErrors) && this.currentErrors.length > 0) {
const errFiles = this.currentErrors.map(err => { if (err.sourceLocation && err.sourceLocation.file) return err.sourceLocation.file })
if (errFiles.includes(file)) return
} else if (this.currentErrors.sourceLocation && this.currentErrors.sourceLocation.file && this.currentErrors.sourceLocation.file === file) return
}
// if current file is changed while debugging and one of the files imported in test file are opened // if current file is changed while debugging and one of the files imported in test file are opened
// do not clear the test results in SUT plugin // do not clear the test results in SUT plugin
if (this.isDebugging && this.allFilesInvolved.includes(file)) return if (this.isDebugging && this.allFilesInvolved.includes(file)) return
@ -377,12 +386,13 @@ module.exports = class TestTab extends ViewPlugin {
this.testsOutput.hidden = false this.testsOutput.hidden = false
if (!result && (_errors && (_errors.errors || (Array.isArray(_errors) && (_errors[0].message || _errors[0].formattedMessage))))) { if (!result && (_errors && (_errors.errors || (Array.isArray(_errors) && (_errors[0].message || _errors[0].formattedMessage))))) {
this.testCallback({ type: 'contract', filename }) this.testCallback({ type: 'contract', filename })
this.currentErrors = _errors.errors
this.setHeader(false) this.setHeader(false)
} }
if (_errors && _errors.errors) { if (_errors && _errors.errors) {
_errors.errors.forEach((err) => this.renderer.error(err.formattedMessage || err.message, this.testsOutput, { type: err.severity })) _errors.errors.forEach((err) => this.renderer.error(err.formattedMessage || err.message, this.testsOutput, { type: err.severity, errorType: err.type }))
} else if (_errors && Array.isArray(_errors) && (_errors[0].message || _errors[0].formattedMessage)) { } else if (_errors && Array.isArray(_errors) && (_errors[0].message || _errors[0].formattedMessage)) {
_errors.forEach((err) => this.renderer.error(err.formattedMessage || err.message, this.testsOutput, { type: err.severity })) _errors.forEach((err) => this.renderer.error(err.formattedMessage || err.message, this.testsOutput, { type: err.severity, errorType: err.type }))
} else if (_errors && !_errors.errors && !Array.isArray(_errors)) { } else if (_errors && !_errors.errors && !Array.isArray(_errors)) {
// To track error like this: https://github.com/ethereum/remix/pull/1438 // To track error like this: https://github.com/ethereum/remix/pull/1438
this.renderer.error(_errors.formattedMessage || _errors.message, this.testsOutput, { type: 'error' }) this.renderer.error(_errors.formattedMessage || _errors.message, this.testsOutput, { type: 'error' })

@ -232,6 +232,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
testCallback(undefined, resp) testCallback(undefined, resp)
async.eachOfLimit(runList, 1, function (func, index, next) { async.eachOfLimit(runList, 1, function (func, index, next) {
let sender: string | null = null let sender: string | null = null
let hhLogs
if (func.signature) { if (func.signature) {
sender = getOverridedSender(contractDetails.userdoc, func.signature, contractDetails.evm.methodIdentifiers) sender = getOverridedSender(contractDetails.userdoc, func.signature, contractDetails.evm.methodIdentifiers)
if (opts.accounts && sender) { if (opts.accounts && sender) {
@ -293,7 +294,6 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
sendParams.gas = 10000000 * 8 sendParams.gas = 10000000 * 8
method.send(sendParams).on('receipt', async (receipt) => { method.send(sendParams).on('receipt', async (receipt) => {
try { try {
let hhLogs
if (web3.eth && web3.eth.getHHLogsForTx) hhLogs = await web3.eth.getHHLogsForTx(receipt.transactionHash) if (web3.eth && web3.eth.getHHLogsForTx) hhLogs = await web3.eth.getHHLogsForTx(receipt.transactionHash)
const time: number = (Date.now() - startTime) / 1000.0 const time: number = (Date.now() - startTime) / 1000.0
const assertionEventHashes = assertionEvents.map(e => Web3.utils.sha3(e.name + '(' + e.params.join() + ')')) const assertionEventHashes = assertionEvents.map(e => Web3.utils.sha3(e.name + '(' + e.params.join() + ')'))
@ -366,7 +366,7 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
console.error(err) console.error(err)
return next(err) return next(err)
} }
}).on('error', function (err: Error) { }).on('error', async (err: Error) => {
const time: number = (Date.now() - startTime) / 1000.0 const time: number = (Date.now() - startTime) / 1000.0
const resp: TestResultInterface = { const resp: TestResultInterface = {
type: 'testFailure', type: 'testFailure',
@ -377,6 +377,11 @@ export function runTest (testName: string, testObject: any, contractDetails: Com
context: testName, context: testName,
web3 web3
} }
if (err.message.includes('Transaction has been reverted by the EVM')) {
const txHash = JSON.parse(err.message.replace('Transaction has been reverted by the EVM:', '')).transactionHash
if (web3.eth && web3.eth.getHHLogsForTx) hhLogs = await web3.eth.getHHLogsForTx(txHash)
if (hhLogs) resp.hhLogs = hhLogs
}
testCallback(undefined, resp) testCallback(undefined, resp)
failureNum += 1 failureNum += 1
timePassed += time timePassed += time

@ -126,6 +126,9 @@
}, },
"solidity-compiler": { "solidity-compiler": {
"tags": [] "tags": []
},
"remix-ide-e2e-src-local-plugin": {
"tags": []
} }
} }
} }

@ -74,7 +74,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_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_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_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.spec.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_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_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_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", "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",

@ -961,6 +961,80 @@
} }
} }
} }
},
"remix-ide-e2e-src-local-plugin": {
"root": "apps/remix-ide-e2e/src/local-plugin",
"sourceRoot": "apps/remix-ide-e2e/src/local-plugin/src",
"projectType": "application",
"schematics": {},
"architect": {
"build": {
"builder": "@nrwl/web:build",
"options": {
"outputPath": "dist/apps/remix-ide-e2e/src/local-plugin",
"index": "apps/remix-ide-e2e/src/local-plugin/src/index.html",
"main": "apps/remix-ide-e2e/src/local-plugin/src/main.tsx",
"polyfills": "apps/remix-ide-e2e/src/local-plugin/src/polyfills.ts",
"tsConfig": "apps/remix-ide-e2e/src/local-plugin/tsconfig.app.json",
"assets": [
"apps/remix-ide-e2e/src/local-plugin/src/favicon.ico",
"apps/remix-ide-e2e/src/local-plugin/src/assets"
],
"styles": ["apps/remix-ide-e2e/src/local-plugin/src/styles.css"],
"scripts": [],
"webpackConfig": "@nrwl/react/plugins/webpack"
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "apps/remix-ide-e2e/src/local-plugin/src/environments/environment.ts",
"with": "apps/remix-ide-e2e/src/local-plugin/src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"extractLicenses": true,
"vendorChunk": false,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
}
]
}
}
},
"serve": {
"builder": "@nrwl/web:dev-server",
"options": {
"buildTarget": "remix-ide-e2e-src-local-plugin:build",
"port": 2020
},
"configurations": {
"production": {
"buildTarget": "remix-ide-e2e-src-local-plugin:build:production"
}
}
},
"lint": {
"builder": "@nrwl/linter:lint",
"options": {
"linter": "eslint",
"tsConfig": [
"apps/remix-ide-e2e/src/local-plugin/tsconfig.app.json"
],
"exclude": [
"**/node_modules/**",
"!apps/remix-ide-e2e/src/local-plugin/**/*"
]
}
}
}
} }
}, },
"cli": { "cli": {

Loading…
Cancel
Save