Skip to content
代码片段 群组 项目
提交 066ca76b 编辑于 作者: Wu Jeremy's avatar Wu Jeremy 提交者: Anna Vovchenko
浏览文件

Feat: implement rss functionality for profile edit overflow menu

* Add RSS subscription link to the newly introduced overflow menu.
* Add test cases against the addition.
上级 13e8fe4f
No related branches found
No related tags found
无相关合并请求
...@@ -11,13 +11,17 @@ export default { ...@@ -11,13 +11,17 @@ export default {
type: String, type: String,
required: true, required: true,
}, },
rssSubscriptionPath: {
type: String,
required: true,
},
}, },
data() { data() {
return { return {
// Only implement the copy function in MR for now // Only implement the copy function and RSS subscription in MR for now
// https://gitlab.com/gitlab-org/gitlab/-/merge_requests/122971 // https://gitlab.com/gitlab-org/gitlab/-/merge_requests/122971
// The rest will be implemented in the upcoming MR. // The rest will be implemented in the upcoming MR.
dropdownItems: [ defaultDropdownItems: [
{ {
action: this.onUserIdCopy, action: this.onUserIdCopy,
text: sprintf(this.$options.i18n.userId, { id: this.userId }), text: sprintf(this.$options.i18n.userId, { id: this.userId }),
...@@ -28,6 +32,23 @@ export default { ...@@ -28,6 +32,23 @@ export default {
], ],
}; };
}, },
computed: {
dropdownItems() {
if (this.rssSubscriptionPath) {
return [
...this.defaultDropdownItems,
{
href: this.rssSubscriptionPath,
text: this.$options.i18n.rssSubscribe,
extraAttrs: {
'data-testid': 'user-profile-rss-subscription-link',
},
},
];
}
return this.defaultDropdownItems;
},
},
methods: { methods: {
onUserIdCopy() { onUserIdCopy() {
this.$toast.show(this.$options.i18n.userIdCopied); this.$toast.show(this.$options.i18n.userIdCopied);
...@@ -36,6 +57,7 @@ export default { ...@@ -36,6 +57,7 @@ export default {
i18n: { i18n: {
userId: s__('UserProfile|Copy user ID: %{id}'), userId: s__('UserProfile|Copy user ID: %{id}'),
userIdCopied: s__('UserProfile|User ID copied to clipboard'), userIdCopied: s__('UserProfile|User ID copied to clipboard'),
rssSubscribe: s__('UserProfile|Subscribe'),
}, },
}; };
</script> </script>
......
...@@ -7,7 +7,7 @@ export const initUserActionsApp = () => { ...@@ -7,7 +7,7 @@ export const initUserActionsApp = () => {
if (!mountingEl) return false; if (!mountingEl) return false;
const { userId } = mountingEl.dataset; const { userId, rssSubscriptionPath } = mountingEl.dataset;
Vue.use(GlToast); Vue.use(GlToast);
...@@ -18,6 +18,7 @@ export const initUserActionsApp = () => { ...@@ -18,6 +18,7 @@ export const initUserActionsApp = () => {
return createElement(UserActionsApp, { return createElement(UserActionsApp, {
props: { props: {
userId, userId,
rssSubscriptionPath,
}, },
}); });
}, },
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
= s_("UserProfile|Edit profile") = s_("UserProfile|Edit profile")
= render 'users/view_gpg_keys' = render 'users/view_gpg_keys'
= render 'users/view_user_in_admin_area' = render 'users/view_user_in_admin_area'
.js-user-profile-actions{ data: { user_id: @user.id } } .js-user-profile-actions{ data: { user_id: @user.id, rss_subscription_path: can?(current_user, :read_user_profile, @user) ? user_path(@user, rss_url_options) : '' } }
- else - else
= render layout: 'users/cover_controls' do = render layout: 'users/cover_controls' do
- if @user == current_user - if @user == current_user
......
...@@ -6,28 +6,53 @@ ...@@ -6,28 +6,53 @@
let(:user) { create(:user) } let(:user) { create(:user) }
let(:path) { user_path(create(:user)) } let(:path) { user_path(create(:user)) }
before do describe 'with "user_profile_overflow_menu_vue" feature flag off' do
stub_feature_flags(user_profile_overflow_menu_vue: false)
end
context 'when signed in' do
before do before do
sign_in(user) stub_feature_flags(user_profile_overflow_menu_vue: false)
visit path
end end
it_behaves_like "it has an RSS button with current_user's feed token" context 'when signed in' do
end before do
sign_in(user)
visit path
end
context 'when signed out' do it_behaves_like "it has an RSS button with current_user's feed token"
before do
visit path
end end
it_behaves_like "it has an RSS button without a feed token" context 'when signed out' do
before do
visit path
end
it_behaves_like "it has an RSS button without a feed token"
end
end end
# TODO: implement tests before the FF "user_profile_overflow_menu_vue" is turned on describe 'with "user_profile_overflow_menu_vue" feature flag on', :js do
# See: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/122971 context 'when signed in' do
# Related Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/416974 before do
sign_in(user)
visit path
end
it 'shows the RSS link with overflow menu' do
find('[data-testid="base-dropdown-toggle"').click
expect(page).to have_link 'Subscribe', href: /feed_token=glft-.*-#{user.id}/
end
end
context 'when signed out' do
before do
visit path
end
it 'has an RSS without a feed token' do
find('[data-testid="base-dropdown-toggle"').click
expect(page).not_to have_link 'Subscribe', href: /feed_token=glft-.*-#{user.id}/
end
end
end
end end
...@@ -6,11 +6,13 @@ describe('User Actions App', () => { ...@@ -6,11 +6,13 @@ describe('User Actions App', () => {
let wrapper; let wrapper;
const USER_ID = 'test-id'; const USER_ID = 'test-id';
const DEFAULT_SUBSCRIPTION_PATH = '';
const createWrapper = (propsData = {}) => { const createWrapper = (propsData = {}) => {
wrapper = mountExtended(UserActionsApp, { wrapper = mountExtended(UserActionsApp, {
propsData: { propsData: {
userId: USER_ID, userId: USER_ID,
rssSubscriptionPath: DEFAULT_SUBSCRIPTION_PATH,
...propsData, ...propsData,
}, },
}); });
...@@ -19,15 +21,25 @@ describe('User Actions App', () => { ...@@ -19,15 +21,25 @@ describe('User Actions App', () => {
const findDropdown = () => wrapper.findComponent(GlDisclosureDropdown); const findDropdown = () => wrapper.findComponent(GlDisclosureDropdown);
const findActions = () => wrapper.findAllByTestId('disclosure-dropdown-item'); const findActions = () => wrapper.findAllByTestId('disclosure-dropdown-item');
const findAction = (position = 0) => findActions().at(position); const findAction = (position = 0) => findActions().at(position);
const findSubscriptionLink = () => wrapper.findByTestId('user-profile-rss-subscription-link');
it('shows dropdown', () => { it('shows dropdown', () => {
createWrapper(); createWrapper();
expect(findDropdown().exists()).toBe(true); expect(findDropdown().exists()).toBe(true);
}); });
it('shows actions correctly', () => { describe('shows user action items', () => {
createWrapper(); it('should show items without RSS subscriptions', () => {
expect(findActions()).toHaveLength(1); createWrapper();
expect(findActions()).toHaveLength(1);
});
it('should show items with RSS subscriptions', () => {
createWrapper({
rssSubscriptionPath: '/test/path',
});
expect(findActions()).toHaveLength(2);
});
}); });
it('shows copy user id action', () => { it('shows copy user id action', () => {
...@@ -35,4 +47,17 @@ describe('User Actions App', () => { ...@@ -35,4 +47,17 @@ describe('User Actions App', () => {
expect(findAction().text()).toBe(`Copy user ID: ${USER_ID}`); expect(findAction().text()).toBe(`Copy user ID: ${USER_ID}`);
expect(findAction().findComponent('button').attributes('data-clipboard-text')).toBe(USER_ID); expect(findAction().findComponent('button').attributes('data-clipboard-text')).toBe(USER_ID);
}); });
it('shows subscription link when subscription url was presented', () => {
const testSubscriptionPath = '/test/path';
createWrapper({
rssSubscriptionPath: testSubscriptionPath,
});
const rssLink = findSubscriptionLink();
expect(rssLink.exists()).toBe(true);
expect(rssLink.attributes('href')).toBe(testSubscriptionPath);
expect(rssLink.text()).toBe('Subscribe');
});
}); });
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册