pull/5370/head
filip mertens 3 years ago
parent 260aa6c94e
commit 3ba601d359
  1. 73
      apps/remix-ide-e2e/src/tests/migrateFileSystem.test.ts
  2. 11
      apps/remix-ide/src/app/components/preload.tsx
  3. 3
      apps/remix-ide/src/app/files/fileSystem.ts
  4. 2
      apps/remix-ide/src/app/files/filesystems/localStorage.ts
  5. 1
      apps/remix-ide/src/assets/js/lightning-fs.min.js
  6. 139
      apps/remix-ide/src/assets/js/migrate.js
  7. 1
      libs/remix-ui/terminal/src/lib/terminalWelcome.tsx

@ -1,25 +1,69 @@
'use strict'
import { NightwatchBrowser } from 'nightwatch'
import init from '../helpers/init'
module.exports = {
before: function (browser: NightwatchBrowser, done: VoidFunction) {
init(browser, done, 'http://127.0.0.1:8080?e2e_testmigration=true', false)
'@disabled': true,
'Should load the testmigration url #group1': function (browser: NightwatchBrowser) {
browser.url('http://127.0.0.1:8080?e2e_testmigration=true')
.pause(6000)
.switchBrowserTab(0)
.maximizeWindow()
.waitForElementVisible('*[data-id="skipbackup-btn"]', 5000)
.click('*[data-id="skipbackup-btn"]')
.waitForElementVisible('[id="remixTourSkipbtn"]')
.click('[id="remixTourSkipbtn"]')
},
'Should have README file with TEST README as content': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('*[data-id="remixIdeSidePanel"]', 5000)
'should have indexedDB storage in terminal #group1': function (browser: NightwatchBrowser) {
browser.assert.containsText('*[data-id="terminalJournal"]', 'indexedDB')
},
'Should fallback to localstorage with default data #group2': function (browser: NightwatchBrowser) {
browser.url('http://127.0.0.1:8080?e2e_testmigration_fallback=true')
.pause(6000)
.switchBrowserTab(0)
.maximizeWindow()
.waitForElementVisible('[id="remixTourSkipbtn"]')
.click('[id="remixTourSkipbtn"]')
.waitForElementVisible('*[data-id="remixIdeSidePanel"]', 5000)
.waitForElementVisible('div[data-id="filePanelFileExplorerTree"]')
.openFile('README.txt')
.getEditorValue((content) => {
browser.assert.ok(content.includes('Output from script will appear in remix terminal.'))
})
.click('*[data-id="treeViewLitreeViewItemcontracts"]')
.openFile('contracts/1_Storage.sol')
.getEditorValue((content) => {
browser.assert.ok(content.includes('function retrieve() public view returns (uint256){'))
})
},
'Should load the testmigration url with local storage enablbed #group3': function (browser: NightwatchBrowser) {
browser.url('http://127.0.0.1:8080?e2e_testmigration=true&e2e_testmigration_fallback=true')
.pause(6000)
.switchBrowserTab(0)
.maximizeWindow()
.waitForElementVisible('*[data-id="skipbackup-btn"]', 5000)
.click('*[data-id="skipbackup-btn"]')
.waitForElementVisible('[id="remixTourSkipbtn"]')
.click('[id="remixTourSkipbtn"]')
},
'should have localstorage storage in terminal #group2 #group3': function (browser: NightwatchBrowser) {
browser.assert.containsText('*[data-id="terminalJournal"]', 'localstorage')
},
'Should have README file with TEST README as content #group1 #group3': function (browser: NightwatchBrowser) {
browser
.waitForElementVisible('*[data-id="remixIdeSidePanel"]', 5000)
.waitForElementVisible('div[data-id="filePanelFileExplorerTree"]')
.openFile('TEST_README.txt')
.getEditorValue((content) => {
browser.assert.equal(content, 'TEST README')
})
},
'Should have a workspace_test': function (browser: NightwatchBrowser) {
'Should have a workspace_test #group1 #group3': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('*[data-id="remixIdeSidePanel"]', 5000)
.click('*[data-id="workspacesSelect"] option[value="workspace_test"]')
.waitForElementVisible('*[data-id="treeViewLitreeViewItemtest_contracts"]')
},
'Should have a sol file with test data': function (browser: NightwatchBrowser) {
'Should have a sol file with test data #group1 #group3': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('*[data-id="remixIdeSidePanel"]', 5000)
.click('*[data-id="treeViewLitreeViewItemtest_contracts"]')
.openFile('test_contracts/1_Storage.sol')
@ -27,7 +71,7 @@ module.exports = {
browser.assert.equal(content, 'testing')
})
},
'Should have a artifacts file with JSON test data': function (browser: NightwatchBrowser) {
'Should have a artifacts file with JSON test data #group1 #group3': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('*[data-id="remixIdeSidePanel"]', 5000)
.click('*[data-id="treeViewLitreeViewItemtest_contracts/artifacts"]')
.openFile('test_contracts/artifacts/Storage_metadata.json')
@ -35,5 +79,16 @@ module.exports = {
const metadata = JSON.parse(content)
browser.assert.equal(metadata.test, 'data')
})
}
},
'Should have a empty workspace #group1 #group3': function (browser: NightwatchBrowser) {
browser.waitForElementVisible('*[data-id="remixIdeSidePanel"]', 5000)
.click('*[data-id="workspacesSelect"] option[value="emptyspace"]')
},
'Should load with all storage blocked #group4': function (browser: NightwatchBrowser) {
browser.url('http://127.0.0.1:8080?e2e_testblock_storage=true')
.pause(6000)
.switchBrowserTab(0)
.maximizeWindow()
.assert.containsText('.alert-warning', 'Your browser does not support')
},
}

