Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
c57e10faab
commit
696b362945
8 changed files with 261 additions and 244 deletions
|
@ -81,7 +81,7 @@ export default {
|
|||
<span v-if="latestPipeline && latestPipeline.details" class="ide-status-pipeline">
|
||||
<button
|
||||
type="button"
|
||||
class="p-0 border-0 h-50"
|
||||
class="p-0 border-0 bg-transparent"
|
||||
@click="openRightPane($options.rightSidebarViews.pipelines)"
|
||||
>
|
||||
<ci-icon
|
||||
|
|
|
@ -8,8 +8,8 @@ class Oauth::ApplicationsController < Doorkeeper::ApplicationsController
|
|||
include Gitlab::Experimentation::ControllerConcern
|
||||
include InitializesCurrentUserMode
|
||||
|
||||
before_action :verify_user_oauth_applications_enabled, except: :index
|
||||
before_action :authenticate_user!
|
||||
prepend_before_action :verify_user_oauth_applications_enabled, except: :index
|
||||
prepend_before_action :authenticate_user!
|
||||
before_action :add_gon_variables
|
||||
before_action :load_scopes, only: [:index, :create, :edit, :update]
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix 500 error while accessing Oauth::ApplicationsController without a valid session
|
||||
merge_request: 24775
|
||||
author:
|
||||
type: fixed
|
5
changelogs/unreleased/fix-ide-pipeline-background.yml
Normal file
5
changelogs/unreleased/fix-ide-pipeline-background.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix pipeline icon background in Web IDE
|
||||
merge_request: 24707
|
||||
author:
|
||||
type: fixed
|
|
@ -19239,6 +19239,9 @@ msgstr ""
|
|||
msgid "There was an error gathering the chart data"
|
||||
msgstr ""
|
||||
|
||||
msgid "There was an error getting the epic participants."
|
||||
msgstr ""
|
||||
|
||||
msgid "There was an error loading users activity calendar."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -4,31 +4,82 @@ require 'spec_helper'
|
|||
|
||||
describe Oauth::ApplicationsController do
|
||||
let(:user) { create(:user) }
|
||||
let(:application) { create(:oauth_application, owner: user) }
|
||||
|
||||
context 'project members' do
|
||||
before do
|
||||
sign_in(user)
|
||||
end
|
||||
|
||||
shared_examples 'redirects to login page when the user is not signed in' do
|
||||
before do
|
||||
sign_out(user)
|
||||
end
|
||||
|
||||
it { is_expected.to redirect_to(new_user_session_path) }
|
||||
end
|
||||
|
||||
describe 'GET #new' do
|
||||
subject { get :new }
|
||||
|
||||
it { is_expected.to have_gitlab_http_status(:ok) }
|
||||
|
||||
it_behaves_like 'redirects to login page when the user is not signed in'
|
||||
end
|
||||
|
||||
describe 'DELETE #destroy' do
|
||||
subject { delete :destroy, params: { id: application.id } }
|
||||
|
||||
it { is_expected.to redirect_to(oauth_applications_url) }
|
||||
|
||||
it_behaves_like 'redirects to login page when the user is not signed in'
|
||||
end
|
||||
|
||||
describe 'GET #edit' do
|
||||
subject { get :edit, params: { id: application.id } }
|
||||
|
||||
it { is_expected.to have_gitlab_http_status(:ok) }
|
||||
|
||||
it_behaves_like 'redirects to login page when the user is not signed in'
|
||||
end
|
||||
|
||||
describe 'PUT #update' do
|
||||
subject { put :update, params: { id: application.id, doorkeeper_application: { name: 'application' } } }
|
||||
|
||||
it { is_expected.to redirect_to(oauth_application_url(application)) }
|
||||
|
||||
it_behaves_like 'redirects to login page when the user is not signed in'
|
||||
end
|
||||
|
||||
describe 'GET #show' do
|
||||
subject { get :show, params: { id: application.id } }
|
||||
|
||||
it { is_expected.to have_gitlab_http_status(:ok) }
|
||||
|
||||
it_behaves_like 'redirects to login page when the user is not signed in'
|
||||
end
|
||||
|
||||
describe 'GET #index' do
|
||||
it 'shows list of applications' do
|
||||
get :index
|
||||
subject { get :index }
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
it { is_expected.to have_gitlab_http_status(:ok) }
|
||||
|
||||
context 'when OAuth applications are disabled' do
|
||||
before do
|
||||
disable_user_oauth
|
||||
end
|
||||
|
||||
it { is_expected.to have_gitlab_http_status(:ok) }
|
||||
end
|
||||
|
||||
it 'redirects back to profile page if OAuth applications are disabled' do
|
||||
disable_user_oauth
|
||||
|
||||
get :index
|
||||
|
||||
expect(response).to have_gitlab_http_status(:ok)
|
||||
end
|
||||
it_behaves_like 'redirects to login page when the user is not signed in'
|
||||
end
|
||||
|
||||
describe 'POST #create' do
|
||||
subject { post :create, params: oauth_params }
|
||||
|
||||
it 'creates an application' do
|
||||
post :create, params: oauth_params
|
||||
subject
|
||||
|
||||
expect(response).to have_gitlab_http_status(:found)
|
||||
expect(response).to redirect_to(oauth_application_path(Doorkeeper::Application.last))
|
||||
|
@ -37,7 +88,7 @@ describe Oauth::ApplicationsController do
|
|||
it 'redirects back to profile page if OAuth applications are disabled' do
|
||||
disable_user_oauth
|
||||
|
||||
post :create, params: oauth_params
|
||||
subject
|
||||
|
||||
expect(response).to have_gitlab_http_status(:found)
|
||||
expect(response).to redirect_to(profile_path)
|
||||
|
@ -59,6 +110,8 @@ describe Oauth::ApplicationsController do
|
|||
expect(response.body).to include 'Redirect URI is forbidden by the server'
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'redirects to login page when the user is not signed in'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import EnvironmentsFolderViewComponent from '~/environments/folder/environments_folder_view.vue';
|
||||
import EnvironmentTable from '~/environments/components/environments_table.vue';
|
||||
import { environmentsList } from '../mock_data';
|
||||
import { removeBreakLine, removeWhitespace } from 'helpers/text_helper';
|
||||
import { GlPagination } from '@gitlab/ui';
|
||||
|
||||
describe('Environments Folder View', () => {
|
||||
let mock;
|
||||
let wrapper;
|
||||
|
||||
const mockData = {
|
||||
endpoint: 'environments.json',
|
||||
folderName: 'review',
|
||||
canReadEnvironment: true,
|
||||
cssContainerClass: 'container',
|
||||
canaryDeploymentFeatureId: 'canary_deployment',
|
||||
showCanaryDeploymentCallout: true,
|
||||
userCalloutsPath: '/callouts',
|
||||
lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
|
||||
helpCanaryDeploymentsPath: 'help/canary-deployments',
|
||||
};
|
||||
|
||||
const mockEnvironments = environmentList => {
|
||||
mock.onGet(mockData.endpoint).reply(
|
||||
200,
|
||||
{
|
||||
environments: environmentList,
|
||||
stopped_count: 1,
|
||||
available_count: 0,
|
||||
},
|
||||
{
|
||||
'X-nExt-pAge': '2',
|
||||
'x-page': '1',
|
||||
'X-Per-Page': '2',
|
||||
'X-Prev-Page': '',
|
||||
'X-TOTAL': '20',
|
||||
'X-Total-Pages': '10',
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
const createWrapper = () => {
|
||||
wrapper = mount(EnvironmentsFolderViewComponent, { propsData: mockData });
|
||||
};
|
||||
|
||||
const findEnvironmentsTabAvailable = () => wrapper.find('.js-environments-tab-available');
|
||||
|
||||
const findEnvironmentsTabStopped = () => wrapper.find('.js-environments-tab-stopped');
|
||||
|
||||
beforeEach(() => {
|
||||
mock = new MockAdapter(axios);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mock.restore();
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
describe('successful request', () => {
|
||||
beforeEach(() => {
|
||||
mockEnvironments(environmentsList);
|
||||
createWrapper();
|
||||
return axios.waitForAll();
|
||||
});
|
||||
|
||||
it('should render a table with environments', () => {
|
||||
const table = wrapper.find(EnvironmentTable);
|
||||
|
||||
expect(table.exists()).toBe(true);
|
||||
expect(table.find('.environment-name').text()).toEqual(environmentsList[0].name);
|
||||
});
|
||||
|
||||
it('should render available tab with count', () => {
|
||||
const tabTable = findEnvironmentsTabAvailable();
|
||||
|
||||
expect(tabTable.text()).toContain('Available');
|
||||
expect(tabTable.find('.badge').text()).toContain('0');
|
||||
});
|
||||
|
||||
it('should render stopped tab with count', () => {
|
||||
const tabTable = findEnvironmentsTabStopped();
|
||||
|
||||
expect(tabTable.text()).toContain('Stopped');
|
||||
expect(tabTable.find('.badge').text()).toContain('1');
|
||||
});
|
||||
|
||||
it('should render parent folder name', () => {
|
||||
expect(removeBreakLine(removeWhitespace(wrapper.find('.js-folder-name').text()))).toContain(
|
||||
'Environments / review',
|
||||
);
|
||||
});
|
||||
|
||||
describe('pagination', () => {
|
||||
it('should render pagination', () => {
|
||||
expect(wrapper.find(GlPagination).exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('should make an API request when changing page', () => {
|
||||
jest.spyOn(wrapper.vm, 'updateContent').mockImplementation(() => {});
|
||||
wrapper.find('.gl-pagination .page-item:nth-last-of-type(2) .page-link').trigger('click');
|
||||
expect(wrapper.vm.updateContent).toHaveBeenCalledWith({
|
||||
scope: wrapper.vm.scope,
|
||||
page: '10',
|
||||
});
|
||||
});
|
||||
|
||||
it('should make an API request when using tabs', () => {
|
||||
jest.spyOn(wrapper.vm, 'updateContent').mockImplementation(() => {});
|
||||
findEnvironmentsTabStopped().trigger('click');
|
||||
expect(wrapper.vm.updateContent).toHaveBeenCalledWith({ scope: 'stopped', page: '1' });
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('unsuccessfull request', () => {
|
||||
beforeEach(() => {
|
||||
mock.onGet(mockData.endpoint).reply(500, { environments: [] });
|
||||
createWrapper();
|
||||
return axios.waitForAll();
|
||||
});
|
||||
|
||||
it('should not render a table', () => {
|
||||
expect(wrapper.find(EnvironmentTable).exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('should render available tab with count 0', () => {
|
||||
const tabTable = findEnvironmentsTabAvailable();
|
||||
|
||||
expect(tabTable.text()).toContain('Available');
|
||||
expect(tabTable.find('.badge').text()).toContain('0');
|
||||
});
|
||||
|
||||
it('should render stopped tab with count 0', () => {
|
||||
const tabTable = findEnvironmentsTabStopped();
|
||||
|
||||
expect(tabTable.text()).toContain('Stopped');
|
||||
expect(tabTable.find('.badge').text()).toContain('0');
|
||||
});
|
||||
});
|
||||
|
||||
describe('methods', () => {
|
||||
beforeEach(() => {
|
||||
mockEnvironments([]);
|
||||
createWrapper();
|
||||
jest.spyOn(window.history, 'pushState').mockImplementation(() => {});
|
||||
return axios.waitForAll();
|
||||
});
|
||||
|
||||
describe('updateContent', () => {
|
||||
it('should set given parameters', () =>
|
||||
wrapper.vm.updateContent({ scope: 'stopped', page: '4' }).then(() => {
|
||||
expect(wrapper.vm.page).toEqual('4');
|
||||
expect(wrapper.vm.scope).toEqual('stopped');
|
||||
expect(wrapper.vm.requestData.page).toEqual('4');
|
||||
}));
|
||||
});
|
||||
|
||||
describe('onChangeTab', () => {
|
||||
it('should set page to 1', () => {
|
||||
jest.spyOn(wrapper.vm, 'updateContent').mockImplementation(() => {});
|
||||
wrapper.vm.onChangeTab('stopped');
|
||||
expect(wrapper.vm.updateContent).toHaveBeenCalledWith({ scope: 'stopped', page: '1' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('onChangePage', () => {
|
||||
it('should update page and keep scope', () => {
|
||||
jest.spyOn(wrapper.vm, 'updateContent').mockImplementation(() => {});
|
||||
wrapper.vm.onChangePage(4);
|
||||
expect(wrapper.vm.updateContent).toHaveBeenCalledWith({
|
||||
scope: wrapper.vm.scope,
|
||||
page: '4',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -1,229 +0,0 @@
|
|||
import Vue from 'vue';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import mountComponent from 'spec/helpers/vue_mount_component_helper';
|
||||
import { removeBreakLine, removeWhitespace } from 'spec/helpers/text_helper';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import environmentsFolderViewComponent from '~/environments/folder/environments_folder_view.vue';
|
||||
import { environmentsList } from '../mock_data';
|
||||
|
||||
describe('Environments Folder View', () => {
|
||||
let Component;
|
||||
let component;
|
||||
let mock;
|
||||
|
||||
const mockData = {
|
||||
endpoint: 'environments.json',
|
||||
folderName: 'review',
|
||||
canReadEnvironment: true,
|
||||
cssContainerClass: 'container',
|
||||
canaryDeploymentFeatureId: 'canary_deployment',
|
||||
showCanaryDeploymentCallout: true,
|
||||
userCalloutsPath: '/callouts',
|
||||
lockPromotionSvgPath: '/assets/illustrations/lock-promotion.svg',
|
||||
helpCanaryDeploymentsPath: 'help/canary-deployments',
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
mock = new MockAdapter(axios);
|
||||
|
||||
Component = Vue.extend(environmentsFolderViewComponent);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
mock.restore();
|
||||
|
||||
component.$destroy();
|
||||
});
|
||||
|
||||
describe('successful request', () => {
|
||||
beforeEach(() => {
|
||||
mock.onGet(mockData.endpoint).reply(
|
||||
200,
|
||||
{
|
||||
environments: environmentsList,
|
||||
stopped_count: 1,
|
||||
available_count: 0,
|
||||
},
|
||||
{
|
||||
'X-nExt-pAge': '2',
|
||||
'x-page': '1',
|
||||
'X-Per-Page': '2',
|
||||
'X-Prev-Page': '',
|
||||
'X-TOTAL': '20',
|
||||
'X-Total-Pages': '10',
|
||||
},
|
||||
);
|
||||
|
||||
component = mountComponent(Component, mockData);
|
||||
});
|
||||
|
||||
it('should render a table with environments', done => {
|
||||
setTimeout(() => {
|
||||
expect(component.$el.querySelectorAll('table')).not.toBeNull();
|
||||
expect(component.$el.querySelector('.environment-name').textContent.trim()).toEqual(
|
||||
environmentsList[0].name,
|
||||
);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should render available tab with count', done => {
|
||||
setTimeout(() => {
|
||||
expect(component.$el.querySelector('.js-environments-tab-available').textContent).toContain(
|
||||
'Available',
|
||||
);
|
||||
|
||||
expect(
|
||||
component.$el.querySelector('.js-environments-tab-available .badge').textContent,
|
||||
).toContain('0');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should render stopped tab with count', done => {
|
||||
setTimeout(() => {
|
||||
expect(component.$el.querySelector('.js-environments-tab-stopped').textContent).toContain(
|
||||
'Stopped',
|
||||
);
|
||||
|
||||
expect(
|
||||
component.$el.querySelector('.js-environments-tab-stopped .badge').textContent,
|
||||
).toContain('1');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should render parent folder name', done => {
|
||||
setTimeout(() => {
|
||||
expect(
|
||||
removeBreakLine(
|
||||
removeWhitespace(component.$el.querySelector('.js-folder-name').textContent.trim()),
|
||||
),
|
||||
).toContain('Environments / review');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
describe('pagination', () => {
|
||||
it('should render pagination', done => {
|
||||
setTimeout(() => {
|
||||
expect(component.$el.querySelectorAll('.gl-pagination')).not.toBeNull();
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should make an API request when changing page', done => {
|
||||
spyOn(component, 'updateContent');
|
||||
setTimeout(() => {
|
||||
component.$el
|
||||
.querySelector('.gl-pagination .page-item:nth-last-of-type(2) .page-link')
|
||||
.click();
|
||||
|
||||
expect(component.updateContent).toHaveBeenCalledWith({
|
||||
scope: component.scope,
|
||||
page: '10',
|
||||
});
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should make an API request when using tabs', done => {
|
||||
setTimeout(() => {
|
||||
spyOn(component, 'updateContent');
|
||||
component.$el.querySelector('.js-environments-tab-stopped').click();
|
||||
|
||||
expect(component.updateContent).toHaveBeenCalledWith({ scope: 'stopped', page: '1' });
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('unsuccessfull request', () => {
|
||||
beforeEach(() => {
|
||||
mock.onGet(mockData.endpoint).reply(500, {
|
||||
environments: [],
|
||||
});
|
||||
|
||||
component = mountComponent(Component, mockData);
|
||||
});
|
||||
|
||||
it('should not render a table', done => {
|
||||
setTimeout(() => {
|
||||
expect(component.$el.querySelector('table')).toBe(null);
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should render available tab with count 0', done => {
|
||||
setTimeout(() => {
|
||||
expect(component.$el.querySelector('.js-environments-tab-available').textContent).toContain(
|
||||
'Available',
|
||||
);
|
||||
|
||||
expect(
|
||||
component.$el.querySelector('.js-environments-tab-available .badge').textContent,
|
||||
).toContain('0');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should render stopped tab with count 0', done => {
|
||||
setTimeout(() => {
|
||||
expect(component.$el.querySelector('.js-environments-tab-stopped').textContent).toContain(
|
||||
'Stopped',
|
||||
);
|
||||
|
||||
expect(
|
||||
component.$el.querySelector('.js-environments-tab-stopped .badge').textContent,
|
||||
).toContain('0');
|
||||
done();
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('methods', () => {
|
||||
beforeEach(() => {
|
||||
mock.onGet(mockData.endpoint).reply(200, {
|
||||
environments: [],
|
||||
});
|
||||
|
||||
component = mountComponent(Component, mockData);
|
||||
spyOn(window.history, 'pushState').and.stub();
|
||||
});
|
||||
|
||||
describe('updateContent', () => {
|
||||
it('should set given parameters', done => {
|
||||
component
|
||||
.updateContent({ scope: 'stopped', page: '4' })
|
||||
.then(() => {
|
||||
expect(component.page).toEqual('4');
|
||||
expect(component.scope).toEqual('stopped');
|
||||
expect(component.requestData.scope).toEqual('stopped');
|
||||
expect(component.requestData.page).toEqual('4');
|
||||
done();
|
||||
})
|
||||
.catch(done.fail);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onChangeTab', () => {
|
||||
it('should set page to 1', () => {
|
||||
spyOn(component, 'updateContent');
|
||||
component.onChangeTab('stopped');
|
||||
|
||||
expect(component.updateContent).toHaveBeenCalledWith({ scope: 'stopped', page: '1' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('onChangePage', () => {
|
||||
it('should update page and keep scope', () => {
|
||||
spyOn(component, 'updateContent');
|
||||
|
||||
component.onChangePage(4);
|
||||
|
||||
expect(component.updateContent).toHaveBeenCalledWith({ scope: component.scope, page: '4' });
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue