From 0748a27426e9b9e23f34b07b8a3fbf24944f196f Mon Sep 17 00:00:00 2001 From: Luke Schoen Date: Fri, 3 Aug 2018 13:46:17 +0200 Subject: [PATCH] fix: Fixes #94 by adding missing filter for extrinsics timestamp (#165) * refactor: Rename InputStorage key to method to be consistent with InputExtrinsic * fix: Add filter to both section and method that considers isHidden prop * refactor: Move into meaningful private functions * fix: Fix linting errors * test: Add Unit Tests to check shouldDisplaySection function * fix: Remove unnecessary import * restore file naming * refactor: Move shouldDisplaySection into utils folder * refactor: Move more common functionality into util * remove unused isObject * restore by removing unnecessary types. propose private type for storage * fix: Remove explicit passing through the type for storage since its default * feat: Use shared logic for showing section and methods in InputRpc * refactor: Move shared types into util folder with section visibility type * fix: type is public or private * WIP: methods[name] TypeScript error Element implicitly has an 'any' type because type '{}' has no index signature * fix: Fix TSLint errors using jacos solution --- .../src/InputExtrinsic/SelectMethod.tsx | 4 +- .../src/InputExtrinsic/SelectSection.tsx | 2 +- packages/ui-app/src/InputExtrinsic/index.tsx | 4 +- .../src/InputExtrinsic/options/method.tsx | 9 ++- .../src/InputExtrinsic/options/section.ts | 15 +--- packages/ui-app/src/InputRpc/SelectMethod.tsx | 2 +- .../ui-app/src/InputRpc/SelectSection.tsx | 2 +- packages/ui-app/src/InputRpc/index.tsx | 2 +- .../ui-app/src/InputRpc/options/method.tsx | 2 +- .../ui-app/src/InputRpc/options/section.ts | 20 +---- .../ui-app/src/InputStorage/SelectKey.tsx | 2 +- .../ui-app/src/InputStorage/SelectSection.tsx | 2 +- packages/ui-app/src/InputStorage/index.tsx | 2 +- .../ui-app/src/InputStorage/options/key.tsx | 2 +- .../src/InputStorage/options/section.ts | 19 +---- .../src/util/shouldDisplaySection.spec.js | 75 +++++++++++++++++++ .../ui-app/src/util/shouldDisplaySection.ts | 34 +++++++++ .../src/{InputExtrinsic => util}/types.d.ts | 2 + 18 files changed, 142 insertions(+), 58 deletions(-) create mode 100644 packages/ui-app/src/util/shouldDisplaySection.spec.js create mode 100644 packages/ui-app/src/util/shouldDisplaySection.ts rename packages/ui-app/src/{InputExtrinsic => util}/types.d.ts (86%) diff --git a/packages/ui-app/src/InputExtrinsic/SelectMethod.tsx b/packages/ui-app/src/InputExtrinsic/SelectMethod.tsx index dd0003b290..561c87757d 100644 --- a/packages/ui-app/src/InputExtrinsic/SelectMethod.tsx +++ b/packages/ui-app/src/InputExtrinsic/SelectMethod.tsx @@ -5,7 +5,7 @@ import { SectionItem } from '@polkadot/params/types'; import { Extrinsics, Extrinsic$Sections } from '@polkadot/extrinsics/types'; import { I18nProps } from '../types'; -import { DropdownOptions } from './types'; +import { DropdownOptions, SectionVisibilityAll } from '../util/types'; import React from 'react'; @@ -20,7 +20,7 @@ type Props = I18nProps & { label?: string, onChange: (value: SectionItem) => void, options: DropdownOptions, - type: 'private' | 'public', + type: SectionVisibilityAll, value: SectionItem, withLabel?: boolean }; diff --git a/packages/ui-app/src/InputExtrinsic/SelectSection.tsx b/packages/ui-app/src/InputExtrinsic/SelectSection.tsx index cb017fca3c..86bbc81d99 100644 --- a/packages/ui-app/src/InputExtrinsic/SelectSection.tsx +++ b/packages/ui-app/src/InputExtrinsic/SelectSection.tsx @@ -5,7 +5,7 @@ import { SectionItem } from '@polkadot/params/types'; import { Extrinsics, Extrinsic$Sections } from '@polkadot/extrinsics/types'; import { I18nProps } from '../types'; -import { DropdownOptions } from './types'; +import { DropdownOptions } from '../util/types'; import React from 'react'; diff --git a/packages/ui-app/src/InputExtrinsic/index.tsx b/packages/ui-app/src/InputExtrinsic/index.tsx index 80527cd457..1df75434e1 100644 --- a/packages/ui-app/src/InputExtrinsic/index.tsx +++ b/packages/ui-app/src/InputExtrinsic/index.tsx @@ -7,7 +7,7 @@ import { SectionItem } from '@polkadot/params/types'; import { Extrinsics, Extrinsic$Sections } from '@polkadot/extrinsics/types'; import { I18nProps } from '../types'; -import { DropdownOptions } from './types'; +import { DropdownOptions, SectionVisibilityAll } from '../util/types'; import './InputExtrinsic.css'; @@ -35,7 +35,7 @@ type Props = I18nProps & { type State = { optionsMethod: DropdownOptions, optionsSection: DropdownOptions, - type: 'private' | 'public', + type: SectionVisibilityAll, value: SectionItem }; diff --git a/packages/ui-app/src/InputExtrinsic/options/method.tsx b/packages/ui-app/src/InputExtrinsic/options/method.tsx index 7fbe05815d..eb3e2290a0 100644 --- a/packages/ui-app/src/InputExtrinsic/options/method.tsx +++ b/packages/ui-app/src/InputExtrinsic/options/method.tsx @@ -3,13 +3,13 @@ // of the ISC license. See the LICENSE file for details. import { Extrinsic$Sections } from '@polkadot/extrinsics/types'; -import { DropdownOptions } from '../types'; +import { DropdownOptions, SectionVisibilityAll } from '../../util/types'; import React from 'react'; import map from '@polkadot/extrinsics'; -export default function createOptions (sectionName: Extrinsic$Sections, type: 'private' | 'public'): DropdownOptions { +export default function createOptions (sectionName: Extrinsic$Sections, type: SectionVisibilityAll): DropdownOptions { const section = map[sectionName]; if (!section) { @@ -21,6 +21,11 @@ export default function createOptions (sectionName: Extrinsic$Sections, type: 'p return Object .keys(methods) .sort() + .filter((name) => { + const { isDeprecated, isHidden } = methods[name]; + + return !isDeprecated && !isHidden; + }) .map((name) => { const { description, params } = methods[name]; const inputs = params.map(({ name }) => name).join(', '); diff --git a/packages/ui-app/src/InputExtrinsic/options/section.ts b/packages/ui-app/src/InputExtrinsic/options/section.ts index 0c7cd48dc3..9c41ca81c6 100644 --- a/packages/ui-app/src/InputExtrinsic/options/section.ts +++ b/packages/ui-app/src/InputExtrinsic/options/section.ts @@ -3,26 +3,19 @@ // of the ISC license. See the LICENSE file for details. import { Extrinsic$Sections } from '@polkadot/extrinsics/types'; - -import { DropdownOptions } from '../types'; +import { DropdownOptions, SectionVisibilityAll } from '../../util/types'; +import { shouldDisplaySection } from '../../util/shouldDisplaySection'; import map from '@polkadot/extrinsics'; -export default function createOptions (type: 'private' | 'public'): DropdownOptions { +export default function createOptions (type: SectionVisibilityAll): DropdownOptions { return Object .keys(map) .sort() .filter((name) => { const section = map[name as Extrinsic$Sections]; - // cannot really get here - if (!section) { - return false; - } - - const methods = section[type]; - - return Object.keys(methods).length !== 0; + return shouldDisplaySection(section, type); }) .map((name) => ({ text: name, diff --git a/packages/ui-app/src/InputRpc/SelectMethod.tsx b/packages/ui-app/src/InputRpc/SelectMethod.tsx index d077928760..6a45b435e3 100644 --- a/packages/ui-app/src/InputRpc/SelectMethod.tsx +++ b/packages/ui-app/src/InputRpc/SelectMethod.tsx @@ -4,7 +4,7 @@ import { SectionItem } from '@polkadot/params/types'; import { Interfaces, Interface$Sections } from '@polkadot/jsonrpc/types'; -import { DropdownOptions } from '../InputExtrinsic/types'; +import { DropdownOptions } from '../util/types'; import { I18nProps } from '../types'; import React from 'react'; diff --git a/packages/ui-app/src/InputRpc/SelectSection.tsx b/packages/ui-app/src/InputRpc/SelectSection.tsx index 6b14743871..01524d501d 100644 --- a/packages/ui-app/src/InputRpc/SelectSection.tsx +++ b/packages/ui-app/src/InputRpc/SelectSection.tsx @@ -4,7 +4,7 @@ import { SectionItem } from '@polkadot/params/types'; import { Interfaces, Interface$Sections } from '@polkadot/jsonrpc/types'; -import { DropdownOptions } from '../InputExtrinsic/types'; +import { DropdownOptions } from '../util/types'; import { I18nProps } from '../types'; import React from 'react'; diff --git a/packages/ui-app/src/InputRpc/index.tsx b/packages/ui-app/src/InputRpc/index.tsx index 42f43865fc..0436ec686e 100644 --- a/packages/ui-app/src/InputRpc/index.tsx +++ b/packages/ui-app/src/InputRpc/index.tsx @@ -6,7 +6,7 @@ import { SectionItem } from '@polkadot/params/types'; import { Interfaces, Interface$Sections } from '@polkadot/jsonrpc/types'; -import { DropdownOptions } from '../InputExtrinsic/types'; +import { DropdownOptions } from '../util/types'; import { I18nProps } from '../types'; import '../InputExtrinsic/InputExtrinsic.css'; diff --git a/packages/ui-app/src/InputRpc/options/method.tsx b/packages/ui-app/src/InputRpc/options/method.tsx index a47b2b5ae7..7ff492ca7b 100644 --- a/packages/ui-app/src/InputRpc/options/method.tsx +++ b/packages/ui-app/src/InputRpc/options/method.tsx @@ -3,7 +3,7 @@ // of the ISC license. See the LICENSE file for details. import { Interface$Sections } from '@polkadot/jsonrpc/types'; -import { DropdownOptions } from '../../InputExtrinsic/types'; +import { DropdownOptions } from '../../util/types'; import React from 'react'; diff --git a/packages/ui-app/src/InputRpc/options/section.ts b/packages/ui-app/src/InputRpc/options/section.ts index d08cccf37d..4a4d4e90a0 100644 --- a/packages/ui-app/src/InputRpc/options/section.ts +++ b/packages/ui-app/src/InputRpc/options/section.ts @@ -3,8 +3,8 @@ // of the ISC license. See the LICENSE file for details. import { Interface$Sections } from '@polkadot/jsonrpc/types'; - -import { DropdownOptions } from '../../InputExtrinsic/types'; +import { DropdownOptions } from '../../util/types'; +import { shouldDisplaySection } from '../../util/shouldDisplaySection'; import map from '@polkadot/jsonrpc'; @@ -15,21 +15,7 @@ export default function createOptions (): DropdownOptions { .filter((name) => { const section = map[name as Interface$Sections]; - // cannot really get here - if (!section) { - return false; - } - - const { isDeprecated } = section; - const available = Object - .keys(section.public) - .filter((name) => { - const { isDeprecated, isHidden } = section.public[name]; - - return !isDeprecated && !isHidden; - }); - - return !isDeprecated && available.length !== 0; + return shouldDisplaySection(section, 'public'); }) .map((name) => ({ text: name, diff --git a/packages/ui-app/src/InputStorage/SelectKey.tsx b/packages/ui-app/src/InputStorage/SelectKey.tsx index 2d03d22080..f1bb904200 100644 --- a/packages/ui-app/src/InputStorage/SelectKey.tsx +++ b/packages/ui-app/src/InputStorage/SelectKey.tsx @@ -4,7 +4,7 @@ import { SectionItem } from '@polkadot/params/types'; import { Storages } from '@polkadot/storage/types'; -import { DropdownOptions } from '../InputExtrinsic/types'; +import { DropdownOptions } from '../util/types'; import { I18nProps } from '../types'; import React from 'react'; diff --git a/packages/ui-app/src/InputStorage/SelectSection.tsx b/packages/ui-app/src/InputStorage/SelectSection.tsx index d714c82ee3..2372c106f4 100644 --- a/packages/ui-app/src/InputStorage/SelectSection.tsx +++ b/packages/ui-app/src/InputStorage/SelectSection.tsx @@ -4,7 +4,7 @@ import { SectionItem } from '@polkadot/params/types'; import { Storages, Storage$Sections } from '@polkadot/storage/types'; -import { DropdownOptions } from '../InputExtrinsic/types'; +import { DropdownOptions } from '../util/types'; import { I18nProps } from '../types'; import React from 'react'; diff --git a/packages/ui-app/src/InputStorage/index.tsx b/packages/ui-app/src/InputStorage/index.tsx index 2ef9987680..48d92668c1 100644 --- a/packages/ui-app/src/InputStorage/index.tsx +++ b/packages/ui-app/src/InputStorage/index.tsx @@ -6,7 +6,7 @@ import { SectionItem } from '@polkadot/params/types'; import { Storages, Storage$Sections } from '@polkadot/storage/types'; -import { DropdownOptions } from '../InputExtrinsic/types'; +import { DropdownOptions } from '../util/types'; import { I18nProps } from '../types'; import '../InputExtrinsic/InputExtrinsic.css'; diff --git a/packages/ui-app/src/InputStorage/options/key.tsx b/packages/ui-app/src/InputStorage/options/key.tsx index 24eaf97259..c0e8cf339b 100644 --- a/packages/ui-app/src/InputStorage/options/key.tsx +++ b/packages/ui-app/src/InputStorage/options/key.tsx @@ -3,7 +3,7 @@ // of the ISC license. See the LICENSE file for details. import { Storage$Sections } from '@polkadot/storage/types'; -import { DropdownOptions } from '../../InputExtrinsic/types'; +import { DropdownOptions } from '../../util/types'; import React from 'react'; diff --git a/packages/ui-app/src/InputStorage/options/section.ts b/packages/ui-app/src/InputStorage/options/section.ts index 80ec92c29e..042afbe195 100644 --- a/packages/ui-app/src/InputStorage/options/section.ts +++ b/packages/ui-app/src/InputStorage/options/section.ts @@ -3,7 +3,9 @@ // of the ISC license. See the LICENSE file for details. import { Storage$Sections } from '@polkadot/storage/types'; -import { DropdownOptions } from '../../InputExtrinsic/types'; +import { DropdownOptions } from '../../util/types'; + +import { shouldDisplaySection } from '../../util/shouldDisplaySection'; import map from '@polkadot/storage'; @@ -14,20 +16,7 @@ export default function createOptions (): DropdownOptions { .filter((name) => { const section = map[name as Storage$Sections]; - // cannot really get here - if (!section) { - return false; - } - - const methods = Object - .keys(section.public) - .filter((name) => { - const { isDeprecated, isHidden } = section.public[name]; - - return !isDeprecated && !isHidden; - }); - - return !section.isDeprecated && methods.length !== 0; + return shouldDisplaySection(section, 'public'); }) .map((name) => ({ text: name, diff --git a/packages/ui-app/src/util/shouldDisplaySection.spec.js b/packages/ui-app/src/util/shouldDisplaySection.spec.js new file mode 100644 index 0000000000..f719f5adb8 --- /dev/null +++ b/packages/ui-app/src/util/shouldDisplaySection.spec.js @@ -0,0 +1,75 @@ +// Copyright 2017-2018 @polkadot/ui-app authors & contributors +// This software may be modified and distributed under the terms +// of the ISC license. See the LICENSE file for details. + +import { shouldDisplaySection } from './shouldDisplaySection'; + +describe('input extrinsic section', () => { + let type, dummySection; + + beforeEach(() => { + type = 'public'; + + dummySection = { + name: 'dummy', + description: 'an dummy extrinsic section', + isDeprecated: false, + isHidden: false, + private: {}, + public: { + didUpdate: { + isDeprecated: false, + isHidden: false + } + } + } + }); + + it('will be shown if section and its associated methods are not deprecated or hidden', () => { + const expectedOutput = true; + const actualOutput = shouldDisplaySection(dummySection, type); + + expect(actualOutput).toEqual(expectedOutput); + }); + + it('will not be shown if section is hidden', () => { + dummySection['isHidden'] = true; + const expectedOutput = false; + const actualOutput = shouldDisplaySection(dummySection, type); + + expect(actualOutput).toEqual(expectedOutput); + }); + + it('will not be shown if section is deprecated', () => { + dummySection['isDeprecated'] = true; + const expectedOutput = false; + const actualOutput = shouldDisplaySection(dummySection, type); + + expect(actualOutput).toEqual(expectedOutput); + }); + + it('will not be shown if section is not deprecated or hidden and no associated methods exist', () => { + type = 'private'; + const expectedOutput = false; + const actualOutput = shouldDisplaySection(dummySection, type); + + expect(actualOutput).toEqual(expectedOutput); + }); + + it('will not be shown if section is not deprecated or hidden but an associated method is deprecated or hidden', () => { + dummySection['public']['didUpdate']['isHidden'] = true; + const expectedOutput = false; + const actualOutput = shouldDisplaySection(dummySection, type); + + expect(actualOutput).toEqual(expectedOutput); + }); + + it('will not be shown if section methods are undefined or not an object', () => { + type = 'non-existant-type'; + const expectedOutput = false; + const actualOutput = shouldDisplaySection(dummySection, type); + + expect(actualOutput).toEqual(expectedOutput); + }); + +}); diff --git a/packages/ui-app/src/util/shouldDisplaySection.ts b/packages/ui-app/src/util/shouldDisplaySection.ts new file mode 100644 index 0000000000..3dfc65e718 --- /dev/null +++ b/packages/ui-app/src/util/shouldDisplaySection.ts @@ -0,0 +1,34 @@ +// Copyright 2017-2018 @polkadot/ui-app authors & contributors +// This software may be modified and distributed under the terms +// of the ISC license. See the LICENSE file for details. + +import { Section, SectionItems } from '@polkadot/params/types'; +import { SectionVisibilityAll } from '../util/types'; + +import isUndefined from '@polkadot/util/is/undefined'; +import isNull from '@polkadot/util/is/null'; + +function anyMethodToDisplay (methods: SectionItems) { + if (isUndefined(methods) || isNull(methods)) { + return false; + } + + return Object + .keys(methods) + .filter((name) => { + const { isDeprecated, isHidden } = methods[name]; + + return !isDeprecated && !isHidden; + }) + .length !== 0; +} + +export function shouldDisplaySection (section: Section, type: SectionVisibilityAll) { + if (isUndefined(section)) { + return false; + } + + const methods = section[type]; + + return !section.isDeprecated && !section.isHidden && anyMethodToDisplay(methods); +} diff --git a/packages/ui-app/src/InputExtrinsic/types.d.ts b/packages/ui-app/src/util/types.d.ts similarity index 86% rename from packages/ui-app/src/InputExtrinsic/types.d.ts rename to packages/ui-app/src/util/types.d.ts index 836276f768..1fa35af2fc 100644 --- a/packages/ui-app/src/InputExtrinsic/types.d.ts +++ b/packages/ui-app/src/util/types.d.ts @@ -10,3 +10,5 @@ export type DropdownOption = { }; export type DropdownOptions = Array; + +export type SectionVisibilityAll = 'private' | 'public';