Commit b782bf8b authored by Marin Jankovski's avatar Marin Jankovski

Merge branch 'ce-to-ee-2018-04-12' into 'master'

CE upstream - 2018-04-12 08:01 UTC

Closes gitaly#1126

See merge request gitlab-org/gitlab-ee!5335
parents e55f766c 581f10ee
...@@ -467,12 +467,12 @@ update-tests-metadata: ...@@ -467,12 +467,12 @@ update-tests-metadata:
- rspec_flaky/ - rspec_flaky/
policy: push policy: push
script: script:
- retry gem install fog-aws mime-types - retry gem install fog-aws mime-types activesupport
- scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec-pg_node_*.json - scripts/merge-reports ${KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec-pg_node_*.json
- scripts/merge-reports ${KNAPSACK_SPINACH_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/spinach-pg_node_*.json - scripts/merge-reports ${KNAPSACK_SPINACH_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/spinach-pg_node_*.json
- scripts/merge-reports ${EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec-pg-ee_node_*.json - scripts/merge-reports ${EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH} knapsack/${CI_PROJECT_NAME}/rspec-pg-ee_node_*.json
- scripts/merge-reports ${FLAKY_RSPEC_SUITE_REPORT_PATH} rspec_flaky/all_*_*.json - scripts/merge-reports ${FLAKY_RSPEC_SUITE_REPORT_PATH} rspec_flaky/all_*_*.json
- scripts/prune-old-flaky-specs ${FLAKY_RSPEC_SUITE_REPORT_PATH} - FLAKY_RSPEC_GENERATE_REPORT=1 scripts/prune-old-flaky-specs ${FLAKY_RSPEC_SUITE_REPORT_PATH}
- '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $KNAPSACK_RSPEC_SUITE_REPORT_PATH $KNAPSACK_SPINACH_SUITE_REPORT_PATH' - '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $KNAPSACK_RSPEC_SUITE_REPORT_PATH $KNAPSACK_SPINACH_SUITE_REPORT_PATH'
- '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH' - '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $EE_KNAPSACK_RSPEC_SUITE_REPORT_PATH'
- '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $FLAKY_RSPEC_SUITE_REPORT_PATH' - '[[ -z ${TESTS_METADATA_S3_BUCKET} ]] || scripts/sync-reports put $TESTS_METADATA_S3_BUCKET $FLAKY_RSPEC_SUITE_REPORT_PATH'
......
...@@ -5,7 +5,7 @@ import AccessorUtilities from '~/lib/utils/accessor'; ...@@ -5,7 +5,7 @@ import AccessorUtilities from '~/lib/utils/accessor';
* Does that setting the current selected tab in the localStorage * Does that setting the current selected tab in the localStorage
*/ */
export default class SigninTabsMemoizer { export default class SigninTabsMemoizer {
constructor({ currentTabKey = 'current_signin_tab', tabSelector = 'ul.nav-tabs' } = {}) { constructor({ currentTabKey = 'current_signin_tab', tabSelector = 'ul.new-session-tabs' } = {}) {
this.currentTabKey = currentTabKey; this.currentTabKey = currentTabKey;
this.tabSelector = tabSelector; this.tabSelector = tabSelector;
this.isLocalStorageAvailable = AccessorUtilities.isLocalStorageAccessSafe(); this.isLocalStorageAvailable = AccessorUtilities.isLocalStorageAccessSafe();
......
<script>
export default { export default {
name: 'time-tracking-estimate-only-pane', name: 'TimeTrackingEstimateOnlyPane',
props: { props: {
timeEstimateHumanReadable: { timeEstimateHumanReadable: {
type: String, type: String,
required: true, required: true,
}, },
}, },
template: `
<div class="time-tracking-estimate-only-pane">
<span class="bold">
{{ s__('TimeTracking|Estimated:') }}
</span>
{{ timeEstimateHumanReadable }}
</div>
`,
}; };
</script>
<template>
<div class="time-tracking-estimate-only-pane">
<span class="bold">
{{ s__('TimeTracking|Estimated:') }}
</span>
{{ timeEstimateHumanReadable }}
</div>
</template>
...@@ -3,7 +3,7 @@ import timeTrackingHelpState from './help_state'; ...@@ -3,7 +3,7 @@ import timeTrackingHelpState from './help_state';
import TimeTrackingCollapsedState from './collapsed_state.vue'; import TimeTrackingCollapsedState from './collapsed_state.vue';
import timeTrackingSpentOnlyPane from './spent_only_pane'; import timeTrackingSpentOnlyPane from './spent_only_pane';
import timeTrackingNoTrackingPane from './no_tracking_pane'; import timeTrackingNoTrackingPane from './no_tracking_pane';
import timeTrackingEstimateOnlyPane from './estimate_only_pane'; import TimeTrackingEstimateOnlyPane from './estimate_only_pane.vue';
import TimeTrackingComparisonPane from './comparison_pane.vue'; import TimeTrackingComparisonPane from './comparison_pane.vue';
import eventHub from '../../event_hub'; import eventHub from '../../event_hub';
...@@ -12,7 +12,7 @@ export default { ...@@ -12,7 +12,7 @@ export default {
name: 'IssuableTimeTracker', name: 'IssuableTimeTracker',
components: { components: {
TimeTrackingCollapsedState, TimeTrackingCollapsedState,
'time-tracking-estimate-only-pane': timeTrackingEstimateOnlyPane, TimeTrackingEstimateOnlyPane,
'time-tracking-spent-only-pane': timeTrackingSpentOnlyPane, 'time-tracking-spent-only-pane': timeTrackingSpentOnlyPane,
'time-tracking-no-tracking-pane': timeTrackingNoTrackingPane, 'time-tracking-no-tracking-pane': timeTrackingNoTrackingPane,
TimeTrackingComparisonPane, TimeTrackingComparisonPane,
......
...@@ -7,7 +7,10 @@ export default { ...@@ -7,7 +7,10 @@ export default {
statusIcon, statusIcon,
}, },
props: { props: {
mr: { type: Object, required: true }, mr: {
type: Object,
required: true,
},
}, },
}; };
</script> </script>
...@@ -20,13 +23,14 @@ export default { ...@@ -20,13 +23,14 @@ export default {
/> />
<div class="media-body space-children"> <div class="media-body space-children">
<span class="bold"> <span class="bold">
There are unresolved discussions. Please resolve these discussions {{ s__("mrWidget|There are unresolved discussions. Please resolve these discussions") }}
</span> </span>
<a <a
v-if="mr.createIssueToResolveDiscussionsPath" v-if="mr.createIssueToResolveDiscussionsPath"
:href="mr.createIssueToResolveDiscussionsPath" :href="mr.createIssueToResolveDiscussionsPath"
class="btn btn-default btn-xs js-create-issue"> class="btn btn-default btn-xs js-create-issue"
Create an issue to resolve them later >
{{ s__("mrWidget|Create an issue to resolve them later") }}
</a> </a>
</div> </div>
</div> </div>
......
...@@ -154,26 +154,10 @@ ...@@ -154,26 +154,10 @@
a { a {
width: 100%; width: 100%;
font-size: 18px; font-size: 18px;
margin-right: 0;
&:hover {
border: 1px solid transparent;
}
} }
&.active { &.active > a {
border-bottom: 1px solid $border-color; cursor: default;
a {
border: 0;
border-bottom: 2px solid $link-underline-blue;
margin-right: 0;
color: $black;
&:hover {
border-bottom: 2px solid $link-underline-blue;
}
}
} }
} }
} }
......
%ul.nav-links.nav-tabs.new-session-tabs.single-tab %ul.nav-links.new-session-tabs.single-tab
%li.active %li.active
%a= tab_title %a= tab_title
%ul.new-session-tabs.nav-links.nav-tabs{ class: ('custom-provider-tabs' if form_based_providers.any?) } %ul.nav-links.new-session-tabs{ class: ('custom-provider-tabs' if form_based_providers.any?) }
- if crowd_enabled? - if crowd_enabled?
%li.active %li.active
= link_to "Crowd", "#crowd", 'data-toggle' => 'tab' = link_to "Crowd", "#crowd", 'data-toggle' => 'tab'
......
%ul.nav-links.new-session-tabs.nav-tabs{ role: 'tablist' } %ul.nav-links.new-session-tabs{ role: 'tablist' }
%li.active{ role: 'presentation' } %li.active{ role: 'presentation' }
%a{ href: '#login-pane', data: { toggle: 'tab' }, role: 'tab' } Sign in %a{ href: '#login-pane', data: { toggle: 'tab' }, role: 'tab' } Sign in
- if allow_signup? - if allow_signup?
......
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
- else - else
Job has been erased #{time_ago_with_tooltip(@build.erased_at)} Job has been erased #{time_ago_with_tooltip(@build.erased_at)}
- if @build.has_trace? - if @build.running? || @build.has_trace?
.build-trace-container.prepend-top-default .build-trace-container.prepend-top-default
.top-bar.js-top-bar .top-bar.js-top-bar
.js-truncated-info.truncated-info.hidden-xs.pull-left.hidden< .js-truncated-info.truncated-info.hidden-xs.pull-left.hidden<
......
---
title: Refactor CSS to eliminate vertical misalignment of login nav
merge_request: 16275
author: Takuya Noguchi
type: fixed
---
title: Fix finding wiki file when Gitaly is enabled
merge_request:
author:
type: fixed
---
title: Move TimeTrackingEstimateOnlyPane vue component
merge_request: 18318
author: George Tsiolis
type: performance
---
title: Add i18n and update specs for UnresolvedDiscussions vue component
merge_request: 17866
author: George Tsiolis
type: performance
var path = require('path'); var path = require('path');
var webpack = require('webpack'); var webpack = require('webpack');
var argumentsParser = require('commander');
var webpackConfig = require('./webpack.config.js'); var webpackConfig = require('./webpack.config.js');
var ROOT_PATH = path.resolve(__dirname, '..'); var ROOT_PATH = path.resolve(__dirname, '..');
...@@ -14,6 +15,24 @@ if (webpackConfig.plugins) { ...@@ -14,6 +15,24 @@ if (webpackConfig.plugins) {
}); });
} }
var testFiles = argumentsParser
.option(
'-f, --filter-spec [filter]',
'Filter run spec files by path. Multiple filters are like a logical OR.',
(val, memo) => {
memo.push(val);
return memo;
},
[]
)
.parse(process.argv).filterSpec;
webpackConfig.plugins.push(
new webpack.DefinePlugin({
'process.env.TEST_FILES': JSON.stringify(testFiles),
})
);
webpackConfig.devtool = 'cheap-inline-source-map'; webpackConfig.devtool = 'cheap-inline-source-map';
// Karma configuration // Karma configuration
......
...@@ -131,6 +131,9 @@ There is also and alternative method to [translate messages from validation erro ...@@ -131,6 +131,9 @@ There is also and alternative method to [translate messages from validation erro
### Interpolation ### Interpolation
Placeholders in translated text should match the code style of the respective source file.
For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript.
- In Ruby/HAML: - In Ruby/HAML:
```ruby ```ruby
...@@ -141,11 +144,19 @@ There is also and alternative method to [translate messages from validation erro ...@@ -141,11 +144,19 @@ There is also and alternative method to [translate messages from validation erro
```js ```js
import { __, sprintf } from '~/locale'; import { __, sprintf } from '~/locale';
sprintf(__('Hello %{username}'), { username: 'Joe' }) => 'Hello Joe'
sprintf(__('Hello %{username}'), { username: 'Joe' }); // => 'Hello Joe'
``` ```
The placeholders should match the code style of the respective source file. By default, `sprintf` escapes the placeholder values.
For example use `%{created_at}` in Ruby but `%{createdAt}` in JavaScript. If you want to take care of that yourself, you can pass `false` as third argument.
```js
import { __, sprintf } from '~/locale';
sprintf(__('This is %{value}'), { value: '<strong>bold</strong>' }); // => 'This is &lt;strong&gt;bold&lt;/strong&gt;'
sprintf(__('This is %{value}'), { value: '<strong>bold</strong>' }, false); // => 'This is <strong>bold</strong>'
```
### Plurals ### Plurals
......
...@@ -152,19 +152,33 @@ is sufficient (and saves you some time). ...@@ -152,19 +152,33 @@ is sufficient (and saves you some time).
### Live testing and focused testing ### Live testing and focused testing
While developing locally, it may be helpful to keep karma running so that you While developing locally, it may be helpful to keep karma running so that you
can get instant feedback on as you write tests and modify code. To do this can get instant feedback on as you write tests and modify code. To do this
you can start karma with `npm run karma-start`. It will compile the javascript you can start karma with `yarn run karma-start`. It will compile the javascript
assets and run a server at `http://localhost:9876/` where it will automatically assets and run a server at `http://localhost:9876/` where it will automatically
run the tests on any browser which connects to it. You can enter that url on run the tests on any browser which connects to it. You can enter that url on
multiple browsers at once to have it run the tests on each in parallel. multiple browsers at once to have it run the tests on each in parallel.
While karma is running, any changes you make will instantly trigger a recompile While karma is running, any changes you make will instantly trigger a recompile
and retest of the entire test suite, so you can see instantly if you've broken and retest of the entire test suite, so you can see instantly if you've broken
a test with your changes. You can use [jasmine focused][jasmine-focus] or a test with your changes. You can use [jasmine focused][jasmine-focus] or
excluded tests (with `fdescribe` or `xdescribe`) to get karma to run only the excluded tests (with `fdescribe` or `xdescribe`) to get karma to run only the
tests you want while you're working on a specific feature, but make sure to tests you want while you're working on a specific feature, but make sure to
remove these directives when you commit your code. remove these directives when you commit your code.
It is also possible to only run karma on specific folders or files by filtering
the run tests via the argument `--filter-spec` or short `-f`:
```bash
# Run all files
yarn karma-start
# Run specific spec files
yarn karma-start --filter-spec profile/account/components/update_username_spec.js
# Run specific spec folder
yarn karma-start --filter-spec profile/account/components/
# Run all specs which path contain vue_shared or vie
yarn karma-start -f vue_shared -f vue_mr_widget
```
## RSpec feature integration tests ## RSpec feature integration tests
Information on setting up and running RSpec integration tests with Information on setting up and running RSpec integration tests with
...@@ -176,7 +190,7 @@ Information on setting up and running RSpec integration tests with ...@@ -176,7 +190,7 @@ Information on setting up and running RSpec integration tests with
Similar errors will be thrown if you're using JavaScript features not yet Similar errors will be thrown if you're using JavaScript features not yet
supported by the PhantomJS test runner which is used for both Karma and RSpec supported by the PhantomJS test runner which is used for both Karma and RSpec
tests. We polyfill some JavaScript objects for older browsers, but some tests. We polyfill some JavaScript objects for older browsers, but some
features are still unavailable: features are still unavailable:
- Array.from - Array.from
...@@ -188,7 +202,7 @@ features are still unavailable: ...@@ -188,7 +202,7 @@ features are still unavailable:
- Symbol/Symbol.iterator - Symbol/Symbol.iterator
- Spread - Spread
Until these are polyfilled appropriately, they should not be used. Please Until these are polyfilled appropriately, they should not be used. Please
update this list with additional unsupported features. update this list with additional unsupported features.
### RSpec errors due to JavaScript ### RSpec errors due to JavaScript
...@@ -223,7 +237,7 @@ end ...@@ -223,7 +237,7 @@ end
### Spinach errors due to missing JavaScript ### Spinach errors due to missing JavaScript
NOTE: **Note:** Since we are discouraging the use of Spinach when writing new NOTE: **Note:** Since we are discouraging the use of Spinach when writing new
feature tests, you shouldn't ever need to use this. This information is kept feature tests, you shouldn't ever need to use this. This information is kept
available for legacy purposes only. available for legacy purposes only.
In Spinach, the JavaScript driver is enabled differently. In the `*.feature` In Spinach, the JavaScript driver is enabled differently. In the `*.feature`
......
...@@ -3,6 +3,14 @@ module Gitlab ...@@ -3,6 +3,14 @@ module Gitlab
module Status module Status
module Build module Build
module Common module Common
def illustration
{
image: 'illustrations/skipped-job_empty.svg',
size: 'svg-430',
title: _('This job does not have a trace.')
}
end
def has_details? def has_details?
can?(user, :read_build, subject) can?(user, :read_build, subject)
end end
......
...@@ -136,7 +136,7 @@ module Gitlab ...@@ -136,7 +136,7 @@ module Gitlab
wiki_file = nil wiki_file = nil
response.each do |message| response.each do |message|
next unless message.name.present? next unless message.name.present? || wiki_file
if wiki_file if wiki_file
wiki_file.raw_data << message.raw_data wiki_file.raw_data << message.raw_data
......
...@@ -5,8 +5,8 @@ ...@@ -5,8 +5,8 @@
"eslint": "eslint --max-warnings 0 --ext .js,.vue .", "eslint": "eslint --max-warnings 0 --ext .js,.vue .",
"eslint-fix": "eslint --max-warnings 0 --ext .js,.vue --fix .", "eslint-fix": "eslint --max-warnings 0 --ext .js,.vue --fix .",
"eslint-report": "eslint --max-warnings 0 --ext .js,.vue --format html --output-file ./eslint-report.html .", "eslint-report": "eslint --max-warnings 0 --ext .js,.vue --format html --output-file ./eslint-report.html .",
"karma": "karma start config/karma.config.js --single-run", "karma": "karma start --single-run true config/karma.config.js",
"karma-coverage": "BABEL_ENV=coverage karma start config/karma.config.js --single-run", "karma-coverage": "BABEL_ENV=coverage karma start --single-run true config/karma.config.js",
"karma-start": "karma start config/karma.config.js", "karma-start": "karma start config/karma.config.js",
"prettier-staged": "node ./scripts/frontend/prettier.js", "prettier-staged": "node ./scripts/frontend/prettier.js",
"prettier-staged-save": "node ./scripts/frontend/prettier.js save", "prettier-staged-save": "node ./scripts/frontend/prettier.js save",
...@@ -100,6 +100,7 @@ ...@@ -100,6 +100,7 @@
"axios-mock-adapter": "^1.10.0", "axios-mock-adapter": "^1.10.0",
"babel-eslint": "^8.0.2", "babel-eslint": "^8.0.2",
"babel-plugin-istanbul": "^4.1.5", "babel-plugin-istanbul": "^4.1.5",
"commander": "^2.15.1",
"eslint": "^3.18.0", "eslint": "^3.18.0",
"eslint-config-airbnb-base": "^10.0.1", "eslint-config-airbnb-base": "^10.0.1",
"eslint-import-resolver-webpack": "^0.8.3", "eslint-import-resolver-webpack": "^0.8.3",
......
#!/usr/bin/env ruby #!/usr/bin/env ruby
# lib/rspec_flaky/flaky_examples_collection.rb is requiring
# `active_support/hash_with_indifferent_access`, and we install the `activesupport`
# gem manually on the CI
require 'rubygems'
require_relative '../lib/rspec_flaky/report' require_relative '../lib/rspec_flaky/report'
report_file = ARGV.shift report_file = ARGV.shift
......
...@@ -475,6 +475,17 @@ feature 'Jobs' do ...@@ -475,6 +475,17 @@ feature 'Jobs' do
expect(page).to have_content('This job has been skipped') expect(page).to have_content('This job has been skipped')
end end
end end
context 'when job is failed but has no trace' do
let(:job) { create(:ci_build, :failed, pipeline: pipeline) }
it 'renders empty state' do
visit project_job_path(project, job)
expect(job).not_to have_trace
expect(page).to have_content('This job does not have a trace.')
end
end
end end
describe "POST /:project/jobs/:id/cancel", :js do describe "POST /:project/jobs/:id/cancel", :js do
......
...@@ -406,7 +406,7 @@ feature 'Login' do ...@@ -406,7 +406,7 @@ feature 'Login' do
end end
def ensure_one_active_tab def ensure_one_active_tab
expect(page).to have_selector('.nav-tabs > li.active', count: 1) expect(page).to have_selector('ul.new-session-tabs > li.active', count: 1)
end end
def ensure_one_active_pane def ensure_one_active_pane
......
%ul.nav.nav-tabs.linked-tabs %ul.nav-links.new-session-tabs.linked-tabs
%li %li
%a{ href: 'foo/bar/1', data: { target: 'div#tab1', action: 'tab1', toggle: 'tab' } } %a{ href: 'foo/bar/1', data: { target: 'div#tab1', action: 'tab1', toggle: 'tab' } }
Tab 1 Tab 1
......
%ul.nav-tabs %ul.nav-links.new-session-tabs
%li.active
%a{ href: '#ldap' } LDAP
%li %li
%a.active{ id: 'standard', href: '#standard'} Standard %a{ href: '#login-pane'} Standard
%li
%a{ id: 'ldap', href: '#ldap'} Ldap
...@@ -4,7 +4,7 @@ import SigninTabsMemoizer from '~/pages/sessions/new/signin_tabs_memoizer'; ...@@ -4,7 +4,7 @@ import SigninTabsMemoizer from '~/pages/sessions/new/signin_tabs_memoizer';
(() => { (() => {
describe('SigninTabsMemoizer', () => { describe('SigninTabsMemoizer', () => {
const fixtureTemplate = 'static/signin_tabs.html.raw'; const fixtureTemplate = 'static/signin_tabs.html.raw';
const tabSelector = 'ul.nav-tabs'; const tabSelector = 'ul.new-session-tabs';
const currentTabKey = 'current_signin_tab'; const currentTabKey = 'current_signin_tab';
let memo; let memo;
...@@ -27,7 +27,7 @@ import SigninTabsMemoizer from '~/pages/sessions/new/signin_tabs_memoizer'; ...@@ -27,7 +27,7 @@ import SigninTabsMemoizer from '~/pages/sessions/new/signin_tabs_memoizer';
it('does nothing if no tab was previously selected', () => { it('does nothing if no tab was previously selected', () => {
createMemoizer(); createMemoizer();
expect(document.querySelector('li a.active').getAttribute('id')).toEqual('standard'); expect(document.querySelector(`${tabSelector} > li.active a`).getAttribute('href')).toEqual('#ldap');
}); });
it('shows last selected tab on boot', () => { it('shows last selected tab on boot', () => {
...@@ -48,9 +48,9 @@ import SigninTabsMemoizer from '~/pages/sessions/new/signin_tabs_memoizer'; ...@@ -48,9 +48,9 @@ import SigninTabsMemoizer from '~/pages/sessions/new/signin_tabs_memoizer';
it('saves last selected tab on change', () => { it('saves last selected tab on change', () => {
createMemoizer(); createMemoizer();
document.getElementById('standard').click(); document.querySelector('a[href="#login-pane"]').click();
expect(memo.readData()).toEqual('#standard'); expect(memo.readData()).toEqual('#login-pane');
}); });
it('overrides last selected tab with hash tag when given', () => { it('overrides last selected tab with hash tag when given', () => {
......
...@@ -4,6 +4,7 @@ import 'vendor/jasmine-jquery'; ...@@ -4,6 +4,7 @@ import 'vendor/jasmine-jquery';
import '~/commons'; import '~/commons';
import Vue from 'vue'; import Vue from 'vue';
import VueResource from 'vue-resource'; import VueResource from 'vue-resource';
import Translate from '~/vue_shared/translate';
import { getDefaultAdapter } from '~/lib/utils/axios_utils'; import { getDefaultAdapter } from '~/lib/utils/axios_utils';
import { FIXTURES_PATH, TEST_HOST } from './test_constants'; import { FIXTURES_PATH, TEST_HOST } from './test_constants';
...@@ -27,6 +28,7 @@ Vue.config.errorHandler = function(err) { ...@@ -27,6 +28,7 @@ Vue.config.errorHandler = function(err) {
}; };
Vue.use(VueResource); Vue.use(VueResource);
Vue.use(Translate);
// enable test fixtures // enable test fixtures
jasmine.getFixtures().fixturesPath = FIXTURES_PATH; jasmine.getFixtures().fixturesPath = FIXTURES_PATH;
...@@ -69,11 +71,21 @@ beforeEach(() => { ...@@ -69,11 +71,21 @@ beforeEach(() => {
const axiosDefaultAdapter = getDefaultAdapter(); const axiosDefaultAdapter = getDefaultAdapter();
let testFiles = process.env.TEST_FILES || [];
if (testFiles.length > 0) {
testFiles = testFiles.map(path => path.replace(/^spec\/javascripts\//, '').replace(/\.js$/, ''));
console.log(`Running only tests matching: ${testFiles}`);
} else {
console.log('Running all tests');
}
// render all of our tests // render all of our tests
const testsContext = require.context('.', true, /_spec$/); const testsContext = require.context('.', true, /_spec$/);
testsContext.keys().forEach(function(path) { testsContext.keys().forEach(function(path) {
try { try {
testsContext(path); if (testFiles.length === 0 || testFiles.some(p => path.includes(p))) {
testsContext(path);
}
} catch (err) { } catch (err) {
console.error('[ERROR] Unable to load spec: ', path); console.error('[ERROR] Unable to load spec: ', path);
describe('Test bundle', function() { describe('Test bundle', function() {
......
import Vue from 'vue'; import Vue from 'vue';
import UnresolvedDiscussions from '~/vue_merge_request_widget/components/states/unresolved_discussions.vue'; import UnresolvedDiscussions from '~/vue_merge_request_widget/components/states/unresolved_discussions.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
describe('UnresolvedDiscussions', () => { describe('UnresolvedDiscussions', () => {
describe('props', () => { const Component = Vue.extend(UnresolvedDiscussions);
it('should have props', () => { let vm;
const { mr } = UnresolvedDiscussions.props;
expect(mr.type instanceof Object).toBeTruthy(); afterEach(() => {
expect(mr.required).toBeTruthy(); vm.$destroy();
});
}); });
describe('template', () => { describe('with discussions path', () => {
let el;
let vm;
const path = 'foo/bar';
beforeEach(() => { beforeEach(() => {
const Component = Vue.extend(UnresolvedDiscussions); vm = mountComponent(Component, { mr: {
const mr = { createIssueToResolveDiscussionsPath: gl.TEST_HOST,
createIssueToResolveDiscussionsPath: path, } });
};
vm = new Component({
el: document.createElement('div'),
propsData: { mr },
});
el = vm.$el;
}); });
it('should have correct elements', () => { it('should have correct elements', () => {
expect(el.classList.contains('mr-widget-body')).toBeTruthy(); expect(vm.$el.innerText).toContain('There are unresolved discussions. Please resolve these discussions');
expect(el.innerText).toContain('There are unresolved discussions. Please resolve these discussions'); expect(vm.$el.innerText).toContain('Create an issue to resolve them later');
expect(el.innerText).toContain('Create an issue to resolve them later'); expect(vm.$el.querySelector('.js-create-issue').getAttribute('href')).toEqual(gl.TEST_HOST);
expect(el.querySelector('.js-create-issue').getAttribute('href')).toEqual(path);
}); });
});
it('should not show create issue button if user cannot create issue', (done) => { describe('without discussions path', () => {
vm.mr.createIssueToResolveDiscussionsPath = ''; beforeEach(() => {
vm = mountComponent(Component, { mr: {} });
});
Vue.nextTick(() => { it('should not show create issue link if user cannot create issue', () => {
expect(el.querySelector('.js-create-issue')).toEqual(null); expect(vm.$el.innerText).toContain('There are unresolved discussions. Please resolve these discussions');
done(); expect(vm.$el.querySelector('.js-create-issue')).toEqual(null);
});
}); });
}); });
}); });
...@@ -38,4 +38,10 @@ describe Gitlab::Ci::Status::Build::Common do ...@@ -38,4 +38,10 @@ describe Gitlab::Ci::Status::Build::Common do
expect(subject.details_path).to include "jobs/#{build.id}" expect(subject.details_path).to include "jobs/#{build.id}"
end end
end end
describe '#illustration' do
it 'provides a fallback empty state illustration' do
expect(subject.illustration).not_to be_empty
end
end
end end
...@@ -75,7 +75,8 @@ describe Gitlab::Ci::Status::Build::Factory do ...@@ -75,7 +75,8 @@ describe Gitlab::Ci::Status::Build::Factory do
it 'matches correct extended statuses' do it 'matches correct extended statuses' do
expect(factory.extended_statuses) expect(factory.extended_statuses)
.to eq [Gitlab::Ci::Status::Build::Retryable, Gitlab::Ci::Status::Build::Failed] .to eq [Gitlab::Ci::Status::Build::Retryable,
Gitlab::Ci::Status::Build::Failed]
end end
it 'fabricates a failed build status' do it 'fabricates a failed build status' do
...@@ -94,7 +95,7 @@ describe Gitlab::Ci::Status::Build::Factory do ...@@ -94,7 +95,7 @@ describe Gitlab::Ci::Status::Build::Factory do
end end
context 'when build is allowed to fail' do context 'when build is allowed to fail' do
let(:build) { create(:ci_build, :failed, :allowed_to_fail) } let(:build) { create(:ci_build, :failed, :allowed_to_fail, :trace_artifact) }
it 'matches correct core status' do it 'matches correct core status' do
expect(factory.core_status).to be_a Gitlab::Ci::Status::Failed expect(factory.core_status).to be_a Gitlab::Ci::Status::Failed
......
...@@ -180,11 +180,12 @@ describe ProjectWiki do ...@@ -180,11 +180,12 @@ describe ProjectWiki do
describe '#find_file' do describe '#find_file' do
shared_examples 'finding a wiki file' do shared_examples 'finding a wiki file' do
let(:image) { File.open(Rails.root.join('spec', 'fixtures', 'big-image.png')) }
before do before do
file = File.open(Rails.root.join('spec', 'fixtures', 'dk.png'))
subject.wiki # Make sure the wiki repo exists subject.wiki # Make sure the wiki repo exists
BareRepoOperations.new(subject.repository.path_to_repo).commit_file(file, 'image.png') BareRepoOperations.new(subject.repository.path_to_repo).commit_file(image, 'image.png')
end end
it 'returns the latest version of the file if it exists' do it 'returns the latest version of the file if it exists' do
...@@ -200,6 +201,13 @@ describe ProjectWiki do ...@@ -200,6 +201,13 @@ describe ProjectWiki do
file = subject.find_file('image.png') file = subject.find_file('image.png')
expect(file).to be_a Gitlab::Git::WikiFile expect(file).to be_a Gitlab::Git::WikiFile
end end
it 'returns the whole file' do
file = subject.find_file('image.png')
image.rewind
expect(file.raw_data.b).to eq(image.read.b)
end
end end
context 'when Gitaly wiki_find_file is enabled' do context 'when Gitaly wiki_find_file is enabled' do
......
...@@ -1859,9 +1859,9 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5: ...@@ -1859,9 +1859,9 @@ combined-stream@1.0.6, combined-stream@^1.0.5, combined-stream@~1.0.5:
dependencies: dependencies:
delayed-stream "~1.0.0" delayed-stream "~1.0.0"
commander@^2.13.0, commander@^2.9.0: commander@^2.13.0, commander@^2.15.1, commander@^2.9.0:
version "2.14.1" version "2.15.1"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.14.1.tgz#2235123e37af8ca3c65df45b026dbd357b01b9aa" resolved "https://registry.yarnpkg.com/commander/-/commander-2.15.1.tgz#df46e867d0fc2aec66a34662b406a9ccafff5b0f"
commondir@^1.0.1: commondir@^1.0.1:
version "1.0.1" version "1.0.1"
......
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