This repository has been archived by the owner on Dec 13, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 681
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Summary: this is a very basic e2e test for nuclide. It won't run on CI, this is just a starting point for building abstractions and integrations Reviewed By: semmypurewal, wanderley Differential Revision: D9696717 fbshipit-source-id: d435a8293060bd7c5730ef457efb4309be7b318b
- Loading branch information
1 parent
06d4dcf
commit 638ef12
Showing
7 changed files
with
361 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the license found in the LICENSE file in | ||
* the root directory of this source tree. | ||
* | ||
* @flow strict-local | ||
* @format | ||
* @emails oncall+nuclide | ||
*/ | ||
|
||
import { | ||
makeTempDir, | ||
openLocalDirectory, | ||
openFileTree, | ||
writeFiles, | ||
getAllPanes, | ||
} from '../jest/e2e/tools'; | ||
|
||
test('some random test', async () => { | ||
const tmpDir = makeTempDir('random_test'); | ||
writeFiles(tmpDir, {'file1.js': 'module.exports = {}'}); | ||
openLocalDirectory(tmpDir); | ||
const fileTree = await openFileTree(); | ||
const matchingFiles = fileTree.findTextFilesWithNameMatching('file1.js'); | ||
expect(matchingFiles).toHaveLength(1); | ||
await fileTree.previewFile('file1.js'); | ||
const panes = getAllPanes(); | ||
expect(panes.getAllTabNames()).toContain('file1.js'); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the license found in the LICENSE file in | ||
* the root directory of this source tree. | ||
* | ||
* @noflow | ||
* @format | ||
*/ | ||
'use strict'; | ||
|
||
/* eslint nuclide-internal/no-commonjs: 0 */ | ||
|
||
module.exports = { | ||
atomExecutable: '/Applications/Atom.app/Contents/MacOS/Atom', | ||
consoleFilter: consoleOutput => { | ||
if (!consoleOutput) { | ||
return consoleOutput; | ||
} | ||
return consoleOutput.filter(consoleBuffer => { | ||
const {origin, message} = consoleBuffer; | ||
return !( | ||
origin.match(/track-nuclide-ready/) || | ||
message.match(/Starting local RPC process with/) || | ||
message.match('let notifier =') || | ||
message.match('nvm is not compatible with the npm config "prefix"') || | ||
message.match('nvm use --delete-prefix') || | ||
message.match('Successfully loaded Chrome extension') | ||
); | ||
}); | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the license found in the LICENSE file in | ||
* the root directory of this source tree. | ||
* | ||
* @noflow | ||
* @format | ||
*/ | ||
'use strict'; | ||
|
||
/* eslint nuclide-internal/no-commonjs: 0 */ | ||
|
||
const fs = require('fs-extra'); | ||
const path = require('path'); | ||
const os = require('os'); | ||
// eslint-disable-next-line nuclide-internal/consistent-import-name | ||
const {spawnSync} = require('child_process'); | ||
|
||
const CACHE_DIR = path.join( | ||
os.tmpdir(), | ||
'NUCLIDE_E2E_TMP_DIR_WITH_APM_DEPENDENCIES', | ||
); | ||
const NUCLIDE_PKG_JSON_PATH = path.resolve(__dirname, '../../package.json'); | ||
const NUCLIDE_PKG_JSON = require(NUCLIDE_PKG_JSON_PATH); | ||
const TAR_PATH = path.resolve(__dirname, '../third_party/apm_deps.tar.gz'); | ||
const PACK_SCRIPT_PATH = require.resolve('../../scripts/package_apm_deps.js'); | ||
const NUCLIDE_DIR = path.resolve(__dirname, '../..'); | ||
|
||
const {'package-deps': packageDeps} = NUCLIDE_PKG_JSON; | ||
|
||
// Are all packages that listed as dependencies present in the cache dir? | ||
const isCacheValid = () => | ||
packageDeps.every(dep => fs.existsSync(path.resolve(CACHE_DIR, dep))); | ||
|
||
const buildCache = () => { | ||
fs.removeSync(CACHE_DIR); | ||
fs.mkdirpSync(CACHE_DIR); | ||
|
||
let result; | ||
try { | ||
result = spawnSync('tar', ['xvf', TAR_PATH, '-C', CACHE_DIR]); | ||
|
||
const {stdout, stderr, status} = result; | ||
if (status !== 0) { | ||
// eslint-disable-next-line no-console | ||
console.error(result); | ||
throw new Error(` | ||
tar process exited with non 0 status code | ||
stdout: ${String(stdout)} | ||
stderr: ${String(stderr)} | ||
status: ${status} | ||
`); | ||
} | ||
} catch (error) { | ||
const {stdout, stderr} = result || {}; | ||
// eslint-disable-next-line no-console | ||
console.error(result); | ||
// eslint-disable-next-line no-console | ||
console.error({stdout: String(stdout), stderr: String(stderr)}); | ||
throw error; | ||
} | ||
if (!isCacheValid()) { | ||
throw new Error(` | ||
Missing dependencies after extracting APM package dependencies to from ${TAR_PATH} | ||
to ${CACHE_DIR}. | ||
Make sure that ${TAR_PATH} contains all dependencies listed in ${NUCLIDE_PKG_JSON_PATH}. | ||
If you need to update the dependencies see: ${PACK_SCRIPT_PATH} | ||
`); | ||
} | ||
}; | ||
|
||
// If not, drop everything and recreate the cache | ||
if (!isCacheValid()) { | ||
buildCache(); | ||
} | ||
|
||
// Make sure we disable conflicting packages before we start atom. | ||
// The list is taken from the notifications that pop up when you start | ||
// nuclide for the first time. | ||
const CONFIG_CSON = `"*": | ||
core: | ||
disabledPackages: [ | ||
"encoding-selector" | ||
"line-ending-selector" | ||
"tree-view" | ||
"image-view" | ||
"file-icons" | ||
] | ||
"exception-reporting": | ||
userId: "e3d9fc22-e4f7-4e0a-8949-f13b1584be3d"`; | ||
|
||
const CONFIG_CSON_NAME = 'config.cson'; | ||
|
||
module.exports = async ({atomHome}) => { | ||
const configCsonPath = path.resolve(atomHome, CONFIG_CSON_NAME); | ||
fs.writeFileSync(configCsonPath, CONFIG_CSON); | ||
|
||
fs.ensureSymlinkSync(NUCLIDE_DIR, path.join(atomHome, 'packages/nuclide')); | ||
|
||
for (const dep of packageDeps) { | ||
fs.ensureSymlinkSync( | ||
path.join(CACHE_DIR, dep), | ||
path.join(atomHome, 'packages', dep), | ||
); | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the license found in the LICENSE file in | ||
* the root directory of this source tree. | ||
* | ||
* @noflow | ||
* @format | ||
*/ | ||
'use strict'; | ||
|
||
/* eslint nuclide-internal/no-commonjs: 0 */ | ||
|
||
require('../../modules/nuclide-node-transpiler/lib/require-hook.js'); | ||
const {closeAllTabs} = require('../e2e/tools'); | ||
|
||
beforeEach(async () => { | ||
await closeAllTabs(); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the license found in the LICENSE file in | ||
* the root directory of this source tree. | ||
* | ||
* @flow | ||
* @format | ||
*/ | ||
|
||
import fs from 'fs-extra'; | ||
import os from 'os'; | ||
import path from 'path'; | ||
import uuid4 from 'uuid/v4'; | ||
|
||
import _waitsFor from '../waits_for'; | ||
|
||
export const invariant = (condition: any, message: string) => { | ||
if (!condition) { | ||
throw new Error('message'); | ||
} | ||
}; | ||
export const makeTempDir = (name: string = 'nuclide_temp_dir') => { | ||
const dirPath = path.resolve(os.tmpdir(), `${name}-${uuid4()}`); | ||
fs.mkdirpSync(dirPath); | ||
return dirPath; | ||
}; | ||
|
||
export const openLocalDirectory = (dir: string) => atom.project.addPath(dir); | ||
|
||
export const writeFiles = (dir: string, files: {[path: string]: string}) => { | ||
for (const [filePath, content] of Object.entries(files)) { | ||
fs.writeFileSync(path.resolve(dir, filePath), content); | ||
} | ||
}; | ||
|
||
export const sleep = (n: number): Promise<void> => | ||
new Promise(r => setTimeout(r, n)); | ||
|
||
export const waitsFor = _waitsFor; | ||
|
||
export const closeAllTabs = async () => { | ||
await atom.commands.dispatch( | ||
atom.workspace.getElement(), | ||
'tabs:close-all-tabs', | ||
); | ||
}; | ||
|
||
const FILE_TREE_SELECTOR = | ||
'.atom-dock-open .nuclide-file-tree-toolbar-container'; | ||
export const openFileTree = async () => { | ||
atom.commands.dispatch(atom.workspace.getElement(), 'tree-view:toggle'); | ||
await waitsFor(() => !!document.querySelector(FILE_TREE_SELECTOR)); | ||
const element = document.querySelector(FILE_TREE_SELECTOR); | ||
invariant(element, 'File tree must be present'); | ||
const fileTree = new FileTree(element); | ||
return fileTree; | ||
}; | ||
|
||
export const getAllPanes = () => { | ||
// $FlowFixMe | ||
return new Panes(document.body); | ||
}; | ||
|
||
const TEXT_FILE_SELECTOR = '.nuclide-file-tree-path.icon-file-text'; | ||
|
||
class FileTree { | ||
element: Element; | ||
constructor(element: Element) { | ||
this.element = element; | ||
} | ||
|
||
findTextFilesWithNameMatching(pattern: string): Array<Element> { | ||
return [...this.element.querySelectorAll(TEXT_FILE_SELECTOR)].filter(el => { | ||
const name = el.getAttribute('data-name'); | ||
return name != null && name.indexOf(pattern) !== -1; | ||
}); | ||
} | ||
|
||
async previewFile(name: string) { | ||
const files = this.findTextFilesWithNameMatching(name); | ||
expect(files).toHaveLength(1); | ||
const file = files[0]; | ||
expect(file).toBeDefined(); | ||
expect(file.getAttribute('data-name')).toBe(name); | ||
(file: any).click(); | ||
await waitsFor( | ||
() => !!document.querySelector(`[is=tabs-tab] div[data-name="${name}"]`), | ||
); | ||
} | ||
} | ||
|
||
class Panes { | ||
element: Element; | ||
panes: Array<Pane>; | ||
constructor(element: Element) { | ||
this.element = element; | ||
this.panes = [...this.element.querySelectorAll('.pane')].map( | ||
el => new Pane(el), | ||
); | ||
} | ||
|
||
getAllTabNames() { | ||
return this.panes.reduce((tabNames, pane) => { | ||
const names = pane.tabs.map(tab => tab.getName()); | ||
return [...(tabNames || []), ...(names || [])]; | ||
}, []); | ||
} | ||
} | ||
|
||
class Pane { | ||
element: Element; | ||
tabs: Array<Tab>; | ||
|
||
constructor(element: Element) { | ||
this.element = element; | ||
this.tabs = [...this.element.querySelectorAll('[is=tabs-tab]')].map( | ||
el => new Tab(el), | ||
); | ||
} | ||
|
||
getTabNames() { | ||
return this.tabs.map(tab => tab.getName()); | ||
} | ||
} | ||
|
||
class Tab { | ||
element: Element; | ||
constructor(element: Element) { | ||
this.element = element; | ||
} | ||
|
||
getName() { | ||
const div = this.element.querySelector('div'); | ||
invariant(div); | ||
return div.getAttribute('data-name'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the license found in the LICENSE file in | ||
* the root directory of this source tree. | ||
* | ||
* @noflow | ||
* @format | ||
*/ | ||
'use strict'; | ||
|
||
/* eslint nuclide-internal/no-commonjs: 0 */ | ||
|
||
const path = require('path'); | ||
const p = nuclidePath => path.resolve(__dirname, '..', nuclidePath); | ||
|
||
module.exports = { | ||
displayName: 'e2e', | ||
reporters: require('./reporters.config'), | ||
rootDir: p(''), | ||
roots: [p('')], | ||
runner: '@jest-runner/nuclide-e2e', | ||
setupFiles: [p('jest/e2e/setup.js')], | ||
setupTestFrameworkScriptFile: p('jest/e2e/setupTestFrameworkScriptFile.js'), | ||
testMatch: ['**/__e2e_tests__/**/*.js?(x)'], | ||
testPathIgnorePatterns: ['/node_modules/'], | ||
}; |