Merge branch 'master' into rmflaxyremixdtest

pull/5370/head
bunsenstraat 3 years ago committed by GitHub
commit 71de42c337
  1. 103
      .circleci/config.yml
  2. 44
      apps/remix-ide-e2e/src/buildGroupTests.js
  3. 19
      apps/remix-ide-e2e/src/commands/getBrowserLogs.ts
  4. 34
      apps/remix-ide-e2e/src/tests/workspace.test.ts
  5. 1
      apps/remix-ide-e2e/src/types/index.d.ts
  6. 37
      apps/remix-ide/ci/flaky.sh
  7. 2
      apps/remix-ide/src/app/files/fileManager.ts
  8. 14
      apps/remix-ide/src/app/panels/tab-proxy.js

@ -3,6 +3,10 @@
# Check https://circleci.com/docs/2.0/language-javascript/ for more details
#
version: 2.1
parameters:
run_flaky_tests:
type: boolean
default: false
orbs:
browser-tools: circleci/browser-tools@1.2.3
jobs:
@ -91,7 +95,7 @@ jobs:
- run: npm i
- run: cd dist/libs/remix-tests && npm install
- run: npm run test:libs
remix-ide-chrome:
docker:
# specify the version you desire here
@ -135,6 +139,49 @@ jobs:
- store_artifacts:
path: ./reports/screenshots
flaky-chrome:
docker:
# specify the version you desire here
- image: cimg/node:14.17.6-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"
working_directory: ~/remix-project
parallelism: 80
steps:
- browser-tools/install-chrome
- browser-tools/install-chromedriver
- run:
command: |
google-chrome --version
chromedriver --version
java -jar /usr/local/bin/selenium.jar --version
name: Check install
- checkout
- attach_workspace:
at: .
- run: unzip ./persist/dist.zip
- restore_cache:
keys:
- v1-deps-{{ checksum "package-lock.json" }}
- run: npm install
- run:
name: Start Selenium
command: java -jar /usr/local/bin/selenium.jar
background: true
- run: ./apps/remix-ide/ci/flaky.sh chrome
- store_test_results:
path: ./reports/tests
- store_artifacts:
path: ./reports/screenshots
remix-ide-firefox:
docker:
# specify the version you desire here
@ -177,7 +224,49 @@ jobs:
path: ./reports/tests
- store_artifacts:
path: ./reports/screenshots
flaky-firefox:
docker:
# specify the version you desire here
- image: cimg/node:14.17.6-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"
working_directory: ~/remix-project
parallelism: 80
steps:
- browser-tools/install-firefox
- browser-tools/install-geckodriver
- run:
command: |
firefox --version
geckodriver --version
java -jar /usr/local/bin/selenium.jar --version
name: Check install
- checkout
- attach_workspace:
at: .
- run: unzip ./persist/dist.zip
- restore_cache:
keys:
- v1-deps-{{ checksum "package-lock.json" }}
- run: npm install
- run:
name: Start Selenium
command: java -jar /usr/local/bin/selenium.jar
background: true
- run: ./apps/remix-ide/ci/flaky.sh firefox
- store_test_results:
path: ./reports/tests
- store_artifacts:
path: ./reports/screenshots
remix-ide-plugin-api:
docker:
# specify the version you desire here
@ -306,10 +395,20 @@ jobs:
if [ "${CIRCLE_BRANCH}" == "remix_beta" ]; then
./apps/remix-ide/ci/deploy_from_travis_remix-beta.sh;
fi
workflows:
version: 2
run_flaky_tests:
when: << pipeline.parameters.run_flaky_tests >>
jobs:
- build
- flaky-chrome:
requires:
- build
- flaky-firefox:
requires:
- build
build_all:
unless: << pipeline.parameters.run_flaky_tests >>
jobs:
- build
- lint:

