From a54dc052dea6236b6dd9f36bc1ae4c53f0e68a42 Mon Sep 17 00:00:00 2001 From: Anthony Law Date: Fri, 21 Oct 2022 23:44:23 +0800 Subject: [PATCH] [explorer] task: hide hash lock section #1137 * [explorer] task: fix fetch hash lock logic in transaction info * [explorer] task: refactor isItemShown method, added unit test * [explorer] task: patch mixed-spaces-and-tabs fix * [explorer] task: refactor on hideEmptyData logic --- __tests__/store/transaction.spec.js | 58 ++++++++++++ __tests__/views/PageAssembler.spec.js | 113 +++++++++++++++++++++++ src/config/pages/transaction-detail.json | 2 + src/store/transaction.js | 12 ++- src/views/PageAssembler.vue | 15 ++- 5 files changed, 188 insertions(+), 12 deletions(-) create mode 100644 __tests__/store/transaction.spec.js create mode 100644 __tests__/views/PageAssembler.spec.js diff --git a/__tests__/store/transaction.spec.js b/__tests__/store/transaction.spec.js new file mode 100644 index 000000000..b4e313928 --- /dev/null +++ b/__tests__/store/transaction.spec.js @@ -0,0 +1,58 @@ +import Constants from '../../src/config/constants'; +import transaction from '../../src/store/transaction'; +import { TransactionType } from 'symbol-sdk'; + +describe('store/transaction', () => { + describe('action/getTransactionInfoByHash', () => { + const runBasicFetchHashLockTests = (transactionType, transactionName) => { + const context = { + dispatch: jest.fn(), + getters: { + info: { + setStore: jest.fn().mockReturnThis(), + initialFetch: jest.fn() + }, + hashLock: { + setStore: jest.fn().mockReturnThis(), + initialFetch: jest.fn() + }, + transactionDetail: { + transactionType + } + } + }; + + const isAggregateBonded = transactionType === TransactionType.AGGREGATE_BONDED; + + it(`${isAggregateBonded ? '' : 'skips '}fetch hash lock when transaction type is ${transactionName}`, async () => { + // Arrange: + const payload = { + transactionHash: '5E699B430581BE31A175952F88876166EAEE713FB05465F7CAC6B182F25B995F' + }; + + // Act: + await transaction.actions.getTransactionInfoByHash(context, payload); + + // Assert: + const { info, hashLock } = context.getters; + + expect(context.dispatch).toHaveBeenNthCalledWith(1, 'uninitializeDetail'); + + expect(info.setStore).toHaveBeenNthCalledWith(1, context); + expect(hashLock.setStore).toHaveBeenNthCalledWith(1, context); + + expect(info.initialFetch).toHaveBeenCalledWith(payload.transactionHash); + + if (isAggregateBonded) + expect(hashLock.initialFetch).toHaveBeenCalledWith(payload.transactionHash); + else + expect(hashLock.initialFetch).not.toHaveBeenCalled(); + }); + }; + + // Arrange: + Object.keys(Constants.TransactionType).forEach(type => { + runBasicFetchHashLockTests(Number(type), Constants.TransactionType[type]); + }); + }); +}); diff --git a/__tests__/views/PageAssembler.spec.js b/__tests__/views/PageAssembler.spec.js new file mode 100644 index 000000000..0b09a419f --- /dev/null +++ b/__tests__/views/PageAssembler.spec.js @@ -0,0 +1,113 @@ +import PageAssembler from '../../src/views/PageAssembler.vue'; +import { createLocalVue, shallowMount } from '@vue/test-utils'; +import Vuex from 'vuex'; + +const localVue = createLocalVue(); +localVue.use(Vuex); + +describe('views/PageAssembler', () => { + const createWrapper = () => { + const propsData = { + layout: 'flex', + schema: [{ + managerGetter: 'test/info' + }] + }; + + return shallowMount(PageAssembler, { + localVue, + propsData + }); + }; + describe('method', () => { + describe('isItemShown', () => { + const runBasicHideEmptyDataTests = (data, expectedResult) => { + const action = expectedResult ? 'renders' : 'hides'; + const condition = expectedResult ? 'non empty' : 'empty'; + const dataType = Array.isArray(data) ? 'array' : 'object'; + + it(`${action} item when hideEmptyData set true and data in ${dataType} is ${condition}`, () => { + // Arrange: + const wrapper = createWrapper(); + + const schemaConfig = { + hideEmptyData: true + }; + + jest.spyOn(wrapper.vm, 'getData').mockReturnValue(data); + + // Act: + const result = wrapper.vm.isItemShown(schemaConfig); + + // Assert: + expect(result).toBe(expectedResult); + }); + + }; + + const runItemShownTests = (schemaConfig, getter, expectedResult) => { + const action = expectedResult ? 'renders' : 'hides'; + const condition = expectedResult ? 'non errors' : 'errors'; + + it(`${action} item when ${Object.keys(schemaConfig)[0]} is set and getters has ${condition}`, () => { + // Arrange: + const wrapper = createWrapper(); + + jest.spyOn(wrapper.vm, 'getter').mockReturnValue(getter); + + // Act: + const result = wrapper.vm.isItemShown(schemaConfig); + + // Assert: + expect(result).toBe(expectedResult); + }); + }; + + runBasicHideEmptyDataTests([], false); + runBasicHideEmptyDataTests(['1'], true); + + runBasicHideEmptyDataTests({}, false); + runBasicHideEmptyDataTests({ test: '1'}, true); + + runItemShownTests( + { + hideDependOnGetter: 'test/info' + }, + { + error: true + }, + false + ); + + runItemShownTests( + { + hideDependOnGetter: 'test/info' + }, + { + error: false + }, + true + ); + + runItemShownTests( + { + hideOnError: true + }, + { + error: true + }, + false + ); + + runItemShownTests( + { + hideOnError: true + }, + { + error: false + }, + true + ); + }); + }); +}); diff --git a/src/config/pages/transaction-detail.json b/src/config/pages/transaction-detail.json index a2717e913..22b471da4 100644 --- a/src/config/pages/transaction-detail.json +++ b/src/config/pages/transaction-detail.json @@ -53,6 +53,8 @@ "managerGetter": "transaction/hashLock", "errorMessage": "transactionHashLockError", "pagination": "none", + "hideEmptyData": true, + "hideOnError": false, "fields": [ "endHeight", "ownerAddress", diff --git a/src/store/transaction.js b/src/store/transaction.js index 2c1973636..a65d34e8d 100644 --- a/src/store/transaction.js +++ b/src/store/transaction.js @@ -27,6 +27,7 @@ import { } from './manager'; import { filters, Constants } from '../config'; import { TransactionService } from '../infrastructure'; +import { TransactionType } from 'symbol-sdk'; const managers = [ new Pagination({ @@ -143,10 +144,15 @@ export default { context.getters.timeline.setStore(context).initialFetch(); }, - getTransactionInfoByHash (context, payload) { + async getTransactionInfoByHash (context, payload) { context.dispatch('uninitializeDetail'); - context.getters.info.setStore(context).initialFetch(payload.transactionHash); - context.getters.hashLock.setStore(context).initialFetch(payload.transactionHash); + await context.getters.info.setStore(context).initialFetch(payload.transactionHash); + + const hashLockDataSet = context.getters.hashLock.setStore(context); + + // fetch Hash lock info when transaction type is aggregate bonded transaction + if (context.getters.transactionDetail.transactionType === TransactionType.AGGREGATE_BONDED) + hashLockDataSet.initialFetch(payload.transactionHash); }, uninitializeDetail (context) { diff --git a/src/views/PageAssembler.vue b/src/views/PageAssembler.vue index 8a8dcdeb0..c8a343e83 100644 --- a/src/views/PageAssembler.vue +++ b/src/views/PageAssembler.vue @@ -95,7 +95,6 @@ export default { }, async mounted () { - console.log('initialize', this.storeNamespaces); await this.$store.dispatch('initialize', this.$route); if (this.storeNamespaces?.length) { for (const namespace of this.storeNamespaces) @@ -122,19 +121,17 @@ export default { }, isItemShown (item) { - if (this.getter(item.hideDependOnGetter)?.error) + if (this.getter(item.hideDependOnGetter)?.error) { return false; + } - if (item.hideEmptyData && ( - !this.getData(item) || ( - Array.isArray(this.getData(item)) && !this.getData(item)?.length - ) - ) - ) + if (item.hideEmptyData && Object.keys(this.getData(item)).length === 0) { return false; + } - if (item.hideOnError && this.getter(item.managerGetter)?.error) + if (item.hideOnError && this.getter(item.managerGetter)?.error) { return false; + } return true; },