summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-02-28 12:09:05 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-02-28 12:09:05 +0000
commit5426ca9908085087d465fa52800335f408eb965a (patch)
tree6b442cff02fda9402fc7bb9cf9986e363dd5aaa6 /spec
parent67cdfd2683b89bce260600fa8925eefdcdf9e3e5 (diff)
downloadgitlab-ce-5426ca9908085087d465fa52800335f408eb965a.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/deploy_token.json31
-rw-r--r--spec/fixtures/api/schemas/public_api/v4/deploy_tokens.json6
-rw-r--r--spec/frontend/frequent_items/components/frequent_items_list_item_spec.js4
-rw-r--r--spec/frontend/frequent_items/components/frequent_items_list_spec.js101
-rw-r--r--spec/frontend/frequent_items/mock_data.js52
-rw-r--r--spec/frontend/lib/utils/unit_format/formatter_factory_spec.js282
-rw-r--r--spec/frontend/lib/utils/unit_format/index_spec.js158
-rw-r--r--spec/frontend/notes/components/note_app_spec.js11
-rw-r--r--spec/javascripts/frequent_items/components/frequent_items_list_spec.js90
-rw-r--r--spec/models/issue_spec.rb68
-rw-r--r--spec/policies/project_policy_spec.rb2
-rw-r--r--spec/requests/api/deploy_tokens_spec.rb69
12 files changed, 560 insertions, 314 deletions
diff --git a/spec/fixtures/api/schemas/public_api/v4/deploy_token.json b/spec/fixtures/api/schemas/public_api/v4/deploy_token.json
new file mode 100644
index 00000000000..c8a8b8d1e7d
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/deploy_token.json
@@ -0,0 +1,31 @@
+{
+ "type": "object",
+ "required": [
+ "id",
+ "name",
+ "username",
+ "expires_at",
+ "scopes"
+ ],
+ "properties": {
+ "id": {
+ "type": "integer"
+ },
+ "name": {
+ "type": "string"
+ },
+ "username": {
+ "type": "string"
+ },
+ "expires_at": {
+ "type": "date"
+ },
+ "scopes": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "additionalProperties": false
+} \ No newline at end of file
diff --git a/spec/fixtures/api/schemas/public_api/v4/deploy_tokens.json b/spec/fixtures/api/schemas/public_api/v4/deploy_tokens.json
new file mode 100644
index 00000000000..71c30cb2a73
--- /dev/null
+++ b/spec/fixtures/api/schemas/public_api/v4/deploy_tokens.json
@@ -0,0 +1,6 @@
+{
+ "type": "array",
+ "items": {
+ "$ref": "deploy_token.json"
+ }
+} \ No newline at end of file
diff --git a/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js b/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js
index 925699f5623..ab5784b8f7a 100644
--- a/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js
+++ b/spec/frontend/frequent_items/components/frequent_items_list_item_spec.js
@@ -1,9 +1,7 @@
import { shallowMount } from '@vue/test-utils';
import { trimText } from 'helpers/text_helper';
import frequentItemsListItemComponent from '~/frequent_items/components/frequent_items_list_item.vue';
-import mockData from '../mock_data'; // can also use 'mockGroup', but not useful to test here
-
-const mockProject = mockData();
+import { mockProject } from '../mock_data'; // can also use 'mockGroup', but not useful to test here
describe('FrequentItemsListItemComponent', () => {
let wrapper;
diff --git a/spec/frontend/frequent_items/components/frequent_items_list_spec.js b/spec/frontend/frequent_items/components/frequent_items_list_spec.js
new file mode 100644
index 00000000000..238fd508053
--- /dev/null
+++ b/spec/frontend/frequent_items/components/frequent_items_list_spec.js
@@ -0,0 +1,101 @@
+import { mount } from '@vue/test-utils';
+import frequentItemsListComponent from '~/frequent_items/components/frequent_items_list.vue';
+import frequentItemsListItemComponent from '~/frequent_items/components/frequent_items_list_item.vue';
+import { mockFrequentProjects } from '../mock_data';
+
+describe('FrequentItemsListComponent', () => {
+ let wrapper;
+
+ const createComponent = (props = {}) => {
+ wrapper = mount(frequentItemsListComponent, {
+ propsData: {
+ namespace: 'projects',
+ items: mockFrequentProjects,
+ isFetchFailed: false,
+ hasSearchQuery: false,
+ matcher: 'lab',
+ ...props,
+ },
+ });
+ };
+
+ afterEach(() => {
+ wrapper.destroy();
+ });
+
+ describe('computed', () => {
+ describe('isListEmpty', () => {
+ it('should return `true` or `false` representing whether if `items` is empty or not with projects', () => {
+ createComponent({
+ items: [],
+ });
+
+ expect(wrapper.vm.isListEmpty).toBe(true);
+
+ wrapper.setProps({
+ items: mockFrequentProjects,
+ });
+
+ expect(wrapper.vm.isListEmpty).toBe(false);
+ });
+ });
+
+ describe('fetched item messages', () => {
+ it('should return appropriate empty list message based on value of `localStorageFailed` prop with projects', () => {
+ createComponent({
+ isFetchFailed: true,
+ });
+
+ expect(wrapper.vm.listEmptyMessage).toBe(
+ 'This feature requires browser localStorage support',
+ );
+
+ wrapper.setProps({
+ isFetchFailed: false,
+ });
+
+ expect(wrapper.vm.listEmptyMessage).toBe('Projects you visit often will appear here');
+ });
+ });
+
+ describe('searched item messages', () => {
+ it('should return appropriate empty list message based on value of `searchFailed` prop with projects', () => {
+ createComponent({
+ hasSearchQuery: true,
+ isFetchFailed: true,
+ });
+
+ expect(wrapper.vm.listEmptyMessage).toBe('Something went wrong on our end.');
+
+ wrapper.setProps({
+ isFetchFailed: false,
+ });
+
+ expect(wrapper.vm.listEmptyMessage).toBe('Sorry, no projects matched your search');
+ });
+ });
+ });
+
+ describe('template', () => {
+ it('should render component element with list of projects', () => {
+ createComponent();
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.classes('frequent-items-list-container')).toBe(true);
+ expect(wrapper.findAll({ ref: 'frequentItemsList' })).toHaveLength(1);
+ expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(5);
+ });
+ });
+
+ it('should render component element with empty message', () => {
+ createComponent({
+ items: [],
+ });
+
+ return wrapper.vm.$nextTick(() => {
+ expect(wrapper.vm.$el.querySelectorAll('li.section-empty')).toHaveLength(1);
+ expect(wrapper.findAll(frequentItemsListItemComponent)).toHaveLength(0);
+ });
+ });
+ });
+});
diff --git a/spec/frontend/frequent_items/mock_data.js b/spec/frontend/frequent_items/mock_data.js
index 81f34053543..5cd4cddd877 100644
--- a/spec/frontend/frequent_items/mock_data.js
+++ b/spec/frontend/frequent_items/mock_data.js
@@ -1,9 +1,57 @@
import { TEST_HOST } from 'helpers/test_constants';
-export default () => ({
+export const mockFrequentProjects = [
+ {
+ id: 1,
+ name: 'GitLab Community Edition',
+ namespace: 'gitlab-org / gitlab-ce',
+ webUrl: `${TEST_HOST}/gitlab-org/gitlab-foss`,
+ avatarUrl: null,
+ frequency: 1,
+ lastAccessedOn: Date.now(),
+ },
+ {
+ id: 2,
+ name: 'GitLab CI',
+ namespace: 'gitlab-org / gitlab-ci',
+ webUrl: `${TEST_HOST}/gitlab-org/gitlab-ci`,
+ avatarUrl: null,
+ frequency: 9,
+ lastAccessedOn: Date.now(),
+ },
+ {
+ id: 3,
+ name: 'Typeahead.Js',
+ namespace: 'twitter / typeahead-js',
+ webUrl: `${TEST_HOST}/twitter/typeahead-js`,
+ avatarUrl: '/uploads/-/system/project/avatar/7/TWBS.png',
+ frequency: 2,
+ lastAccessedOn: Date.now(),
+ },
+ {
+ id: 4,
+ name: 'Intel',
+ namespace: 'platform / hardware / bsp / intel',
+ webUrl: `${TEST_HOST}/platform/hardware/bsp/intel`,
+ avatarUrl: null,
+ frequency: 3,
+ lastAccessedOn: Date.now(),
+ },
+ {
+ id: 5,
+ name: 'v4.4',
+ namespace: 'platform / hardware / bsp / kernel / common / v4.4',
+ webUrl: `${TEST_HOST}/platform/hardware/bsp/kernel/common/v4.4`,
+ avatarUrl: null,
+ frequency: 8,
+ lastAccessedOn: Date.now(),
+ },
+];
+
+export const mockProject = {
id: 1,
name: 'GitLab Community Edition',
namespace: 'gitlab-org / gitlab-ce',
webUrl: `${TEST_HOST}/gitlab-org/gitlab-foss`,
avatarUrl: null,
-});
+};
diff --git a/spec/frontend/lib/utils/unit_format/formatter_factory_spec.js b/spec/frontend/lib/utils/unit_format/formatter_factory_spec.js
index 071ecde6a6d..26b942c3567 100644
--- a/spec/frontend/lib/utils/unit_format/formatter_factory_spec.js
+++ b/spec/frontend/lib/utils/unit_format/formatter_factory_spec.js
@@ -2,6 +2,7 @@ import {
numberFormatter,
suffixFormatter,
scaledSIFormatter,
+ scaledBinaryFormatter,
} from '~/lib/utils/unit_format/formatter_factory';
describe('unit_format/formatter_factory', () => {
@@ -12,28 +13,28 @@ describe('unit_format/formatter_factory', () => {
});
it('formats a integer', () => {
- expect(formatNumber(1)).toEqual('1');
- expect(formatNumber(100)).toEqual('100');
- expect(formatNumber(1000)).toEqual('1,000');
- expect(formatNumber(10000)).toEqual('10,000');
- expect(formatNumber(1000000)).toEqual('1,000,000');
+ expect(formatNumber(1)).toBe('1');
+ expect(formatNumber(100)).toBe('100');
+ expect(formatNumber(1000)).toBe('1,000');
+ expect(formatNumber(10000)).toBe('10,000');
+ expect(formatNumber(1000000)).toBe('1,000,000');
});
it('formats a floating point number', () => {
- expect(formatNumber(0.1)).toEqual('0.1');
- expect(formatNumber(0.1, 0)).toEqual('0');
- expect(formatNumber(0.1, 2)).toEqual('0.10');
- expect(formatNumber(0.1, 3)).toEqual('0.100');
+ expect(formatNumber(0.1)).toBe('0.1');
+ expect(formatNumber(0.1, 0)).toBe('0');
+ expect(formatNumber(0.1, 2)).toBe('0.10');
+ expect(formatNumber(0.1, 3)).toBe('0.100');
- expect(formatNumber(12.345)).toEqual('12.345');
- expect(formatNumber(12.345, 2)).toEqual('12.35');
- expect(formatNumber(12.345, 4)).toEqual('12.3450');
+ expect(formatNumber(12.345)).toBe('12.345');
+ expect(formatNumber(12.345, 2)).toBe('12.35');
+ expect(formatNumber(12.345, 4)).toBe('12.3450');
});
it('formats a large integer with a length limit', () => {
- expect(formatNumber(10 ** 7, undefined)).toEqual('10,000,000');
- expect(formatNumber(10 ** 7, undefined, 9)).toEqual('1.00e+7');
- expect(formatNumber(10 ** 7, undefined, 10)).toEqual('10,000,000');
+ expect(formatNumber(10 ** 7, undefined)).toBe('10,000,000');
+ expect(formatNumber(10 ** 7, undefined, 9)).toBe('1.00e+7');
+ expect(formatNumber(10 ** 7, undefined, 10)).toBe('10,000,000');
});
});
@@ -44,112 +45,112 @@ describe('unit_format/formatter_factory', () => {
});
it('formats a integer', () => {
- expect(formatSuffix(1)).toEqual('1pop.');
- expect(formatSuffix(100)).toEqual('100pop.');
- expect(formatSuffix(1000)).toEqual('1,000pop.');
- expect(formatSuffix(10000)).toEqual('10,000pop.');
- expect(formatSuffix(1000000)).toEqual('1,000,000pop.');
+ expect(formatSuffix(1)).toBe('1pop.');
+ expect(formatSuffix(100)).toBe('100pop.');
+ expect(formatSuffix(1000)).toBe('1,000pop.');
+ expect(formatSuffix(10000)).toBe('10,000pop.');
+ expect(formatSuffix(1000000)).toBe('1,000,000pop.');
});
it('formats a floating point number', () => {
- expect(formatSuffix(0.1)).toEqual('0.1pop.');
- expect(formatSuffix(0.1, 0)).toEqual('0pop.');
- expect(formatSuffix(0.1, 2)).toEqual('0.10pop.');
- expect(formatSuffix(0.1, 3)).toEqual('0.100pop.');
+ expect(formatSuffix(0.1)).toBe('0.1pop.');
+ expect(formatSuffix(0.1, 0)).toBe('0pop.');
+ expect(formatSuffix(0.1, 2)).toBe('0.10pop.');
+ expect(formatSuffix(0.1, 3)).toBe('0.100pop.');
- expect(formatSuffix(12.345)).toEqual('12.345pop.');
- expect(formatSuffix(12.345, 2)).toEqual('12.35pop.');
- expect(formatSuffix(12.345, 4)).toEqual('12.3450pop.');
+ expect(formatSuffix(12.345)).toBe('12.345pop.');
+ expect(formatSuffix(12.345, 2)).toBe('12.35pop.');
+ expect(formatSuffix(12.345, 4)).toBe('12.3450pop.');
});
it('formats a negative integer', () => {
- expect(formatSuffix(-1)).toEqual('-1pop.');
- expect(formatSuffix(-100)).toEqual('-100pop.');
- expect(formatSuffix(-1000)).toEqual('-1,000pop.');
- expect(formatSuffix(-10000)).toEqual('-10,000pop.');
- expect(formatSuffix(-1000000)).toEqual('-1,000,000pop.');
+ expect(formatSuffix(-1)).toBe('-1pop.');
+ expect(formatSuffix(-100)).toBe('-100pop.');
+ expect(formatSuffix(-1000)).toBe('-1,000pop.');
+ expect(formatSuffix(-10000)).toBe('-10,000pop.');
+ expect(formatSuffix(-1000000)).toBe('-1,000,000pop.');
});
it('formats a floating point nugative number', () => {
- expect(formatSuffix(-0.1)).toEqual('-0.1pop.');
- expect(formatSuffix(-0.1, 0)).toEqual('-0pop.');
- expect(formatSuffix(-0.1, 2)).toEqual('-0.10pop.');
- expect(formatSuffix(-0.1, 3)).toEqual('-0.100pop.');
+ expect(formatSuffix(-0.1)).toBe('-0.1pop.');
+ expect(formatSuffix(-0.1, 0)).toBe('-0pop.');
+ expect(formatSuffix(-0.1, 2)).toBe('-0.10pop.');
+ expect(formatSuffix(-0.1, 3)).toBe('-0.100pop.');
- expect(formatSuffix(-12.345)).toEqual('-12.345pop.');
- expect(formatSuffix(-12.345, 2)).toEqual('-12.35pop.');
- expect(formatSuffix(-12.345, 4)).toEqual('-12.3450pop.');
+ expect(formatSuffix(-12.345)).toBe('-12.345pop.');
+ expect(formatSuffix(-12.345, 2)).toBe('-12.35pop.');
+ expect(formatSuffix(-12.345, 4)).toBe('-12.3450pop.');
});
it('formats a large integer', () => {
- expect(formatSuffix(10 ** 7)).toEqual('10,000,000pop.');
- expect(formatSuffix(10 ** 10)).toEqual('10,000,000,000pop.');
+ expect(formatSuffix(10 ** 7)).toBe('10,000,000pop.');
+ expect(formatSuffix(10 ** 10)).toBe('10,000,000,000pop.');
});
it('formats a large integer with a length limit', () => {
- expect(formatSuffix(10 ** 7, undefined, 10)).toEqual('1.00e+7pop.');
- expect(formatSuffix(10 ** 10, undefined, 10)).toEqual('1.00e+10pop.');
+ expect(formatSuffix(10 ** 7, undefined, 10)).toBe('1.00e+7pop.');
+ expect(formatSuffix(10 ** 10, undefined, 10)).toBe('1.00e+10pop.');
});
});
describe('scaledSIFormatter', () => {
describe('scaled format', () => {
- let formatScaled;
+ let formatGibibytes;
beforeEach(() => {
- formatScaled = scaledSIFormatter('B');
+ formatGibibytes = scaledSIFormatter('B');
});
it('formats bytes', () => {
- expect(formatScaled(12.345)).toEqual('12.345B');
- expect(formatScaled(12.345, 0)).toEqual('12B');
- expect(formatScaled(12.345, 1)).toEqual('12.3B');
- expect(formatScaled(12.345, 2)).toEqual('12.35B');
+ expect(formatGibibytes(12.345)).toBe('12.345B');
+ expect(formatGibibytes(12.345, 0)).toBe('12B');
+ expect(formatGibibytes(12.345, 1)).toBe('12.3B');
+ expect(formatGibibytes(12.345, 2)).toBe('12.35B');
});
- it('formats bytes in a scale', () => {
- expect(formatScaled(1)).toEqual('1B');
- expect(formatScaled(10)).toEqual('10B');
- expect(formatScaled(10 ** 2)).toEqual('100B');
- expect(formatScaled(10 ** 3)).toEqual('1kB');
- expect(formatScaled(10 ** 4)).toEqual('10kB');
- expect(formatScaled(10 ** 5)).toEqual('100kB');
- expect(formatScaled(10 ** 6)).toEqual('1MB');
- expect(formatScaled(10 ** 7)).toEqual('10MB');
- expect(formatScaled(10 ** 8)).toEqual('100MB');
- expect(formatScaled(10 ** 9)).toEqual('1GB');
- expect(formatScaled(10 ** 10)).toEqual('10GB');
- expect(formatScaled(10 ** 11)).toEqual('100GB');
+ it('formats bytes in a decimal scale', () => {
+ expect(formatGibibytes(1)).toBe('1B');
+ expect(formatGibibytes(10)).toBe('10B');
+ expect(formatGibibytes(10 ** 2)).toBe('100B');
+ expect(formatGibibytes(10 ** 3)).toBe('1kB');
+ expect(formatGibibytes(10 ** 4)).toBe('10kB');
+ expect(formatGibibytes(10 ** 5)).toBe('100kB');
+ expect(formatGibibytes(10 ** 6)).toBe('1MB');
+ expect(formatGibibytes(10 ** 7)).toBe('10MB');
+ expect(formatGibibytes(10 ** 8)).toBe('100MB');
+ expect(formatGibibytes(10 ** 9)).toBe('1GB');
+ expect(formatGibibytes(10 ** 10)).toBe('10GB');
+ expect(formatGibibytes(10 ** 11)).toBe('100GB');
});
});
describe('scaled format with offset', () => {
- let formatScaled;
+ let formatGigaBytes;
beforeEach(() => {
// formats gigabytes
- formatScaled = scaledSIFormatter('B', 3);
+ formatGigaBytes = scaledSIFormatter('B', 3);
});
it('formats floating point numbers', () => {
- expect(formatScaled(12.345)).toEqual('12.345GB');
- expect(formatScaled(12.345, 0)).toEqual('12GB');
- expect(formatScaled(12.345, 1)).toEqual('12.3GB');
- expect(formatScaled(12.345, 2)).toEqual('12.35GB');
+ expect(formatGigaBytes(12.345)).toBe('12.345GB');
+ expect(formatGigaBytes(12.345, 0)).toBe('12GB');
+ expect(formatGigaBytes(12.345, 1)).toBe('12.3GB');
+ expect(formatGigaBytes(12.345, 2)).toBe('12.35GB');
});
it('formats large numbers scaled', () => {
- expect(formatScaled(1)).toEqual('1GB');
- expect(formatScaled(1, 1)).toEqual('1.0GB');
- expect(formatScaled(10)).toEqual('10GB');
- expect(formatScaled(10 ** 2)).toEqual('100GB');
- expect(formatScaled(10 ** 3)).toEqual('1TB');
- expect(formatScaled(10 ** 4)).toEqual('10TB');
- expect(formatScaled(10 ** 5)).toEqual('100TB');
- expect(formatScaled(10 ** 6)).toEqual('1PB');
- expect(formatScaled(10 ** 7)).toEqual('10PB');
- expect(formatScaled(10 ** 8)).toEqual('100PB');
- expect(formatScaled(10 ** 9)).toEqual('1EB');
+ expect(formatGigaBytes(1)).toBe('1GB');
+ expect(formatGigaBytes(1, 1)).toBe('1.0GB');
+ expect(formatGigaBytes(10)).toBe('10GB');
+ expect(formatGigaBytes(10 ** 2)).toBe('100GB');
+ expect(formatGigaBytes(10 ** 3)).toBe('1TB');
+ expect(formatGigaBytes(10 ** 4)).toBe('10TB');
+ expect(formatGigaBytes(10 ** 5)).toBe('100TB');
+ expect(formatGigaBytes(10 ** 6)).toBe('1PB');
+ expect(formatGigaBytes(10 ** 7)).toBe('10PB');
+ expect(formatGigaBytes(10 ** 8)).toBe('100PB');
+ expect(formatGigaBytes(10 ** 9)).toBe('1EB');
});
it('formatting of too large numbers is not suported', () => {
@@ -159,41 +160,116 @@ describe('unit_format/formatter_factory', () => {
});
describe('scaled format with negative offset', () => {
- let formatScaled;
+ let formatMilligrams;
beforeEach(() => {
- formatScaled = scaledSIFormatter('g', -1);
+ formatMilligrams = scaledSIFormatter('g', -1);
});
it('formats floating point numbers', () => {
- expect(formatScaled(12.345)).toEqual('12.345mg');
- expect(formatScaled(12.345, 0)).toEqual('12mg');
- expect(formatScaled(12.345, 1)).toEqual('12.3mg');
- expect(formatScaled(12.345, 2)).toEqual('12.35mg');
+ expect(formatMilligrams(1.0)).toBe('1mg');
+ expect(formatMilligrams(12.345)).toBe('12.345mg');
+ expect(formatMilligrams(12.345, 0)).toBe('12mg');
+ expect(formatMilligrams(12.345, 1)).toBe('12.3mg');
+ expect(formatMilligrams(12.345, 2)).toBe('12.35mg');
});
it('formats large numbers scaled', () => {
- expect(formatScaled(1)).toEqual('1mg');
- expect(formatScaled(1, 1)).toEqual('1.0mg');
- expect(formatScaled(10)).toEqual('10mg');
- expect(formatScaled(10 ** 2)).toEqual('100mg');
- expect(formatScaled(10 ** 3)).toEqual('1g');
- expect(formatScaled(10 ** 4)).toEqual('10g');
- expect(formatScaled(10 ** 5)).toEqual('100g');
- expect(formatScaled(10 ** 6)).toEqual('1kg');
- expect(formatScaled(10 ** 7)).toEqual('10kg');
- expect(formatScaled(10 ** 8)).toEqual('100kg');
+ expect(formatMilligrams(10)).toBe('10mg');
+ expect(formatMilligrams(10 ** 2)).toBe('100mg');
+ expect(formatMilligrams(10 ** 3)).toBe('1g');
+ expect(formatMilligrams(10 ** 4)).toBe('10g');
+ expect(formatMilligrams(10 ** 5)).toBe('100g');
+ expect(formatMilligrams(10 ** 6)).toBe('1kg');
+ expect(formatMilligrams(10 ** 7)).toBe('10kg');
+ expect(formatMilligrams(10 ** 8)).toBe('100kg');
});
it('formats negative numbers scaled', () => {
- expect(formatScaled(-12.345)).toEqual('-12.345mg');
- expect(formatScaled(-12.345, 0)).toEqual('-12mg');
- expect(formatScaled(-12.345, 1)).toEqual('-12.3mg');
- expect(formatScaled(-12.345, 2)).toEqual('-12.35mg');
-
- expect(formatScaled(-10)).toEqual('-10mg');
- expect(formatScaled(-100)).toEqual('-100mg');
- expect(formatScaled(-(10 ** 4))).toEqual('-10g');
+ expect(formatMilligrams(-12.345)).toBe('-12.345mg');
+ expect(formatMilligrams(-12.345, 0)).toBe('-12mg');
+ expect(formatMilligrams(-12.345, 1)).toBe('-12.3mg');
+ expect(formatMilligrams(-12.345, 2)).toBe('-12.35mg');
+
+ expect(formatMilligrams(-10)).toBe('-10mg');
+ expect(formatMilligrams(-100)).toBe('-100mg');
+ expect(formatMilligrams(-(10 ** 4))).toBe('-10g');
+ });
+ });
+ });
+
+ describe('scaledBinaryFormatter', () => {
+ describe('scaled format', () => {
+ let formatScaledBin;
+
+ beforeEach(() => {
+ formatScaledBin = scaledBinaryFormatter('B');
+ });
+
+ it('formats bytes', () => {
+ expect(formatScaledBin(12.345)).toBe('12.345B');
+ expect(formatScaledBin(12.345, 0)).toBe('12B');
+ expect(formatScaledBin(12.345, 1)).toBe('12.3B');
+ expect(formatScaledBin(12.345, 2)).toBe('12.35B');
+ });
+
+ it('formats bytes in a binary scale', () => {
+ expect(formatScaledBin(1)).toBe('1B');
+ expect(formatScaledBin(10)).toBe('10B');
+ expect(formatScaledBin(100)).toBe('100B');
+ expect(formatScaledBin(1000)).toBe('1,000B');
+ expect(formatScaledBin(10000)).toBe('9.766KiB');
+
+ expect(formatScaledBin(1 * 1024)).toBe('1KiB');
+ expect(formatScaledBin(10 * 1024)).toBe('10KiB');
+ expect(formatScaledBin(100 * 1024)).toBe('100KiB');
+
+ expect(formatScaledBin(1 * 1024 ** 2)).toBe('1MiB');
+ expect(formatScaledBin(10 * 1024 ** 2)).toBe('10MiB');
+ expect(formatScaledBin(100 * 1024 ** 2)).toBe('100MiB');
+
+ expect(formatScaledBin(1 * 1024 ** 3)).toBe('1GiB');
+ expect(formatScaledBin(10 * 1024 ** 3)).toBe('10GiB');
+ expect(formatScaledBin(100 * 1024 ** 3)).toBe('100GiB');
+ });
+ });
+
+ describe('scaled format with offset', () => {
+ let formatGibibytes;
+
+ beforeEach(() => {
+ formatGibibytes = scaledBinaryFormatter('B', 3);
+ });
+
+ it('formats floating point numbers', () => {
+ expect(formatGibibytes(12.888)).toBe('12.888GiB');
+ expect(formatGibibytes(12.888, 0)).toBe('13GiB');
+ expect(formatGibibytes(12.888, 1)).toBe('12.9GiB');
+ expect(formatGibibytes(12.888, 2)).toBe('12.89GiB');
+ });
+
+ it('formats large numbers scaled', () => {
+ expect(formatGibibytes(1)).toBe('1GiB');
+ expect(formatGibibytes(10)).toBe('10GiB');
+ expect(formatGibibytes(100)).toBe('100GiB');
+ expect(formatGibibytes(1000)).toBe('1,000GiB');
+
+ expect(formatGibibytes(1 * 1024)).toBe('1TiB');
+ expect(formatGibibytes(10 * 1024)).toBe('10TiB');
+ expect(formatGibibytes(100 * 1024)).toBe('100TiB');
+
+ expect(formatGibibytes(1 * 1024 ** 2)).toBe('1PiB');
+ expect(formatGibibytes(10 * 1024 ** 2)).toBe('10PiB');
+ expect(formatGibibytes(100 * 1024 ** 2)).toBe('100PiB');
+
+ expect(formatGibibytes(1 * 1024 ** 3)).toBe('1EiB');
+ expect(formatGibibytes(10 * 1024 ** 3)).toBe('10EiB');
+ expect(formatGibibytes(100 * 1024 ** 3)).toBe('100EiB');
+ });
+
+ it('formatting of too large numbers is not suported', () => {
+ // formatting YB is out of range
+ expect(() => scaledBinaryFormatter('B', 9)).toThrow();
});
});
});
diff --git a/spec/frontend/lib/utils/unit_format/index_spec.js b/spec/frontend/lib/utils/unit_format/index_spec.js
index e0991f2909b..5b2fdf1f02b 100644
--- a/spec/frontend/lib/utils/unit_format/index_spec.js
+++ b/spec/frontend/lib/utils/unit_format/index_spec.js
@@ -3,109 +3,149 @@ import { getFormatter, SUPPORTED_FORMATS } from '~/lib/utils/unit_format';
describe('unit_format', () => {
describe('when a supported format is provided, the returned function formats', () => {
it('numbers, by default', () => {
- expect(getFormatter()(1)).toEqual('1');
+ expect(getFormatter()(1)).toBe('1');
});
it('numbers', () => {
const formatNumber = getFormatter(SUPPORTED_FORMATS.number);
- expect(formatNumber(1)).toEqual('1');
- expect(formatNumber(100)).toEqual('100');
- expect(formatNumber(1000)).toEqual('1,000');
- expect(formatNumber(10000)).toEqual('10,000');
- expect(formatNumber(1000000)).toEqual('1,000,000');
+ expect(formatNumber(1)).toBe('1');
+ expect(formatNumber(100)).toBe('100');
+ expect(formatNumber(1000)).toBe('1,000');
+ expect(formatNumber(10000)).toBe('10,000');
+ expect(formatNumber(1000000)).toBe('1,000,000');
});
it('percent', () => {
const formatPercent = getFormatter(SUPPORTED_FORMATS.percent);
- expect(formatPercent(1)).toEqual('100%');
- expect(formatPercent(1, 2)).toEqual('100.00%');
+ expect(formatPercent(1)).toBe('100%');
+ expect(formatPercent(1, 2)).toBe('100.00%');
- expect(formatPercent(0.1)).toEqual('10%');
- expect(formatPercent(0.5)).toEqual('50%');
+ expect(formatPercent(0.1)).toBe('10%');
+ expect(formatPercent(0.5)).toBe('50%');
- expect(formatPercent(0.888888)).toEqual('89%');
- expect(formatPercent(0.888888, 2)).toEqual('88.89%');
- expect(formatPercent(0.888888, 5)).toEqual('88.88880%');
+ expect(formatPercent(0.888888)).toBe('89%');
+ expect(formatPercent(0.888888, 2)).toBe('88.89%');
+ expect(formatPercent(0.888888, 5)).toBe('88.88880%');
- expect(formatPercent(2)).toEqual('200%');
- expect(formatPercent(10)).toEqual('1,000%');
+ expect(formatPercent(2)).toBe('200%');
+ expect(formatPercent(10)).toBe('1,000%');
});
it('percentunit', () => {
const formatPercentHundred = getFormatter(SUPPORTED_FORMATS.percentHundred);
- expect(formatPercentHundred(1)).toEqual('1%');
- expect(formatPercentHundred(1, 2)).toEqual('1.00%');
+ expect(formatPercentHundred(1)).toBe('1%');
+ expect(formatPercentHundred(1, 2)).toBe('1.00%');
- expect(formatPercentHundred(88.8888)).toEqual('89%');
- expect(formatPercentHundred(88.8888, 2)).toEqual('88.89%');
- expect(formatPercentHundred(88.8888, 5)).toEqual('88.88880%');
+ expect(formatPercentHundred(88.8888)).toBe('89%');
+ expect(formatPercentHundred(88.8888, 2)).toBe('88.89%');
+ expect(formatPercentHundred(88.8888, 5)).toBe('88.88880%');
- expect(formatPercentHundred(100)).toEqual('100%');
- expect(formatPercentHundred(100, 2)).toEqual('100.00%');
+ expect(formatPercentHundred(100)).toBe('100%');
+ expect(formatPercentHundred(100, 2)).toBe('100.00%');
- expect(formatPercentHundred(200)).toEqual('200%');
- expect(formatPercentHundred(1000)).toEqual('1,000%');
+ expect(formatPercentHundred(200)).toBe('200%');
+ expect(formatPercentHundred(1000)).toBe('1,000%');
});
it('seconds', () => {
- expect(getFormatter(SUPPORTED_FORMATS.seconds)(1)).toEqual('1s');
+ expect(getFormatter(SUPPORTED_FORMATS.seconds)(1)).toBe('1s');
});
- it('miliseconds', () => {
- const formatMiliseconds = getFormatter(SUPPORTED_FORMATS.miliseconds);
+ it('milliseconds', () => {
+ const formatMilliseconds = getFormatter(SUPPORTED_FORMATS.milliseconds);
- expect(formatMiliseconds(1)).toEqual('1ms');
- expect(formatMiliseconds(100)).toEqual('100ms');
- expect(formatMiliseconds(1000)).toEqual('1,000ms');
- expect(formatMiliseconds(10000)).toEqual('10,000ms');
- expect(formatMiliseconds(1000000)).toEqual('1,000,000ms');
+ expect(formatMilliseconds(1)).toBe('1ms');
+ expect(formatMilliseconds(100)).toBe('100ms');
+ expect(formatMilliseconds(1000)).toBe('1,000ms');
+ expect(formatMilliseconds(10000)).toBe('10,000ms');
+ expect(formatMilliseconds(1000000)).toBe('1,000,000ms');
});
- it('bytes', () => {
- const formatBytes = getFormatter(SUPPORTED_FORMATS.bytes);
-
- expect(formatBytes(1)).toEqual('1B');
- expect(formatBytes(1, 1)).toEqual('1.0B');
-
- expect(formatBytes(10)).toEqual('10B');
- expect(formatBytes(10 ** 2)).toEqual('100B');
- expect(formatBytes(10 ** 3)).toEqual('1kB');
- expect(formatBytes(10 ** 4)).toEqual('10kB');
- expect(formatBytes(10 ** 5)).toEqual('100kB');
- expect(formatBytes(10 ** 6)).toEqual('1MB');
- expect(formatBytes(10 ** 7)).toEqual('10MB');
- expect(formatBytes(10 ** 8)).toEqual('100MB');
- expect(formatBytes(10 ** 9)).toEqual('1GB');
- expect(formatBytes(10 ** 10)).toEqual('10GB');
- expect(formatBytes(10 ** 11)).toEqual('100GB');
+ it('decimalBytes', () => {
+ const formatDecimalBytes = getFormatter(SUPPORTED_FORMATS.decimalBytes);
+
+ expect(formatDecimalBytes(1)).toBe('1B');
+ expect(formatDecimalBytes(1, 1)).toBe('1.0B');
+
+ expect(formatDecimalBytes(10)).toBe('10B');
+ expect(formatDecimalBytes(10 ** 2)).toBe('100B');
+ expect(formatDecimalBytes(10 ** 3)).toBe('1kB');
+ expect(formatDecimalBytes(10 ** 4)).toBe('10kB');
+ expect(formatDecimalBytes(10 ** 5)).toBe('100kB');
+ expect(formatDecimalBytes(10 ** 6)).toBe('1MB');
+ expect(formatDecimalBytes(10 ** 7)).toBe('10MB');
+ expect(formatDecimalBytes(10 ** 8)).toBe('100MB');
+ expect(formatDecimalBytes(10 ** 9)).toBe('1GB');
+ expect(formatDecimalBytes(10 ** 10)).toBe('10GB');
+ expect(formatDecimalBytes(10 ** 11)).toBe('100GB');
});
it('kilobytes', () => {
- expect(getFormatter(SUPPORTED_FORMATS.kilobytes)(1)).toEqual('1kB');
- expect(getFormatter(SUPPORTED_FORMATS.kilobytes)(1, 1)).toEqual('1.0kB');
+ expect(getFormatter(SUPPORTED_FORMATS.kilobytes)(1)).toBe('1kB');
+ expect(getFormatter(SUPPORTED_FORMATS.kilobytes)(1, 1)).toBe('1.0kB');
});
it('megabytes', () => {
- expect(getFormatter(SUPPORTED_FORMATS.megabytes)(1)).toEqual('1MB');
- expect(getFormatter(SUPPORTED_FORMATS.megabytes)(1, 1)).toEqual('1.0MB');
+ expect(getFormatter(SUPPORTED_FORMATS.megabytes)(1)).toBe('1MB');
+ expect(getFormatter(SUPPORTED_FORMATS.megabytes)(1, 1)).toBe('1.0MB');
});
it('gigabytes', () => {
- expect(getFormatter(SUPPORTED_FORMATS.gigabytes)(1)).toEqual('1GB');
- expect(getFormatter(SUPPORTED_FORMATS.gigabytes)(1, 1)).toEqual('1.0GB');
+ expect(getFormatter(SUPPORTED_FORMATS.gigabytes)(1)).toBe('1GB');
+ expect(getFormatter(SUPPORTED_FORMATS.gigabytes)(1, 1)).toBe('1.0GB');
});
it('terabytes', () => {
- expect(getFormatter(SUPPORTED_FORMATS.terabytes)(1)).toEqual('1TB');
- expect(getFormatter(SUPPORTED_FORMATS.terabytes)(1, 1)).toEqual('1.0TB');
+ expect(getFormatter(SUPPORTED_FORMATS.terabytes)(1)).toBe('1TB');
+ expect(getFormatter(SUPPORTED_FORMATS.terabytes)(1, 1)).toBe('1.0TB');
});
it('petabytes', () => {
- expect(getFormatter(SUPPORTED_FORMATS.petabytes)(1)).toEqual('1PB');
- expect(getFormatter(SUPPORTED_FORMATS.petabytes)(1, 1)).toEqual('1.0PB');
+ expect(getFormatter(SUPPORTED_FORMATS.petabytes)(1)).toBe('1PB');
+ expect(getFormatter(SUPPORTED_FORMATS.petabytes)(1, 1)).toBe('1.0PB');
+ });
+
+ it('bytes', () => {
+ const formatBytes = getFormatter(SUPPORTED_FORMATS.bytes);
+
+ expect(formatBytes(1)).toBe('1B');
+ expect(formatBytes(1, 1)).toBe('1.0B');
+
+ expect(formatBytes(10)).toBe('10B');
+ expect(formatBytes(100)).toBe('100B');
+ expect(formatBytes(1000)).toBe('1,000B');
+
+ expect(formatBytes(1 * 1024)).toBe('1KiB');
+ expect(formatBytes(1 * 1024 ** 2)).toBe('1MiB');
+ expect(formatBytes(1 * 1024 ** 3)).toBe('1GiB');
+ });
+
+ it('kibibytes', () => {
+ expect(getFormatter(SUPPORTED_FORMATS.kibibytes)(1)).toBe('1KiB');
+ expect(getFormatter(SUPPORTED_FORMATS.kibibytes)(1, 1)).toBe('1.0KiB');
+ });
+
+ it('mebibytes', () => {
+ expect(getFormatter(SUPPORTED_FORMATS.mebibytes)(1)).toBe('1MiB');
+ expect(getFormatter(SUPPORTED_FORMATS.mebibytes)(1, 1)).toBe('1.0MiB');
+ });
+
+ it('gibibytes', () => {
+ expect(getFormatter(SUPPORTED_FORMATS.gibibytes)(1)).toBe('1GiB');
+ expect(getFormatter(SUPPORTED_FORMATS.gibibytes)(1, 1)).toBe('1.0GiB');
+ });
+
+ it('tebibytes', () => {
+ expect(getFormatter(SUPPORTED_FORMATS.tebibytes)(1)).toBe('1TiB');
+ expect(getFormatter(SUPPORTED_FORMATS.tebibytes)(1, 1)).toBe('1.0TiB');
+ });
+
+ it('pebibytes', () => {
+ expect(getFormatter(SUPPORTED_FORMATS.pebibytes)(1)).toBe('1PiB');
+ expect(getFormatter(SUPPORTED_FORMATS.pebibytes)(1, 1)).toBe('1.0PiB');
});
});
diff --git a/spec/frontend/notes/components/note_app_spec.js b/spec/frontend/notes/components/note_app_spec.js
index a51c7c57f6c..2d0cca18647 100644
--- a/spec/frontend/notes/components/note_app_spec.js
+++ b/spec/frontend/notes/components/note_app_spec.js
@@ -5,7 +5,6 @@ import { mount } from '@vue/test-utils';
import { setTestTimeout } from 'helpers/timeout';
import axios from '~/lib/utils/axios_utils';
import NotesApp from '~/notes/components/notes_app.vue';
-import service from '~/notes/services/notes_service';
import createStore from '~/notes/stores';
import '~/behaviors/markdown/render_gfm';
// TODO: use generated fixture (https://gitlab.com/gitlab-org/gitlab-foss/issues/62491)
@@ -192,7 +191,6 @@ describe('note_app', () => {
describe('individual note', () => {
beforeEach(() => {
axiosMock.onAny().reply(mockData.getIndividualNoteResponse);
- jest.spyOn(service, 'updateNote');
wrapper = mountComponent();
return waitForDiscussionsRequest().then(() => {
wrapper.find('.js-note-edit').trigger('click');
@@ -203,18 +201,18 @@ describe('note_app', () => {
expect(wrapper.find('.js-vue-issue-note-form').exists()).toBe(true);
});
- it('calls the service to update the note', () => {
+ it('calls the store action to update the note', () => {
+ jest.spyOn(axios, 'put').mockImplementation(() => Promise.resolve({ data: {} }));
wrapper.find('.js-vue-issue-note-form').value = 'this is a note';
wrapper.find('.js-vue-issue-save').trigger('click');
- expect(service.updateNote).toHaveBeenCalled();
+ expect(axios.put).toHaveBeenCalled();
});
});
describe('discussion note', () => {
beforeEach(() => {
axiosMock.onAny().reply(mockData.getDiscussionNoteResponse);
- jest.spyOn(service, 'updateNote');
wrapper = mountComponent();
return waitForDiscussionsRequest().then(() => {
wrapper.find('.js-note-edit').trigger('click');
@@ -226,10 +224,11 @@ describe('note_app', () => {
});
it('updates the note and resets the edit form', () => {
+ jest.spyOn(axios, 'put').mockImplementation(() => Promise.resolve({ data: {} }));
wrapper.find('.js-vue-issue-note-form').value = 'this is a note';
wrapper.find('.js-vue-issue-save').trigger('click');
- expect(service.updateNote).toHaveBeenCalled();
+ expect(axios.put).toHaveBeenCalled();
});
});
});
diff --git a/spec/javascripts/frequent_items/components/frequent_items_list_spec.js b/spec/javascripts/frequent_items/components/frequent_items_list_spec.js
deleted file mode 100644
index 3fcd79480cc..00000000000
--- a/spec/javascripts/frequent_items/components/frequent_items_list_spec.js
+++ /dev/null
@@ -1,90 +0,0 @@
-import Vue from 'vue';
-import mountComponent from 'spec/helpers/vue_mount_component_helper';
-import frequentItemsListComponent from '~/frequent_items/components/frequent_items_list.vue';
-import { mockFrequentProjects } from '../mock_data';
-
-const createComponent = (namespace = 'projects') => {
- const Component = Vue.extend(frequentItemsListComponent);
-
- return mountComponent(Component, {
- namespace,
- items: mockFrequentProjects,
- isFetchFailed: false,
- hasSearchQuery: false,
- matcher: 'lab',
- });
-};
-
-describe('FrequentItemsListComponent', () => {
- let vm;
-
- beforeEach(() => {
- vm = createComponent();
- });
-
- afterEach(() => {
- vm.$destroy();
- });
-
- describe('computed', () => {
- describe('isListEmpty', () => {
- it('should return `true` or `false` representing whether if `items` is empty or not with projects', () => {
- vm.items = [];
-
- expect(vm.isListEmpty).toBe(true);
-
- vm.items = mockFrequentProjects;
-
- expect(vm.isListEmpty).toBe(false);
- });
- });
-
- describe('fetched item messages', () => {
- it('should return appropriate empty list message based on value of `localStorageFailed` prop with projects', () => {
- vm.isFetchFailed = true;
-
- expect(vm.listEmptyMessage).toBe('This feature requires browser localStorage support');
-
- vm.isFetchFailed = false;
-
- expect(vm.listEmptyMessage).toBe('Projects you visit often will appear here');
- });
- });
-
- describe('searched item messages', () => {
- it('should return appropriate empty list message based on value of `searchFailed` prop with projects', () => {
- vm.hasSearchQuery = true;
- vm.isFetchFailed = true;
-
- expect(vm.listEmptyMessage).toBe('Something went wrong on our end.');
-
- vm.isFetchFailed = false;
-
- expect(vm.listEmptyMessage).toBe('Sorry, no projects matched your search');
- });
- });
- });
-
- describe('template', () => {
- it('should render component element with list of projects', done => {
- vm.items = mockFrequentProjects;
-
- Vue.nextTick(() => {
- expect(vm.$el.classList.contains('frequent-items-list-container')).toBe(true);
- expect(vm.$el.querySelectorAll('ul.list-unstyled').length).toBe(1);
- expect(vm.$el.querySelectorAll('li.frequent-items-list-item-container').length).toBe(5);
- done();
- });
- });
-
- it('should render component element with empty message', done => {
- vm.items = [];
-
- Vue.nextTick(() => {
- expect(vm.$el.querySelectorAll('li.section-empty').length).toBe(1);
- expect(vm.$el.querySelectorAll('li.frequent-items-list-item-container').length).toBe(0);
- done();
- });
- });
- });
-});
diff --git a/spec/models/issue_spec.rb b/spec/models/issue_spec.rb
index c0501fb16c6..dd1588036b6 100644
--- a/spec/models/issue_spec.rb
+++ b/spec/models/issue_spec.rb
@@ -178,67 +178,63 @@ describe Issue do
let(:namespace) { build(:namespace, path: 'sample-namespace') }
let(:project) { build(:project, name: 'sample-project', namespace: namespace) }
let(:issue) { build(:issue, iid: 1, project: project) }
- let(:group) { create(:group, name: 'Group', path: 'sample-group') }
context 'when nil argument' do
it 'returns issue id' do
expect(issue.to_reference).to eq "#1"
end
- end
- context 'when full is true' do
- it 'returns complete path to the issue' do
- expect(issue.to_reference(full: true)).to eq 'sample-namespace/sample-project#1'
- expect(issue.to_reference(project, full: true)).to eq 'sample-namespace/sample-project#1'
- expect(issue.to_reference(group, full: true)).to eq 'sample-namespace/sample-project#1'
- end
- end
-
- context 'when same project argument' do
- it 'returns issue id' do
- expect(issue.to_reference(project)).to eq("#1")
+ it 'returns complete path to the issue with full: true' do
+ expect(issue.to_reference(full: true)).to eq 'sample-namespace/sample-project#1'
end
end
- context 'when cross namespace project argument' do
- let(:another_namespace_project) { create(:project, name: 'another-project') }
+ context 'when argument is a project' do
+ context 'when same project' do
+ it 'returns issue id' do
+ expect(issue.to_reference(project)).to eq("#1")
+ end
- it 'returns complete path to the issue' do
- expect(issue.to_reference(another_namespace_project)).to eq 'sample-namespace/sample-project#1'
+ it 'returns full reference with full: true' do
+ expect(issue.to_reference(project, full: true)).to eq 'sample-namespace/sample-project#1'
+ end
end
- end
- it 'supports a cross-project reference' do
- another_project = build(:project, name: 'another-project', namespace: project.namespace)
- expect(issue.to_reference(another_project)).to eq "sample-project#1"
- end
-
- context 'when same namespace / cross-project argument' do
- let(:another_project) { create(:project, namespace: namespace) }
+ context 'when cross-project in same namespace' do
+ let(:another_project) do
+ build(:project, name: 'another-project', namespace: project.namespace)
+ end
- it 'returns path to the issue with the project name' do
- expect(issue.to_reference(another_project)).to eq 'sample-project#1'
+ it 'returns a cross-project reference' do
+ expect(issue.to_reference(another_project)).to eq "sample-project#1"
+ end
end
- end
- context 'when different namespace / cross-project argument' do
- let(:another_namespace) { create(:namespace, path: 'another-namespace') }
- let(:another_project) { create(:project, path: 'another-project', namespace: another_namespace) }
+ context 'when cross-project in different namespace' do
+ let(:another_namespace) { build(:namespace, path: 'another-namespace') }
+ let(:another_namespace_project) { build(:project, path: 'another-project', namespace: another_namespace) }
- it 'returns full path to the issue' do
- expect(issue.to_reference(another_project)).to eq 'sample-namespace/sample-project#1'
+ it 'returns complete path to the issue' do
+ expect(issue.to_reference(another_namespace_project)).to eq 'sample-namespace/sample-project#1'
+ end
end
end
context 'when argument is a namespace' do
- context 'with same project path' do
+ context 'when same as issue' do
it 'returns path to the issue with the project name' do
expect(issue.to_reference(namespace)).to eq 'sample-project#1'
end
+
+ it 'returns full reference with full: true' do
+ expect(issue.to_reference(namespace, full: true)).to eq 'sample-namespace/sample-project#1'
+ end
end
- context 'with different project path' do
- it 'returns full path to the issue' do
+ context 'when different to issue namespace' do
+ let(:group) { build(:group, name: 'Group', path: 'sample-group') }
+
+ it 'returns full path to the issue with full: true' do
expect(issue.to_reference(group)).to eq 'sample-namespace/sample-project#1'
end
end
diff --git a/spec/policies/project_policy_spec.rb b/spec/policies/project_policy_spec.rb
index e1466ad2b73..635349955b1 100644
--- a/spec/policies/project_policy_spec.rb
+++ b/spec/policies/project_policy_spec.rb
@@ -52,7 +52,7 @@ describe ProjectPolicy do
admin_snippet admin_project_member admin_note admin_wiki admin_project
admin_commit_status admin_build admin_container_image
admin_pipeline admin_environment admin_deployment destroy_release add_cluster
- daily_statistics
+ daily_statistics read_deploy_token
]
end
diff --git a/spec/requests/api/deploy_tokens_spec.rb b/spec/requests/api/deploy_tokens_spec.rb
index 0e3256edcd8..9aa181db7fc 100644
--- a/spec/requests/api/deploy_tokens_spec.rb
+++ b/spec/requests/api/deploy_tokens_spec.rb
@@ -3,43 +3,84 @@
require 'spec_helper'
describe API::DeployTokens do
+ let(:user) { create(:user) }
let(:creator) { create(:user) }
let(:project) { create(:project, creator_id: creator.id) }
let!(:deploy_token) { create(:deploy_token, projects: [project]) }
describe 'GET /deploy_tokens' do
- subject { get api('/deploy_tokens', user) }
+ subject do
+ get api('/deploy_tokens', user)
+ response
+ end
context 'when unauthenticated' do
let(:user) { nil }
- it 'rejects the response as unauthorized' do
- subject
-
- expect(response).to have_gitlab_http_status(:unauthorized)
- end
+ it { is_expected.to have_gitlab_http_status(:unauthorized) }
end
context 'when authenticated as non-admin user' do
let(:user) { creator }
- it 'rejects the response as forbidden' do
- subject
-
- expect(response).to have_gitlab_http_status(:forbidden)
- end
+ it { is_expected.to have_gitlab_http_status(:forbidden) }
end
context 'when authenticated as admin' do
let(:user) { create(:admin) }
+ it { is_expected.to have_gitlab_http_status(:ok) }
+
it 'returns all deploy tokens' do
subject
- expect(response).to have_gitlab_http_status(:ok)
expect(response).to include_pagination_headers
- expect(json_response).to be_an Array
- expect(json_response.first['id']).to eq(deploy_token.id)
+ expect(response).to match_response_schema('public_api/v4/deploy_tokens')
+ end
+ end
+ end
+
+ describe 'GET /projects/:id/deploy_tokens' do
+ subject do
+ get api("/projects/#{project.id}/deploy_tokens", user)
+ response
+ end
+
+ context 'when unauthenticated' do
+ let(:user) { nil }
+
+ it { is_expected.to have_gitlab_http_status(:not_found) }
+ end
+
+ context 'when authenticated as non-admin user' do
+ before do
+ project.add_developer(user)
+ end
+
+ it { is_expected.to have_gitlab_http_status(:forbidden) }
+ end
+
+ context 'when authenticated as maintainer' do
+ let!(:other_deploy_token) { create(:deploy_token) }
+
+ before do
+ project.add_maintainer(user)
+ end
+
+ it { is_expected.to have_gitlab_http_status(:ok) }
+
+ it 'returns all deploy tokens for the project' do
+ subject
+
+ expect(response).to include_pagination_headers
+ expect(response).to match_response_schema('public_api/v4/deploy_tokens')
+ end
+
+ it 'does not return deploy tokens for other projects' do
+ subject
+
+ token_ids = json_response.map { |token| token['id'] }
+ expect(token_ids).not_to include(other_deploy_token.id)
end
end
end