@ -15,19 +15,41 @@ fs.readdirSync(testFolder).forEach(file => {
if (!file.includes('group')) {
const content = fs.readFileSync(testFolder + file, 'utf8')
const matches = content.match(/group\d+/g)
if (matches) {
const unique = matches.filter(onlyUnique)
unique.map((group) => {
const rewrite = source.replace('#groupname', group).replace('#file', file.replace('.ts', ''))
const extension = file.split('.')
extension.shift()
const filename = `${testFolder}${file.split('.').shift()}_${group}.${extension.join('.')}`
fs.writeFileSync(filename, rewrite)
})
}
createFlakyTestFiles(file, content)
createFiles(file, matches)
}
})
function onlyUnique (value, index, self) {
function createFiles(file, matches, flaky = false) {
if (matches) {
const unique = matches.filter(onlyUnique)
unique.map((group) => {
const rewrite = source.replace('#groupname', group).replace('#file', file.replace('.ts', ''))
const extension = file.split('.')
extension.shift()
let filename
if (!flaky) {
filename = `${testFolder}${file.split('.').shift()}_${group}.${extension.join('.')}`
} else {
filename = `${testFolder}${file.split('.').shift()}_${group}.flaky.ts`
}
fs.writeFileSync(filename, rewrite)
})
}
}
function onlyUnique(value, index, self) {
return self.indexOf(value) === index
}
function createFlakyTestFiles(file, text) {
const lines = text.split('\n')
lines.forEach((line, index) => {
// if line contains #flaky
if (line.includes('#flaky')) {
const matches = line.match(/group\d+/g)
const unique = matches.filter(onlyUnique)
createFiles(file, matches, true)
}
})
}

@ -0,0 +1,19 @@
import { NightwatchBrowser } from 'nightwatch'
import EventEmitter from 'events'
class GetBrowserLogs extends EventEmitter {
command(this: NightwatchBrowser): NightwatchBrowser {
this.api.getLog('browser', function (logs) {
if (logs && Array.isArray(logs)) {
logs.forEach(function (log) {
console.log(log)
}
)
}
}).perform(() => {
this.emit('complete')
})
return this
}
}
module.exports = GetBrowserLogs

@ -4,6 +4,7 @@ import init from '../helpers/init'
import sauce from './sauce'
module.exports = {
'@disabled': true,
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, 'http://127.0.0.1:8080?activate=solidity,udapp&call=fileManager//open//contracts/3_Ballot.sol&deactivate=home', false)
},
@ -15,7 +16,7 @@ module.exports = {
.clickLaunchIcon('udapp')
},
'Editor should be focused on the 3_Ballot.sol': function (browser: NightwatchBrowser) {
'Editor should be focused on the 3_Ballot.sol #group1': function (browser: NightwatchBrowser) {
browser
.pause(5000)
.refresh()
@ -25,21 +26,22 @@ module.exports = {
})
},
'Home page should be deactivated': function (browser: NightwatchBrowser) {
'Home page should be deactivated #group1': function (browser: NightwatchBrowser) {
browser
.waitForElementNotPresent('[data-id="landingPageHomeContainer"]')
},
'Should create two workspace and switch to the first one': function (browser: NightwatchBrowser) {
'Should create two workspace and switch to the first one #group1': function (browser: NightwatchBrowser) {
browser
.clickLaunchIcon('filePanel')
.click('*[data-id="workspaceCreate"]') // create workspace_name
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > span')
// eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_name' })
.click('*[data-id="modalDialogCustomPromptTextCreate"]')
.clearValue('*[data-id="modalDialogCustomPromptTextCreate"]')
.setValue('*[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_name')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.click('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.pause(1000)
.addFile('test.sol', { content: 'test' })
@ -47,10 +49,11 @@ module.exports = {
.click('*[data-id="workspaceCreate"]') // create workspace_name_1
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextCreate"]')
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] > span')
// eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextCreate"]')['value'] = 'workspace_name_1' })
.click('*[data-id="modalDialogCustomPromptTextCreate"]')
.clearValue('*[data-id="modalDialogCustomPromptTextCreate"]')
.setValue('*[data-id="modalDialogCustomPromptTextCreate"]', 'workspace_name_1')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.click('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.pause(2000)
.waitForElementNotPresent('*[data-id="treeViewLitreeViewItemtest.sol"]')
@ -59,15 +62,16 @@ module.exports = {
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
},
'Should rename a workspace': function (browser: NightwatchBrowser) {
'Should rename a workspace #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspaceRename"]') // rename workspace_name
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtests"]')
.waitForElementVisible('*[data-id="modalDialogCustomPromptTextRename"]')
// eslint-disable-next-line dot-notation
.execute(function () { document.querySelector('*[data-id="modalDialogCustomPromptTextRename"]')['value'] = 'workspace_name_renamed' })
.click('*[data-id="modalDialogCustomPromptTextRename"]')
.clearValue('*[data-id="modalDialogCustomPromptTextRename"]')
.setValue('*[data-id="modalDialogCustomPromptTextRename"]', 'workspace_name_renamed')
.waitForElementPresent('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.click('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.waitForElementPresent('*[data-id="workspacesSelect"] option[value="workspace_name_1"]')
.click('*[data-id="workspacesSelect"] option[value="workspace_name_1"]')
.pause(2000)
@ -78,12 +82,12 @@ module.exports = {
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtest.sol"]')
},
'Should delete a workspace': function (browser: NightwatchBrowser) {
'Should delete a workspace #group1': function (browser: NightwatchBrowser) {
browser
.click('*[data-id="workspacesSelect"] option[value="workspace_name_1"]')
.click('*[data-id="workspaceDelete"]') // delete workspace_name_1
.waitForElementVisible('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.execute(function () { (document.querySelector('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok') as HTMLElement).click() })
.click('[data-id="fileSystemModalDialogModalFooter-react"] .modal-ok')
.waitForElementNotPresent('*[data-id="workspacesSelect"] option[value="workspace_name_1"]')
.end()
},

@ -61,6 +61,7 @@ declare module 'nightwatch' {
acceptAndRemember (this: NightwatchBrowser, remember: boolean, accept: boolean): NightwatchBrowser
clearConsole (this: NightwatchBrowser): NightwatchBrowser
clearTransactions (this: NightwatchBrowser): NightwatchBrowser
getBrowserLogs (this: NightwatchBrowser): NightwatchBrowser
currentSelectedFileIs (name: string): NightwatchBrowser
}

@ -0,0 +1,37 @@
#!/usr/bin/env bash
set -e
npm run build:e2e
TESTFILES=$(grep -IRiL "\'@disabled\': \?true" "dist/apps/remix-ide-e2e/src/tests" | grep "\.flaky" | sort )
# count test files
fileCount=$(grep -IRiL "\'@disabled\': \?true" "dist/apps/remix-ide-e2e/src/tests" | grep "\.flaky" | wc -l )
# if fileCount is 0
if [ $fileCount -eq 0 ]
then
echo "No flaky tests found"
exit 0
fi
BUILD_ID=${CIRCLE_BUILD_NUM:-${TRAVIS_JOB_NUMBER}}
echo "$BUILD_ID"
TEST_EXITCODE=0
npm run ganache-cli &
npm run serve:production &
echo 'sharing folder: ' $PWD '/apps/remix-ide/contracts' &
npm run remixd &
npx nx serve remix-ide-e2e-src-local-plugin &
sleep 5
for TESTFILE in $TESTFILES; do
npx nightwatch --config dist/apps/remix-ide-e2e/nightwatch.js $TESTFILE --env=$1 || TEST_EXITCODE=1
done
echo "$TEST_EXITCODE"
if [ "$TEST_EXITCODE" -eq 1 ]
then
exit 1
fi

@ -600,7 +600,7 @@ class FileManager extends Plugin {
// TODO: Only keep `this.emit` (issue#2210)
this.emit('fileRemoved', path)
this.events.emit('fileRemoved', path)
this.openFile()
this.openFile(this._deps.config.get('currentFile'))
}
async unselectCurrentFile() {

@ -41,7 +41,13 @@ export class TabProxy extends Plugin {
if (this.fileManager.mode === 'browser') {
name = name.startsWith(workspace + '/') ? name : workspace + '/' + name
this.removeTab(name)
// If deleted file is not current file and not an active tab in editor,
// ensure current file is active in the editor
if (this.fileManager.currentFile() && name !== this.fileManager.currentFile()) {
const currentFile = this.fileManager.currentFile()
const currentFileTabPath = currentFile.startsWith(workspace + '/') ? currentFile : workspace + '/' + currentFile
this.removeTab(name, { name: currentFileTabPath })
} else this.removeTab(name)
} else {
name = name.startsWith(this.fileManager.mode + '/') ? name : this.fileManager.mode + '/' + name
this.removeTab(name)
@ -261,11 +267,11 @@ export class TabProxy extends Plugin {
this._handlers[name] = { switchTo, close }
}
removeTab (name) {
removeTab (name, currentFileTab) {
delete this._handlers[name]
let previous = null
let previous = currentFileTab
this.loadedTabs = this.loadedTabs.filter((tab, index) => {
if (tab.name === name) previous = this.loadedTabs[index - 1]
if (!previous && tab.name === name) previous = this.loadedTabs[index - 1]
return tab.name !== name
})
this.renderComponent()

Loading…
Cancel
Save