Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-02-11 00:09:11 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-11 00:09:11 +0300
commit696b36294520f8a311586f99e838b6a61b1b3f32 (patch)
treeaa043fc07393643a80453a579c590fe437d02ead
parentc57e10faab0abb213e7a18274fd5a98ba87a5c09 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/ide/components/ide_status_bar.vue2
-rw-r--r--app/controllers/oauth/applications_controller.rb4
-rw-r--r--changelogs/unreleased/204729-nomethoderror-undefined-method-oauth_applications-for-nil-nilclass.yml5
-rw-r--r--changelogs/unreleased/fix-ide-pipeline-background.yml5
-rw-r--r--locale/gitlab.pot3
-rw-r--r--spec/controllers/oauth/applications_controller_spec.rb75
-rw-r--r--spec/frontend/environments/folder/environments_folder_view_spec.js180
-rw-r--r--spec/javascripts/environments/folder/environments_folder_view_spec.js229
8 files changed, 260 insertions, 243 deletions
diff --git a/app/assets/javascripts/ide/components/ide_status_bar.vue b/app/assets/javascripts/ide/components/ide_status_bar.vue
index 4da417a37ce..7ce33fd2278 100644
--- a/app/assets/javascripts/ide/components/ide_status_bar.vue
+++ b/app/assets/javascripts/ide/components/ide_status_bar.vue
@@ -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
diff --git a/app/controllers/oauth/applications_controller.rb b/app/controllers/oauth/applications_controller.rb
index bbf0bdd3662..f0e6cebe0e4 100644
--- a/app/controllers/oauth/applications_controller.rb
+++ b/app/controllers/oauth/applications_controller.rb
@@ -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]
diff --git a/changelogs/unreleased/204729-nomethoderror-undefined-method-oauth_applications-for-nil-nilclass.yml b/changelogs/unreleased/204729-nomethoderror-undefined-method-oauth_applications-for-nil-nilclass.yml
new file mode 100644
index 00000000000..1a4fdf5d941
--- /dev/null
+++ b/changelogs/unreleased/204729-nomethoderror-undefined-method-oauth_applications-for-nil-nilclass.yml
@@ -0,0 +1,5 @@
+---
+title: Fix 500 error while accessing Oauth::ApplicationsController without a valid session
+merge_request: 24775
+author:
+type: fixed
diff --git a/changelogs/unreleased/fix-ide-pipeline-background.yml b/changelogs/unreleased/fix-ide-pipeline-background.yml
new file mode 100644
index 00000000000..50aa656a748
--- /dev/null
+++ b/changelogs/unreleased/fix-ide-pipeline-background.yml
@@ -0,0 +1,5 @@
+---
+title: Fix pipeline icon background in Web IDE
+merge_request: 24707
+author:
+type: fixed
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 0274679fd2c..b6ecd5e5926 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -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 ""
diff --git a/spec/controllers/oauth/applications_controller_spec.rb b/spec/controllers/oauth/applications_controller_spec.rb
index 5f1f6af3999..09f8ad4332d 100644
--- a/spec/controllers/oauth/applications_controller_spec.rb
+++ b/spec/controllers/oauth/applications_controller_spec.rb
@@ -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
- describe 'GET #index' do
- it 'shows list of applications' do
- get :index
-
- expect(response).to have_gitlab_http_status(:ok)
+ shared_examples 'redirects to login page when the user is not signed in' do
+ before do
+ sign_out(user)
end
- it 'redirects back to profile page if OAuth applications are disabled' do
- disable_user_oauth
+ 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
+ subject { get :index }
+
+ it { is_expected.to have_gitlab_http_status(:ok) }
- get :index
+ context 'when OAuth applications are disabled' do
+ before do
+ disable_user_oauth
+ end
- expect(response).to have_gitlab_http_status(:ok)
+ it { is_expected.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
diff --git a/spec/frontend/environments/folder/environments_folder_view_spec.js b/spec/frontend/environments/folder/environments_folder_view_spec.js
new file mode 100644
index 00000000000..740225ddd9d
--- /dev/null
+++ b/spec/frontend/environments/folder/environments_folder_view_spec.js
@@ -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',
+ });
+ });
+ });
+ });
+});
diff --git a/spec/javascripts/environments/folder/environments_folder_view_spec.js b/spec/javascripts/environments/folder/environments_folder_view_spec.js
deleted file mode 100644
index 6530201240f..00000000000
--- a/spec/javascripts/environments/folder/environments_folder_view_spec.js
+++ /dev/null
@@ -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' });
- });
- });
- });
-});