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 {
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
......@@ -3482,6 +3482,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