Commit 3c19d44c authored by Himanshu Kapoor's avatar Himanshu Kapoor

Fix authored message when snippet is viewed publicly

Unauthenticated users cannot view author information for public
snippets. So for those cases, just display the creation time and omit
the author information. (Instead of omitting the entire message right
now due to a console error.)
parent c96920b5
......@@ -68,6 +68,11 @@ export default {
snippetHasBinary() {
return Boolean(this.snippet.blobs.find(blob => blob.binary));
},
authoredMessage() {
return this.snippet.author
? __('Authored %{timeago} by %{author}')
: __('Authored %{timeago}');
},
personalSnippetActions() {
return [
{
......@@ -178,8 +183,8 @@ export default {
</span>
<gl-icon :name="visibilityLevelIcon" :size="14" />
</div>
<div class="creator">
<gl-sprintf :message="__('Authored %{timeago} by %{author}')">
<div class="creator" data-testid="authored-message">
<gl-sprintf :message="authoredMessage">
<template #timeago>
<time-ago-tooltip
:time="snippet.createdAt"
......
---
title: Display authored message correctly on public snippets viewed by unauthenticated users
merge_request: 38614
author:
type: fixed
......@@ -3459,6 +3459,9 @@ msgstr ""
msgid "Author: %{author_name}"
msgstr ""
msgid "Authored %{timeago}"
msgstr ""
msgid "Authored %{timeago} by %{author}"
msgstr ""
......
......@@ -2,45 +2,18 @@ import SnippetHeader from '~/snippets/components/snippet_header.vue';
import DeleteSnippetMutation from '~/snippets/mutations/deleteSnippet.mutation.graphql';
import { ApolloMutation } from 'vue-apollo';
import { GlButton, GlModal } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { mount } from '@vue/test-utils';
import { Blob, BinaryBlob } from 'jest/blob/components/mock_data';
import waitForPromises from 'helpers/wait_for_promises';
describe('Snippet header component', () => {
let wrapper;
const snippet = {
id: 'gid://gitlab/PersonalSnippet/50',
title: 'The property of Thor',
visibilityLevel: 'private',
webUrl: 'http://personal.dev.null/42',
userPermissions: {
adminSnippet: true,
updateSnippet: true,
reportSnippet: false,
},
project: null,
author: {
name: 'Thor Odinson',
},
blobs: [Blob],
};
const mutationVariables = {
mutation: DeleteSnippetMutation,
variables: {
id: snippet.id,
},
};
const errorMsg = 'Foo bar';
const err = { message: errorMsg };
let snippet;
let mutationTypes;
let mutationVariables;
const resolveMutate = jest.fn(() =>
Promise.resolve({ data: { destroySnippet: { errors: [] } } }),
);
const rejectMutation = jest.fn(() => Promise.reject(err));
const mutationTypes = {
RESOLVE: resolveMutate,
REJECT: rejectMutation,
};
let errorMsg;
let err;
function createComponent({
loading = false,
......@@ -63,7 +36,7 @@ describe('Snippet header component', () => {
mutate: mutationRes,
};
wrapper = shallowMount(SnippetHeader, {
wrapper = mount(SnippetHeader, {
mocks: { $apollo },
propsData: {
snippet: {
......@@ -76,6 +49,41 @@ describe('Snippet header component', () => {
});
}
beforeEach(() => {
snippet = {
id: 'gid://gitlab/PersonalSnippet/50',
title: 'The property of Thor',
visibilityLevel: 'private',
webUrl: 'http://personal.dev.null/42',
userPermissions: {
adminSnippet: true,
updateSnippet: true,
reportSnippet: false,
},
project: null,
author: {
name: 'Thor Odinson',
},
blobs: [Blob],
createdAt: new Date(Date.now() - 32 * 24 * 3600 * 1000).toISOString(),
};
mutationVariables = {
mutation: DeleteSnippetMutation,
variables: {
id: snippet.id,
},
};
errorMsg = 'Foo bar';
err = { message: errorMsg };
mutationTypes = {
RESOLVE: jest.fn(() => Promise.resolve({ data: { destroySnippet: { errors: [] } } })),
REJECT: jest.fn(() => Promise.reject(err)),
};
});
afterEach(() => {
wrapper.destroy();
});
......@@ -85,6 +93,23 @@ describe('Snippet header component', () => {
expect(wrapper.find('.detail-page-header').exists()).toBe(true);
});
it('renders a message showing snippet creation date and author', () => {
createComponent();
const text = wrapper.find('[data-testid="authored-message"]').text();
expect(text).toContain('Authored 1 month ago by');
expect(text).toContain('Thor Odinson');
});
it('renders a message showing only snippet creation date if author is null', () => {
snippet.author = null;
createComponent();
const text = wrapper.find('[data-testid="authored-message"]').text();
expect(text).toBe('Authored 1 month ago');
});
it('renders action buttons based on permissions', () => {
createComponent({
permissions: {
......@@ -163,15 +188,16 @@ describe('Snippet header component', () => {
expect(mutationTypes.RESOLVE).toHaveBeenCalledWith(mutationVariables);
});
it('sets error message if mutation fails', () => {
it('sets error message if mutation fails', async () => {
createComponent({ mutationRes: mutationTypes.REJECT });
expect(Boolean(wrapper.vm.errorMessage)).toBe(false);
wrapper.vm.deleteSnippet();
return wrapper.vm.$nextTick().then(() => {
await waitForPromises();
expect(wrapper.vm.errorMessage).toEqual(errorMsg);
});
});
describe('in case of successful mutation, closes modal and redirects to correct listing', () => {
const createDeleteSnippet = (snippetProps = {}) => {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment