Commit 8154198f authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 7f1f4bfb 6298ed71
......@@ -61,55 +61,6 @@ const removeFlashClickListener = (flashEl, fadeTransition) => {
.addEventListener('click', () => hideFlash(flashEl, fadeTransition));
};
/*
* Flash banner supports different types of Flash configurations
* along with ability to provide actionConfig which can be used to show
* additional action or link on banner next to message
*
* @param {String} message Flash message text
* @param {String} type Type of Flash, it can be `notice`, `success`, `warning` or `alert` (default)
* @param {Object} parent Reference to parent element under which Flash needs to appear
* @param {Object} actionConfig Map of config to show action on banner
* @param {String} href URL to which action config should point to (default: '#')
* @param {String} title Title of action
* @param {Function} clickHandler Method to call when action is clicked on
* @param {Boolean} fadeTransition Boolean to determine whether to fade the alert out
*/
const deprecatedCreateFlash = function deprecatedCreateFlash(
message,
type = FLASH_TYPES.ALERT,
parent = document,
actionConfig = null,
fadeTransition = true,
addBodyClass = false,
) {
const flashContainer = parent.querySelector('.flash-container');
if (!flashContainer) return null;
flashContainer.innerHTML = createFlashEl(message, type);
const flashEl = flashContainer.querySelector(`.flash-${type}`);
if (actionConfig) {
flashEl.innerHTML += createAction(actionConfig);
if (actionConfig.clickHandler) {
flashEl
.querySelector('.flash-action')
.addEventListener('click', (e) => actionConfig.clickHandler(e));
}
}
removeFlashClickListener(flashEl, fadeTransition);
flashContainer.style.display = 'block';
if (addBodyClass) document.body.classList.add('flash-shown');
return flashContainer;
};
/*
* Flash banner supports different types of Flash configurations
* along with ability to provide actionConfig which can be used to show
......@@ -166,6 +117,31 @@ const createFlash = function createFlash({
return flashContainer;
};
/*
* Flash banner supports different types of Flash configurations
* along with ability to provide actionConfig which can be used to show
* additional action or link on banner next to message
*
* @param {String} message Flash message text
* @param {String} type Type of Flash, it can be `notice`, `success`, `warning` or `alert` (default)
* @param {Object} parent Reference to parent element under which Flash needs to appear
* @param {Object} actionConfig Map of config to show action on banner
* @param {String} href URL to which action config should point to (default: '#')
* @param {String} title Title of action
* @param {Function} clickHandler Method to call when action is clicked on
* @param {Boolean} fadeTransition Boolean to determine whether to fade the alert out
*/
const deprecatedCreateFlash = function deprecatedCreateFlash(
message,
type,
parent,
actionConfig,
fadeTransition,
addBodyClass,
) {
return createFlash({ message, type, parent, actionConfig, fadeTransition, addBodyClass });
};
export {
createFlash as default,
deprecatedCreateFlash,
......
......@@ -4,6 +4,8 @@
module GitlabRoutingHelper
extend ActiveSupport::Concern
include ::ProjectsHelper
include ::ApplicationSettingsHelper
include API::Helpers::RelatedResourcesHelpers
included do
Gitlab::Routing.includes_helpers(self)
......
......@@ -36,6 +36,8 @@ class Project < ApplicationRecord
include Integration
include Repositories::CanHousekeepRepository
include EachBatch
include GitlabRoutingHelper
extend Gitlab::Cache::RequestCache
extend Gitlab::Utils::Override
......
---
title: Support daily DORA metrics API
merge_request: 56080
author:
type: added
---
title: Document how to use custom omniauth button icon
merge_request: 55388
author: Diego Louzán
type: other
---
name: dora_daily_metrics
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55473
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/291746
milestone: '13.10'
type: development
group: group::release
default_enabled: false
---
name: variable_inside_variable
introduced_by_url:
rollout_issue_url:
milestone: '13.7'
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50156
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/297382
milestone: '13.11'
type: development
group: group::runner
default_enabled: false
......@@ -860,8 +860,8 @@ Parameters for all comments:
| `position[line_range]` | hash | no | Line range for a multi-line diff note |
| `position[width]` | integer | no | Width of the image (for `image` diff notes) |
| `position[height]` | integer | no | Height of the image (for `image` diff notes) |
| `position[x]` | integer | no | X coordinate (for `image` diff notes) |
| `position[y]` | integer | no | Y coordinate (for `image` diff notes) |
| `position[x]` | float | no | X coordinate (for `image` diff notes) |
| `position[y]` | float | no | Y coordinate (for `image` diff notes) |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/11/discussions?body=comment"
......
---
stage: Release
group: Release
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
type: reference, api
---
# DevOps Research and Assessment (DORA) key metrics API **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.10.
All methods require [reporter permissions and above](../../user/permissions.md).
## Get project-level DORA metrics
Get project-level DORA metrics.
```plaintext
GET /projects/:id/dora/metrics
```
| Attribute | Type | Required | Description |
|-------------- |-------- |----------|----------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding) can be accessed by the authenticated user. |
| `metric` | string | yes | The [metric name](../../user/analytics/ci_cd_analytics.md#supported-metrics-in-gitlab). One of `deployment_frequency` or `lead_time_for_changes`. |
| `start_date` | string | no | Date range to start from. ISO 8601 Date format, for example `2021-03-01`. Default is 3 months ago. |
| `end_date` | string | no | Date range to end at. ISO 8601 Date format, for example `2021-03-01`. Default is the current date. |
| `interval` | string | no | The bucketing interval. One of `all`, `monthly` or `daily`. Default is `daily`. |
| `environment_tier` | string | no | The [tier of the environment](../../ci/environments/index.md#deployment-tier-of-environments). Default is `production`. |
Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/dora/metrics?metric=deployment_frequency"
```
Example response:
```json
[
{ "2021-03-01": 3 },
{ "2021-03-02": 6 },
{ "2021-03-03": 0 },
{ "2021-03-04": 0 },
{ "2021-03-05": 0 },
{ "2021-03-06": 0 },
{ "2021-03-07": 0 },
{ "2021-03-08": 4 }
]
```
## Get group-level DORA metrics
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.10.
Get group-level DORA metrics.
```plaintext
GET /groups/:id/dora/metrics
```
| Attribute | Type | Required | Description |
|-------------- |-------- |----------|----------------------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding) can be accessed by the authenticated user. |
| `metric` | string | yes | The [metric name](../../user/analytics/ci_cd_analytics.md#supported-metrics-in-gitlab). One of `deployment_frequency` or `lead_time_for_changes`. |
| `start_date` | string | no | Date range to start from. ISO 8601 Date format, for example `2021-03-01`. Default is 3 months ago. |
| `end_date` | string | no | Date range to end at. ISO 8601 Date format, for example `2021-03-01`. Default is the current date. |
| `interval` | string | no | The bucketing interval. One of `all`, `monthly` or `daily`. Default is `daily`. |
| `environment_tier` | string | no | The [tier of the environment](../../ci/environments/index.md#deployment-tier-of-environments). Default is `production`. |
Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/dora/metrics?metric=deployment_frequency"
```
Example response:
```json
[
{ "2021-03-01": 3 },
{ "2021-03-02": 6 },
{ "2021-03-03": 0 },
{ "2021-03-04": 0 },
{ "2021-03-05": 0 },
{ "2021-03-06": 0 },
{ "2021-03-07": 0 },
{ "2021-03-08": 4 }
]
```
......@@ -356,3 +356,32 @@ You may also bypass the auto sign in feature by browsing to
The [Generated passwords for users created through integrated authentication](../security/passwords_for_integrated_authentication_methods.md)
guide provides an overview about how GitLab generates and sets passwords for
users created with OmniAuth.
## Custom OmniAuth provider icon
Most supported providers include a built-in icon for the rendered sign-in button.
After you ensure your image is optimized for rendering at 64 x 64 pixels,
you can override this icon in one of two ways:
- **Provide a custom image path**:
1. *If you are hosting the image outside of your GitLab server domain,* ensure
your [content security policies](https://docs.gitlab.com/omnibus/settings/configuration.html#content-security-policy)
are configured to allow access to the image file.
1. Depending on your method of installing GitLab, add a custom `icon` parameter
to your GitLab configuration file. Read [OpenID Connect OmniAuth provider](../administration/auth/oidc.md)
for an example for the OpenID Connect provider.
- **Directly embed an image in a configuration file**: This example creates a Base64-encoded
version of your image you can serve through a
[Data URL](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs):
1. Encode your image file with GNU `base64` command (such as `base64 -w 0 <logo.png>`)
which returns a single-line `<base64-data>` string.
1. Add the Base64-encoded data to a custom `icon` parameter in your GitLab configuration file:
```yaml
omniauth:
providers:
- { name: '...'
icon: 'data:image/png;base64,<base64-data>'
...
}
```
......@@ -51,7 +51,7 @@ and the work required to fix them - all without leaving GitLab.
- Discover and view errors generated by your applications with
[Error Tracking](error_tracking.md).
## Trace application health and performance **(ULTIMATE)**
## Trace application health and performance
Application tracing in GitLab is a way to measure an application's performance and
health while it's running. After configuring your application to enable tracing, you
......@@ -63,7 +63,7 @@ GitLab integrates with [Jaeger](https://www.jaegertracing.io/) - an open-source,
end-to-end distributed tracing system tool used for monitoring and troubleshooting
microservices-based distributed systems - and displays results within GitLab.
- [Trace the performance and health](tracing.md) of a deployed application. **(ULTIMATE)**
- [Trace the performance and health](tracing.md) of a deployed application.
## Aggregate and store logs
......
......@@ -22,7 +22,10 @@ View pipeline duration history:
![Pipeline duration](img/pipelines_duration_chart.png)
## DORA4 Metrics
## DevOps Research and Assessment (DORA) key metrics **(ULTIMATE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/275991) in GitLab 13.7.
> - Added support for [lead time for changes](https://gitlab.com/gitlab-org/gitlab/-/issues/291746) in GitLab 13.10.
Customer experience is a key metric. Users want to measure platform stability and other
post-deployment performance KPIs, and set targets for customer behavior, experience, and financial
......@@ -41,9 +44,18 @@ performance indicators for software development teams:
- Time to restore service: How long it takes an organization to recover from a failure in
production.
GitLab plans to add support for all the DORA4 metrics at the project and group levels. GitLab added
the first metric, deployment frequency, at the project and group scopes for [CI/CD charts](ci_cd_analytics.md#deployment-frequency-charts),
the [Project API]( ../../api/dora4_project_analytics.md), and the [Group API]( ../../api/dora4_group_analytics.md).
### Supported metrics in GitLab
The following table shows the supported metrics, at which level they are supported, and which GitLab version (API and UI) they were introduced:
| Metric | Level | API version | Chart (UI) version | Comments |
| --------------- | ----------- | --------------- | ---------- | ------- |
| `deployment_frequency` | Project-level | [13.7+](../../api/dora/metrics.md) | [13.8+](#deployment-frequency-charts) | The [old API endopint](../../api/dora4_project_analytics.md) was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/323713) in 13.10. |
| `deployment_frequency` | Group-level | [13.10+](../../api/dora/metrics.md) | To be supported | |
| `lead_time_for_changes` | Project-level | [13.10+](../../api/dora/metrics.md) | To be supported | Unit in seconds. Aggregation method is median. |
| `lead_time_for_changes` | Group-level | [13.10+](../../api/dora/metrics.md) | To be supported | Unit in seconds. Aggregation method is median. |
| `change_failure_rate` | Project/Group-level | To be supported | To be supported | |
| `time_to_restore_service` | Project/Group-level | To be supported | To be supported | |
## Deployment frequency charts **(ULTIMATE)**
......
......@@ -87,6 +87,7 @@ The following table depicts the various user permission levels in a project.
| See a commit status | | ✓ | ✓ | ✓ | ✓ |
| See a container registry | | ✓ | ✓ | ✓ | ✓ |
| See environments | | ✓ | ✓ | ✓ | ✓ |
| See [DORA metrics](analytics/ci_cd_analytics.md) | | ✓ | ✓ | ✓ | ✓ |
| See a list of merge requests | | ✓ | ✓ | ✓ | ✓ |
| View CI/CD analytics | | ✓ | ✓ | ✓ | ✓ |
| View Code Review analytics **(STARTER)** | | ✓ | ✓ | ✓ | ✓ |
......
......@@ -54,11 +54,6 @@ export default {
GlTooltip: GlTooltipDirective,
},
inject: ['projectPath', 'timezones'],
provide() {
return {
selectedTimezone: this.selectedTimezone,
};
},
props: {
schedule: {
type: Object,
......
......@@ -4,7 +4,6 @@ import { uniqueId } from 'lodash';
import { formatDate } from '~/lib/utils/datetime_utility';
import { truncate } from '~/lib/utils/text_utility';
import { __, sprintf } from '~/locale';
import { selectedTimezoneFormattedOffset } from '../../schedule/utils';
export const SHIFT_WIDTHS = {
md: 100,
......@@ -13,7 +12,7 @@ export const SHIFT_WIDTHS = {
};
const ROTATION_CENTER_CLASS = 'gl-display-flex gl-justify-content-center gl-align-items-center';
export const TIME_DATE_FORMAT = 'mmmm d, yyyy, HH:MM';
export const TIME_DATE_FORMAT = 'mmmm d, yyyy, HH:MM ("UTC:" o)';
export default {
ROTATION_CENTER_CLASS,
......@@ -21,7 +20,6 @@ export default {
GlAvatar,
GlPopover,
},
inject: ['selectedTimezone'],
props: {
assignee: {
type: Object,
......@@ -57,9 +55,7 @@ export default {
},
endsAt() {
return sprintf(__('Ends: %{endsAt}'), {
endsAt: `${formatDate(this.rotationAssigneeEndsAt, TIME_DATE_FORMAT)} ${
this.timezoneOffset
}`,
endsAt: `${formatDate(this.rotationAssigneeEndsAt, TIME_DATE_FORMAT)}`,
});
},
rotationAssigneeUniqueID() {
......@@ -73,14 +69,9 @@ export default {
},
startsAt() {
return sprintf(__('Starts: %{startsAt}'), {
startsAt: `${formatDate(this.rotationAssigneeStartsAt, TIME_DATE_FORMAT)} ${
this.timezoneOffset
}`,
startsAt: `${formatDate(this.rotationAssigneeStartsAt, TIME_DATE_FORMAT)}`,
});
},
timezoneOffset() {
return selectedTimezoneFormattedOffset(this.selectedTimezone.formatted_offset);
},
},
};
</script>
......
......@@ -78,9 +78,12 @@ export default {
const baseWidth =
this.shiftEndsAt.getTime() >= this.currentTimeframeEndsAt.getTime()
? HOURS_IN_DAY
: this.shiftRangeOverlap.hoursOverlap;
: this.shiftRangeOverlap.hoursOverlap + this.shiftOffset;
return this.shiftTimeUnitWidth * baseWidth - ASSIGNEE_SPACER;
},
shiftOffset() {
return (this.shiftStartsAt.getTimezoneOffset() - this.shiftEndsAt.getTimezoneOffset()) / 60;
},
},
};
</script>
......
......@@ -2,9 +2,6 @@
module EE
module GitlabRoutingHelper
include ::ProjectsHelper
include ::ApplicationSettingsHelper
def geo_primary_web_url(container)
File.join(::Gitlab::Geo.primary_node.url, container.full_path)
end
......
......@@ -13,8 +13,6 @@ module EE
state_machine :status do
after_transition any => :success do |deployment|
next unless ::Feature.enabled?(:dora_daily_metrics, deployment.project, default_enabled: :yaml)
deployment.run_after_commit do
# Schedule to refresh the DORA daily metrics.
# It has 5 minutes delay due to waiting for the other async processes
......
......@@ -843,5 +843,3 @@ module EE
end
end
end
EE::Project.include_if_ee('::EE::GitlabRoutingHelper')
......@@ -15,8 +15,6 @@ module API
end
def fetch!(container)
not_found! unless ::Feature.enabled?(:dora_daily_metrics, container, default_enabled: :yaml)
result = ::Dora::AggregateMetricsService
.new(container: container, current_user: current_user, params: declared_params(include_missing: false))
.execute
......
......@@ -4,12 +4,10 @@ import RotationAssignee, {
SHIFT_WIDTHS,
TIME_DATE_FORMAT,
} from 'ee/oncall_schedules/components/rotations/components/rotation_assignee.vue';
import { selectedTimezoneFormattedOffset } from 'ee/oncall_schedules/components/schedule/utils';
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
import { formatDate } from '~/lib/utils/datetime_utility';
import { truncate } from '~/lib/utils/text_utility';
import mockRotations from '../../mocks/mock_rotation.json';
import mockTimezones from '../../mocks/mock_timezones.json';
jest.mock('lodash/uniqueId', () => (prefix) => `${prefix}fakeUniqueId`);
......@@ -29,14 +27,9 @@ describe('RotationAssignee', () => {
return formatDate(date, TIME_DATE_FORMAT);
};
const selectedTimezone = mockTimezones[0];
function createComponent({ props = {} } = {}) {
wrapper = extendedWrapper(
shallowMount(RotationAssignee, {
provide: {
selectedTimezone,
},
propsData: {
assignee: { ...assignee.participant },
rotationAssigneeStartsAt: assignee.startsAt,
......@@ -87,10 +80,9 @@ describe('RotationAssignee', () => {
});
it('should render an assignee schedule and rotation information in a popover', () => {
const timezone = selectedTimezoneFormattedOffset(selectedTimezone.formatted_offset);
expect(findPopOver().attributes('target')).toBe('rotation-assignee-fakeUniqueId');
expect(findStartsAt().text()).toContain(`${formattedDate(assignee.startsAt)} ${timezone}`);
expect(findEndsAt().text()).toContain(`${formattedDate(assignee.endsAt)} ${timezone}`);
expect(findStartsAt().text()).toContain(formattedDate(assignee.startsAt));
expect(findEndsAt().text()).toContain(formattedDate(assignee.endsAt));
});
});
});
......@@ -102,7 +102,7 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
data-testid="rotation-assignee-starts-at"
>
Starts: January 12, 2021, 10:04 (UTC -12:00)
Starts: January 12, 2021, 10:04 (UTC: +0000)
</p>
......@@ -111,7 +111,7 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
data-testid="rotation-assignee-ends-at"
>
Ends: January 15, 2021, 10:04 (UTC -12:00)
Ends: January 15, 2021, 10:04 (UTC: +0000)
</p>
</div>
......@@ -142,7 +142,7 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
data-testid="rotation-assignee-starts-at"
>
Starts: January 16, 2021, 10:04 (UTC -12:00)
Starts: January 16, 2021, 10:04 (UTC: +0000)
</p>
......@@ -151,7 +151,7 @@ exports[`RotationsListSectionComponent when the timeframe includes today renders
data-testid="rotation-assignee-ends-at"
>
Ends: January 18, 2021, 10:04 (UTC -12:00)
Ends: January 18, 2021, 10:04 (UTC: +0000)
</p>
</div>
......
......@@ -8,7 +8,6 @@ import { PRESET_TYPES } from 'ee/oncall_schedules/constants';
import { useFakeDate } from 'helpers/fake_date';
import { scheduleIid } from '../../mocks/apollo_mock';
import mockRotations from '../../mocks/mock_rotation.json';
import mockTimezones from '../../mocks/mock_timezones.json';
describe('RotationsListSectionComponent', () => {
let wrapper;
......@@ -29,7 +28,6 @@ describe('RotationsListSectionComponent', () => {
},
provide: {
projectPath,
selectedTimezone: mockTimezones[0],
},
stubs: {
GlCard,
......
......@@ -65,8 +65,8 @@ describe('ee/oncall_schedules/components/schedule/components/shifts/components/d
it('calculates the correct rotation assignee styles when the shift does not start at the beginning of the time-frame cell', () => {
/**
* Where left should be 500px i.e. ((HOURS_IN_DAY - (HOURS_IN_DAY - overlapStartTime)) * CELL_WIDTH)(((24 - (24 - 10)) * 50))
* and width should be overlapping hours * CELL_WIDTH(12 * 50 - 2)
* Where left should be 500px i.e. ((HOURS_IN_DAY - (HOURS_IN_DAY - overlapStartTime)) * CELL_WIDTH) (((24 - (24 - 10)) * 50))
* and width should be overlapping hours * CELL_WIDTH (12 * 50 - 2)
*/
createComponent({
props: {
......@@ -83,5 +83,30 @@ describe('ee/oncall_schedules/components/schedule/components/shifts/components/d
width: '598px',
});
});
it('handles the offset for timezone changes', () => {
const DLSTimeframeItem = new Date(2021, 2, 14);
const DSLTimeframe = [timeframeItem, nDaysAfter(timeframeItem, DAYS_IN_WEEK)];
/**
* Where left should be: ((HOURS_IN_DAY - (HOURS_IN_DAY - overlapStartTime)) * CELL_WIDTH)
* and width should be: (overlappingHours + timezoneOffset) * CELL_WIDTH
*/
createComponent({
props: {
shift: {
...shift,
startsAt: '2021-03-14T05:00:00Z',
endsAt: '2021-03-14T07:00:00Z',
},
timeframeItem: DLSTimeframeItem,
timeframe: DSLTimeframe,
},
data: { shiftTimeUnitWidth: CELL_WIDTH },
});
expect(findRotationAssignee().props('rotationAssigneeStyle')).toEqual({
left: '250px',
width: '98px',
});
});
});
});
......@@ -18,18 +18,6 @@ RSpec.describe Deployment do
deployment.succeed!
end
end
context 'when dora_daily_metrics feature flag is disabled' do
before do
stub_feature_flags(dora_daily_metrics: false)
end
it 'does not schedule Dora::DailyMetrics::RefreshWorker' do
expect(::Dora::DailyMetrics::RefreshWorker).not_to receive(:perform_in)
deployment.succeed!
end
end
end
end
end
......@@ -49,18 +49,6 @@ RSpec.describe API::Dora::Metrics do
expect(json_response['message']).to eq('You do not have permission to access dora metrics.')
end
end
context 'when dora_daily_metrics feature flag is disabled' do
before do
stub_feature_flags(dora_daily_metrics: false)
end
it 'returns not found' do
subject
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
describe 'GET /groups/:id/dora/metrics' do
......@@ -110,17 +98,5 @@ RSpec.describe API::Dora::Metrics do
expect(json_response['message']).to eq('You do not have permission to access dora metrics.')
end
end
context 'when dora_daily_metrics feature flag is disabled' do
before do
stub_feature_flags(dora_daily_metrics: false)
end
it 'returns not found' do
subject
expect(response).to have_gitlab_http_status(:not_found)
end
end
end
end
......@@ -126,9 +126,17 @@ describe('Flash', () => {
});
describe('deprecatedCreateFlash', () => {
const message = 'test';
const type = 'alert';
const parent = document;
const actionConfig = null;
const fadeTransition = false;
const addBodyClass = true;
const defaultParams = [message, type, parent, actionConfig, fadeTransition, addBodyClass];
describe('no flash-container', () => {
it('does not add to the DOM', () => {
const flashEl = deprecatedCreateFlash('testing');
const flashEl = deprecatedCreateFlash(message);
expect(flashEl).toBeNull();
......@@ -138,11 +146,9 @@ describe('Flash', () => {
describe('with flash-container', () => {
beforeEach(() => {
document.body.innerHTML += `
<div class="content-wrapper js-content-wrapper">
<div class="flash-container"></div>
</div>
`;
setFixtures(
'<div class="content-wrapper js-content-wrapper"><div class="flash-container"></div></div>',
);
});
afterEach(() => {
......@@ -150,7 +156,7 @@ describe('Flash', () => {
});
it('adds flash element into container', () => {
deprecatedCreateFlash('test', 'alert', document, null, false, true);
deprecatedCreateFlash(...defaultParams);
expect(document.querySelector('.flash-alert')).not.toBeNull();
......@@ -158,26 +164,35 @@ describe('Flash', () => {
});
it('adds flash into specified parent', () => {
deprecatedCreateFlash('test', 'alert', document.querySelector('.content-wrapper'));
deprecatedCreateFlash(
message,
type,
document.querySelector('.content-wrapper'),
actionConfig,
fadeTransition,
addBodyClass,
);
expect(document.querySelector('.content-wrapper .flash-alert')).not.toBeNull();
expect(document.querySelector('.content-wrapper').innerText.trim()).toEqual(message);
});
it('adds container classes when inside content-wrapper', () => {
deprecatedCreateFlash('test');
deprecatedCreateFlash(...defaultParams);
expect(document.querySelector('.flash-text').className).toBe('flash-text');
expect(document.querySelector('.content-wrapper').innerText.trim()).toEqual(message);
});
it('does not add container when outside of content-wrapper', () => {
document.querySelector('.content-wrapper').className = 'js-content-wrapper';
deprecatedCreateFlash('test');
deprecatedCreateFlash(...defaultParams);
expect(document.querySelector('.flash-text').className.trim()).toContain('flash-text');
});
it('removes element after clicking', () => {
deprecatedCreateFlash('test', 'alert', document, null, false, true);
deprecatedCreateFlash(...defaultParams);
document.querySelector('.flash-alert .js-close-icon').click();
......@@ -188,24 +203,37 @@ describe('Flash', () => {
describe('with actionConfig', () => {
it('adds action link', () => {
deprecatedCreateFlash('test', 'alert', document, {
title: 'test',
});
const newActionConfig = { title: 'test' };
deprecatedCreateFlash(
message,
type,
parent,
newActionConfig,
fadeTransition,
addBodyClass,
);
expect(document.querySelector('.flash-action')).not.toBeNull();
});
it('calls actionConfig clickHandler on click', () => {
const actionConfig = {
const newActionConfig = {
title: 'test',
clickHandler: jest.fn(),
};
deprecatedCreateFlash('test', 'alert', document, actionConfig);
deprecatedCreateFlash(
message,
type,
parent,
newActionConfig,
fadeTransition,
addBodyClass,
);
document.querySelector('.flash-action').click();
expect(actionConfig.clickHandler).toHaveBeenCalled();
expect(newActionConfig.clickHandler).toHaveBeenCalled();
});
});
});
......
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