Commit 6c3038e8 authored by Filipa Lacerda's avatar Filipa Lacerda

Merge branch 'master' into 30985-cancel-pipelines

* master:
  Remove special naming of pipelines folder
  remove changelog (not needed)
  Fix active user count
  add spec and changelog
  Add migration to remove orphaned notification settings
  Improve container registry repository path specs
  Fix duplicated container repository names
  update textarea height and refocus when attaching files
  Remove IIFEs in filtered_search_bundle.js
  Remove IIFEs from diff_notes_bundle.js
parents dbbcb32c a9da3743
import Vue from 'vue';
import Visibility from 'visibilityjs';
import PipelinesTableComponent from '../../vue_shared/components/pipelines_table';
import PipelinesService from '../../vue_pipelines_index/services/pipelines_service';
import PipelineStore from '../../vue_pipelines_index/stores/pipelines_store';
import eventHub from '../../vue_pipelines_index/event_hub';
import EmptyState from '../../vue_pipelines_index/components/empty_state.vue';
import ErrorState from '../../vue_pipelines_index/components/error_state.vue';
import PipelinesService from '../../pipelines/services/pipelines_service';
import PipelineStore from '../../pipelines/stores/pipelines_store';
import eventHub from '../../pipelines/event_hub';
import EmptyState from '../../pipelines/components/empty_state.vue';
import ErrorState from '../../pipelines/components/error_state.vue';
import '../../lib/utils/common_utils';
import '../../vue_shared/vue_resource_interceptor';
import Poll from '../../lib/utils/poll';
......
......@@ -3,8 +3,7 @@
import Vue from 'vue';
(() => {
const CommentAndResolveBtn = Vue.extend({
const CommentAndResolveBtn = Vue.extend({
props: {
discussionId: String,
},
......@@ -61,7 +60,6 @@ import Vue from 'vue';
$(`.js-discussion-note-form[data-discussion-id=${this.discussionId}] .note-textarea`).off('input.comment-and-resolve-btn');
}
});
});
Vue.component('comment-and-resolve-btn', CommentAndResolveBtn);
})(window);
Vue.component('comment-and-resolve-btn', CommentAndResolveBtn);
......@@ -4,8 +4,7 @@
import Vue from 'vue';
import collapseIcon from '../icons/collapse_icon.svg';
(() => {
const DiffNoteAvatars = Vue.extend({
const DiffNoteAvatars = Vue.extend({
props: ['discussionId'],
data() {
return {
......@@ -152,7 +151,6 @@ import collapseIcon from '../icons/collapse_icon.svg';
this.isVisible = $(`.diffs .notes[data-discussion-id="${this.discussion.id}"]`).is(':visible');
},
},
});
});
Vue.component('diff-note-avatars', DiffNoteAvatars);
})();
Vue.component('diff-note-avatars', DiffNoteAvatars);
......@@ -4,8 +4,7 @@
import Vue from 'vue';
(() => {
const JumpToDiscussion = Vue.extend({
const JumpToDiscussion = Vue.extend({
mixins: [DiscussionMixins],
props: {
discussionId: String
......@@ -189,7 +188,6 @@ import Vue from 'vue';
created() {
this.discussion = this.discussions[this.discussionId];
},
});
});
Vue.component('jump-to-discussion', JumpToDiscussion);
})();
Vue.component('jump-to-discussion', JumpToDiscussion);
......@@ -2,8 +2,7 @@
import Vue from 'vue';
(() => {
const NewIssueForDiscussion = Vue.extend({
const NewIssueForDiscussion = Vue.extend({
props: {
discussionId: {
type: String,
......@@ -24,7 +23,6 @@ import Vue from 'vue';
return false;
},
},
});
});
Vue.component('new-issue-for-discussion-btn', NewIssueForDiscussion);
})();
Vue.component('new-issue-for-discussion-btn', NewIssueForDiscussion);
......@@ -5,8 +5,7 @@
import Vue from 'vue';
(() => {
const ResolveBtn = Vue.extend({
const ResolveBtn = Vue.extend({
props: {
noteId: Number,
discussionId: String,
......@@ -115,7 +114,6 @@ import Vue from 'vue';
noteTruncated: this.noteTruncated,
});
}
});
});
Vue.component('resolve-btn', ResolveBtn);
})();
Vue.component('resolve-btn', ResolveBtn);
......@@ -4,8 +4,7 @@
import Vue from 'vue';
((w) => {
w.ResolveCount = Vue.extend({
window.ResolveCount = Vue.extend({
mixins: [DiscussionMixins],
props: {
loggedOut: Boolean
......@@ -23,5 +22,4 @@ import Vue from 'vue';
return this.discussionCount === 1 ? 'discussion' : 'discussions';
}
}
});
})(window);
});
......@@ -4,8 +4,7 @@
import Vue from 'vue';
(() => {
const ResolveDiscussionBtn = Vue.extend({
const ResolveDiscussionBtn = Vue.extend({
props: {
discussionId: String,
mergeRequestId: Number,
......@@ -56,7 +55,6 @@ import Vue from 'vue';
this.discussion = CommentsStore.state[this.discussionId];
}
});
});
Vue.component('resolve-discussion-btn', ResolveDiscussionBtn);
})();
Vue.component('resolve-discussion-btn', ResolveDiscussionBtn);
/* eslint-disable object-shorthand, func-names, guard-for-in, no-restricted-syntax, comma-dangle, no-param-reassign, max-len */
((w) => {
w.DiscussionMixins = {
window.DiscussionMixins = {
computed: {
discussionCount: function () {
return Object.keys(this.discussions).length;
......@@ -33,5 +32,4 @@
return unresolvedCount;
}
}
};
})(window);
};
......@@ -9,10 +9,9 @@ require('../../vue_shared/vue_resource_interceptor');
Vue.use(VueResource);
(() => {
window.gl = window.gl || {};
window.gl = window.gl || {};
class ResolveServiceClass {
class ResolveServiceClass {
constructor(root) {
this.noteResource = Vue.resource(`${root}/notes{/noteId}/resolve`);
this.discussionResource = Vue.resource(`${root}/merge_requests{/mergeRequestId}/discussions{/discussionId}/resolve`);
......@@ -78,7 +77,6 @@ Vue.use(VueResource);
discussionId
}, {});
}
}
}
gl.DiffNotesResolveServiceClass = ResolveServiceClass;
})();
gl.DiffNotesResolveServiceClass = ResolveServiceClass;
......@@ -3,8 +3,7 @@
import Vue from 'vue';
((w) => {
w.CommentsStore = {
window.CommentsStore = {
state: {},
get: function (discussionId, noteId) {
return this.state[discussionId].getNote(noteId);
......@@ -54,5 +53,4 @@ import Vue from 'vue';
return ids;
}
};
})(window);
};
......@@ -130,13 +130,15 @@ window.DropzoneInput = (function() {
var afterSelection, beforeSelection, caretEnd, caretStart, textEnd;
var formattedText = text;
if (shouldPad) formattedText += "\n\n";
caretStart = $(child)[0].selectionStart;
caretEnd = $(child)[0].selectionEnd;
const textarea = child.get(0);
caretStart = textarea.selectionStart;
caretEnd = textarea.selectionEnd;
textEnd = $(child).val().length;
beforeSelection = $(child).val().substring(0, caretStart);
afterSelection = $(child).val().substring(caretEnd, textEnd);
$(child).val(beforeSelection + formattedText + afterSelection);
child.get(0).setSelectionRange(caretStart + formattedText.length, caretEnd + formattedText.length);
textarea.setSelectionRange(caretStart + formattedText.length, caretEnd + formattedText.length);
textarea.style.height = `${textarea.scrollHeight}px`;
return form_textarea.trigger("input");
};
getFilename = function(e) {
......@@ -180,7 +182,7 @@ window.DropzoneInput = (function() {
};
insertToTextArea = function(filename, url) {
return $(child).val(function(index, val) {
return val.replace("{{" + filename + "}}", url + "\n");
return val.replace("{{" + filename + "}}", url);
});
};
appendToTextArea = function(url) {
......@@ -215,6 +217,7 @@ window.DropzoneInput = (function() {
form.find(".markdown-selector").click(function(e) {
e.preventDefault();
$(this).closest('.gfm-form').find('.div-dropzone').click();
form_textarea.focus();
});
}
......
......@@ -2,8 +2,7 @@ import Filter from '~/droplab/plugins/filter';
require('./filtered_search_dropdown');
(() => {
class DropdownHint extends gl.FilteredSearchDropdown {
class DropdownHint extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input, filter) {
super(droplab, dropdown, input, filter);
this.config = {
......@@ -76,8 +75,7 @@ require('./filtered_search_dropdown');
init() {
this.droplab.addHook(this.input, this.dropdown, [Filter], this.config).init();
}
}
}
window.gl = window.gl || {};
gl.DropdownHint = DropdownHint;
})();
window.gl = window.gl || {};
gl.DropdownHint = DropdownHint;
......@@ -5,8 +5,7 @@ import Filter from '~/droplab/plugins/filter';
require('./filtered_search_dropdown');
(() => {
class DropdownNonUser extends gl.FilteredSearchDropdown {
class DropdownNonUser extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input, filter, endpoint, symbol) {
super(droplab, dropdown, input, filter);
this.symbol = symbol;
......@@ -45,8 +44,7 @@ require('./filtered_search_dropdown');
this.droplab
.addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init();
}
}
}
window.gl = window.gl || {};
gl.DropdownNonUser = DropdownNonUser;
})();
window.gl = window.gl || {};
gl.DropdownNonUser = DropdownNonUser;
......@@ -4,8 +4,7 @@ import AjaxFilter from '~/droplab/plugins/ajax_filter';
require('./filtered_search_dropdown');
(() => {
class DropdownUser extends gl.FilteredSearchDropdown {
class DropdownUser extends gl.FilteredSearchDropdown {
constructor(droplab, dropdown, input, filter) {
super(droplab, dropdown, input, filter);
this.config = {
......@@ -65,8 +64,7 @@ require('./filtered_search_dropdown');
init() {
this.droplab.addHook(this.input, this.dropdown, [AjaxFilter], this.config).init();
}
}
}
window.gl = window.gl || {};
gl.DropdownUser = DropdownUser;
})();
window.gl = window.gl || {};
gl.DropdownUser = DropdownUser;
import FilteredSearchContainer from './container';
(() => {
class DropdownUtils {
class DropdownUtils {
static getEscapedText(text) {
let escapedText = text;
const hasSpace = text.indexOf(' ') !== -1;
......@@ -176,8 +175,7 @@ import FilteredSearchContainer from './container';
right,
};
}
}
}
window.gl = window.gl || {};
gl.DropdownUtils = DropdownUtils;
})();
window.gl = window.gl || {};
gl.DropdownUtils = DropdownUtils;
(() => {
const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger';
const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger';
class FilteredSearchDropdown {
class FilteredSearchDropdown {
constructor(droplab, dropdown, input, filter) {
this.droplab = droplab;
this.hookId = input && input.id;
......@@ -117,8 +116,7 @@
hook.list.render(results);
}
}
}
}
window.gl = window.gl || {};
gl.FilteredSearchDropdown = FilteredSearchDropdown;
})();
window.gl = window.gl || {};
gl.FilteredSearchDropdown = FilteredSearchDropdown;
import DropLab from '~/droplab/drop_lab';
import FilteredSearchContainer from './container';
(() => {
class FilteredSearchDropdownManager {
class FilteredSearchDropdownManager {
constructor(baseEndpoint = '', page) {
this.container = FilteredSearchContainer.container;
this.baseEndpoint = baseEndpoint.replace(/\/$/, '');
......@@ -184,8 +183,7 @@ import FilteredSearchContainer from './container';
destroyDroplab() {
this.droplab.destroy();
}
}
}
window.gl = window.gl || {};
gl.FilteredSearchDropdownManager = FilteredSearchDropdownManager;
})();
window.gl = window.gl || {};
gl.FilteredSearchDropdownManager = FilteredSearchDropdownManager;
......@@ -6,8 +6,7 @@ import RecentSearchesStore from './stores/recent_searches_store';
import RecentSearchesService from './services/recent_searches_service';
import eventHub from './event_hub';
(() => {
class FilteredSearchManager {
class FilteredSearchManager {
constructor(page) {
this.container = FilteredSearchContainer.container;
this.filteredSearchInput = this.container.querySelector('.filtered-search');
......@@ -487,8 +486,7 @@ import eventHub from './event_hub';
this.filteredSearchInput.dispatchEvent(new CustomEvent('input'));
this.search();
}
}
}
window.gl = window.gl || {};
gl.FilteredSearchManager = FilteredSearchManager;
})();
window.gl = window.gl || {};
gl.FilteredSearchManager = FilteredSearchManager;
(() => {
const tokenKeys = [{
const tokenKeys = [{
key: 'author',
type: 'string',
param: 'username',
symbol: '@',
}, {
}, {
key: 'assignee',
type: 'string',
param: 'username',
symbol: '@',
}, {
}, {
key: 'milestone',
type: 'string',
param: 'title',
symbol: '%',
}, {
}, {
key: 'label',
type: 'array',
param: 'name[]',
symbol: '~',
}];
}];
const alternativeTokenKeys = [{
const alternativeTokenKeys = [{
key: 'label',
type: 'string',
param: 'name',
symbol: '~',
}];
}];
const tokenKeysWithAlternative = tokenKeys.concat(alternativeTokenKeys);
const tokenKeysWithAlternative = tokenKeys.concat(alternativeTokenKeys);
const conditions = [{
const conditions = [{
url: 'assignee_id=0',
tokenKey: 'assignee',
value: 'none',
}, {
}, {
url: 'milestone_title=No+Milestone',
tokenKey: 'milestone',
value: 'none',
}, {
}, {
url: 'milestone_title=%23upcoming',
tokenKey: 'milestone',
value: 'upcoming',
}, {
}, {
url: 'milestone_title=%23started',
tokenKey: 'milestone',
value: 'started',
}, {
}, {
url: 'label_name[]=No+Label',
tokenKey: 'label',
value: 'none',
}];
}];
class FilteredSearchTokenKeys {
class FilteredSearchTokenKeys {
static get() {
return tokenKeys;
}
......@@ -93,8 +92,7 @@
return conditions
.find(condition => condition.tokenKey === key && condition.value === value) || null;
}
}
}
window.gl = window.gl || {};
gl.FilteredSearchTokenKeys = FilteredSearchTokenKeys;
})();
window.gl = window.gl || {};
gl.FilteredSearchTokenKeys = FilteredSearchTokenKeys;
require('./filtered_search_token_keys');
(() => {
class FilteredSearchTokenizer {
class FilteredSearchTokenizer {
static processTokens(input) {
const allowedKeys = gl.FilteredSearchTokenKeys.get().map(i => i.key);
// Regex extracts `(token):(symbol)(value)`
......@@ -51,8 +50,7 @@ require('./filtered_search_token_keys');
searchToken,
};
}
}
}
window.gl = window.gl || {};
gl.FilteredSearchTokenizer = FilteredSearchTokenizer;
})();
window.gl = window.gl || {};
gl.FilteredSearchTokenizer = FilteredSearchTokenizer;
/* eslint-disable no-param-reassign */
import AsyncButtonComponent from '../../vue_pipelines_index/components/async_button.vue';
import PipelinesActionsComponent from '../../vue_pipelines_index/components/pipelines_actions';
import PipelinesArtifactsComponent from '../../vue_pipelines_index/components/pipelines_artifacts';
import PipelinesStatusComponent from '../../vue_pipelines_index/components/status';
import PipelinesStageComponent from '../../vue_pipelines_index/components/stage';
import PipelinesUrlComponent from '../../vue_pipelines_index/components/pipeline_url';
import PipelinesTimeagoComponent from '../../vue_pipelines_index/components/time_ago';
import AsyncButtonComponent from '../../pipelines/components/async_button.vue';
import PipelinesActionsComponent from '../../pipelines/components/pipelines_actions';
import PipelinesArtifactsComponent from '../../pipelines/components/pipelines_artifacts';
import PipelinesStatusComponent from '../../pipelines/components/status';
import PipelinesStageComponent from '../../pipelines/components/stage';
import PipelinesUrlComponent from '../../pipelines/components/pipeline_url';
import PipelinesTimeagoComponent from '../../pipelines/components/time_ago';
import CommitComponent from './commit';
/**
......
......@@ -197,7 +197,7 @@ class User < ActiveRecord::Base
scope :admins, -> { where(admin: true) }
scope :blocked, -> { with_states(:blocked, :ldap_blocked) }
scope :external, -> { where(external: true) }
scope :active, -> { with_state(:active) }
scope :active, -> { with_state(:active).non_internal }
scope :not_in_project, ->(project) { project.users.present? ? where("id not in (:ids)", ids: project.users.map(&:id) ) : all }
scope :without_projects, -> { where('id NOT IN (SELECT DISTINCT(user_id) FROM members WHERE user_id IS NOT NULL AND requested_at IS NULL)') }
scope :todo_authors, ->(user_id, state) { where(id: Todo.where(user_id: user_id, state: state).select(:author_id)) }
......
......@@ -17,4 +17,4 @@
"ci-lint-path" => ci_lint_path } }
= page_specific_javascript_bundle_tag('common_vue')
= page_specific_javascript_bundle_tag('vue_pipelines')
= page_specific_javascript_bundle_tag('pipelines')
---
title: refocus textarea after attaching a file
merge_request:
author:
---
title: Removed orphaned notification settings without a namespace
merge_request:
author:
......@@ -19,12 +19,11 @@ var WEBPACK_REPORT = process.env.WEBPACK_REPORT;
var config = {
context: path.join(ROOT_PATH, 'app/assets/javascripts'),
entry: {
blob: './blob_edit/blob_bundle.js',
boards: './boards/boards_bundle.js',
common: './commons/index.js',
common_vue: ['vue', './vue_shared/common_vue.js'],
common_d3: ['d3'],
main: './main.js',
blob: './blob_edit/blob_bundle.js',
boards: './boards/boards_bundle.js',
cycle_analytics: './cycle_analytics/cycle_analytics_bundle.js',
commit_pipelines: './commit/pipelines/pipelines_bundle.js',
diff_notes: './diff_notes/diff_notes_bundle.js',
......@@ -32,26 +31,27 @@ var config = {
environments_folder: './environments/folder/environments_folder_bundle.js',
filtered_search: './filtered_search/filtered_search_bundle.js',
graphs: './graphs/graphs_bundle.js',
group: './group.js',
groups_list: './groups_list.js',
issuable: './issuable/issuable_bundle.js',
issue_show: './issue_show/index.js',
main: './main.js',
merge_conflicts: './merge_conflicts/merge_conflicts_bundle.js',
merge_request_widget: './merge_request_widget/ci_bundle.js',
monitoring: './monitoring/monitoring_bundle.js',
network: './network/network_bundle.js',
notebook_viewer: './blob/notebook_viewer.js',
sketch_viewer: './blob/sketch_viewer.js',
pdf_viewer: './blob/pdf_viewer.js',
pipelines: './pipelines/index.js',
profile: './profile/profile_bundle.js',
protected_branches: './protected_branches/protected_branches_bundle.js',
protected_tags: './protected_tags',
snippet: './snippet/snippet_bundle.js',
sketch_viewer: './blob/sketch_viewer.js',
stl_viewer: './blob/stl_viewer.js',
terminal: './terminal/terminal_bundle.js',
u2f: ['vendor/u2f'],
users: './users/users_bundle.js',
vue_pipelines: './vue_pipelines_index/index.js',
issue_show: './issue_show/index.js',
group: './group.js',
},
output: {
......@@ -121,11 +121,11 @@ var config = {
'environments',
'environments_folder',
'issuable',
'issue_show',
'merge_conflicts',
'notebook_viewer',
'pdf_viewer',
'vue_pipelines',
'issue_show',
'pipelines',
],
minChunks: function(module, count) {
return module.resource && (/vue_shared/).test(module.resource);
......
class DeleteOrphanNotificationSettings < ActiveRecord::Migration
DOWNTIME = false
def up
execute("DELETE FROM notification_settings WHERE EXISTS (SELECT true FROM (#{orphan_notification_settings}) AS ns WHERE ns.id = notification_settings.id)")
end
def down
# This is a no-op method to make the migration reversible.
# If someone is trying to rollback for other reasons, we should not throw an Exception.
# raise ActiveRecord::IrreversibleMigration
end
def orphan_notification_settings
<<-SQL
SELECT notification_settings.id
FROM notification_settings
LEFT OUTER JOIN namespaces
ON namespaces.id = notification_settings.source_id
WHERE notification_settings.source_type = 'Namespace'
AND namespaces.id IS NULL
SQL
end
end
......@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170408033905) do
ActiveRecord::Schema.define(version: 20170418103908) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......
......@@ -48,7 +48,7 @@ module ContainerRegistry
end
def root_repository?
@path == repository_project.full_path
@path == project_path
end
def repository_project
......@@ -60,7 +60,13 @@ module ContainerRegistry
def repository_name
return unless has_project?
@path.remove(%r(^#{Regexp.escape(repository_project.full_path)}/?))
@path.remove(%r(^#{Regexp.escape(project_path)}/?))
end
def project_path
return unless has_project?
repository_project.full_path.downcase
end
def to_s
......
......@@ -5,8 +5,7 @@ require('~/diff_notes/models/discussion');
require('~/diff_notes/models/note');
require('~/diff_notes/stores/comments');
(() => {
function createDiscussion(noteId = 1, resolved = true) {
function createDiscussion(noteId = 1, resolved = true) {
CommentsStore.create({
discussionId: 'a',
noteId,
......@@ -17,13 +16,13 @@ require('~/diff_notes/stores/comments');
authorAvatar: 'test',
noteTruncated: 'test...',
});
}
}
beforeEach(() => {
beforeEach(() => {
CommentsStore.state = {};
});
});
describe('New discussion', () => {
describe('New discussion', () => {
it('creates new discussion', () => {
expect(Object.keys(CommentsStore.state).length).toBe(0);
createDiscussion();
......@@ -37,9 +36,9 @@ require('~/diff_notes/stores/comments');
const discussion = CommentsStore.state['a'];
expect(Object.keys(discussion.notes).length).toBe(2);
});
});
});
describe('Get note', () => {
describe('Get note', () => {
beforeEach(() => {
expect(Object.keys(CommentsStore.state).length).toBe(0);
createDiscussion();
......@@ -50,9 +49,9 @@ require('~/diff_notes/stores/comments');
expect(note).toBeDefined();
expect(note.id).toBe(1);
});
});
});
describe('Delete discussion', () => {
describe('Delete discussion', () => {
beforeEach(() => {
expect(Object.keys(CommentsStore.state).length).toBe(0);
createDiscussion();
......@@ -73,9 +72,9 @@ require('~/diff_notes/stores/comments');
CommentsStore.delete('a', 2);
expect(Object.keys(CommentsStore.state).length).toBe(0);
});
});
});
describe('Update note', () => {
describe('Update note', () => {
beforeEach(() => {
expect(Object.keys(CommentsStore.state).length).toBe(0);
createDiscussion();
......@@ -87,9 +86,9 @@ require('~/diff_notes/stores/comments');
const note = CommentsStore.get('a', 1);
expect(note.resolved).toBe(false);
});
});
});
describe('Discussion resolved', () => {
describe('Discussion resolved', () => {
beforeEach(() => {
expect(Object.keys(CommentsStore.state).length).toBe(0);
createDiscussion();
......@@ -129,5 +128,4 @@ require('~/diff_notes/stores/comments');
discussion.unResolveAllNotes();
expect(discussion.isResolved()).toBe(false);
});
});
})();
});
......@@ -3,8 +3,7 @@ require('~/filtered_search/filtered_search_tokenizer');
require('~/filtered_search/filtered_search_dropdown');
require('~/filtered_search/dropdown_user');
(() => {
describe('Dropdown User', () => {
describe('Dropdown User', () => {
describe('getSearchInput', () => {
let dropdownUser;
......@@ -67,5 +66,4 @@ require('~/filtered_search/dropdown_user');
window.gon = {};
});
});
});
})();
});
......@@ -3,8 +3,7 @@ require('~/filtered_search/dropdown_utils');
require('~/filtered_search/filtered_search_tokenizer');
require('~/filtered_search/filtered_search_dropdown_manager');
(() => {
describe('Dropdown Utils', () => {
describe('Dropdown Utils', () => {
describe('getEscapedText', () => {
it('should return same word when it has no space', () => {
const escaped = gl.DropdownUtils.getEscapedText('textWithoutSpace');
......@@ -306,5 +305,4 @@ require('~/filtered_search/filtered_search_dropdown_manager');
});
});
});
});
})();
});
......@@ -3,8 +3,7 @@ require('~/filtered_search/filtered_search_visual_tokens');
require('~/filtered_search/filtered_search_tokenizer');
require('~/filtered_search/filtered_search_dropdown_manager');
(() => {
describe('Filtered Search Dropdown Manager', () => {
describe('Filtered Search Dropdown Manager', () => {
describe('addWordToInput', () => {
function getInputValue() {
return document.querySelector('.filtered-search').value;
......@@ -97,5 +96,4 @@ require('~/filtered_search/filtered_search_dropdown_manager');
});
});
});
});
})();
});
......@@ -6,8 +6,7 @@ require('~/filtered_search/filtered_search_dropdown_manager');
require('~/filtered_search/filtered_search_manager');
const FilteredSearchSpecHelper = require('../helpers/filtered_search_spec_helper');
(() => {
describe('Filtered Search Manager', () => {
describe('Filtered Search Manager', () => {
let input;
let manager;
let tokensContainer;
......@@ -272,5 +271,4 @@ const FilteredSearchSpecHelper = require('../helpers/filtered_search_spec_helper
expect(document.querySelector('.filtered-search-box').classList.contains('focus')).toEqual(false);
});
});
});
})();
});
require('~/extensions/array');
require('~/filtered_search/filtered_search_token_keys');
(() => {
describe('Filtered Search Token Keys', () => {
describe('Filtered Search Token Keys', () => {
describe('get', () => {
let tokenKeys;
......@@ -106,5 +105,4 @@ require('~/filtered_search/filtered_search_token_keys');
expect(result).toEqual(conditions[0]);
});
});
});
})();
});
......@@ -2,8 +2,7 @@ require('~/extensions/array');
require('~/filtered_search/filtered_search_token_keys');
require('~/filtered_search/filtered_search_tokenizer');
(() => {
describe('Filtered Search Tokenizer', () => {
describe('Filtered Search Tokenizer', () => {
describe('processTokens', () => {
it('returns for input containing only search value', () => {
const results = gl.FilteredSearchTokenizer.processTokens('searchTerm');
......@@ -131,5 +130,4 @@ require('~/filtered_search/filtered_search_tokenizer');
expect(results.tokens[0].symbol).toBe('~');
});
});
});
})();
});
import Vue from 'vue';
import asyncButtonComp from '~/vue_pipelines_index/components/async_button.vue';
import asyncButtonComp from '~/pipelines/components/async_button.vue';
describe('Pipelines Async Button', () => {
let component;
......
import Vue from 'vue';
import emptyStateComp from '~/vue_pipelines_index/components/empty_state.vue';
import emptyStateComp from '~/pipelines/components/empty_state.vue';
describe('Pipelines Empty State', () => {
let component;
......
import Vue from 'vue';
import errorStateComp from '~/vue_pipelines_index/components/error_state.vue';
import errorStateComp from '~/pipelines/components/error_state.vue';
describe('Pipelines Error State', () => {
let component;
......
import Vue from 'vue';
import navControlsComp from '~/vue_pipelines_index/components/nav_controls';
import navControlsComp from '~/pipelines/components/nav_controls';
describe('Pipelines Nav Controls', () => {
let NavControlsComponent;
......
import Vue from 'vue';
import pipelineUrlComp from '~/vue_pipelines_index/components/pipeline_url';
import pipelineUrlComp from '~/pipelines/components/pipeline_url';
describe('Pipeline Url Component', () => {
let PipelineUrlComponent;
......
import Vue from 'vue';
import pipelinesActionsComp from '~/vue_pipelines_index/components/pipelines_actions';
import pipelinesActionsComp from '~/pipelines/components/pipelines_actions';
describe('Pipelines Actions dropdown', () => {
let component;
......
import Vue from 'vue';
import artifactsComp from '~/vue_pipelines_index/components/pipelines_artifacts';
import artifactsComp from '~/pipelines/components/pipelines_artifacts';
describe('Pipelines Artifacts dropdown', () => {
let component;
......
import Vue from 'vue';
import pipelinesComp from '~/vue_pipelines_index/pipelines';
import Store from '~/vue_pipelines_index/stores/pipelines_store';
import pipelinesComp from '~/pipelines/pipelines';
import Store from '~/pipelines/stores/pipelines_store';
import pipelinesData from './mock_data';
describe('Pipelines', () => {
......
import PipelineStore from '~/vue_pipelines_index/stores/pipelines_store';
import PipelineStore from '~/pipelines/stores/pipelines_store';
describe('Pipelines Store', () => {
let store;
......
import Vue from 'vue';
import { SUCCESS_SVG } from '~/ci_status_icons';
import Stage from '~/vue_pipelines_index/components/stage';
import Stage from '~/pipelines/components/stage';
function minify(string) {
return string.replace(/\s/g, '');
......
......@@ -189,15 +189,10 @@ describe ContainerRegistry::Path do
end
context 'when project exists' do
let(:group) { create(:group, path: 'some_group') }
let(:project) do
create(:empty_project, group: group, name: 'some_project')
end
let(:group) { create(:group, path: 'Some_Group') }
before do
allow(path).to receive(:repository_project)
.and_return(project)
create(:empty_project, group: group, name: 'some_project')
end
context 'when project path equal repository path' do
......@@ -225,4 +220,27 @@ describe ContainerRegistry::Path do
end
end
end
describe '#project_path' do
context 'when project does not exist' do
let(:path) { 'some/name' }
it 'returns nil' do
expect(subject.project_path).to be_nil
end
end
context 'when project with uppercase characters in path exists' do
let(:path) { 'somegroup/myproject/my/image' }
let(:group) { create(:group, path: 'SomeGroup') }
before do
create(:empty_project, group: group, name: 'MyProject')
end
it 'returns downcased project path' do
expect(subject.project_path).to eq 'somegroup/myproject'
end
end
end
end
......@@ -1631,4 +1631,16 @@ describe User, models: true do
end
end
end
context '.active' do
before do
User.ghost
create(:user, name: 'user', state: 'active')
create(:user, name: 'user', state: 'blocked')
end
it 'only counts active and non internal users' do
expect(User.active.count).to eq(1)
end
end
end
......@@ -7,6 +7,7 @@ describe Groups::DestroyService, services: true do
let!(:group) { create(:group) }
let!(:nested_group) { create(:group, parent: group) }
let!(:project) { create(:empty_project, namespace: group) }
let!(:notification_setting) { create(:notification_setting, source: group)}
let!(:gitlab_shell) { Gitlab::Shell.new }
let!(:remove_path) { group.path + "+#{group.id}+deleted" }
......@@ -23,6 +24,7 @@ describe Groups::DestroyService, services: true do
it { expect(Group.unscoped.all).not_to include(group) }
it { expect(Group.unscoped.all).not_to include(nested_group) }
it { expect(Project.unscoped.all).not_to include(project) }
it { expect(NotificationSetting.unscoped.all).not_to include(notification_setting) }
end
context 'file system' do
......
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