Skip to content

Commit da1b055

Browse files
edwhclaude
andcommitted
Restore GroupsTable in GroupsRequiringModeration (was stubbed with TODO)
PR #744 changed GroupsTable's prop API from `groups` (an array of group objects) to `groupids` (an array of group ids), but the migration of GroupsRequiringModeration was left half-finished: the template had a literal 'TODO' string visible to admins / NCs and the original `<GroupsTable :groups="groups" approve />` was commented out next to it. Render the table with `:groupids="groupIds" :approve="true"` and add a computed `groupIds` derived from the moderation store (which uses `idgroups`, but fall back to `id` for safety). Tests cover: - renders GroupsTable (not literal TODO) when groups exist - renders nothing when there are no groups - filters by the networks prop Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 9beecf1 commit da1b055

2 files changed

Lines changed: 109 additions & 2 deletions

File tree

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
import Vue from "vue"
2+
import { BootstrapVue } from 'bootstrap-vue'
3+
Vue.use(BootstrapVue)
4+
5+
import { mount, createLocalVue } from '@vue/test-utils'
6+
import Vuex from 'vuex'
7+
import LangMixin from 'resources/js/mixins/lang.js'
8+
import GroupsRequiringModeration from './GroupsRequiringModeration.vue'
9+
10+
const localVue = createLocalVue()
11+
localVue.use(Vuex)
12+
13+
function makeStore(moderate) {
14+
return new Vuex.Store({
15+
modules: {
16+
groups: {
17+
namespaced: true,
18+
getters: {
19+
getModerate: () => moderate || {},
20+
},
21+
actions: {
22+
getModerationRequired: () => Promise.resolve(),
23+
}
24+
}
25+
}
26+
})
27+
}
28+
29+
async function flush(wrapper) {
30+
// mounted() awaits a store dispatch then calls $nextTick to flip `loaded`.
31+
// Wait long enough for both to settle.
32+
await new Promise(resolve => setTimeout(resolve, 0))
33+
await wrapper.vm.$nextTick()
34+
await wrapper.vm.$nextTick()
35+
}
36+
37+
const groupsTableStub = {
38+
name: 'GroupsTable',
39+
// Declare approve as Boolean so Vue applies its boolean prop coercion
40+
// (presence-without-value becomes true) — matches the real component.
41+
props: { groupids: { type: Array }, approve: { type: Boolean, default: false } },
42+
template: '<div class="stub-groups-table" />'
43+
}
44+
45+
test('renders GroupsTable (not literal TODO) when there are groups awaiting moderation', async () => {
46+
const store = makeStore({
47+
1: { idgroups: 1, name: 'G1', networks: [] },
48+
2: { idgroups: 2, name: 'G2', networks: [] },
49+
})
50+
const wrapper = mount(GroupsRequiringModeration, {
51+
localVue,
52+
store,
53+
mixins: [LangMixin],
54+
stubs: { GroupsTable: groupsTableStub },
55+
})
56+
57+
await flush(wrapper)
58+
59+
// Must not display the literal "TODO" placeholder
60+
expect(wrapper.text()).not.toContain('TODO')
61+
62+
// Must render a GroupsTable with the moderation group ids and approve flag
63+
const stub = wrapper.findComponent(groupsTableStub)
64+
expect(stub.exists()).toBe(true)
65+
expect(stub.props('groupids')).toEqual([1, 2])
66+
expect(stub.props('approve')).toBe(true)
67+
})
68+
69+
test('renders nothing when there are no groups to moderate', async () => {
70+
const store = makeStore({})
71+
const wrapper = mount(GroupsRequiringModeration, {
72+
localVue,
73+
store,
74+
mixins: [LangMixin],
75+
stubs: { GroupsTable: groupsTableStub },
76+
})
77+
78+
await flush(wrapper)
79+
80+
expect(wrapper.findComponent(groupsTableStub).exists()).toBe(false)
81+
expect(wrapper.text()).not.toContain('TODO')
82+
})
83+
84+
test('filters groups by the networks prop when supplied', async () => {
85+
const store = makeStore({
86+
1: { idgroups: 1, name: 'In', networks: [{ id: 10 }] },
87+
2: { idgroups: 2, name: 'Out', networks: [{ id: 99 }] },
88+
3: { idgroups: 3, name: 'Also in', networks: [{ id: 10 }, { id: 20 }] },
89+
})
90+
const wrapper = mount(GroupsRequiringModeration, {
91+
localVue,
92+
store,
93+
mixins: [LangMixin],
94+
propsData: { networks: [10] },
95+
stubs: { GroupsTable: groupsTableStub },
96+
})
97+
98+
await flush(wrapper)
99+
100+
const stub = wrapper.findComponent(groupsTableStub)
101+
expect(stub.exists()).toBe(true)
102+
expect(stub.props('groupids').sort()).toEqual([1, 3])
103+
})

resources/js/components/GroupsRequiringModeration.vue

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
<template>
22
<div v-if="loaded && groups.length">
33
<section class="table-section" id="groups-1">
4-
TODO
5-
<!-- <GroupsTable :groups="groups" approve />-->
4+
<GroupsTable :groupids="groupIds" approve />
65
</section>
76
</div>
87
</template>
@@ -46,6 +45,11 @@ export default {
4645
4746
return ret
4847
},
48+
groupIds() {
49+
// GroupsTable's `groupids` prop is the ids it should render — the
50+
// moderate store uses { idgroups, id } (via newToOld), so accept either.
51+
return this.groups.map(g => g.idgroups || g.id)
52+
},
4953
},
5054
async mounted() {
5155
try {

0 commit comments

Comments
 (0)