Expose GK api on client

Summary: Make sure that GKs can be used in pure sandy plugins.

Reviewed By: jknoxville

Differential Revision: D25368358

fbshipit-source-id: c7c6aa4ecf0443cb3b5d90e22e8aca9a73a69389
This commit is contained in:
Michel Weststrate
2020-12-07 09:43:42 -08:00
committed by Facebook GitHub Bot
parent 031cec299b
commit 698df77553
6 changed files with 59 additions and 3 deletions

View File

@@ -11,6 +11,7 @@ import type {FlipperLib} from 'flipper-plugin';
import type {Logger} from '../fb-interfaces/Logger'; import type {Logger} from '../fb-interfaces/Logger';
import type {Store} from '../reducers'; import type {Store} from '../reducers';
import createPaste from '../fb-stubs/createPaste'; import createPaste from '../fb-stubs/createPaste';
import GK from '../fb-stubs/GK';
let flipperLibInstance: FlipperLib | undefined; let flipperLibInstance: FlipperLib | undefined;
@@ -25,6 +26,9 @@ export function initializeFlipperLibImplementation(
addSandyPluginEntries(entries); addSandyPluginEntries(entries);
}, },
createPaste, createPaste,
GK(gatekeeper: string) {
return GK.get(gatekeeper);
},
}; };
} }

View File

@@ -401,3 +401,31 @@ test('available methods can be overridden', async () => {
); );
expect(await plugin.instance.checkEnabled()).toBeFalsy(); expect(await plugin.instance.checkEnabled()).toBeFalsy();
}); });
test('GKs are supported', () => {
const pluginModule = {
plugin(client: PluginClient<{}, {}>) {
return {
isTest() {
return client.GK('bla');
},
};
},
Component() {
return null;
},
};
{
const plugin = TestUtils.startPlugin(pluginModule);
expect(plugin.instance.isTest()).toBe(false);
}
{
const plugin = TestUtils.startPlugin(pluginModule, {GKs: ['bla']});
expect(plugin.instance.isTest()).toBe(true);
}
{
const plugin = TestUtils.startPlugin(pluginModule, {GKs: ['x']});
expect(plugin.instance.isTest()).toBe(false);
}
});

View File

@@ -15,4 +15,5 @@ import {NormalizedMenuEntry} from './MenuEntry';
export interface FlipperLib { export interface FlipperLib {
enableMenuEntries(menuEntries: NormalizedMenuEntry[]): void; enableMenuEntries(menuEntries: NormalizedMenuEntry[]): void;
createPaste(input: string): Promise<string | undefined>; createPaste(input: string): Promise<string | undefined>;
GK(gatekeeper: string): boolean;
} }

View File

@@ -48,6 +48,12 @@ export interface BasePluginClient {
* Facebook only function. Resolves to undefined if creating a paste failed. * Facebook only function. Resolves to undefined if creating a paste failed.
*/ */
createPaste(input: string): Promise<string | undefined>; createPaste(input: string): Promise<string | undefined>;
/**
* Returns true if the user is taking part in the given gatekeeper.
* Always returns `false` in open source.
*/
GK(gkName: string): boolean;
} }
let currentPluginInstance: BasePluginInstance | undefined = undefined; let currentPluginInstance: BasePluginInstance | undefined = undefined;
@@ -155,6 +161,7 @@ export abstract class BasePluginInstance {
} }
}, },
createPaste: this.flipperLib.createPaste, createPaste: this.flipperLib.createPaste,
GK: this.flipperLib.GK,
}; };
} }

View File

