diff --git a/flow-libs/atom.js b/flow-libs/atom.js.flow similarity index 97% rename from flow-libs/atom.js rename to flow-libs/atom.js.flow index 5facb197..8cd4bcdf 100644 --- a/flow-libs/atom.js +++ b/flow-libs/atom.js.flow @@ -229,7 +229,7 @@ declare class atom$Decoration { destroy(): void, onDidChangeProperties( callback: (event: {oldProperties: Object, newProperties: Object}) => mixed - ): IDisposable, + ): IDisposable, onDidDestroy(callback: () => mixed): IDisposable, getMarker(): atom$Marker, getProperties(): Object, @@ -240,6 +240,7 @@ declare class atom$DisplayMarkerLayer { destroy(): void, clear(): void, isDestroyed(): boolean, + markBufferPosition(position: atom$PointLike, options?: MarkerOptions): atom$Marker, markBufferRange(range: atom$Range | atom$RangeLike, options: MarkerOptions): atom$Marker, getMarkers(): Array, } @@ -273,24 +274,26 @@ declare class atom$Gutter { onDidDestroy(callback: () => void): IDisposable, } +declare type atom$MarkerChangeEvent = { + oldHeadScreenPosition: atom$Point, + newHeadScreenPosition: atom$Point, + oldTailScreenPosition: atom$Point, + newTailScreenPosition: atom$Point, + + oldHeadBufferPosition: atom$Point, + newHeadBufferPosition: atom$Point, + oldTailBufferPosition: atom$Point, + newTailBufferPosition: atom$Point, + + isValid: boolean, + textChanged: boolean, +} + declare class atom$Marker { destroy(): void, getBufferRange(): atom$Range, getStartBufferPosition(): atom$Point, - onDidChange(callback: (event: { - oldHeadScreenPosition: atom$Point, - newHeadScreenPosition: atom$Point, - oldTailScreenPosition: atom$Point, - newTailScreenPosition: atom$Point, - - oldHeadBufferPosition: atom$Point, - newHeadBufferPosition: atom$Point, - oldTailBufferPosition: atom$Point, - newTailBufferPosition: atom$Point, - - isValid: boolean, - textChanged: boolean, - }) => void): IDisposable, + onDidChange(callback: (event: atom$MarkerChangeEvent) => mixed): IDisposable, isValid(): boolean, isDestroyed(): boolean, onDidDestroy(callback: () => mixed): IDisposable, @@ -485,7 +488,9 @@ declare interface atom$PaneItem { +getURI?: () => ?string, +onDidChangeIcon?: (cb: (icon: string) => void) => IDisposable, +onDidChangeTitle?: (cb: (title: string) => void) => IDisposable, + +onDidTerminatePendingState?: (() => mixed) => IDisposable; +serialize?: () => Object, + +terminatePendingState?: () => void, } // Undocumented class @@ -500,11 +505,11 @@ declare class atom$PaneAxis { // are typed here as AbstractPaneContainers and, in the current implementation, wrap these.) declare class atom$PaneContainer { constructor({ - config: atom$Config, - applicationDelegate: atom$applicationDelegate, - notificationManager: atom$NotificationManager, - deserializerManager: atom$DeserializerManager, - }): atom$PaneContainer, + config: atom$Config, + applicationDelegate: atom$applicationDelegate, + notificationManager: atom$NotificationManager, + deserializerManager: atom$DeserializerManager, + }): atom$PaneContainer, destroy(): void, getActivePane(): atom$Pane, getActivePaneItem(): ?Object, @@ -541,8 +546,8 @@ declare class atom$Panel { type atom$PointObject = {row: number, column: number}; type atom$PointLike = atom$Point - | [number, number] - | atom$PointObject; +| [number, number] +| atom$PointObject; declare class atom$Point { static fromObject(object: atom$PointLike, copy: ? boolean): atom$Point, @@ -578,9 +583,9 @@ type atom$RangeLike = atom$Range | atom$RangeObject // TODO: Flow doesn't really handle the real signature below... | [atom$PointLike, atom$PointLike] | { - start: atom$PointLike, - end: atom$PointLike, -}; + start: atom$PointLike, + end: atom$PointLike, + }; declare class atom$Range { static fromObject( @@ -747,12 +752,12 @@ type ChangeCursorPositionEvent = { cursor: atom$Cursor, }; -type MarkerOptions = {| +type MarkerOptions = { reversed?: boolean, tailed?: boolean, invalidate?: 'never' | 'surround' | 'overlap' | 'inside' | 'touch', exclusive?: boolean, -|}; +}; type ChangeSelectionRangeEvent = {| oldBufferRange: atom$Range, @@ -769,7 +774,7 @@ declare class atom$TextEditor extends atom$Model { // Event Subscription onDidChange(callback: () => void): IDisposable, onDidChangePath(callback: (newPath: string) => mixed): IDisposable, - onDidStopChanging(callback: () => void): IDisposable, + onDidStopChanging(callback: () => mixed): IDisposable, onDidChangeCursorPosition(callback: (event: ChangeCursorPositionEvent) => mixed): IDisposable, onDidDestroy(callback: () => mixed): IDisposable, @@ -777,7 +782,7 @@ declare class atom$TextEditor extends atom$Model { getBuffer(): atom$TextBuffer, observeGrammar(callback: (grammar: atom$Grammar) => mixed): IDisposable, onWillInsertText(callback: (event: {cancel: () => void, text: string}) => void): - IDisposable, + IDisposable, // Note that the range property of the event is undocumented. onDidInsertText(callback: (event: {text: string, range: atom$Range}) => mixed): IDisposable, onDidChangeSoftWrapped(callback: (softWrapped: boolean) => mixed): IDisposable, @@ -814,6 +819,7 @@ declare class atom$TextEditor extends atom$Model { getText(): string, getTextInBufferRange(range: atom$RangeLike): string, getLineCount(): number, + getLastScreenRow(): number, // Mutating Text setText(text: string, options?: InsertTextOptions): void, @@ -834,8 +840,10 @@ declare class atom$TextEditor extends atom$Model { // History createCheckpoint(): atom$TextBufferCheckpoint, revertToCheckpoint(checkpoint: atom$TextBufferCheckpoint): boolean, + terminatePendingState(): void, transact(fn: () => mixed, _: void): void, transact(groupingInterval: number, fn: () => mixed): void, + onDidTerminatePendingState(() => mixed): IDisposable; // TextEditor Coordinates screenPositionForBufferPosition( @@ -868,11 +876,13 @@ declare class atom$TextEditor extends atom$Model { getDecorations(options?: {class?: string, type?: string}): Array, // Markers + addMarkerLayer(): atom$DisplayMarkerLayer, getDefaultMarkerLayer(): atom$DisplayMarkerLayer, markBufferPosition(position: atom$PointLike, options?: MarkerOptions): atom$Marker, markBufferRange(range: atom$RangeLike, options?: MarkerOptions): atom$Marker, markScreenRange(range: atom$RangeLike, options?: MarkerOptions): atom$Marker, markScreenPosition(position: atom$PointLike, options?: MarkerOptions): atom$Marker, + findMarkers(options: MarkerOptions): Array, getMarkerCount(): number, // Cursors @@ -966,6 +976,7 @@ declare class atom$TextEditor extends atom$Model { // Clipboard Operations pasteText: (options?: Object) => void, + copySelectedText: () => void, // Managing Syntax Scopes scopeDescriptorForBufferPosition( @@ -1020,7 +1031,7 @@ declare class atom$TextEditor extends atom$Model { onDidConflict(callback: () => void): IDisposable, serialize(): Object, foldBufferRowRange(startRow: number, endRow: number): void, - getNonWordCharacters(scope?: atom$ScopeDescriptor): string, + getNonWordCharacters(position?: atom$PointLike): string, } /** @@ -1628,7 +1639,11 @@ declare class atom$Project { onDidChangePaths(callback: (projectPaths: Array) => mixed): IDisposable, onDidAddBuffer(callback: (buffer: atom$TextBuffer) => mixed): IDisposable, observeBuffers(callback: (buffer: atom$TextBuffer) => mixed): IDisposable, - + replace?: (newSettings: {| + originPath?: string, + paths?: Array, + config?: {[string]: mixed} + |}) => void, // Accessing the git repository getRepositories(): Array, repositoryForDirectory(directory: atom$Directory): Promise, @@ -1845,6 +1860,7 @@ declare class atom$NotificationManager { addWarning(message: string, options?: atom$NotificationOptions): atom$Notification, addError(message: string, options?: atom$NotificationOptions): atom$Notification, addFatalError(message: string, options?: atom$NotificationOptions): atom$Notification, + addNotification(notification: atom$Notification): atom$Notification, // Getting Notifications getNotifications(): Array, @@ -2041,6 +2057,9 @@ type atom$AutocompleteProvider = { +getSuggestions: ( request: atom$AutocompleteRequest, ) => Promise> | ?Array, + +getSuggestionDetailsOnSelect?: ( + suggestion: atom$AutocompleteSuggestion + ) => Promise, +disableForSelector?: string, +inclusionPriority?: number, +excludeLowerPriority?: boolean, diff --git a/flow-libs/electron.js b/flow-libs/electron.js.flow similarity index 94% rename from flow-libs/electron.js rename to flow-libs/electron.js.flow index 5cff04c3..4dd1270a 100644 --- a/flow-libs/electron.js +++ b/flow-libs/electron.js.flow @@ -170,8 +170,8 @@ type electron$BrowserWindowOptions = { darkTheme?: boolean, transparent?: boolean, type?: 'desktop' | 'dock' | 'toolbar' | 'splash' | 'notification' | - /* macOS */ 'desktop' | 'textured' | - /* Windows */ 'toolbar', + /* macOS */ 'desktop' | 'textured' | + /* Windows */ 'toolbar', titleBarStyle?: 'default' | 'hidden' | 'hidden-inset', thickFrame?: boolean, webPreferences?: electron$BrowserWindowWebPreferences, @@ -343,7 +343,7 @@ declare class electron$BrowserWindow { click: Function, tooltip?: string, flags?: Array<'enabled' | 'disabled' | 'dismissonclick' | 'nobackground' | - 'hidden' | 'noninteractive'>, + 'hidden' | 'noninteractive'>, }>): void, // Windows setThumbnailClip(region: electron$rect): void, // Windows showDefinitionForSelection(): void, // macOS @@ -495,10 +495,10 @@ type electron$MenuItemOptions = { event: Object ) => void, role?: 'undo' | 'redo' | 'cut' | 'copy' | 'paste' | 'pasteandmatchstyle' | - 'selectall' | 'delete' | 'minimize' | 'close' | 'quit' | 'togglefullscreen' | - // macOS-only - 'about' | 'hide' | 'hideothers' | 'unhide' | 'front' | 'zoom' | 'window' | - 'help' | 'services', + 'selectall' | 'delete' | 'minimize' | 'close' | 'quit' | 'togglefullscreen' | + // macOS-only + 'about' | 'hide' | 'hideothers' | 'unhide' | 'front' | 'zoom' | 'window' | + 'help' | 'services', type?: 'normal' | 'separator' | 'submenu' | 'checkbox' | 'radio', label?: string, sublabel?: string, @@ -561,8 +561,8 @@ declare class electron$Tray {} type electron$InputEventModifiers = Array<'shift' | 'control' | 'alt' | 'meta' | - 'isKeypad' | 'isAutoRepeat' | 'leftButtonDown' | 'middleButtonDown' | - 'rightButtonDown' | 'capsLock' | 'numLock' | 'left' | 'right'>; + 'isKeypad' | 'isAutoRepeat' | 'leftButtonDown' | 'middleButtonDown' | + 'rightButtonDown' | 'capsLock' | 'numLock' | 'left' | 'right'>; declare class electron$WebContents extends events$EventEmitter { loadURL( @@ -669,36 +669,36 @@ declare class electron$WebContents extends events$EventEmitter { modifiers?: electron$InputEventModifiers, keyCode: string, } | { - type: 'mouseDown' | 'mouseUp' | 'mouseEnter' | 'mouseLeave' | 'contextMenu', - modifiers?: electron$InputEventModifiers, - x: number, - y: number, - button: 'left' | 'middle' | 'right', - globalX: number, - globalY: number, - movementX: number, - movementY: number, - clickCount: number, - } | { - type: 'mouseWheel', - modifiers?: electron$InputEventModifiers, - x: number, - y: number, - button: 'left' | 'middle' | 'right', - globalX: number, - globalY: number, - movementX: number, - movementY: number, - clickCount: number, - deltaX: number, - deltaY: number, - wheelTicksX: number, - wheelTicksY: number, - accelerationRatioX: number, - accelerationRatioY: number, - hasPreciseScrollingDeltas: boolean, - canScroll: boolean, - }, + type: 'mouseDown' | 'mouseUp' | 'mouseEnter' | 'mouseLeave' | 'contextMenu', + modifiers?: electron$InputEventModifiers, + x: number, + y: number, + button: 'left' | 'middle' | 'right', + globalX: number, + globalY: number, + movementX: number, + movementY: number, + clickCount: number, + } | { + type: 'mouseWheel', + modifiers?: electron$InputEventModifiers, + x: number, + y: number, + button: 'left' | 'middle' | 'right', + globalX: number, + globalY: number, + movementX: number, + movementY: number, + clickCount: number, + deltaX: number, + deltaY: number, + wheelTicksX: number, + wheelTicksY: number, + accelerationRatioX: number, + accelerationRatioY: number, + hasPreciseScrollingDeltas: boolean, + canScroll: boolean, + }, ): void, beginFrameSubscription( callback: (frameBuffer: Buffer, dirtyRect: electron$rect) => void, @@ -871,7 +871,7 @@ type electron$Display = { }; type electron$DisplayEvents = - 'display-added' + 'display-added' | 'display-removed' | 'display-metrics-changed'; diff --git a/flow-libs/jest.js.flow b/flow-libs/jest.js.flow new file mode 100644 index 00000000..7079891b --- /dev/null +++ b/flow-libs/jest.js.flow @@ -0,0 +1,579 @@ +/** + * 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 + */ + +// Derived from https://github.com/flowtype/flow-typed/blob/b14f68e407c3c0365f00bc9cf42f954b124012cb/cli/flow-typed/npm/jest_v22.x.x.js +// Keep in sync with future changes. + +declare module 'nuclide-jest/globals' { + /** Runs this function after every test inside this context */ + declare function afterEach( + fn: (done: () => void) => ?Promise, + timeout?: number + ): void; + /** Runs this function before every test inside this context */ + declare function beforeEach( + fn: (done: () => void) => ?Promise, + timeout?: number + ): void; + /** Runs this function after all tests have finished inside this context */ + declare function afterAll( + fn: (done: () => void) => ?Promise, + timeout?: number + ): void; + /** Runs this function before any tests have started inside this context */ + declare function beforeAll( + fn: (done: () => void) => ?Promise, + timeout?: number + ): void; + + /** A context for grouping tests together */ + declare var describe: { + /** + * Creates a block that groups together several related tests in one "test suite" + */ + (name: JestTestName, fn: () => void): void, + + /** + * Only run this describe block + */ + only(name: JestTestName, fn: () => void): void, + + /** + * Skip running this describe block + */ + skip(name: JestTestName, fn: () => void): void + }; + + /** An individual test unit */ + declare var it: { + /** + * An individual test unit + * + * @param {JestTestName} Name of Test + * @param {Function} Test + * @param {number} Timeout for the test, in milliseconds. + */ + ( + name: JestTestName, + fn?: (done: () => void) => ?Promise, + timeout?: number + ): void, + /** + * Only run this test + * + * @param {JestTestName} Name of Test + * @param {Function} Test + * @param {number} Timeout for the test, in milliseconds. + */ + only( + name: JestTestName, + fn?: (done: () => void) => ?Promise, + timeout?: number + ): void, + /** + * Skip running this test + * + * @param {JestTestName} Name of Test + * @param {Function} Test + * @param {number} Timeout for the test, in milliseconds. + */ + skip( + name: JestTestName, + fn?: (done: () => void) => ?Promise, + timeout?: number + ): void, + /** + * Run the test concurrently + * + * @param {JestTestName} Name of Test + * @param {Function} Test + * @param {number} Timeout for the test, in milliseconds. + */ + concurrent( + name: JestTestName, + fn?: (done: () => void) => ?Promise, + timeout?: number + ): void + }; + declare function fit( + name: JestTestName, + fn: (done: () => void) => ?Promise, + timeout?: number + ): void; + /** An individual test unit */ + declare var test: typeof it; + /** A disabled group of tests */ + declare var xdescribe: typeof describe; + /** A focused group of tests */ + declare var fdescribe: typeof describe; + /** A disabled individual test */ + declare var xit: typeof it; + /** A disabled individual test */ + declare var xtest: typeof it; + + declare var expect: { + /** The object that you want to make assertions against */ + (value: any): JestExpectType & JestPromiseType & EnzymeMatchersType, + /** Add additional Jasmine matchers to Jest's roster */ + extend(matchers: {[name: string]: JestMatcher}): void, + /** Add a module that formats application-specific data structures. */ + addSnapshotSerializer(serializer: (input: Object) => string): void, + assertions(expectedAssertions: number): void, + hasAssertions(): void, + any(value: mixed): JestAsymmetricEqualityType, + anything(): void, + arrayContaining(value: Array): void, + objectContaining(value: Object): void, + /** Matches any received string that contains the exact expected string. */ + stringContaining(value: string): void, + stringMatching(value: string | RegExp): void, + }; + + // TODO handle return type + // http://jasmine.github.io/2.4/introduction.html#section-Spies + declare function spyOn(value: mixed, method: string): Object; + + /** Holds all functions related to manipulating test runner */ + declare var jest: JestObjectType; +} + +type JestMockFn, TReturn> = { + (...args: TArguments): TReturn, + /** + * An object for introspecting mock calls + */ + mock: { + /** + * An array that represents all calls that have been made into this mock + * function. Each call is represented by an array of arguments that were + * passed during the call. + */ + calls: Array, + /** + * An array that contains all the object instances that have been + * instantiated from this mock function. + */ + instances: Array + }, + /** + * Resets all information stored in the mockFn.mock.calls and + * mockFn.mock.instances arrays. Often this is useful when you want to clean + * up a mock's usage data between two assertions. + */ + mockClear(): void, + /** + * Resets all information stored in the mock. This is useful when you want to + * completely restore a mock back to its initial state. + */ + mockReset(): void, + /** + * Removes the mock and restores the initial implementation. This is useful + * when you want to mock functions in certain test cases and restore the + * original implementation in others. Beware that mockFn.mockRestore only + * works when mock was created with jest.spyOn. Thus you have to take care of + * restoration yourself when manually assigning jest.fn(). + */ + mockRestore(): void, + /** + * Accepts a function that should be used as the implementation of the mock. + * The mock itself will still record all calls that go into and instances + * that come from itself -- the only difference is that the implementation + * will also be executed when the mock is called. + */ + mockImplementation( + fn: (...args: TArguments) => TReturn + ): JestMockFn, + /** + * Accepts a function that will be used as an implementation of the mock for + * one call to the mocked function. Can be chained so that multiple function + * calls produce different results. + */ + mockImplementationOnce( + fn: (...args: TArguments) => TReturn + ): JestMockFn, + /** + * Just a simple sugar function for returning `this` + */ + mockReturnThis(): void, + /** + * Deprecated: use jest.fn(() => value) instead + */ + mockReturnValue(value: TReturn): JestMockFn, + /** + * Sugar for only returning a value once inside your mock + */ + mockReturnValueOnce(value: TReturn): JestMockFn +}; + +type JestAsymmetricEqualityType = { + /** + * A custom Jasmine equality tester + */ + asymmetricMatch(value: mixed): boolean +}; + +type JestCallsType = { + allArgs(): mixed, + all(): mixed, + any(): boolean, + count(): number, + first(): mixed, + mostRecent(): mixed, + reset(): void +}; + +type JestMatcherResult = { + message?: string | (() => string), + pass: boolean +}; + +type JestMatcher = (actual: any, expected: any) => JestMatcherResult; + +type JestPromiseType = { + /** + * Use rejects to unwrap the reason of a rejected promise so any other + * matcher can be chained. If the promise is fulfilled the assertion fails. + */ + rejects: JestExpectType, + /** + * Use resolves to unwrap the value of a fulfilled promise so any other + * matcher can be chained. If the promise is rejected the assertion fails. + */ + resolves: JestExpectType +}; + +/** + * Jest allows functions and classes to be used as test names in test() and + * describe() + */ +type JestTestName = string | Function; + +/** + * Plugin: jest-enzyme + */ +type EnzymeMatchersType = { + toBeChecked(): void, + toBeDisabled(): void, + toBeEmpty(): void, + toBeEmptyRender(): void, + toBePresent(): void, + toContainReact(element: React$Element): void, + toExist(): void, + toHaveClassName(className: string): void, + toHaveHTML(html: string): void, + toHaveProp: ((propKey: string, propValue?: any) => void) & ((props: Object) => void), + toHaveRef(refName: string): void, + toHaveState: ((stateKey: string, stateValue?: any) => void) & ((state: Object) => void), + toHaveStyle: ((styleKey: string, styleValue?: any) => void) & ((style: Object) => void), + toHaveTagName(tagName: string): void, + toHaveText(text: string): void, + toIncludeText(text: string): void, + toHaveValue(value: any): void, + toMatchElement(element: React$Element): void, + toMatchSelector(selector: string): void +}; + +type JestExpectType = { + not: JestExpectType & EnzymeMatchersType, + /** + * If you have a mock function, you can use .lastCalledWith to test what + * arguments it was last called with. + */ + lastCalledWith(...args: Array): void, + /** + * toBe just checks that a value is what you expect. It uses === to check + * strict equality. + */ + toBe(value: any): void, + /** + * Use .toHaveBeenCalled to ensure that a mock function got called. + */ + toBeCalled(): void, + /** + * Use .toBeCalledWith to ensure that a mock function was called with + * specific arguments. + */ + toBeCalledWith(...args: Array): void, + /** + * Using exact equality with floating point numbers is a bad idea. Rounding + * means that intuitive things fail. + */ + toBeCloseTo(num: number, delta: any): void, + /** + * Use .toBeDefined to check that a variable is not undefined. + */ + toBeDefined(): void, + /** + * Use .toBeFalsy when you don't care what a value is, you just want to + * ensure a value is false in a boolean context. + */ + toBeFalsy(): void, + /** + * To compare floating point numbers, you can use toBeGreaterThan. + */ + toBeGreaterThan(number: number): void, + /** + * To compare floating point numbers, you can use toBeGreaterThanOrEqual. + */ + toBeGreaterThanOrEqual(number: number): void, + /** + * To compare floating point numbers, you can use toBeLessThan. + */ + toBeLessThan(number: number): void, + /** + * To compare floating point numbers, you can use toBeLessThanOrEqual. + */ + toBeLessThanOrEqual(number: number): void, + /** + * Use .toBeInstanceOf(Class) to check that an object is an instance of a + * class. + */ + toBeInstanceOf(cls: Class<*>): void, + /** + * .toBeNull() is the same as .toBe(null) but the error messages are a bit + * nicer. + */ + toBeNull(): void, + /** + * Use .toBeTruthy when you don't care what a value is, you just want to + * ensure a value is true in a boolean context. + */ + toBeTruthy(): void, + /** + * Use .toBeUndefined to check that a variable is undefined. + */ + toBeUndefined(): void, + /** + * Use .toContain when you want to check that an item is in a list. For + * testing the items in the list, this uses ===, a strict equality check. + */ + toContain(item: any): void, + /** + * Use .toContainEqual when you want to check that an item is in a list. For + * testing the items in the list, this matcher recursively checks the + * equality of all fields, rather than checking for object identity. + */ + toContainEqual(item: any): void, + /** + * Use .toEqual when you want to check that two objects have the same value. + * This matcher recursively checks the equality of all fields, rather than + * checking for object identity. + */ + toEqual(value: any): void, + /** + * Use .toHaveBeenCalled to ensure that a mock function got called. + */ + toHaveBeenCalled(): void, + /** + * Use .toHaveBeenCalledTimes to ensure that a mock function got called exact + * number of times. + */ + toHaveBeenCalledTimes(number: number): void, + /** + * Use .toHaveBeenCalledWith to ensure that a mock function was called with + * specific arguments. + */ + toHaveBeenCalledWith(...args: Array): void, + /** + * Use .toHaveBeenLastCalledWith to ensure that a mock function was last called + * with specific arguments. + */ + toHaveBeenLastCalledWith(...args: Array): void, + /** + * Check that an object has a .length property and it is set to a certain + * numeric value. + */ + toHaveLength(number: number): void, + /** + * + */ + toHaveProperty(propPath: string, value?: any): void, + /** + * Use .toMatch to check that a string matches a regular expression or string. + */ + toMatch(regexpOrString: RegExp | string): void, + /** + * Use .toMatchObject to check that a javascript object matches a subset of the properties of an object. + */ + toMatchObject(object: Object | Array): void, + /** + * This ensures that a React component matches the most recent snapshot. + */ + toMatchSnapshot(name?: string): void, + /** + * Use .toThrow to test that a function throws when it is called. + * If you want to test that a specific error gets thrown, you can provide an + * argument to toThrow. The argument can be a string for the error message, + * a class for the error, or a regex that should match the error. + * + * Alias: .toThrowError + */ + toThrow(message?: string | Error | Class | RegExp): void, + toThrowError(message?: string | Error | Class | RegExp): void, + /** + * Use .toThrowErrorMatchingSnapshot to test that a function throws a error + * matching the most recent snapshot when it is called. + */ + toThrowErrorMatchingSnapshot(): void +}; + +type JestObjectType = { + /** + * Disables automatic mocking in the module loader. + * + * After this method is called, all `require()`s will return the real + * versions of each module (rather than a mocked version). + */ + disableAutomock(): JestObjectType, + /** + * An un-hoisted version of disableAutomock + */ + autoMockOff(): JestObjectType, + /** + * Enables automatic mocking in the module loader. + */ + enableAutomock(): JestObjectType, + /** + * An un-hoisted version of enableAutomock + */ + autoMockOn(): JestObjectType, + /** + * Clears the mock.calls and mock.instances properties of all mocks. + * Equivalent to calling .mockClear() on every mocked function. + */ + clearAllMocks(): JestObjectType, + /** + * Resets the state of all mocks. Equivalent to calling .mockReset() on every + * mocked function. + */ + resetAllMocks(): JestObjectType, + /** + * Restores all mocks back to their original value. + */ + restoreAllMocks(): JestObjectType, + /** + * Removes any pending timers from the timer system. + */ + clearAllTimers(): void, + /** + * The same as `mock` but not moved to the top of the expectation by + * babel-jest. + */ + doMock(moduleName: string, moduleFactory?: any): JestObjectType, + /** + * The same as `unmock` but not moved to the top of the expectation by + * babel-jest. + */ + dontMock(moduleName: string): JestObjectType, + /** + * Returns a new, unused mock function. Optionally takes a mock + * implementation. + */ + fn, TReturn>( + implementation?: (...args: TArguments) => TReturn + ): JestMockFn, + /** + * Determines if the given function is a mocked function. + */ + isMockFunction(fn: Function): boolean, + /** + * Given the name of a module, use the automatic mocking system to generate a + * mocked version of the module for you. + */ + genMockFromModule(moduleName: string): any, + /** + * Mocks a module with an auto-mocked version when it is being required. + * + * The second argument can be used to specify an explicit module factory that + * is being run instead of using Jest's automocking feature. + * + * The third argument can be used to create virtual mocks -- mocks of modules + * that don't exist anywhere in the system. + */ + mock( + moduleName: string, + moduleFactory?: any, + options?: Object + ): JestObjectType, + /** + * Returns the actual module instead of a mock, bypassing all checks on + * whether the module should receive a mock implementation or not. + */ + requireActual(moduleName: string): any, + /** + * Returns a mock module instead of the actual module, bypassing all checks + * on whether the module should be required normally or not. + */ + requireMock(moduleName: string): any, + /** + * Resets the module registry - the cache of all required modules. This is + * useful to isolate modules where local state might conflict between tests. + */ + resetModules(): JestObjectType, + /** + * Exhausts the micro-task queue (usually interfaced in node via + * process.nextTick). + */ + runAllTicks(): void, + /** + * Exhausts the macro-task queue (i.e., all tasks queued by setTimeout(), + * setInterval(), and setImmediate()). + */ + runAllTimers(): void, + /** + * Exhausts all tasks queued by setImmediate(). + */ + runAllImmediates(): void, + /** + * Executes only the macro task queue (i.e. all tasks queued by setTimeout() + * or setInterval() and setImmediate()). + */ + advanceTimersByTime(msToRun: number): void, + // alias + runTimersToTime(msToRun: number): void, + /** + * Executes only the macro-tasks that are currently pending (i.e., only the + * tasks that have been queued by setTimeout() or setInterval() up to this + * point) + */ + runOnlyPendingTimers(): void, + /** + * Explicitly supplies the mock object that the module system should return + * for the specified module. Note: It is recommended to use jest.mock() + * instead. + */ + setMock(moduleName: string, moduleExports: any): JestObjectType, + /** + * Indicates that the module system should never return a mocked version of + * the specified module from require() (e.g. that it should always return the + * real module). + */ + unmock(moduleName: string): JestObjectType, + /** + * Instructs Jest to use fake versions of the standard timer functions + * (setTimeout, setInterval, clearTimeout, clearInterval, nextTick, + * setImmediate and clearImmediate). + */ + useFakeTimers(): JestObjectType, + /** + * Instructs Jest to use the real versions of the standard timer functions. + */ + useRealTimers(): JestObjectType, + /** + * Creates a mock function similar to jest.fn but also tracks calls to + * object[methodName]. + */ + spyOn(object: Object, methodName: string): JestMockFn, + /** + * Set the default timeout interval for tests and before/after hooks in milliseconds. + * Note: The default timeout interval is 5 seconds if this method is not called. + */ + setTimeout(timeout: number): JestObjectType +}; diff --git a/flow-libs/need-to-upstream-to-flow-lib.js.flow b/flow-libs/need-to-upstream-to-flow-lib.js.flow new file mode 100644 index 00000000..db1b92f8 --- /dev/null +++ b/flow-libs/need-to-upstream-to-flow-lib.js.flow @@ -0,0 +1,138 @@ +/** + * 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 + */ + +/* + * APIs listed in this file are ones that should be built into Flow and need to be upstreamed. + */ + +type IDisposable = { + dispose(): mixed, +}; + +/* + * These Notification & NotificationOptions definitions are not exhaustive while standardization, + * browser, and Electron support remain incomplete. + */ +type NotificationOptions = { + body?: string, + icon?: string, +}; + +declare class Notification { + constructor( + message: string, + options?: NotificationOptions, + ): void, + onclick: () => void, +} + +// T9254051 - Fix flow http/https definitions. +declare class http$fixed$Server extends events$EventEmitter { + listen(port: number, hostname?: string, backlog?: number, callback?: Function): http$fixed$Server, + listen(path: string, callback?: Function): http$fixed$Server, + listen(handle: Object, callback?: Function): http$fixed$Server, + close(callback?: Function): http$fixed$Server, + address(): {port: number, fmaily: string, address: string}, + maxHeadersCount: number, +} + +declare class http$fixed$IncomingMessage extends stream$Readable { + headers: Object, + httpVersion: string, + method: string, + trailers: Object, + setTimeout(msecs: number, callback: Function): void, + socket: any, // TODO net.Socket + statusCode: number, + url: string, + connection: { destroy: () => void }, +} + +declare class http$fixed$ClientRequest extends stream$Writable { +} + +declare class http$fixed$ServerResponse { + setHeader(name: string, value: string): void, + statusCode: number, + write(value: string): void, + end(): void, +} + +declare class https$fixed { + Server: typeof http$fixed$Server, + createServer( + options: Object, + requestListener?: ( + request: http$fixed$IncomingMessage, + response: http$fixed$ServerResponse, + ) => void, + ): http$fixed$Server, + request( + options: Object | string, + callback: (response: http$fixed$IncomingMessage) => void + ): http$fixed$ClientRequest, + get( + options: Object | string, + callback: (response: http$fixed$IncomingMessage) => void + ): http$fixed$ClientRequest, +} + +declare class http$fixed { + Server: typeof http$fixed$Server, + createServer( + requestListener?: ( + request: http$fixed$IncomingMessage, + response: http$fixed$ServerResponse, + ) => void + ): http$fixed$Server, + request( + options: Object | string, + callback: (response: http$fixed$IncomingMessage) => void + ): http$fixed$ClientRequest, + get( + options: Object | string, + callback: (response: http$fixed$IncomingMessage) => void + ): http$fixed$ClientRequest, +} + +declare class module$Module { + constructor( + id?: string, + parent?: string | module$Module + ): void, + id: ?string, + exports: any, + parent?: string | module$Module, + filename?: string, + loaded: boolean, + children: Array, + paths: Array, + _compile: (content: string, filename: string) => void, + + static _resolveFilename(filename: string, module: any): string, +} + +declare module 'module' { + declare module.exports: typeof module$Module; +} + +declare module 'console' { + declare module.exports: any; +} + +declare interface net$ListenOptions { + port?: number, + host?: string, + backlog?: number, + path?: string, + exclusive?: boolean, +} + +declare export var module: module$Module; diff --git a/flow-libs/need-to-upstream-to-pty.js.flow b/flow-libs/need-to-upstream-to-pty.js.flow new file mode 100644 index 00000000..8d4895cb --- /dev/null +++ b/flow-libs/need-to-upstream-to-pty.js.flow @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2017-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 + */ + +/* + * APIs listed in this file are ones that should be built into nuclide-prebuilt-libs/pty and need to be upstreamed. + */ + +declare module 'nuclide-prebuilt-libs/pty' { + declare export type ProcessEnv = { + +[key: string]: string; + }; + + declare export type IPtyForkOptions = { + name?: string; + cols?: number; + rows?: number; + cwd?: string; + env?: ProcessEnv; + uid?: number; + gid?: number; + }; + + declare export type IPtyOpenOptions = { + cols?: number; + rows?: number; + }; +} diff --git a/lib/ExecutionControlEpic/PlanConfigurationFeature/AtomLinks/Panels.js b/lib/ExecutionControlEpic/PlanConfigurationFeature/AtomLinks/Panels.js index 230e824d..0c6530ed 100644 --- a/lib/ExecutionControlEpic/PlanConfigurationFeature/AtomLinks/Panels.js +++ b/lib/ExecutionControlEpic/PlanConfigurationFeature/AtomLinks/Panels.js @@ -11,10 +11,8 @@ import PinnedPlanPanel from "../Layouts/PinnedPlanPanel"; import ToolPlansPanel from "../Layouts/ToolPlansPanel"; import { StyleRoot } from "radium"; -declare var atom: any; - export var pinnedPlans = document.createElement("div"); -export var pinnedPlansPanel = atom.workspace.addTopPanel({ +export var pinnedPlansPanel = global.atom.workspace.addTopPanel({ item: pinnedPlans, visible: false, priority: 200, @@ -32,7 +30,7 @@ export function renderPinnedPlans() { } export var toolPlans = document.createElement("div"); -export var toolPlansPanel = atom.workspace.addBottomPanel({ +export var toolPlansPanel = global.atom.workspace.addBottomPanel({ item: toolPlans, visible: false, priority: 50, diff --git a/lib/ExecutionControlEpic/PlanConfigurationFeature/Presenters/Plan.js b/lib/ExecutionControlEpic/PlanConfigurationFeature/Presenters/Plan.js index c26c8957..f68125ef 100644 --- a/lib/ExecutionControlEpic/PlanConfigurationFeature/Presenters/Plan.js +++ b/lib/ExecutionControlEpic/PlanConfigurationFeature/Presenters/Plan.js @@ -5,10 +5,10 @@ import * as React from "react"; import type { TaskState } from "../../TaskExecutionFeature/Types/types"; import DevToolCircle from "./DevToolCircle"; import Radium from "radium"; -import { remote } from "electron"; +import electron from "electron"; +import nullthrows from "nullthrows"; -const Menu = remote ? remote.Menu : undefined; -const MenuItem = remote ? remote.MenuItem : undefined; +const remote = nullthrows(electron.remote); let rippleAnimation = Radium.keyframes( { @@ -77,16 +77,16 @@ export class Plan extends React.Component { }} onClick={() => this.props.onClick()} onContextMenu={() => { - const menu = new Menu(); + const menu = new remote.Menu(); menu.append( this.props.pinnable - ? new MenuItem({ + ? new remote.MenuItem({ label: "Pin", click: () => { this.props.onPin(); }, }) - : new MenuItem({ + : new remote.MenuItem({ label: "Un-pin", click: () => { this.props.onUnpin(); @@ -94,7 +94,7 @@ export class Plan extends React.Component { }), ); menu.append( - new MenuItem({ + new remote.MenuItem({ label: "Remove", enabled: this.props.state !== "running", click: () => { diff --git a/lib/ExecutionControlEpic/Plugins/Eslint/index.js b/lib/ExecutionControlEpic/Plugins/Eslint/index.js index 36028100..b0b46a48 100644 --- a/lib/ExecutionControlEpic/Plugins/Eslint/index.js +++ b/lib/ExecutionControlEpic/Plugins/Eslint/index.js @@ -8,7 +8,6 @@ import type { import type { TaskAPI } from "../../LanguageServerProtocolFeature/Types/pluginApi"; import path from "path"; import moment from "moment"; -import { File } from "atom"; import type { HelperAPI } from "../../TaskExecutionFeature/Types/types"; import EslintDiagnostic from "./Presenters/EslintDiagnostic.js"; import type { PackageTesterResult } from "../../../ProjectSystemEpic/PackageFeature/Types/types"; diff --git a/lib/ExecutionControlEpic/Plugins/Nightwatch/index.js b/lib/ExecutionControlEpic/Plugins/Nightwatch/index.js index fe0ef5dc..a9766ddf 100644 --- a/lib/ExecutionControlEpic/Plugins/Nightwatch/index.js +++ b/lib/ExecutionControlEpic/Plugins/Nightwatch/index.js @@ -7,7 +7,6 @@ import type { } from "../../PlanConfigurationFeature/Types/types"; import type { TaskAPI } from "../../LanguageServerProtocolFeature/Types/pluginApi"; import path from "path"; -import { File } from "atom"; import moment from "moment"; import type { HelperAPI } from "../../TaskExecutionFeature/Types/types"; import fs from "fs"; diff --git a/lib/ExecutionControlEpic/Plugins/ReactNative.js b/lib/ExecutionControlEpic/Plugins/ReactNative.js index bd4dad49..54dbfd2f 100644 --- a/lib/ExecutionControlEpic/Plugins/ReactNative.js +++ b/lib/ExecutionControlEpic/Plugins/ReactNative.js @@ -9,7 +9,6 @@ import type { TaskAPI } from "../LanguageServerProtocolFeature/Types/pluginApi"; import moment from "moment"; import path from "path"; import type { HelperAPI } from "../TaskExecutionFeature/Types/types"; -import { File } from "atom"; import type { PackageTesterResult } from "../../ProjectSystemEpic/PackageFeature/Types/types"; import fs from "fs"; import type { Plugin } from "../DevtoolLoadingFeature/Types/types"; diff --git a/lib/ExecutionControlEpic/Plugins/Testcafe.js b/lib/ExecutionControlEpic/Plugins/Testcafe.js index b3b8c165..54c141da 100644 --- a/lib/ExecutionControlEpic/Plugins/Testcafe.js +++ b/lib/ExecutionControlEpic/Plugins/Testcafe.js @@ -7,7 +7,6 @@ import type { } from "../PlanConfigurationFeature/Types/types"; import type { TaskAPI } from "../LanguageServerProtocolFeature/Types/pluginApi"; import path from "path"; -import { File } from "atom"; import moment from "moment"; import type { HelperAPI } from "../TaskExecutionFeature/Types/types"; import type { PackageTesterResult } from "../../ProjectSystemEpic/PackageFeature/Types/types"; diff --git a/lib/ProjectSystemEpic/PackageFeature/Model/FindPackages.js b/lib/ProjectSystemEpic/PackageFeature/Model/FindPackages.js index 42e9159e..3e12c90e 100644 --- a/lib/ProjectSystemEpic/PackageFeature/Model/FindPackages.js +++ b/lib/ProjectSystemEpic/PackageFeature/Model/FindPackages.js @@ -6,7 +6,7 @@ import type { Package, Plugin, } from "../Types/types"; -import { Directory, File } from "atom"; +import atom from "atom"; import { List } from "immutable"; import path from "path"; import Rx from "rxjs"; @@ -89,7 +89,7 @@ export function findPackages( ) return Rx.Observable.of([]); if (!rootPath.match(/(.)*\.(.)*/gi)) { - const directory = new Directory(rootPath); + const directory = new atom.Directory(rootPath); const getEntries = Rx.Observable.bindNodeCallback( directory.getEntries.bind(directory), ); @@ -123,7 +123,7 @@ export function findPackages( .map(v => v.toArray()); } else { return Rx.Observable.defer(() => - getPackagesOfEntry(plugins, new File(rootPath), []) + getPackagesOfEntry(plugins, new atom.File(rootPath), []) .filter(v => v !== false) .map(v => ({ ...v, isFile: true })) .reduce((acc, v) => acc.concat(v), []), diff --git a/lib/molecule-dev-environment.js b/lib/molecule-dev-environment.js index eab3eff1..41496acb 100644 --- a/lib/molecule-dev-environment.js +++ b/lib/molecule-dev-environment.js @@ -2,11 +2,10 @@ // @flow import "babel-polyfill"; -import { CompositeDisposable } from "atom"; +import atom from "atom"; import store from "./GlobalSystem/Store"; import { provideDevtool } from "./ExecutionControlEpic/DevtoolLoadingFeature/Model/DevtoolLoadingHandler"; import { DevToolsControllerInstance } from "./ExecutionControlEpic/DevtoolLoadingFeature/Model/DevToolsController"; -import { remote } from "electron"; import { toolPlansPanel } from "./ExecutionControlEpic/PlanConfigurationFeature/AtomLinks/Panels"; import handleStateChange from "./ExecutionControlEpic/LinterFeature/Model/StateChangeHandler"; import { createProjectsObservable } from "./EventSystemEpic/ProjectFeature/Model/createProjectsObservable"; @@ -57,7 +56,7 @@ export default { ); // Events subscribed to in atom's system can be easily cleaned up with a CompositeDisposable - this.subscriptions = new CompositeDisposable(); + this.subscriptions = new atom.CompositeDisposable(); // Register command that toggles this view //this.subscriptions.add(); this.subscriptions.add( @@ -81,7 +80,6 @@ export default { }, }), ); - remote.getCurrentWindow().on("close", function() {}); }, deactivate() { diff --git a/package.json b/package.json index d21de360..e25689e9 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "nightwatch": "^0.9.12", "nightwatch-html-reporter": "^2.0.0", "nuclide-prebuilt-libs": "^0.3.8", + "nullthrows": "^1.0.1", "radium": "^0.19.1", "react": "^15.4.2", "react-addons-test-utils": "^15.4.2", @@ -69,7 +70,6 @@ "redux-thunk": "^2.1.0", "remote-redux-devtools": "^0.5.7", "rxjs": "^5.4.3", - "ssh2": "^0.5.4", "stream-buffers": "^3.0.1", "styled-components": "^2.2.0", "tree-kill": "^1.2.0", @@ -103,7 +103,11 @@ "webpack": "^3.10.0" }, "babel": { - "presets": ["env", "react", "flow"], + "presets": [ + "env", + "react", + "flow" + ], "plugins": [ "add-module-exports", "transform-object-rest-spread", diff --git a/yarn.lock b/yarn.lock index 6a9fe593..24aaaabe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5131,6 +5131,10 @@ nullthrows@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.0.0.tgz#34715e53b9debe0750a77233fd494a5835a2d999" +nullthrows@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/nullthrows/-/nullthrows-1.0.1.tgz#db2129889ca3188c323fb71b1be3f4a317e3f106" + num2fraction@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"