From d07b74eed0d80ff84f7bb07fbaf75e5047527154 Mon Sep 17 00:00:00 2001 From: bizzguy Date: Mon, 8 Mar 2021 11:50:53 -0800 Subject: [PATCH] Network Plugin - Disable routes (#1969) Summary: Mock routes may contain quite a bit of data for header values and response bodies. Currently, to turn off a mock a user must delete the mock and then go through the process of creating it when needed again. This change will allow a user to temporarily disable a mock without deleting it. A checkbox on the Routes list is used to enable/disable mocks. As shown in this screenshot: ![image](https://user-images.githubusercontent.com/337874/109360670-3a3fb280-784d-11eb-83fd-724f0bb067d3.png) ## Changelog Network Plugin - disable/enable mock routes Pull Request resolved: https://github.com/facebook/flipper/pull/1969 Test Plan: Create mocks using sample app Verify that mocks are working as expected Disable the mocks Verify that the client has been updated with mocks (minus the disabled ones) user Flipper Messages plugin Use the sample app to send the disabled requests again and verify that they are not mocked Reviewed By: mweststrate Differential Revision: D26888815 Pulled By: passy fbshipit-source-id: cb8a05a27dd69ba4d2b60085a077efe795a99a7c --- .../network/ManageMockResponsePanel.tsx | 80 +++++++++++-------- desktop/plugins/network/index.tsx | 30 +++++-- desktop/plugins/network/types.tsx | 2 + 3 files changed, 72 insertions(+), 40 deletions(-) diff --git a/desktop/plugins/network/ManageMockResponsePanel.tsx b/desktop/plugins/network/ManageMockResponsePanel.tsx index 68b58a214..b203ff3ad 100644 --- a/desktop/plugins/network/ManageMockResponsePanel.tsx +++ b/desktop/plugins/network/ManageMockResponsePanel.tsx @@ -17,14 +17,11 @@ import { Panel, } from 'flipper'; import React, {useContext, useState, useMemo, useEffect} from 'react'; - import {Route, Request, Response} from './types'; - import {MockResponseDetails} from './MockResponseDetails'; import {NetworkRouteContext} from './index'; import {RequestId} from './types'; - -import {message, Modal} from 'antd'; +import {message, Checkbox, Modal, Tooltip} from 'antd'; import {NUX, Layout} from 'flipper-plugin'; type Props = { @@ -77,6 +74,7 @@ function _buildRows( routes: {[id: string]: Route}, duplicatedIds: Array, handleRemoveId: (id: string) => void, + handleEnableId: (id: string) => void, ) { return Object.entries(routes).map(([id, route]) => ({ columns: { @@ -87,6 +85,8 @@ function _buildRows( text={route.requestUrl} showWarning={duplicatedIds.includes(id)} handleRemoveId={() => handleRemoveId(id)} + handleEnableId={() => handleEnableId(id)} + enabled={route.enabled} /> ), }, @@ -99,27 +99,35 @@ function RouteRow(props: { text: string; showWarning: boolean; handleRemoveId: () => void; + handleEnableId: () => void; + enabled: boolean; }) { + const tip = props.enabled + ? 'Un-check to disable mock route' + : 'Check to enable mock route'; return ( - - + + + + + - - {props.showWarning && ( - - )} - {props.text.length === 0 ? ( - - untitled - - ) : ( - {props.text} - )} - - - + + {props.showWarning && ( + + )} + {props.text.length === 0 ? ( + + untitled + + ) : ( + {props.text} + )} + ); } @@ -248,19 +256,25 @@ export function ManageMockResponsePanel(props: Props) { multiline={false} columnSizes={ColumnSizes} columns={Columns} - rowLineHeight={26} - rows={_buildRows(props.routes, duplicatedIds, (id) => { - Modal.confirm({ - title: 'Are you sure you want to delete this item?', - icon: '', - onOk() { - const nextId = getNextId(id); - networkRouteManager.removeRoute(id); - setSelectedId(nextId); - }, - onCancel() {}, - }); - })} + rows={_buildRows( + props.routes, + duplicatedIds, + (id) => { + Modal.confirm({ + title: 'Are you sure you want to delete this item?', + icon: '', + onOk() { + const nextId = getNextId(id); + networkRouteManager.removeRoute(id); + setSelectedId(nextId); + }, + onCancel() {}, + }); + }, + (id) => { + networkRouteManager.enableRoute(id); + }, + )} stickyBottom={true} autoHeight={false} floating={false} diff --git a/desktop/plugins/network/index.tsx b/desktop/plugins/network/index.tsx index fa8c0e949..da31016f3 100644 --- a/desktop/plugins/network/index.tsx +++ b/desktop/plugins/network/index.tsx @@ -127,6 +127,7 @@ export interface NetworkRouteManager { addRoute(): string | null; modifyRoute(id: string, routeChange: Partial): void; removeRoute(id: string): void; + enableRoute(id: string): void; copyHighlightedCalls( highlightedRows: Set, requests: {[id: string]: Request}, @@ -142,6 +143,7 @@ const nullNetworkRouteManager: NetworkRouteManager = { }, modifyRoute(_id: string, _routeChange: Partial) {}, removeRoute(_id: string) {}, + enableRoute(_id: string) {}, copyHighlightedCalls( _highlightedRows: Set, _requests: {[id: string]: Request}, @@ -348,6 +350,7 @@ export function plugin(client: PluginClient) { responseData: '', responseHeaders: {}, responseStatus: '200', + enabled: true, }; }); nextRouteId.set(newNextRouteId + 1); @@ -370,6 +373,14 @@ export function plugin(client: PluginClient) { } informClientMockChange(routes.get()); }, + enableRoute(id: string) { + if (routes.get().hasOwnProperty(id)) { + routes.update((draft) => { + draft[id].enabled = !draft[id].enabled; + }); + } + informClientMockChange(routes.get()); + }, copyHighlightedCalls( highlightedRows: Set | null | undefined, requests: {[id: string]: Request}, @@ -396,6 +407,7 @@ export function plugin(client: PluginClient) { responseData: responseData as string, responseHeaders: headers, responseStatus: responses[row].status.toString(), + enabled: true, }; }); nextRouteId.set(newNextRouteId + 1); @@ -427,6 +439,7 @@ export function plugin(client: PluginClient) { responseData: importedRoute.responseData as string, responseHeaders: importedRoute.responseHeaders, responseStatus: importedRoute.responseStatus, + enabled: true, }; }); nextRouteId.set(newNextRouteId + 1); @@ -541,13 +554,16 @@ export function plugin(client: PluginClient) { try { await client.send('mockResponses', { - routes: routesValuesArray.map((route: Route) => ({ - requestUrl: route.requestUrl, - method: route.requestMethod, - data: route.responseData, - headers: [...Object.values(route.responseHeaders)], - status: route.responseStatus, - })), + routes: routesValuesArray + .filter((e) => e.enabled) + .map((route: Route) => ({ + requestUrl: route.requestUrl, + method: route.requestMethod, + data: route.responseData, + headers: [...Object.values(route.responseHeaders)], + status: route.responseStatus, + enabled: route.enabled, + })), }); } catch (e) { console.error('Failed to mock responses.', e); diff --git a/desktop/plugins/network/types.tsx b/desktop/plugins/network/types.tsx index 149c8e94f..5cb9622c7 100644 --- a/desktop/plugins/network/types.tsx +++ b/desktop/plugins/network/types.tsx @@ -70,6 +70,7 @@ export type Route = { responseData: string; responseHeaders: {[id: string]: Header}; responseStatus: string; + enabled: boolean; }; export type MockRoute = { @@ -78,6 +79,7 @@ export type MockRoute = { data: string; headers: Header[]; status: string; + enabled: boolean; }; export type PersistedState = {