@ -35,19 +35,24 @@ export const Preload = () => {
}
const downloadBackup = async () => {
setShowDownloader(false)
const fsUtility = new fileSystemUtility()
await fsUtility.downloadBackup(remixFileSystems.current.fileSystems['localstorage'])
await migrateAndLoad()
}
const migrateAndLoad = async () => {
setShowDownloader(false)
const fsUtility = new fileSystemUtility()
await fsUtility.migrate(localStorageFileSystem.current, remixIndexedDB.current)
await setFileSystems()
}
const setFileSystems = async() => {
const fsLoaded = await remixFileSystems.current.setFileSystem([remixIndexedDB.current, localStorageFileSystem.current])
// url parameters to e2e test the fallbacks and error warnings
const testmigrationFallback = window.location.hash.includes('e2e_testmigration_fallback=true') && window.location.host === '127.0.0.1:8080' && window.location.protocol === 'http:'
const testBlockStorage = window.location.hash.includes('e2e_testblock_storage=true') && window.location.host === '127.0.0.1:8080' && window.location.protocol === 'http:'
const fsLoaded = await remixFileSystems.current.setFileSystem([(testmigrationFallback || testBlockStorage)? null: remixIndexedDB.current, testBlockStorage? null:localStorageFileSystem.current])
if (fsLoaded) {
console.log(fsLoaded.name + ' activated')
loadAppComponent()
@ -102,8 +107,8 @@ export const Preload = () => {
This app will be updated now. Please download a backup of your files now to make sure you don't lose your work.
<br></br>
You don't need to do anything else, your files will be available when the app loads.
<div onClick={async () => { await downloadBackup() }} className='btn btn-primary mt-1'>download backup</div>
<div onClick={async () => { await migrateAndLoad() }} className='btn btn-primary mt-1'>skip backup</div>
<div onClick={async () => { await downloadBackup() }} data-id='downloadbackup-btn' className='btn btn-primary mt-1'>download backup</div>
<div onClick={async () => { await migrateAndLoad() }} data-id='skipbackup-btn' className='btn btn-primary mt-1'>skip backup</div>
</div> : null}
{(supported && !error && !showDownloader) ?
<div>

@ -43,6 +43,7 @@ export class fileSystem {
const w = (window as any)
if (!this.loaded) return false
w.remixFileSystem = this.fs
w.remixFileSystem.name = this.name
w.remixFileSystemCallback = this.fsCallBack
return true
}
@ -72,7 +73,7 @@ export class fileSystems {
*/
setFileSystem = async (filesystems?: fileSystem[]): Promise<fileSystem> => {
for (const fs of filesystems) {
if (this.fileSystems[fs.name]) {
if (fs && this.fileSystems[fs.name]) {
const result = await this.fileSystems[fs.name].set()
if (result) return this.fileSystems[fs.name]
}

@ -16,7 +16,7 @@ export class localStorageFS extends fileSystem {
fs: 'LocalStorage'
}, async function (e) {
if (e) {
console.log('BROWSEFS Error: ' + e)
console.log('BrowserFS Error: ' + e)
reject(e)
} else {
me.fs = { ...window.require('fs') }

File diff suppressed because one or more lines are too long

@ -1,139 +0,0 @@
// eslint-disable-next-line no-unused-vars
async function migrateFilesFromLocalStorage (cb) {
let testmigration = false // migration loads test data into localstorage with browserfs
// indexeddb will be empty by this point, so there is no danger but do a check for the origin to load test data so it runs only locally
testmigration = window.location.hash.includes('e2e_testmigration=true') && window.location.host === '127.0.0.1:8080' && window.location.protocol === 'http:'
// eslint-disable-next-line no-undef
BrowserFS.install(window)
// eslint-disable-next-line no-undef
BrowserFS.configure({
fs: 'LocalStorage'
}, async function (e) {
if (e) console.log(e)
const browserFS = window.require('fs')
/**
* copy the folder recursively (internal use)
* @param {string} path is the folder to be copied over
* @param {Function} visitFile is a function called for each visited files
* @param {Function} visitFolder is a function called for each visited folders
*/
async function _copyFolderToJsonInternal (path, visitFile, visitFolder, fs) {
visitFile = visitFile || (() => { })
visitFolder = visitFolder || (() => { })
return new Promise((resolve, reject) => {
const json = {}
if (fs.existsSync(path)) {
try {
const items = fs.readdirSync(path)
visitFolder({ path })
if (items.length !== 0) {
items.forEach(async (item, index) => {
const file = {}
const curPath = `${path}${path.endsWith('/') ? '' : '/'}${item}`
if (fs.statSync(curPath).isDirectory()) {
file.children = await _copyFolderToJsonInternal(curPath, visitFile, visitFolder, fs)
} else {
file.content = fs.readFileSync(curPath, 'utf8')
visitFile({ path: curPath, content: file.content })
}
json[curPath] = file
})
}
} catch (e) {
console.log(e)
return reject(e)
}
}
return resolve(json)
})
}
/**
* copy the folder recursively
* @param {string} path is the folder to be copied over
* @param {Function} visitFile is a function called for each visited files
* @param {Function} visitFolder is a function called for each visited folders
*/
async function copyFolderToJson (path, visitFile, visitFolder, fs) {
visitFile = visitFile || (() => { })
visitFolder = visitFolder || (() => { })
return _copyFolderToJsonInternal(path, visitFile, visitFolder, fs)
}
const populateWorkspace = async (json, fs) => {
for (const item in json) {
const isFolder = json[item].content === undefined
if (isFolder) {
await createDir(item, fs)
await populateWorkspace(json[item].children, fs)
} else {
try {
await fs.writeFile(item, json[item].content, 'utf8')
} catch (error) {
console.log(error)
}
}
}
}
const createDir = async (path, fs) => {
const paths = path.split('/')
if (paths.length && paths[0] === '') paths.shift()
let currentCheck = ''
for (const value of paths) {
currentCheck = currentCheck + (currentCheck ? '/' : '') + value
if (!await fs.exists(currentCheck)) {
try {
await fs.mkdir(currentCheck)
} catch (error) {
console.log(error)
}
}
}
}
//
if (testmigration) await populateWorkspace(testData, browserFS)
const files = await copyFolderToJson('/', null, null, browserFS)
await populateWorkspace(files, window.remixFileSystem)
// eslint-disable-next-line no-undef
if (cb) cb()
})
}
/* eslint-disable no-template-curly-in-string */
const testData = {
'.workspaces': {
children: {
'.workspaces/default_workspace': {
children: {
'.workspaces/default_workspace/README.txt': {
content: 'TEST README'
}
}
},
'.workspaces/workspace_test': {
children: {
'.workspaces/workspace_test/TEST_README.txt': {
content: 'TEST README'
},
'.workspaces/workspace_test/test_contracts': {
children: {
'.workspaces/workspace_test/test_contracts/1_Storage.sol': {
content: 'testing'
},
'.workspaces/workspace_test/test_contracts/artifacts': {
children: {
'.workspaces/workspace_test/test_contracts/artifacts/Storage_metadata.json': {
content: '{ "test": "data" }'
}
}
}
}
}
}
}
}
}
}

@ -4,6 +4,7 @@ const TerminalWelcomeMessage = ({ packageJson }) => {
return (
<div className="remix_ui_terminal_block px-4 " data-id="block_null">
<div className="remix_ui_terminal_welcome"> Welcome to Remix {packageJson} </div><br />
<div className="">Your files are stored in {(window as any).remixFileSystem.name} </div><br />
<div>You can use this terminal to: </div>
<ul className='ml-0 mr-4'>
<li>Check transactions details and start debugging.</li>

Loading…
Cancel
Save