Commit 0813822c authored by Mike Greiling's avatar Mike Greiling

Merge branch '220303-public-snippet' into 'master'

Fix authored message when snippet is viewed by unauthenticated users

See merge request gitlab-org/gitlab!38614
parents 69c6c9cf 3c19d44c
...@@ -68,6 +68,11 @@ export default { ...@@ -68,6 +68,11 @@ export default {
snippetHasBinary() { snippetHasBinary() {
return Boolean(this.snippet.blobs.find(blob => blob.binary)); return Boolean(this.snippet.blobs.find(blob => blob.binary));
}, },
authoredMessage() {
return this.snippet.author
? __('Authored %{timeago} by %{author}')
: __('Authored %{timeago}');
},
personalSnippetActions() { personalSnippetActions() {
return [ return [
{ {
...@@ -178,8 +183,8 @@ export default { ...@@ -178,8 +183,8 @@ export default {
</span> </span>
<gl-icon :name="visibilityLevelIcon" :size="14" /> <gl-icon :name="visibilityLevelIcon" :size="14" />
</div> </div>
<div class="creator"> <div class="creator" data-testid="authored-message">
<gl-sprintf :message="__('Authored %{timeago} by %{author}')"> <gl-sprintf :message="authoredMessage">
<template #timeago> <template #timeago>
<time-ago-tooltip <time-ago-tooltip
:time="snippet.createdAt" :time="snippet.createdAt"
......
---
title: Display authored message correctly on public snippets viewed by unauthenticated users
merge_request: 38614
author:
type: fixed
...@@ -3482,6 +3482,9 @@ msgstr "" ...@@ -3482,6 +3482,9 @@ msgstr ""
msgid "Author: %{author_name}" msgid "Author: %{author_name}"
msgstr "" msgstr ""
msgid "Authored %{timeago}"
msgstr ""
msgid "Authored %{timeago} by %{author}" msgid "Authored %{timeago} by %{author}"
msgstr "" msgstr ""
......
...@@ -2,45 +2,18 @@ import SnippetHeader from '~/snippets/components/snippet_header.vue'; ...@@ -2,45 +2,18 @@ import SnippetHeader from '~/snippets/components/snippet_header.vue';
import DeleteSnippetMutation from '~/snippets/mutations/deleteSnippet.mutation.graphql'; import DeleteSnippetMutation from '~/snippets/mutations/deleteSnippet.mutation.graphql';
import { ApolloMutation } from 'vue-apollo'; import { ApolloMutation } from 'vue-apollo';
import { GlButton, GlModal } from '@gitlab/ui'; 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 { Blob, BinaryBlob } from 'jest/blob/components/mock_data';
import waitForPromises from 'helpers/wait_for_promises';
describe('Snippet header component', () => { describe('Snippet header component', () => {
let wrapper; let wrapper;
const snippet = { let snippet;
id: 'gid://gitlab/PersonalSnippet/50', let mutationTypes;
title: 'The property of Thor', let mutationVariables;
visibilityLevel: 'private',
webUrl: 'http://personal.dev.null/42', let errorMsg;
userPermissions: { let err;
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 };
const resolveMutate = jest.fn(() =>
Promise.resolve({ data: { destroySnippet: { errors: [] } } }),
);
const rejectMutation = jest.fn(() => Promise.reject(err));
const mutationTypes = {
RESOLVE: resolveMutate,
REJECT: rejectMutation,
};
function createComponent({ function createComponent({
loading = false, loading = false,
...@@ -63,7 +36,7 @@ describe('Snippet header component', () => { ...@@ -63,7 +36,7 @@ describe('Snippet header component', () => {
mutate: mutationRes, mutate: mutationRes,
}; };
wrapper = shallowMount(SnippetHeader, { wrapper = mount(SnippetHeader, {
mocks: { $apollo }, mocks: { $apollo },
propsData: { propsData: {
snippet: { snippet: {
...@@ -76,6 +49,41 @@ describe('Snippet header component', () => { ...@@ -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(() => { afterEach(() => {
wrapper.destroy(); wrapper.destroy();
}); });
...@@ -85,6 +93,23 @@ describe('Snippet header component', () => { ...@@ -85,6 +93,23 @@ describe('Snippet header component', () => {
expect(wrapper.find('.detail-page-header').exists()).toBe(true); 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', () => { it('renders action buttons based on permissions', () => {
createComponent({ createComponent({
permissions: { permissions: {
...@@ -163,14 +188,15 @@ describe('Snippet header component', () => { ...@@ -163,14 +188,15 @@ describe('Snippet header component', () => {
expect(mutationTypes.RESOLVE).toHaveBeenCalledWith(mutationVariables); expect(mutationTypes.RESOLVE).toHaveBeenCalledWith(mutationVariables);
}); });
it('sets error message if mutation fails', () => { it('sets error message if mutation fails', async () => {
createComponent({ mutationRes: mutationTypes.REJECT }); createComponent({ mutationRes: mutationTypes.REJECT });
expect(Boolean(wrapper.vm.errorMessage)).toBe(false); expect(Boolean(wrapper.vm.errorMessage)).toBe(false);
wrapper.vm.deleteSnippet(); wrapper.vm.deleteSnippet();
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.vm.errorMessage).toEqual(errorMsg); await waitForPromises();
});
expect(wrapper.vm.errorMessage).toEqual(errorMsg);
}); });
describe('in case of successful mutation, closes modal and redirects to correct listing', () => { describe('in case of successful mutation, closes modal and redirects to correct listing', () => {
......
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