From 21b358d89a5842e33822c94941a30177136cff6a Mon Sep 17 00:00:00 2001 From: mahula Date: Fri, 7 Apr 2023 12:15:15 +0200 Subject: [PATCH 1/7] add unit tests for federation visualization in admin interface --- .../FederationVisualizeItem.spec.js | 136 ++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 admin/src/components/Fedaration/FederationVisualizeItem.spec.js diff --git a/admin/src/components/Fedaration/FederationVisualizeItem.spec.js b/admin/src/components/Fedaration/FederationVisualizeItem.spec.js new file mode 100644 index 000000000..f865c3b08 --- /dev/null +++ b/admin/src/components/Fedaration/FederationVisualizeItem.spec.js @@ -0,0 +1,136 @@ +import { mount } from '@vue/test-utils' +import FederationVisualizeItem from './FederationVisualizeItem.vue' + +const localVue = global.localVue +const today = new Date() +const createdDate = new Date() +createdDate.setDate(createdDate.getDate() - 3) + +let propsData = { + item: { + id: 7590, + foreign: false, + publicKey: 'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7', + url: 'http://localhost/api/api/2_0', + lastAnnouncedAt: createdDate, + verifiedAt: today, + lastErrorAt: null, + createdAt: createdDate, + updatedAt: null, + }, +} + +const mocks = { + $i18n: { + locale: 'en', + }, +} + +describe('FederationVisualizeItem', () => { + let wrapper + + const Wrapper = () => { + return mount(FederationVisualizeItem, { localVue, mocks, propsData }) + } + + describe('mount', () => { + beforeEach(() => { + wrapper = Wrapper() + }) + + it('renders the component', () => { + expect(wrapper.find('div.federation-visualize-item').exists()).toBe(true) + }) + + describe('rendering item properties', () => { + it('has the url', () => { + expect(wrapper.find('.row > div:nth-child(2) > div').text()).toBe( + 'http://localhost/api/api/2_0', + ) + }) + + it('has the public key', () => { + expect(wrapper.find('.row > div:nth-child(2) > small').text()).toContain( + 'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7'.substring(0, 26), + ) + }) + + describe('verified item', () => { + it('has the check icon', () => { + expect(wrapper.find('svg.bi-check').exists()).toBe(true) + }) + + it('has the text variant "success"', () => { + expect(wrapper.find('.text-success').exists()).toBe(true) + }) + }) + + describe('not verified item', () => { + beforeEach(() => { + propsData = { + item: { + id: 7590, + foreign: false, + publicKey: 'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7', + url: 'http://localhost/api/api/2_0', + lastAnnouncedAt: createdDate, + verifiedAt: null, + lastErrorAt: null, + createdAt: createdDate, + updatedAt: null, + }, + } + wrapper = Wrapper() + }) + + it('has the x-circle icon', () => { + expect(wrapper.find('svg.bi-x-circle').exists()).toBe(true) + }) + + it('has the text variant "danger"', () => { + expect(wrapper.find('.text-danger').exists()).toBe(true) + }) + }) + + // zwei Varianten: '' bei null und + describe('with different locales (de, en, fr, es, nl)', () => { + it('computes the lastAnnouncedAt time', () => { + // expect(wrapper.find('.row > div:nth-child(3)').text()).toBe('3 days ago') + wrapper.vm.$i18n.locale = 'de' + wrapper = Wrapper() + expect(wrapper.vm.lastAnnouncedAt).toContain('vor 3 Tagen') + + wrapper.vm.$i18n.locale = 'fr' + wrapper = Wrapper() + expect(wrapper.vm.lastAnnouncedAt).toContain('il y a 3 jours') + + wrapper.vm.$i18n.locale = 'es' + wrapper = Wrapper() + expect(wrapper.vm.lastAnnouncedAt).toContain('hace 3 días') + + wrapper.vm.$i18n.locale = 'nl' + wrapper = Wrapper() + expect(wrapper.vm.lastAnnouncedAt).toContain('3 dagen geleden') + }) + + it('computes the createdAt time', () => { + wrapper.vm.$i18n.locale = 'de' + wrapper = Wrapper() + expect(wrapper.vm.createdAt).toContain('vor 3 Tagen') + + wrapper.vm.$i18n.locale = 'fr' + wrapper = Wrapper() + expect(wrapper.vm.createdAt).toContain('il y a 3 jours') + + wrapper.vm.$i18n.locale = 'es' + wrapper = Wrapper() + expect(wrapper.vm.createdAt).toContain('hace 3 días') + + wrapper.vm.$i18n.locale = 'nl' + wrapper = Wrapper() + expect(wrapper.vm.createdAt).toContain('3 dagen geleden') + }) + }) + }) + }) +}) From 81eed73922ba3f4dd68a266857cb6080b56123a8 Mon Sep 17 00:00:00 2001 From: mahula Date: Fri, 7 Apr 2023 12:15:15 +0200 Subject: [PATCH 2/7] add unit tests for federation visualization in admin interface --- .../FederationVisualizeItem.spec.js | 73 +++++++++++++++---- .../FederationVisualizeitem.spec.js | 44 ----------- 2 files changed, 60 insertions(+), 57 deletions(-) delete mode 100644 admin/src/components/Fedaration/FederationVisualizeitem.spec.js diff --git a/admin/src/components/Fedaration/FederationVisualizeItem.spec.js b/admin/src/components/Fedaration/FederationVisualizeItem.spec.js index f865c3b08..aa829209a 100644 --- a/admin/src/components/Fedaration/FederationVisualizeItem.spec.js +++ b/admin/src/components/Fedaration/FederationVisualizeItem.spec.js @@ -92,43 +92,90 @@ describe('FederationVisualizeItem', () => { }) }) - // zwei Varianten: '' bei null und - describe('with different locales (de, en, fr, es, nl)', () => { - it('computes the lastAnnouncedAt time', () => { - // expect(wrapper.find('.row > div:nth-child(3)').text()).toBe('3 days ago') + // describe('with different locales (de, en, fr, es, nl)', () => { + describe('lastAnnouncedAt', () => { + it('computes the time string for different locales (de, en, fr, es, nl)', () => { wrapper.vm.$i18n.locale = 'de' wrapper = Wrapper() - expect(wrapper.vm.lastAnnouncedAt).toContain('vor 3 Tagen') + expect(wrapper.vm.lastAnnouncedAt).toBe('vor 3 Tagen') wrapper.vm.$i18n.locale = 'fr' wrapper = Wrapper() - expect(wrapper.vm.lastAnnouncedAt).toContain('il y a 3 jours') + expect(wrapper.vm.lastAnnouncedAt).toBe('il y a 3 jours') wrapper.vm.$i18n.locale = 'es' wrapper = Wrapper() - expect(wrapper.vm.lastAnnouncedAt).toContain('hace 3 días') + expect(wrapper.vm.lastAnnouncedAt).toBe('hace 3 días') wrapper.vm.$i18n.locale = 'nl' wrapper = Wrapper() - expect(wrapper.vm.lastAnnouncedAt).toContain('3 dagen geleden') + expect(wrapper.vm.lastAnnouncedAt).toBe('3 dagen geleden') }) - it('computes the createdAt time', () => { + describe('lastAnnouncedAt == null', () => { + beforeEach(() => { + propsData = { + item: { + id: 7590, + foreign: false, + publicKey: 'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7', + url: 'http://localhost/api/api/2_0', + lastAnnouncedAt: null, + verifiedAt: null, + lastErrorAt: null, + createdAt: createdDate, + updatedAt: null, + }, + } + wrapper = Wrapper() + }) + + it('computes empty string', async () => { + expect(wrapper.vm.lastAnnouncedAt).toBe('') + }) + }) + }) + + describe('createdAt', () => { + it('computes the time string for different locales (de, en, fr, es, nl)', () => { wrapper.vm.$i18n.locale = 'de' wrapper = Wrapper() - expect(wrapper.vm.createdAt).toContain('vor 3 Tagen') + expect(wrapper.vm.createdAt).toBe('vor 3 Tagen') wrapper.vm.$i18n.locale = 'fr' wrapper = Wrapper() - expect(wrapper.vm.createdAt).toContain('il y a 3 jours') + expect(wrapper.vm.createdAt).toBe('il y a 3 jours') wrapper.vm.$i18n.locale = 'es' wrapper = Wrapper() - expect(wrapper.vm.createdAt).toContain('hace 3 días') + expect(wrapper.vm.createdAt).toBe('hace 3 días') wrapper.vm.$i18n.locale = 'nl' wrapper = Wrapper() - expect(wrapper.vm.createdAt).toContain('3 dagen geleden') + expect(wrapper.vm.createdAt).toBe('3 dagen geleden') + }) + + describe('createdAt == null', () => { + beforeEach(() => { + propsData = { + item: { + id: 7590, + foreign: false, + publicKey: 'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7', + url: 'http://localhost/api/api/2_0', + lastAnnouncedAt: createdDate, + verifiedAt: null, + lastErrorAt: null, + createdAt: null, + updatedAt: null, + }, + } + wrapper = Wrapper() + }) + + it('computes empty string', async () => { + expect(wrapper.vm.createdAt).toBe('') + }) }) }) }) diff --git a/admin/src/components/Fedaration/FederationVisualizeitem.spec.js b/admin/src/components/Fedaration/FederationVisualizeitem.spec.js deleted file mode 100644 index d82a12f33..000000000 --- a/admin/src/components/Fedaration/FederationVisualizeitem.spec.js +++ /dev/null @@ -1,44 +0,0 @@ -import { mount } from '@vue/test-utils' -import FederationVisualizeItem from './FederationVisualizeItem.vue' - -const localVue = global.localVue - -const mocks = { - $t: (key) => key, - $i18n: { - locale: 'de', - t: (key) => key, - }, -} - -describe('FederationVisualizeItem', () => { - let wrapper - - const propsData = { - item: { - id: 7590, - foreign: false, - publicKey: 'eaf6a426b24fd54f8fbae11c17700fc595080ca25159579c63d38dbc64284ba7', - url: 'http://localhost/api/api/2_0', - lastAnnouncedAt: null, - verifiedAt: null, - lastErrorAt: null, - createdAt: '2023-03-29T04:46:38.823Z', - updatedAt: null, - }, - } - - const Wrapper = () => { - return mount(FederationVisualizeItem, { localVue, mocks, propsData }) - } - - describe('mount', () => { - beforeEach(() => { - wrapper = Wrapper() - }) - - it('renders the component', () => { - expect(wrapper.find('div.federation-visualize-item').exists()).toBe(true) - }) - }) -}) From 9435c3620f09b8baeffa904c00509bce1ee86283 Mon Sep 17 00:00:00 2001 From: mahula Date: Fri, 7 Apr 2023 15:19:29 +0200 Subject: [PATCH 3/7] add mocks and button unit test to federation visualization in admin interface --- admin/src/pages/FederationVisualize.spec.js | 76 +++++++++++++++++++-- admin/src/pages/FederationVisualize.vue | 1 + 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/admin/src/pages/FederationVisualize.spec.js b/admin/src/pages/FederationVisualize.spec.js index 867f87ecd..7b4036689 100644 --- a/admin/src/pages/FederationVisualize.spec.js +++ b/admin/src/pages/FederationVisualize.spec.js @@ -1,30 +1,98 @@ import { mount } from '@vue/test-utils' import FederationVisualize from './FederationVisualize' +import VueApollo from 'vue-apollo' +import { createMockClient } from 'mock-apollo-client' +import { getCommunities } from '@/graphql/getCommunities' + +const mockClient = createMockClient() +const apolloProvider = new VueApollo({ + defaultClient: mockClient, +}) const localVue = global.localVue +localVue.use(VueApollo) + const mocks = { $t: (key) => key, + // $t: jest.fn((t) => t), + $d: jest.fn((d) => d), $i18n: { - locale: 'de', + locale: 'en', t: (key) => key, }, } -describe('Overview', () => { +const defaultData = () => { + return { + getCommunities: [ + { + id: 1776, + foreign: true, + publicKey: 'c7ca9e742421bb167b8666cb78f90b40c665b8f35db8f001988d44dbb3ce8527', + url: 'http://localhost/api/api/2_0', + lastAnnouncedAt: '2023-04-07T12:27:24.037Z', + verifiedAt: null, + lastErrorAt: null, + createdAt: '2023-04-07T11:45:06.254Z', + updatedAt: null, + __typename: 'Community', + }, + { + id: 1775, + foreign: true, + publicKey: 'c7ca9e742421bb167b8666cb78f90b40c665b8f35db8f001988d44dbb3ce8527', + url: 'http://localhost/api/api/1_1', + lastAnnouncedAt: '2023-04-07T12:27:24.023Z', + verifiedAt: null, + lastErrorAt: null, + createdAt: '2023-04-07T11:45:06.234Z', + updatedAt: null, + __typename: 'Community', + }, + { + id: 1774, + foreign: true, + publicKey: 'c7ca9e742421bb167b8666cb78f90b40c665b8f35db8f001988d44dbb3ce8527', + url: 'http://localhost/api/api/1_0', + lastAnnouncedAt: '2023-04-07T12:27:24.009Z', + verifiedAt: null, + lastErrorAt: null, + createdAt: '2023-04-07T11:45:06.218Z', + updatedAt: null, + __typename: 'Community', + }, + ], + } +} + +describe('FederationVisualize', () => { let wrapper + const getCommunitiesMock = jest.fn() + + mockClient.setRequestHandler( + getCommunities, + getCommunitiesMock + .mockRejectedValueOnce({ message: 'Ouch!' }) + .mockResolvedValue({ data: defaultData() }), + ) const Wrapper = () => { - return mount(FederationVisualize, { localVue, mocks }) + return mount(FederationVisualize, { localVue, mocks, apolloProvider }) } describe('mount', () => { beforeEach(() => { + jest.clearAllMocks() wrapper = Wrapper() }) - it('has a DIV element with the class.component-confirm-register-mail', () => { + it('has a DIV element with the class "federation-visualize"', () => { expect(wrapper.find('div.federation-visualize').exists()).toBe(true) }) + + it('has a refresh button', () => { + expect(wrapper.find('[data-test="federation-communities-refresh-btn"]').exists()).toBe(true) + }) }) }) diff --git a/admin/src/pages/FederationVisualize.vue b/admin/src/pages/FederationVisualize.vue index 25c1b11a3..b5f590393 100644 --- a/admin/src/pages/FederationVisualize.vue +++ b/admin/src/pages/FederationVisualize.vue @@ -8,6 +8,7 @@ font-scale="2" :animation="animation" @click="$apollo.queries.GetCommunities.refresh()" + data-test="federation-communities-refresh-btn" > From 3e277bcb796692d307fe5eb7f2f58c5ec6927f54 Mon Sep 17 00:00:00 2001 From: mahula Date: Fri, 7 Apr 2023 15:59:50 +0200 Subject: [PATCH 4/7] adapt community resolver unit tests to changes --- .../resolver/CommunityResolver.test.ts | 53 ++++++++++--------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/backend/src/graphql/resolver/CommunityResolver.test.ts b/backend/src/graphql/resolver/CommunityResolver.test.ts index 5b4b26cad..c25c72432 100644 --- a/backend/src/graphql/resolver/CommunityResolver.test.ts +++ b/backend/src/graphql/resolver/CommunityResolver.test.ts @@ -36,6 +36,7 @@ describe('CommunityResolver', () => { let foreignCom1: DbCommunity let foreignCom2: DbCommunity let foreignCom3: DbCommunity + describe('with empty list', () => { it('returns no community entry', async () => { // const result: Community[] = await query({ query: getCommunities }) @@ -77,19 +78,19 @@ describe('CommunityResolver', () => { await DbCommunity.insert(homeCom3) }) - it('returns three home-community entries', async () => { + it('returns 3 home-community entries', async () => { await expect(query({ query: getCommunities })).resolves.toMatchObject({ data: { getCommunities: [ { - id: 1, - foreign: homeCom1.foreign, + id: 3, + foreign: homeCom3.foreign, publicKey: expect.stringMatching('publicKey-HomeCommunity'), - url: expect.stringMatching('http://localhost/api/1_0'), + url: expect.stringMatching('http://localhost/api/2_0'), lastAnnouncedAt: null, verifiedAt: null, lastErrorAt: null, - createdAt: homeCom1.createdAt.toISOString(), + createdAt: homeCom3.createdAt.toISOString(), updatedAt: null, }, { @@ -104,14 +105,14 @@ describe('CommunityResolver', () => { updatedAt: null, }, { - id: 3, - foreign: homeCom3.foreign, + id: 1, + foreign: homeCom1.foreign, publicKey: expect.stringMatching('publicKey-HomeCommunity'), - url: expect.stringMatching('http://localhost/api/2_0'), + url: expect.stringMatching('http://localhost/api/1_0'), lastAnnouncedAt: null, verifiedAt: null, lastErrorAt: null, - createdAt: homeCom3.createdAt.toISOString(), + createdAt: homeCom1.createdAt.toISOString(), updatedAt: null, }, ], @@ -149,19 +150,19 @@ describe('CommunityResolver', () => { await DbCommunity.insert(foreignCom3) }) - it('returns 3x home and 3x foreign-community entries', async () => { + it('returns 3 home community and 3 foreign community entries', async () => { await expect(query({ query: getCommunities })).resolves.toMatchObject({ data: { getCommunities: [ { - id: 1, - foreign: homeCom1.foreign, + id: 3, + foreign: homeCom3.foreign, publicKey: expect.stringMatching('publicKey-HomeCommunity'), - url: expect.stringMatching('http://localhost/api/1_0'), + url: expect.stringMatching('http://localhost/api/2_0'), lastAnnouncedAt: null, verifiedAt: null, lastErrorAt: null, - createdAt: homeCom1.createdAt.toISOString(), + createdAt: homeCom3.createdAt.toISOString(), updatedAt: null, }, { @@ -176,25 +177,25 @@ describe('CommunityResolver', () => { updatedAt: null, }, { - id: 3, - foreign: homeCom3.foreign, + id: 1, + foreign: homeCom1.foreign, publicKey: expect.stringMatching('publicKey-HomeCommunity'), - url: expect.stringMatching('http://localhost/api/2_0'), + url: expect.stringMatching('http://localhost/api/1_0'), lastAnnouncedAt: null, verifiedAt: null, lastErrorAt: null, - createdAt: homeCom3.createdAt.toISOString(), + createdAt: homeCom1.createdAt.toISOString(), updatedAt: null, }, { - id: 4, - foreign: foreignCom1.foreign, + id: 6, + foreign: foreignCom3.foreign, publicKey: expect.stringMatching('publicKey-ForeignCommunity'), - url: expect.stringMatching('http://remotehost/api/1_0'), + url: expect.stringMatching('http://remotehost/api/1_2'), lastAnnouncedAt: null, verifiedAt: null, lastErrorAt: null, - createdAt: foreignCom1.createdAt.toISOString(), + createdAt: foreignCom3.createdAt.toISOString(), updatedAt: null, }, { @@ -209,14 +210,14 @@ describe('CommunityResolver', () => { updatedAt: null, }, { - id: 6, - foreign: foreignCom3.foreign, + id: 4, + foreign: foreignCom1.foreign, publicKey: expect.stringMatching('publicKey-ForeignCommunity'), - url: expect.stringMatching('http://remotehost/api/1_2'), + url: expect.stringMatching('http://remotehost/api/1_0'), lastAnnouncedAt: null, verifiedAt: null, lastErrorAt: null, - createdAt: foreignCom3.createdAt.toISOString(), + createdAt: foreignCom1.createdAt.toISOString(), updatedAt: null, }, ], From 206dcda7750ad1aebce63e44b746610c68224fed Mon Sep 17 00:00:00 2001 From: mahula Date: Fri, 7 Apr 2023 16:22:28 +0200 Subject: [PATCH 5/7] use locales array in federation visualization item component --- .../Fedaration/FederationVisualizeItem.vue | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/admin/src/components/Fedaration/FederationVisualizeItem.vue b/admin/src/components/Fedaration/FederationVisualizeItem.vue index ba23c0433..ebcdb8d27 100644 --- a/admin/src/components/Fedaration/FederationVisualizeItem.vue +++ b/admin/src/components/Fedaration/FederationVisualizeItem.vue @@ -15,6 +15,8 @@ import { formatDistanceToNow } from 'date-fns' import { de, en, fr, es, nl } from 'date-fns/locale' +const locales = { en, de, es, fr, nl } + export default { name: 'FederationVisualizeItem', props: { @@ -37,26 +39,12 @@ export default { variant() { return this.verified ? 'success' : 'danger' }, - fnsLocale() { - switch (this.locale) { - case 'de': - return de - case 'es': - return es - case 'fr': - return fr - case 'nl': - return nl - default: - return en - } - }, lastAnnouncedAt() { if (this.item.lastAnnouncedAt) { return formatDistanceToNow(new Date(this.item.lastAnnouncedAt), { includeSecond: true, addSuffix: true, - locale: this.fnsLocale, + locale: locales[this.locale], }) } return '' @@ -66,7 +54,7 @@ export default { return formatDistanceToNow(new Date(this.item.createdAt), { includeSecond: true, addSuffix: true, - locale: this.fnsLocale, + locale: locales[this.locale], }) } return '' From ab8bec8a4eed93ef54d4aefa6f998a46317e68a5 Mon Sep 17 00:00:00 2001 From: mahula Date: Fri, 7 Apr 2023 16:38:48 +0200 Subject: [PATCH 6/7] remove oldPublicKey from federation visualization item component --- admin/src/components/Fedaration/FederationVisualizeItem.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/admin/src/components/Fedaration/FederationVisualizeItem.vue b/admin/src/components/Fedaration/FederationVisualizeItem.vue index ebcdb8d27..faace7da1 100644 --- a/admin/src/components/Fedaration/FederationVisualizeItem.vue +++ b/admin/src/components/Fedaration/FederationVisualizeItem.vue @@ -24,7 +24,6 @@ export default { }, data() { return { - oldPublicKey: '', formatDistanceToNow, locale: this.$i18n.locale, } From adcff96e293e87208d1e0fc017ab61c53af07ad9 Mon Sep 17 00:00:00 2001 From: mahula Date: Fri, 7 Apr 2023 16:53:45 +0200 Subject: [PATCH 7/7] transform animation to computed method --- admin/src/pages/FederationVisualize.vue | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/admin/src/pages/FederationVisualize.vue b/admin/src/pages/FederationVisualize.vue index b5f590393..383cf064d 100644 --- a/admin/src/pages/FederationVisualize.vue +++ b/admin/src/pages/FederationVisualize.vue @@ -44,24 +44,24 @@ export default { oldPublicKey: '', communities: [], icon: '', - animation: '', } }, + computed: { + animation() { + return this.$apollo.queries.GetCommunities.loading ? 'spin' : '' + }, + }, apollo: { GetCommunities: { fetchPolicy: 'network-only', query() { - this.animation = 'spin' - return getCommunities }, update({ getCommunities }) { this.communities = getCommunities - this.animation = '' }, error({ message }) { this.toastError(message) - this.animation = '' }, }, },