@@ -46,6 +46,10 @@ interface StartPluginOptions {
startUnactivated?: boolean; startUnactivated?: boolean;
/** Provide a set of unsupported methods to simulate older clients that don't support certain methods yet */ /** Provide a set of unsupported methods to simulate older clients that don't support certain methods yet */
unsupportedMethods?: string[]; unsupportedMethods?: string[];
/**
* Provide a set of GKs that are enabled in this test.
*/
GKs?: string[];
} }
type ExtractClientType<Module extends FlipperPluginModule<any>> = Parameters< type ExtractClientType<Module extends FlipperPluginModule<any>> = Parameters<
@@ -179,7 +183,7 @@ export function startPlugin<Module extends FlipperPluginModule<any>>(
} }
const sendStub = jest.fn(); const sendStub = jest.fn();
const flipperUtils = createMockFlipperLib(); const flipperUtils = createMockFlipperLib(options);
const testDevice = createMockDevice(options); const testDevice = createMockDevice(options);
const appName = 'TestApplication'; const appName = 'TestApplication';
const deviceName = 'TestDevice'; const deviceName = 'TestDevice';
@@ -290,7 +294,7 @@ export function startDevicePlugin<Module extends FlipperDevicePluginModule>(
); );
} }
const flipperLib = createMockFlipperLib(); const flipperLib = createMockFlipperLib(options);
const testDevice = createMockDevice(options); const testDevice = createMockDevice(options);
const pluginInstance = new SandyDevicePluginInstance( const pluginInstance = new SandyDevicePluginInstance(
flipperLib, flipperLib,
@@ -340,10 +344,13 @@ export function renderDevicePlugin<Module extends FlipperDevicePluginModule>(
}; };
} }
export function createMockFlipperLib(): FlipperLib { export function createMockFlipperLib(options?: StartPluginOptions): FlipperLib {
return { return {
enableMenuEntries: jest.fn(), enableMenuEntries: jest.fn(),
createPaste: jest.fn(), createPaste: jest.fn(),
GK(gk: string) {
return options?.GKs?.includes(gk) || false;
},
}; };
} }

View File

@@ -218,6 +218,14 @@ The returned promise either contains a string with the URL of the paste, or `und
Details of the failure will be communicated back directly to the user through Flipper notifications. Details of the failure will be communicated back directly to the user through Flipper notifications.
For example if the user is currently not signed in. For example if the user is currently not signed in.
#### `GK`
Facebook only API.
Usage: `client.GK(gatekeeper: string): boolean`
Returns `true` if the current user is part of the given GK. `false` in all other cases.
## DevicePluginClient ## DevicePluginClient
### Properties ### Properties
@@ -435,6 +443,7 @@ The `options` argument is optional, but can specify the following fields:
* `isArchived: boolean`: Setting this flag, will set the `isArchived` on the mocked device as well. Set it if you want to test the behavior of your plugin for imported devices (see also [`Device.isArchived`](#isarchived)). Defaults to `false`. * `isArchived: boolean`: Setting this flag, will set the `isArchived` on the mocked device as well. Set it if you want to test the behavior of your plugin for imported devices (see also [`Device.isArchived`](#isarchived)). Defaults to `false`.
* `isBackgroundPlugin`: This makes sure the test runner emits life-cycle events in a way that is typical for background plugins. Defaults to `false`. The notable difference in behavior is that calling `.active()` on the test runner won't trigger the `connect` event to be fired, nor the `.deactivate()` the `disconnect` event. * `isBackgroundPlugin`: This makes sure the test runner emits life-cycle events in a way that is typical for background plugins. Defaults to `false`. The notable difference in behavior is that calling `.active()` on the test runner won't trigger the `connect` event to be fired, nor the `.deactivate()` the `disconnect` event.
* `startUnactivated`: This does not activate the plugin; `connect` needs to be explicitly called. This can be used in case setting mock implementation for `onSend` is required to make sure Client plugin works as expected. Defaults to `false`. * `startUnactivated`: This does not activate the plugin; `connect` needs to be explicitly called. This can be used in case setting mock implementation for `onSend` is required to make sure Client plugin works as expected. Defaults to `false`.
* `GKs`: A string array of gatekeeper names for which `client.GK` will `true` inside the test. By default GKs are assumed to be disabled inside unit tests.
#### The test runner object #### The test runner object