/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @format */ import { default as ProxyArchiveClient, searchNodes, } from '../ProxyArchiveClient'; import {PersistedState, ElementMap} from '../index'; import {ElementID, Element} from 'flipper'; import {SearchResultTree} from '../Search'; function constructElement( id: string, name: string, children: Array, ): Element { return { id, name, expanded: false, children, attributes: [], data: {}, decoration: 'decoration', extraInfo: {}, }; } function constructPersistedState(axMode: boolean): PersistedState { if (!axMode) { return { rootElement: 'root', rootAXElement: null, elements: {}, AXelements: {}, }; } return { rootElement: null, rootAXElement: 'root', elements: {}, AXelements: {}, }; } let state = constructPersistedState(false); function populateChildren(state: PersistedState, axMode: boolean) { const elements: ElementMap = {}; elements['root'] = constructElement('root', 'root view', [ 'child0', 'child1', ]); elements['child0'] = constructElement('child0', 'child0 view', [ 'child0_child0', 'child0_child1', ]); elements['child1'] = constructElement('child1', 'child1 view', [ 'child1_child0', 'child1_child1', ]); elements['child0_child0'] = constructElement( 'child0_child0', 'child0_child0 view', [], ); elements['child0_child1'] = constructElement( 'child0_child1', 'child0_child1 view', [], ); elements['child1_child0'] = constructElement( 'child1_child0', 'child1_child0 view', [], ); elements['child1_child1'] = constructElement( 'child1_child1', 'child1_child1 view', [], ); state.elements = elements; if (axMode) { state.AXelements = elements; } } beforeEach(() => { state = constructPersistedState(false); populateChildren(state, false); }); test('test the searchNode for root in axMode false', async () => { const searchResult: SearchResultTree | null = await searchNodes( state.elements['root'], 'root', false, state, ); expect(searchResult).toBeDefined(); expect(searchResult).toEqual({ id: 'root', isMatch: true, hasChildren: false, children: [], element: state.elements['root'], axElement: null, }); }); test('test the searchNode for root in axMode true', async () => { state = constructPersistedState(true); populateChildren(state, true); const searchResult: SearchResultTree | null = await searchNodes( state.AXelements['root'], 'RoOT', true, state, ); expect(searchResult).toBeDefined(); expect(searchResult).toEqual({ id: 'root', isMatch: true, hasChildren: false, children: [], element: state.AXelements['root'], // Even though AXElement exists, normal element will exist too axElement: state.AXelements['root'], }); }); test('test the searchNode which matches just one child', async () => { const searchResult: SearchResultTree | null = await searchNodes( state.elements['root'], 'child0_child0', false, state, ); expect(searchResult).toBeDefined(); expect(searchResult).toEqual({ id: 'root', isMatch: false, hasChildren: true, children: [ { id: 'child0', isMatch: false, hasChildren: true, children: [ { id: 'child0_child0', isMatch: true, hasChildren: false, children: [], element: state.elements['child0_child0'], axElement: null, }, ], element: state.elements['child0'], axElement: null, }, ], element: state.elements['root'], axElement: null, }); }); test('test the searchNode for which matches multiple child', async () => { const searchResult: SearchResultTree | null = await searchNodes( state.elements['root'], 'child0', false, state, ); expect(searchResult).toBeDefined(); const expectedSearchResult = { id: 'root', isMatch: false, hasChildren: true, children: [ { id: 'child0', isMatch: true, hasChildren: true, children: [ { id: 'child0_child0', isMatch: true, hasChildren: false, children: [], element: state.elements['child0_child0'], axElement: null, }, { id: 'child0_child1', isMatch: true, hasChildren: false, children: [], element: state.elements['child0_child1'], axElement: null, }, ], element: state.elements['child0'], axElement: null, }, { id: 'child1', isMatch: false, hasChildren: true, children: [ { id: 'child1_child0', isMatch: true, hasChildren: false, children: [], element: state.elements['child1_child0'], axElement: null, }, ], element: state.elements['child1'], axElement: null, }, ], element: state.elements['root'], axElement: null, }; expect(searchResult).toEqual(expectedSearchResult); }); test('test the searchNode, it should not be case sensitive', async () => { const searchResult: SearchResultTree | null = await searchNodes( state.elements['root'], 'ChIlD0', false, state, ); expect(searchResult).toBeDefined(); const expectedSearchResult = { id: 'root', isMatch: false, hasChildren: true, children: [ { id: 'child0', isMatch: true, hasChildren: true, children: [ { id: 'child0_child0', isMatch: true, hasChildren: false, children: [], element: state.elements['child0_child0'], axElement: null, }, { id: 'child0_child1', isMatch: true, hasChildren: false, children: [], element: state.elements['child0_child1'], axElement: null, }, ], element: state.elements['child0'], axElement: null, }, { id: 'child1', isMatch: false, hasChildren: true, children: [ { id: 'child1_child0', isMatch: true, hasChildren: false, children: [], element: state.elements['child1_child0'], axElement: null, }, ], element: state.elements['child1'], axElement: null, }, ], element: state.elements['root'], axElement: null, }; expect(searchResult).toEqual(expectedSearchResult); }); test('test the searchNode for non existent query', async () => { const searchResult: SearchResultTree | null = await searchNodes( state.elements['root'], 'Unknown query', false, state, ); expect(searchResult).toBeNull(); }); test('test the call method with getRoot', async () => { const proxyClient = new ProxyArchiveClient(state); const root: Element = await proxyClient.call('getRoot'); expect(root).toEqual(state.elements['root']); }); test('test the call method with getAXRoot', async () => { state = constructPersistedState(true); populateChildren(state, true); const proxyClient = new ProxyArchiveClient(state); const root: Element = await proxyClient.call('getAXRoot'); expect(root).toEqual(state.AXelements['root']); }); test('test the call method with getNodes', async () => { const proxyClient = new ProxyArchiveClient(state); const nodes: Array = await proxyClient.call('getNodes', { ids: ['child0_child1', 'child1_child0'], }); expect(nodes).toEqual({ elements: [ { id: 'child0_child1', name: 'child0_child1 view', expanded: false, children: [], attributes: [], data: {}, decoration: 'decoration', extraInfo: {}, }, { id: 'child1_child0', name: 'child1_child0 view', expanded: false, children: [], attributes: [], data: {}, decoration: 'decoration', extraInfo: {}, }, ], }); }); test('test the call method with getAXNodes', async () => { state = constructPersistedState(true); populateChildren(state, true); const proxyClient = new ProxyArchiveClient(state); const nodes: Array = await proxyClient.call('getAXNodes', { ids: ['child0_child1', 'child1_child0'], }); expect(nodes).toEqual({ elements: [ { id: 'child0_child1', name: 'child0_child1 view', expanded: false, children: [], attributes: [], data: {}, decoration: 'decoration', extraInfo: {}, }, { id: 'child1_child0', name: 'child1_child0 view', expanded: false, children: [], attributes: [], data: {}, decoration: 'decoration', extraInfo: {}, }, ], }); }); test('test different methods of calls with no params', async () => { const proxyClient = new ProxyArchiveClient(state); await expect(proxyClient.call('getNodes')).rejects.toThrow( new Error('Called getNodes with no params'), ); await expect(proxyClient.call('getAXNodes')).rejects.toThrow( new Error('Called getAXNodes with no params'), ); // let result: Error = await proxyClient.call('getSearchResults'); await expect(proxyClient.call('getSearchResults')).rejects.toThrow( new Error('Called getSearchResults with no params'), ); await expect( proxyClient.call('getSearchResults', { query: 'random', axEnabled: true, }), ).rejects.toThrow(new Error('rootAXElement is undefined')); await expect( proxyClient.call('getSearchResults', { axEnabled: false, }), ).rejects.toThrow( new Error('query is not passed as a params to getSearchResults'), ); }); test('test call method isConsoleEnabled', () => { const proxyClient = new ProxyArchiveClient(state); return expect(proxyClient.call('isConsoleEnabled')).resolves.toBe(false); });