Commit 45482d5a authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent 20450649
......@@ -29,25 +29,25 @@ export default {
});
});
const loadListIssues = listObj => {
const list = boardsStore.findList('title', listObj.title);
if (!list) {
return null;
}
list.id = listObj.id;
list.label.id = listObj.label.id;
return list.getIssues().catch(() => {
// TODO: handle request error
});
};
// Save the labels
boardsStore
.generateDefaultLists()
.then(res => res.data)
.then(data => {
data.forEach(listObj => {
const list = boardsStore.findList('title', listObj.title);
if (!list) {
return;
}
list.id = listObj.id;
list.label.id = listObj.label.id;
list.getIssues().catch(() => {
// TODO: handle request error
});
});
})
.then(data => Promise.all(data.map(loadListIssues)))
.catch(() => {
boardsStore.removeList(undefined, 'label');
Cookies.remove('issue_board_welcome_hidden', {
......
......@@ -251,58 +251,80 @@ export const saveNote = ({ commit, dispatch }, noteData) => {
}
}
return dispatch(methodToDispatch, postData, { root: true }).then(res => {
const processErrors = res => {
const { errors } = res;
const commandsChanges = res.commands_changes;
if (!errors || !Object.keys(errors).length) {
return res;
}
if (errors && Object.keys(errors).length) {
/*
The following reply means that quick actions have been successfully applied:
/*
The following reply means that quick actions have been successfully applied:
{"commands_changes":{},"valid":false,"errors":{"commands_only":["Commands applied"]}}
*/
if (hasQuickActions) {
eTagPoll.makeRequest();
{"commands_changes":{},"valid":false,"errors":{"commands_only":["Commands applied"]}}
*/
if (hasQuickActions) {
eTagPoll.makeRequest();
$('.js-gfm-input').trigger('clear-commands-cache.atwho');
Flash(__('Commands applied'), 'notice', noteData.flashContainer);
} else {
throw new Error(__('Failed to save comment!'));
}
$('.js-gfm-input').trigger('clear-commands-cache.atwho');
const { commands_only: message } = errors;
Flash(message || __('Commands applied'), 'notice', noteData.flashContainer);
return res;
}
if (commandsChanges) {
if (commandsChanges.emoji_award) {
const votesBlock = $('.js-awards-block').eq(0);
loadAwardsHandler()
.then(awardsHandler => {
awardsHandler.addAwardToEmojiBar(votesBlock, commandsChanges.emoji_award);
awardsHandler.scrollToAwards();
})
.catch(() => {
Flash(
__('Something went wrong while adding your award. Please try again.'),
'alert',
noteData.flashContainer,
);
});
}
throw new Error(__('Failed to save comment!'));
};
if (commandsChanges.spend_time != null || commandsChanges.time_estimate != null) {
sidebarTimeTrackingEventHub.$emit('timeTrackingUpdated', res);
}
const processEmojiAward = res => {
const { commands_changes: commandsChanges } = res;
const { emoji_award: emojiAward } = commandsChanges || {};
if (!emojiAward) {
return res;
}
if (errors && errors.commands_only) {
Flash(errors.commands_only, 'notice', noteData.flashContainer);
const votesBlock = $('.js-awards-block').eq(0);
return loadAwardsHandler()
.then(awardsHandler => {
awardsHandler.addAwardToEmojiBar(votesBlock, emojiAward);
awardsHandler.scrollToAwards();
})
.catch(() => {
Flash(
__('Something went wrong while adding your award. Please try again.'),
'alert',
noteData.flashContainer,
);
})
.then(() => res);
};
const processTimeTracking = res => {
const { commands_changes: commandsChanges } = res;
const { spend_time: spendTime, time_estimate: timeEstimate } = commandsChanges || {};
if (spendTime != null || timeEstimate != null) {
sidebarTimeTrackingEventHub.$emit('timeTrackingUpdated', {
commands_changes: commandsChanges,
});
}
return res;
};
const removePlaceholder = res => {
if (replyId) {
commit(types.REMOVE_PLACEHOLDER_NOTES);
}
return res;
});
};
return dispatch(methodToDispatch, postData, { root: true })
.then(processErrors)
.then(processEmojiAward)
.then(processTimeTracking)
.then(removePlaceholder);
};
const pollSuccessCallBack = (resp, commit, state, getters, dispatch) => {
......@@ -430,10 +452,13 @@ export const updateResolvableDiscussionsCounts = ({ commit }) =>
export const submitSuggestion = (
{ commit, dispatch },
{ discussionId, noteId, suggestionId, flashContainer },
) =>
Api.applySuggestion(suggestionId)
) => {
const dispatchResolveDiscussion = () =>
dispatch('resolveDiscussion', { discussionId }).catch(() => {});
return Api.applySuggestion(suggestionId)
.then(() => commit(types.APPLY_SUGGESTION, { discussionId, noteId, suggestionId }))
.then(() => dispatch('resolveDiscussion', { discussionId }).catch(() => {}))
.then(dispatchResolveDiscussion)
.catch(err => {
const defaultMessage = __(
'Something went wrong while applying the suggestion. Please try again.',
......@@ -442,6 +467,7 @@ export const submitSuggestion = (
Flash(__(flashMessage), 'alert', flashContainer);
});
};
export const convertToDiscussion = ({ commit }, noteId) =>
commit(types.CONVERT_TO_DISCUSSION, noteId);
......
......@@ -66,6 +66,7 @@ export default {
<template>
<div class="block issuable-sidebar-item confidentiality">
<div
ref="collapseIcon"
v-tooltip
:title="tooltipLabel"
class="sidebar-collapsed-icon"
......@@ -80,6 +81,7 @@ export default {
{{ __('Confidentiality') }}
<a
v-if="isEditable"
ref="editLink"
class="float-right confidential-edit"
href="#"
data-track-event="click_edit_button"
......
......@@ -108,7 +108,7 @@ This query outputs a list containing all indexes that are never used and sorts
them by indexes sizes in descending order. This query can be useful to
determine if any previously indexes are useful after all. More information on
the meaning of the various columns can be found at
<https://www.postgresql.org/docs/current/static/monitoring-stats.html>.
<https://www.postgresql.org/docs/current/monitoring-stats.html>.
Because the output of this query relies on the actual usage of your database it
may be affected by factors such as (but not limited to):
......
......@@ -157,7 +157,7 @@ Component statuses are linked to configuration documentation for each component.
| [Elasticsearch](#elasticsearch) | Improved search within GitLab | [][elasticsearch-omnibus] | [][elasticsearch-charts] | [][elasticsearch-charts] | [](https://gitlab.com/groups/gitlab-org/-/epics/153) | [][elasticsearch-source] | [][elasticsearch-gdk] | EE Only |
| [Sentry integration](#sentry) | Error tracking for deployed apps | [][sentry-integration] | [][sentry-integration] | [][sentry-integration] | [][sentry-integration] | [][sentry-integration] | [][sentry-integration] | CE & EE |
| [Jaeger integration](#jaeger) | Distributed tracing for deployed apps | [][jaeger-integration] | [][jaeger-integration] | [][jaeger-integration] | [][jaeger-integration] | [][jaeger-integration] | [][jaeger-integration] | EE Only |
| [GitLab Managed Apps](#gitlab-managed-apps) | Deploy [Helm](https://docs.helm.sh/), [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/), [Cert-Manager](https://docs.cert-manager.io/en/latest/), [Prometheus](https://prometheus.io/docs/introduction/overview/), a [Runner](https://docs.gitlab.com/runner/), [JupyterHub](http://jupyter.org/), [Knative](https://cloud.google.com/knative) to a cluster | [][managed-k8s-apps] | [][managed-k8s-apps] | [][managed-k8s-apps] | [][managed-k8s-apps] | [][managed-k8s-apps] | [][managed-k8s-apps] | CE & EE |
| [GitLab Managed Apps](#gitlab-managed-apps) | Deploy [Helm](https://helm.sh/docs/), [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/), [Cert-Manager](https://docs.cert-manager.io/en/latest/), [Prometheus](https://prometheus.io/docs/introduction/overview/), a [Runner](https://docs.gitlab.com/runner/), [JupyterHub](https://jupyter.org), [Knative](https://cloud.google.com/knative/) to a cluster | [][managed-k8s-apps] | [][managed-k8s-apps] | [][managed-k8s-apps] | [][managed-k8s-apps] | [][managed-k8s-apps] | [][managed-k8s-apps] | CE & EE |
### Component details
......
......@@ -18,7 +18,7 @@ recommended to pick someone who knows the domain well. You can read more about t
importance of involving reviewer(s) in the section on the responsibility of the author below.
If you need some guidance (e.g. it's your first merge request), feel free to ask
one of the [Merge request coaches][team].
one of the [Merge request coaches](https://about.gitlab.com/company/team/).
If you need assistance with security scans or comments, feel free to include the
Security Team (`@gitlab-com/gl-security`) in the review.
......@@ -66,13 +66,13 @@ from teams other than your own.
1. If your merge request includes frontend changes [^1], it must be
**approved by a [frontend maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab-ce_maintainers_frontend)**.
1. If your merge request includes UX changes [^1], it must be
**approved by a [UX team member][team]**.
**approved by a [UX team member](https://about.gitlab.com/company/team/)**.
1. If your merge request includes adding a new JavaScript library [^1], it must be
**approved by a [frontend lead][team]**.
**approved by a [frontend lead](https://about.gitlab.com/company/team/)**.
1. If your merge request includes adding a new UI/UX paradigm [^1], it must be
**approved by a [UX lead][team]**.
**approved by a [UX lead](https://about.gitlab.com/company/team/)**.
1. If your merge request includes a new dependency or a filesystem change, it must be
**approved by a [Distribution team member][team]**. See how to work with the [Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/distribution/#how-to-work-with-distribution) for more details.
**approved by a [Distribution team member](https://about.gitlab.com/company/team/)**. See how to work with the [Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/distribution/#how-to-work-with-distribution) for more details.
#### Security requirements
......@@ -172,7 +172,7 @@ required approvers.
Maintainers must check before merging if the merge request is introducing new
vulnerabilities, by inspecting the list in the Merge Request [Security
Widget](../user/project/merge_requests/index.md#security-reports-ultimate).
When in doubt, a [Security Engineer][team] can be involved. The list of detected
When in doubt, a [Security Engineer](https://about.gitlab.com/company/team/) can be involved. The list of detected
vulnerabilities must be either empty or containing:
- dismissed vulnerabilities in case of false positives
......@@ -433,7 +433,6 @@ Largely based on the [thoughtbot code review guide].
[Return to Development documentation](README.md)
[projects]: https://about.gitlab.com/handbook/engineering/projects/
[team]: https://about.gitlab.com/team/
[build handbook]: https://about.gitlab.com/handbook/build/handbook/build#how-to-work-with-build
[^1]: Please note that specs other than JavaScript specs are considered backend code.
[^2]: We encourage you to seek guidance from a database maintainer if your merge request is potentially introducing expensive queries. It is most efficient to comment on the line of code in question with the SQL queries so they can give their advice.
......@@ -5,7 +5,7 @@ For guidance on UX implementation at GitLab, please refer to our [Design System]
The UX team uses labels to manage their workflow.
The ~"UX" label on an issue is a signal to the UX team that it will need UX attention.
To better understand the priority by which UX tackles issues, see the [UX section](https://about.gitlab.com/handbook/engineering/ux) of the handbook.
To better understand the priority by which UX tackles issues, see the [UX section](https://about.gitlab.com/handbook/engineering/ux/) of the handbook.
Once an issue has been worked on and is ready for development, a UXer removes the ~"UX" label and applies the ~"UX ready" label to that issue.
......
......@@ -15,7 +15,7 @@ abbreviation.
To get an overview of GitLab community membership including those that would be reviewing or merging your contributions, please visit [the community roles page](community_roles.md).
If you want to know how the GitLab [core team]
If you want to know how the GitLab [core team](https://about.gitlab.com/community/core-team/)
operates please see [the GitLab contributing process](https://gitlab.com/gitlab-org/gitlab/blob/master/PROCESS.md).
[GitLab Inc engineers should refer to the engineering workflow document](https://about.gitlab.com/handbook/engineering/workflow/)
......@@ -24,7 +24,7 @@ operates please see [the GitLab contributing process](https://gitlab.com/gitlab-
Please report suspected security vulnerabilities in private to
`support@gitlab.com`, also see the
[disclosure section on the GitLab.com website](https://about.gitlab.com/disclosure/).
[disclosure section on the GitLab.com website](https://about.gitlab.com/security/disclosure/).
Please do **NOT** create publicly viewable issues for suspected security
vulnerabilities.
......@@ -48,7 +48,7 @@ for audiences of all ages.
If a contributor is no longer actively working on a submitted merge request
we can decide that the merge request will be finished by one of our
[Merge request coaches][team] or close the merge request. We make this decision
[Merge request coaches](https://about.gitlab.com/company/team/) or close the merge request. We make this decision
based on how important the change is for our product vision. If a merge request
coach is going to finish the merge request we assign the
~"coach will finish" label. When a team member picks up a community contribution,
......@@ -59,10 +59,10 @@ within the MR.
## Helping others
Please help other GitLab users when you can.
The methods people will use to seek help can be found on the [getting help page][getting-help].
The methods people will use to seek help can be found on the [getting help page](https://about.gitlab.com/get-help/).
Sign up for the mailing list, answer GitLab questions on StackOverflow or
respond in the IRC channel. You can also sign up on [CodeTriage][codetriage] to help with
respond in the IRC channel. You can also sign up on [CodeTriage](https://www.codetriage.com/gitlabhq/gitlabhq) to help with
the remaining issues on the GitHub issue tracker.
## I want to contribute
......@@ -70,7 +70,7 @@ the remaining issues on the GitHub issue tracker.
If you want to contribute to GitLab,
[issues with the `Accepting merge requests` label](issue_workflow.md#label-for-community-contributors)
are a great place to start.
If you have any questions or need help visit [Getting Help](https://about.gitlab.com/getting-help/#discussion) to
If you have any questions or need help visit [Getting Help](https://about.gitlab.com/get-help/) to
learn how to communicate with GitLab. If you're looking for a Gitter or Slack channel
please consider we favor
[asynchronous communication](https://about.gitlab.com/handbook/communication/#internal-communication) over real time communication. Thanks for your contribution!
......@@ -85,7 +85,7 @@ When maintainers are reading through a merge request they may request guidance f
Sometimes style guides will be followed but the code will lack structural integrity, or the maintainer will have reservations about the code’s overall quality. When there is a reservation the maintainer will inform the author and provide some guidance. The author may then choose to update the merge request. Once the merge request has been updated and reassigned to the maintainer, they will review the code again. Once the code has been resubmitted any number of times, the maintainer may choose to close the merge request with a summary of why it will not be merged, as well as some guidance. If the merge request is closed the maintainer will be open to discussion as to how to improve the code so it can be approved in the future.
GitLab will do its best to review community contributions as quickly as possible. Specially appointed developers review community contributions daily. You may take a look at the [team page](https://about.gitlab.com/team/) for the merge request coach who specializes in the type of code you have written and mention them in the merge request. For example, if you have written some JavaScript in your code then you should mention the frontend merge request coach. If your code has multiple disciplines you may mention multiple merge request coaches.
GitLab will do its best to review community contributions as quickly as possible. Specially appointed developers review community contributions daily. You may take a look at the [team page](https://about.gitlab.com/company/team/) for the merge request coach who specializes in the type of code you have written and mention them in the merge request. For example, if you have written some JavaScript in your code then you should mention the frontend merge request coach. If your code has multiple disciplines you may mention multiple merge request coaches.
GitLab receives a lot of community contributions, so if your code has not been reviewed within two days (excluding weekend and public holidays) of its initial submission feel free to re-mention the appropriate merge request coach.
......@@ -122,8 +122,3 @@ This [documentation](style_guides.md) outlines the current style guidelines.
---
[Return to Development documentation](../README.md)
[core team]: https://about.gitlab.com/core-team/
[team]: https://about.gitlab.com/company/team/
[getting-help]: https://about.gitlab.com/getting-help/
[codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
......@@ -22,7 +22,7 @@ once every quarter.
The most important thing is making sure valid issues receive feedback from the
development team. Therefore the priority is mentioning developers that can help
on those issues. Please select someone with relevant experience from the
[GitLab team](https://about.gitlab.com/team/).
[GitLab team](https://about.gitlab.com/company/team/).
If there is nobody mentioned with that expertise look in the commit history for
the affected files to find someone.
......@@ -152,7 +152,7 @@ As a team needs some way to collect the work their members are planning to be as
Normally there is a 1:1 relationship between Stage labels and Group labels. In the spirit of "Everyone can contribute",
any issue can be picked up by any group, depending on current priorities. For example, an issue labeled ~"devops::create" may be picked up by the ~"group::access" group.
We also use stage and group labels to help quantify our [throughput](https://about.gitlab.com/handbook/engineering/management/throughput).
We also use stage and group labels to help quantify our [throughput](https://about.gitlab.com/handbook/engineering/management/throughput/).
Please read [Stage and Group labels in Throughtput](https://about.gitlab.com/handbook/engineering/management/throughput/#stage-and-group-labels-in-throughput) for more information on how the labels are used in this context.
### Category labels
......@@ -336,7 +336,7 @@ know how difficult the issue is. Additionally:
- We advertise [`Accepting merge requests` issues with weight < 5](https://gitlab.com/groups/gitlab-org/-/issues?state=opened&label_name[]=Accepting+merge+requests&assignee_id=None&sort=weight)
as suitable for people that have never contributed to GitLab before on the
[Up For Grabs campaign](http://up-for-grabs.net)
[Up For Grabs campaign](https://up-for-grabs.net/#/)
- We encourage people that have never contributed to any open source project to
look for [`Accepting merge requests` issues with a weight of 1](https://gitlab.com/groups/gitlab-org/-/issues?state=opened&label_name[]=Accepting+merge+requests&assignee_id=None&sort=weight&weight=1)
......
......@@ -89,7 +89,7 @@ request is as follows:
1. Write tests for more complex migrations.
1. Merge requests **must** adhere to the [merge request performance guidelines](../merge_request_performance_guidelines.md).
1. For tests that use Capybara, read
[how to write reliable, asynchronous integration tests](https://robots.thoughtbot.com/write-reliable-asynchronous-integration-tests-with-capybara).
[how to write reliable, asynchronous integration tests](https://thoughtbot.com/blog/write-reliable-asynchronous-integration-tests-with-capybara).
1. If your merge request introduces changes that require additional steps when
installing GitLab from source, add them to `doc/install/installation.md` in
the same merge request.
......@@ -101,7 +101,7 @@ request is as follows:
If you would like quick feedback on your merge request feel free to mention someone
from the [core team](https://about.gitlab.com/community/core-team/) or one of the
[merge request coaches](https://about.gitlab.com/team/). When having your code reviewed
[merge request coaches](https://about.gitlab.com/company/team/). When having your code reviewed
and when reviewing merge requests, please keep the [code review guidelines](../code_review.md)
in mind. And if your code also makes changes to the database, or does expensive queries,
check the [database review guidelines](../database_review.md).
......
......@@ -1107,7 +1107,7 @@ Rendered example:
### cURL Examples
Below is a set of [cURL][] examples that you can use in the API documentation.
Below is a set of [cURL](https://curl.haxx.se) examples that you can use in the API documentation.
#### Simple cURL command
......@@ -1179,7 +1179,6 @@ restrict the sign-up e-mail domains of a GitLab instance to `*.example.com` and
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" --data "domain_whitelist[]=*.example.com" --data "domain_whitelist[]=example.net" https://gitlab.example.com/api/v4/application/settings
```
[cURL]: http://curl.haxx.se/ "cURL website"
[single spaces]: http://www.slate.com/articles/technology/technology/2011/01/space_invaders.html
[gfm]: ../../user/markdown.md#newlines "GitLab flavored markdown documentation"
[ce-1242]: https://gitlab.com/gitlab-org/gitlab-foss/issues/1242
......
......@@ -59,7 +59,7 @@ Additionally, if you need large repos or multiple forks for testing, please cons
## How does it work?
The Elasticsearch integration depends on an external indexer. We ship an [indexer written in Go](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer). The user must trigger the initial indexing via a rake task but, after this is done, GitLab itself will trigger reindexing when required via `after_` callbacks on create, update, and destroy that are inherited from [/ee/app/models/concerns/elastic/application_search.rb](https://gitlab.com/gitlab-org/gitlab/blob/cc723071ad337573e0360a879cbf99bc4fb7adb9/ee/app/models/concerns/elastic/application_versioned_search.rb).
The Elasticsearch integration depends on an external indexer. We ship an [indexer written in Go](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer). The user must trigger the initial indexing via a rake task but, after this is done, GitLab itself will trigger reindexing when required via `after_` callbacks on create, update, and destroy that are inherited from [/ee/app/models/concerns/elastic/application_versioned_search.rb](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/models/concerns/elastic/application_versioned_search.rb).
All indexing after the initial one is done via `ElasticIndexerWorker` (sidekiq jobs).
......@@ -243,4 +243,4 @@ cluster.routing.allocation.disk.watermark.high: 10gb
Restart Elasticsearch, and the `read_only_allow_delete` will clear on it's own.
_from "Disk-based Shard Allocation | Elasticsearch Reference" [5.6](https://www.elastic.co/guide/en/elasticsearch/reference/5.6/disk-allocator.html#disk-allocator) and [6.x](https://www.elastic.co/guide/en/elasticsearch/reference/6.x/disk-allocator.html)_
_from "Disk-based Shard Allocation | Elasticsearch Reference" [5.6](https://www.elastic.co/guide/en/elasticsearch/reference/5.6/disk-allocator.html#disk-allocator) and [6.x](https://www.elastic.co/guide/en/elasticsearch/reference/6.7/disk-allocator.html)_
......@@ -17,10 +17,9 @@ dummy data.
The previews live in [`app/mailers/previews`][previews] and can be viewed at
[`/rails/mailers`](http://localhost:3000/rails/mailers).
See the [Rails guides] for more info.
See the [Rails guides](https://guides.rubyonrails.org/action_mailer_basics.html#previewing-emails) for more info.
[previews]: https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/mailers/previews
[Rails guides]: http://guides.rubyonrails.org/action_mailer_basics.html#previewing-emails
## Incoming email
......
......@@ -5,8 +5,8 @@ across GitLab's frontend team.
## Overview
GitLab is built on top of [Ruby on Rails][rails] using [Haml][haml] and also a JavaScript based Frontend with [Vue.js][vue].
Be wary of [the limitations that come with using Hamlit][hamlit-limits]. We also use [SCSS][scss] and plain JavaScript with
GitLab is built on top of [Ruby on Rails](https://rubyonrails.org) using [Haml][haml] and also a JavaScript based Frontend with [Vue.js](https://vuejs.org).
Be wary of [the limitations that come with using Hamlit][hamlit-limits]. We also use [SCSS](https://sass-lang.com) and plain JavaScript with
modern ECMAScript standards supported through [Babel][babel] and ES module support through [webpack][webpack].
Working with our frontend assets requires Node (v8.10.0 or greater) and Yarn
......@@ -83,7 +83,7 @@ changes.
### [SCSS Style Guide](style_guide_scss.md)
Our SCSS conventions which are enforced through [scss-lint][scss-lint].
Our SCSS conventions which are enforced through [scss-lint](https://github.com/sds/scss-lint).
## [Performance](performance.md)
......@@ -102,17 +102,13 @@ Our accessibility standards and resources.
Frontend internationalization support is described in [this document](../i18n/).
The [externalization part of the guide](../i18n/externalization.md) explains the helpers/methods available.
[rails]: http://rubyonrails.org/
[haml]: http://haml.info/
[hamlit]: https://github.com/k0kubun/hamlit
[hamlit-limits]: https://github.com/k0kubun/hamlit/blob/master/REFERENCE.md#limitations
[scss]: http://sass-lang.com/
[babel]: https://babeljs.io/
[webpack]: https://webpack.js.org/
[jquery]: https://jquery.com/
[vue]: http://vuejs.org/
[axios]: https://github.com/axios/axios
[airbnb-js-style-guide]: https://github.com/airbnb/javascript
[scss-lint]: https://github.com/brigade/scss-lint
[install]: ../../install/installation.md#4-node
[requirements]: ../../install/requirements.md#supported-web-browsers
......@@ -165,14 +165,12 @@ General tips:
## Additional Resources
- [WebPage Test][web-page-test] for testing site loading time and size.
- [WebPage Test](https://www.webpagetest.org) for testing site loading time and size.
- [Google PageSpeed Insights][pagespeed-insights] grades web pages and provides feedback to improve the page.
- [Profiling with Chrome DevTools][google-devtools-profiling]
- [Profiling with Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/)
- [Browser Diet][browser-diet] is a community-built guide that catalogues practical tips for improving web page performance.
[web-page-test]: http://www.webpagetest.org/
[pagespeed-insights]: https://developers.google.com/speed/pagespeed/insights/
[google-devtools-profiling]: https://developers.google.com/web/tools/chrome-devtools/profile/?hl=en
[browser-diet]: https://browserdiet.com/
[high-perf-animations]: https://www.html5rocks.com/en/tutorials/speed/high-performance-animations/
[flip]: https://aerotwist.com/blog/flip-your-animations/
......@@ -27,8 +27,8 @@ New utility classes should be added to [`utilities.scss`](https://gitlab.com/git
| Font size | `.text-{size}` | `.text-2` |
- `{variant}` is one of 'primary', 'secondary', 'success', 'warning', 'error'
- `{shade}` is on of the shades listed on [colors](https://design.gitlab.com/foundations/colors/)
- `{size}` is a number from 1-6 from our [Type scale](https://design.gitlab.com/foundations/typography)
- `{shade}` is on of the shades listed on [colors](https://design.gitlab.com/product-foundations/colors/)
- `{size}` is a number from 1-6 from our [Type scale](https://design.gitlab.com/product-foundations/typography)
#### When should I create component classes?
......@@ -46,8 +46,8 @@ Examples of component classes that were created using "utility-first" include:
Inspiration:
- <https://tailwindcss.com/docs/utility-first>
- <https://tailwindcss.com/docs/extracting-components>
- <https://tailwindcss.com/docs/utility-first/>
- <https://tailwindcss.com/docs/extracting-components/>
### Naming
......@@ -236,7 +236,7 @@ Before adding a new variable for a color or a size, guarantee:
## Linting
We use [SCSS Lint][scss-lint] to check for style guide conformity. It uses the
We use [SCSS Lint](https://github.com/sds/scss-lint) to check for style guide conformity. It uses the
ruleset in `.scss-lint.yml`, which is located in the home directory of the
project.
......@@ -245,7 +245,7 @@ scss_lint` in the GitLab directory. SCSS Lint will also run in GitLab CI to
catch any warnings.
If the Rake task is throwing warnings you don't understand, SCSS Lint's
documentation includes [a full list of their linters][scss-lint-documentation].
documentation includes [a full list of their linters][scss-lint-documentation](https://github.com/sds/scss-lint/blob/master/lib/scss_lint/linter/README.md).
### Fixing issues
......@@ -260,7 +260,7 @@ Note that this won't fix every problem, but it should fix a majority.
### Ignoring issues
If you want a line or set of lines to be ignored by the linter, you can use
`// scss-lint:disable RuleName` ([more info][disabling-linters]):
`// scss-lint:disable RuleName` ([more info](https://github.com/sds/scss-lint#disabling-linters-via-source)):
```scss
// This lint rule is disabled because it is supported only in Chrome/Safari
......@@ -279,6 +279,3 @@ guide is ignored in this instance.
[csscomb]: https://github.com/csscomb/csscomb.js
[node]: https://github.com/nodejs/node
[npm]: https://www.npmjs.com/
[scss-lint]: https://github.com/brigade/scss-lint
[scss-lint-documentation]: https://github.com/brigade/scss-lint/blob/master/lib/scss_lint/linter/README.md
[disabling-linters]: https://github.com/brigade/scss-lint#disabling-linters-via-source
# Vue
To get started with Vue, read through [their documentation][vue-docs].
To get started with Vue, read through [their documentation](https://vuejs.org/v2/guide/).
## Examples
......@@ -290,7 +290,6 @@ One should apply to be a Vue.js expert by opening an MR when the Merge Request's
- Vuex code follows the [documented pattern](vuex.md#actions-pattern-request-and-receive-namespaces)
- Knowledge about the existing Vue and Vuex applications and existing reusable components
[vue-docs]: http://vuejs.org/guide/index.html
[issue-boards]: https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/boards
[environments-table]: https://gitlab.com/gitlab-org/gitlab-foss/tree/master/app/assets/javascripts/environments
[page_specific_javascript]: ./performance.md#page-specific-javascript
......@@ -298,5 +297,5 @@ One should apply to be a Vue.js expert by opening an MR when the Merge Request's
[state-management]: https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch
[one-way-data-flow]: https://vuejs.org/v2/guide/components.html#One-Way-Data-Flow
[vue-test]: https://vuejs.org/v2/guide/unit-testing.html
[flux]: https://facebook.github.io/flux
[flux]: https://facebook.github.io/flux/
[axios]: https://github.com/axios/axios
......@@ -232,7 +232,7 @@ import { mapGetters } from 'vuex';
### `mutation_types.js`
From [vuex mutations docs][vuex-mutations]:
From [vuex mutations docs](https://vuex.vuejs.org/guide/mutations.html):
> It is a commonly seen pattern to use constants for mutation types in various Flux implementations. This allows the code to take advantage of tooling like linters, and putting all constants in a single file allows your collaborators to get an at-a-glance view of what mutations are possible in the entire application.
```javascript
......@@ -336,7 +336,7 @@ export default {
#### Testing Vuex concerns
Refer to [vuex docs][vuex-testing] regarding testing Actions, Getters and Mutations.
Refer to [vuex docs](https://vuex.vuejs.org/guide/testing.html) regarding testing Actions, Getters and Mutations.
#### Testing components that need a store
......@@ -396,6 +396,3 @@ export default () => {};
```
[vuex-docs]: https://vuex.vuejs.org
[vuex-structure]: https://vuex.vuejs.org/en/structure.html
[vuex-mutations]: https://vuex.vuejs.org/en/mutations.html
[vuex-testing]: https://vuex.vuejs.org/en/testing.html
......@@ -144,13 +144,11 @@ refresh_service.execute(oldrev, newrev, ref)
## Do not `rescue Exception`
See ["Why is it bad style to `rescue Exception => e` in Ruby?"][Exception].
See ["Why is it bad style to `rescue Exception => e` in Ruby?"](https://stackoverflow.com/questions/10048173/why-is-it-bad-style-to-rescue-exception-e-in-ruby).
_**Note:** This rule is [enforced automatically by
Rubocop](https://gitlab.com/gitlab-org/gitlab/blob/8-4-stable/.rubocop.yml#L911-914)._
[Exception]: http://stackoverflow.com/q/10048173/223897
## Do not use inline JavaScript in views
Using the inline `:javascript` Haml filters comes with a
......@@ -161,4 +159,4 @@ in an initializer._
### Further reading
- Stack Overflow: [Why you should not write inline JavaScript](http://programmers.stackexchange.com/questions/86589/why-should-i-avoid-inline-scripting)
- Stack Overflow: [Why you should not write inline JavaScript](https://softwareengineering.stackexchange.com/questions/86589/why-should-i-avoid-inline-scripting)
......@@ -323,7 +323,7 @@ bin/rake gettext:regenerate
This command will update `locale/gitlab.pot` file with the newly externalized
strings and remove any strings that aren't used anymore. You should check this
file in. Once the changes are on master, they will be picked up by
[Crowdin](http://translate.gitlab.com) and be presented for
[Crowdin](https://translate.gitlab.com) and be presented for
translation.
We don't need to check in any changes to the
......
......@@ -15,8 +15,8 @@ By default Crowdin commits translations with `[skip ci]` in the commit
message. This is done to avoid a bunch of pipelines being run. Before
merging translations, make sure to trigger a pipeline to validate
translations, we have static analysis validating things Crowdin
doesn't do. Create a [new pipeline](https://gitlab.com/gitlab-org/gitlab/pipelines/new) for the
`master-i18n` branch.
doesn't do. Create a new pipeline at `https://gitlab.com/gitlab-org/gitlab/pipelines/new`
(need Developer access permissions) for the `master-i18n` branch.
If there are validation errors, the easiest solution is to disapprove
the offending string in Crowdin, leaving a comment with what is
......@@ -53,7 +53,7 @@ or merged. But it won't recreate the `master-i18n` branch every
time. To force Crowdin to recreate the branch, close any [open merge
request](https://gitlab.com/gitlab-org/gitlab/merge_requests?scope=all&utf8=%E2%9C%93&state=opened&author_username=gitlab-crowdin-bot)
and delete the
[`master-18n`](https://gitlab.com/gitlab-org/gitlab/branches/all?utf8=%E2%9C%93&search=master-i18n).
[`master-18n`](https://gitlab.com/gitlab-org/gitlab/-/branches/all?utf8=✓&search=master-i18n).
This might be needed when the merge request contains failures that
have been fixed on master.
......@@ -128,10 +128,10 @@ are very appreciative of the work done by translators and proofreaders!
have previously translated.
1. Your request to become a proofreader will be considered on the merits of
your previous translations by [GitLab team members](https://about.gitlab.com/team/)
or [Core team members](https://about.gitlab.com/core-team/) who are fluent in
your previous translations by [GitLab team members](https://about.gitlab.com/company/team/)
or [Core team members](https://about.gitlab.com/community/core-team/) who are fluent in
the language or current proofreaders.
- When a request is made for the first proofreader for a language and there are no [GitLab team members](https://about.gitlab.com/team/)
or [Core team members](https://about.gitlab.com/core-team/) who speak the language, we will request links to previous translation work in other communities or projects.
- When a request is made for the first proofreader for a language and there are no [GitLab team members](https://about.gitlab.com/company/team/)
or [Core team members](https://about.gitlab.com/community/core-team/) who speak the language, we will request links to previous translation work in other communities or projects.
[proofreader-src]: https://gitlab.com/gitlab-org/gitlab/blob/master/doc/development/i18n/proofreader.md
......@@ -98,7 +98,8 @@ importing big projects, using a foreground import:
## Security
The Import/Export feature is constantly updated (adding new things to export), however
the code hasn't been refactored in a long time. We should perform a [code audit](https://gitlab.com/gitlab-org/gitlab-foss/issues/42135)
the code hasn't been refactored in a long time. We should perform a code audit (see
[confidential issue](../user/project/issues/confidential_issues.md) `https://gitlab.com/gitlab-org/gitlab/issues/20720`).
to make sure its dynamic nature does not increase the number of security concerns.
### Security in the code
......
......@@ -46,9 +46,9 @@ More detailed information on how the gem and its commands work is available in t
Libraries with the following licenses are acceptable for use:
- [The MIT License][MIT] (the MIT Expat License specifically): The MIT License requires that the license itself is included with all copies of the source. It is a permissive (non-copyleft) license as defined by the Open Source Initiative.
- [LGPL][LGPL] (version 2, version 3): GPL constraints regarding modification and redistribution under the same license are not required of projects using an LGPL library, only upon modification of the LGPL-licensed library itself.
- [Apache 2.0 License][apache-2]: A permissive license that also provides an express grant of patent rights from contributors to users.
- [The MIT License](https://choosealicense.com/licenses/mit/) (the MIT Expat License specifically): The MIT License requires that the license itself is included with all copies of the source. It is a permissive (non-copyleft) license as defined by the Open Source Initiative.
- [LGPL](https://choosealicense.com/licenses/lgpl-3.0/) (version 2, version 3): GPL constraints regarding modification and redistribution under the same license are not required of projects using an LGPL library, only upon modification of the LGPL-licensed library itself.
- [Apache 2.0 License](https://choosealicense.com/licenses/apache-2.0/): A permissive license that also provides an express grant of patent rights from contributors to users.
- [Ruby 1.8 License][ruby-1.8]: Dual-licensed under either itself or the GPLv2, defer to the Ruby License itself. Acceptable because of point 3b: "You may distribute the software in object code or binary form, provided that you do at least ONE of the following: b) accompany the distribution with the machine-readable source of the software."
- [Ruby 1.9 License][ruby-1.9]: Dual-licensed under either itself or the BSD 2-Clause License, defer to BSD 2-Clause.
- [BSD 2-Clause License][BSD-2-Clause]: A permissive (non-copyleft) license as defined by the Open Source Initiative.
......@@ -62,8 +62,8 @@ Libraries with the following licenses are acceptable for use:
Libraries with the following licenses require legal approval for use:
- [GNU GPL][GPL] (version 1, [version 2][GPLv2], [version 3][GPLv3], or any future versions): GPL-licensed libraries cannot be linked to from non-GPL projects.
- [GNU AGPLv3][AGPLv3]: AGPL-licensed libraries cannot be linked to from non-GPL projects.
- [GNU GPL](https://choosealicense.com/licenses/gpl-3.0/) (version 1, [version 2][GPLv2], [version 3][GPLv3], or any future versions): GPL-licensed libraries cannot be linked to from non-GPL projects.
- [GNU AGPLv3](https://choosealicense.com/licenses/agpl-3.0/): AGPL-licensed libraries cannot be linked to from non-GPL projects.
- [Open Software License (OSL)][OSL]: is a copyleft license. In addition, the FSF [recommend against its use][OSL-GNU].
- [Facebook BSD + PATENTS][Facebook]: is a 3-clause BSD license with a patent grant that has been deemed [Category X][x-list] by the Apache foundation.
- [WTFPL][WTFPL]: is a public domain dedication [rejected by the OSI (3.2)][WTFPL-OSI]. Also has a strong language which is not in accordance with our diversity policy.
......@@ -109,19 +109,14 @@ Dependencies which are only used in development or test environment are exempt f
[CE]: https://gitlab.com/gitlab-org/gitlab-foss/blob/master/LICENSE
[EE]: https://gitlab.com/gitlab-org/gitlab/blob/master/LICENSE
[license_finder]: https://github.com/pivotal/LicenseFinder
[MIT]: http://choosealicense.com/licenses/mit/
[LGPL]: http://choosealicense.com/licenses/lgpl-3.0/
[apache-2]: http://choosealicense.com/licenses/apache-2.0/
[ruby-1.8]: https://github.com/ruby/ruby/blob/ruby_1_8_6/COPYING
[ruby-1.9]: https://www.ruby-lang.org/en/about/license.txt
[BSD-2-Clause]: https://opensource.org/licenses/BSD-2-Clause
[BSD-3-Clause]: https://opensource.org/licenses/BSD-3-Clause
[ISC]: https://opensource.org/licenses/ISC
[CC0]: https://creativecommons.org/publicdomain/zero/1.0/
[GPL]: http://choosealicense.com/licenses/gpl-3.0/
[GPLv2]: http://www.gnu.org/licenses/gpl-2.0.txt
[GPLv3]: http://www.gnu.org/licenses/gpl-3.0.txt
[AGPLv3]: http://choosealicense.com/licenses/agpl-3.0/
[GNU-GPL-FAQ]: http://www.gnu.org/licenses/gpl-faq.html#IfLibraryIsGPL
[OSI-GPL]: https://opensource.org/faq#linking-proprietary-code
[OSL]: https://opensource.org/licenses/OSL-3.0
......
......@@ -41,7 +41,7 @@ about the impact.
Sometimes it's hard to assess the impact of a merge request. In this case you
should ask one of the merge request reviewers to review your changes. You can
find a list of these reviewers at <https://about.gitlab.com/team/>. A reviewer
find a list of these reviewers at <https://about.gitlab.com/company/team/>. A reviewer
in turn can request a performance specialist to review the changes.
## Query Counts
......@@ -68,7 +68,7 @@ end
This will end up running one query for every object to update. This code can
easily overload a database given enough rows to update or many instances of this
code running in parallel. This particular problem is known as the
["N+1 query problem"](http://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations). You can write a test with [QueryRecoder](query_recorder.md) to detect this and prevent regressions.
["N+1 query problem"](https://guides.rubyonrails.org/active_record_querying.html#eager-loading-associations). You can write a test with [QueryRecoder](query_recorder.md) to detect this and prevent regressions.
In this particular case the workaround is fairly easy:
......@@ -171,4 +171,4 @@ Caching data per transaction can be done using
[RequestStore](https://github.com/steveklabnik/request_store) (use
`Gitlab::SafeRequestStore` to avoid having to remember to check
`RequestStore.active?`). Caching data in Redis can be done using [Rails' caching
system](http://guides.rubyonrails.org/caching_with_rails.html).
system](https://guides.rubyonrails.org/caching_with_rails.html).
......@@ -188,8 +188,8 @@ disabled due to legacy compatibility reasons but they are in the process of bein
Do not disable specific ESLint rules. Due to technical debt, you may disable the following
rules only if you are invoking/instantiating existing code modules.
- [no-new](http://eslint.org/docs/rules/no-new)
- [class-method-use-this](http://eslint.org/docs/rules/class-methods-use-this)
- [no-new](https://eslint.org/docs/rules/no-new)
- [class-method-use-this](https://eslint.org/docs/rules/class-methods-use-this)
> Note: Disable these rules on a per line basis. This makes it easier to refactor
> in the future. E.g. use `eslint-disable-next-line` or `eslint-disable-line`.
......@@ -86,8 +86,8 @@ that builds on this to add some additional niceties, such as allowing
configuration with a single Yaml file for multiple URLs, and uploading of the
profile and log output to S3.
For GitLab.com, you can find the latest results here:
<http://redash.gitlab.com/dashboard/gitlab-profiler-statistics>
For GitLab.com, you can find the latest results here (restricted to GitLab Team members only):
`https://redash.gitlab.com/dashboard/gitlab-profiler-statistics`
## Sherlock
......
......@@ -2,10 +2,9 @@
## Deep Dive
In December 2018, Tiago Botelho hosted a [Deep Dive] on GitLab's [Pull Repository Mirroring functionality] to share his domain specific knowledge with anyone who may work in this part of the code base in the future. You can find the [recording on YouTube], and the slides on [Google Slides] and in [PDF]. Everything covered in this deep dive was accurate as of GitLab 11.6, and while specific details may have changed since then, it should still serve as a good introduction.
In December 2018, Tiago Botelho hosted a [Deep Dive] on GitLab's [Pull Repository Mirroring functionality] to share his domain specific knowledge with anyone who may work in this part of the code base in the future. You can find the [recording on YouTube], and the slides in [PDF]. Everything covered in this deep dive was accurate as of GitLab 11.6, and while specific details may have changed since then, it should still serve as a good introduction.
[Deep Dive]: https://gitlab.com/gitlab-org/create-stage/issues/1
[Pull Repository Mirroring functionality]: ../workflow/repository_mirroring.md#pulling-from-a-remote-repository-starter
[recording on YouTube]: https://www.youtube.com/watch?v=sSZq0fpdY-Y
[Google Slides]: https://docs.google.com/presentation/d/17BTT6M6RyNRckV4wTt-dr07nIfBvD325_xVBoLtSoPM/edit?usp=sharing
[PDF]: https://gitlab.com/gitlab-org/create-stage/uploads/8693404888a941fd851f8a8ecdec9675/Gitlab_Create_-_Pull_Mirroring_Deep_Dive.pdf
......@@ -5,9 +5,9 @@ These guidelines are meant to make your code more reliable _and_ secure.
## References
- [Google Ruby Security Reviewer's Guide](https://code.google.com/p/ruby-security/wiki/Guide)
- [Google Ruby Security Reviewer's Guide](https://code.google.com/archive/p/ruby-security/wikis/Guide.wiki)
- [OWASP Command Injection](https://www.owasp.org/index.php/Command_Injection)
- [Ruby on Rails Security Guide Command Line Injection](http://guides.rubyonrails.org/security.html#command-line-injection)
- [Ruby on Rails Security Guide Command Line Injection](https://guides.rubyonrails.org/security.html#command-line-injection)
## Use File and FileUtils instead of shell commands
......
......@@ -74,7 +74,7 @@ USING GIN(column_name gin_trgm_ops);
```
The key here is the `GIN(column_name gin_trgm_ops)` part. This creates a [GIN
index][gin-index] with the operator class set to `gin_trgm_ops`. These indexes
index](https://www.postgresql.org/docs/current/gin.html) with the operator class set to `gin_trgm_ops`. These indexes
_can_ be used by `ILIKE` / `LIKE` and can lead to greatly improved performance.
One downside of these indexes is that they can easily get quite large (depending
on the amount of data indexed).
......@@ -247,8 +247,6 @@ WHERE EXISTS (
)
```
[gin-index]: http://www.postgresql.org/docs/current/static/gin.html
## `.find_or_create_by` is not atomic
The inherent pattern with methods like `.find_or_create_by` and
......
......@@ -51,7 +51,7 @@ bundle exec rspec spec/[path]/[to]/[spec].rb
methods.
- Use `context` to test branching logic.
- Try to match the ordering of tests to the ordering within the class.
- Try to follow the [Four-Phase Test][four-phase-test] pattern, using newlines
- Try to follow the [Four-Phase Test](https://thoughtbot.com/blog/four-phase-test) pattern, using newlines
to separate phases.
- Use `Gitlab.config.gitlab.host` rather than hard coding `'localhost'`
- Don't assert against the absolute value of a sequence-generated attribute (see
......@@ -62,8 +62,6 @@ bundle exec rspec spec/[path]/[to]/[spec].rb
use a Capyabara matcher beforehand (e.g. `find('.js-foo')`) to ensure the element actually exists.
- Use `focus: true` to isolate parts of the specs you want to run.
[four-phase-test]: https://robots.thoughtbot.com/four-phase-test
### System / Feature tests
NOTE: **Note:** Before writing a new system test, [please consider **not**
......@@ -185,7 +183,7 @@ instead of 30+ seconds in case of a regular `spec_helper`.
### `let` variables
GitLab's RSpec suite has made extensive use of `let`(along with it strict, non-lazy
version `let!`) variables to reduce duplication. However, this sometimes [comes at the cost of clarity][lets-not],
version `let!`) variables to reduce duplication. However, this sometimes [comes at the cost of clarity](https://thoughtbot.com/blog/lets-not),
so we need to set some guidelines for their use going forward:
- `let!` variables are preferable to instance variables. `let` variables
......@@ -204,8 +202,6 @@ so we need to set some guidelines for their use going forward:
order is required, otherwise `let` will suffice. Remember that `let` is lazy and won't
be evaluated until it is referenced.
[lets-not]: https://robots.thoughtbot.com/lets-not
### `set` variables
In some cases there is no need to recreate the same object for tests again for
......@@ -532,7 +528,7 @@ GitLab uses [factory_bot] as a test fixture replacement.
- There should be only one top-level factory definition per file.
- FactoryBot methods are mixed in to all RSpec groups. This means you can (and
should) call `create(...)` instead of `FactoryBot.create(...)`.
- Make use of [traits] to clean up definitions and usages.
- Make use of [traits](https://www.rubydoc.info/gems/factory_bot/file/GETTING_STARTED.md#Traits) to clean up definitions and usages.
- When defining a factory, don't define attributes that are not required for the
resulting record to pass validation.
- When instantiating from a factory, don't supply attributes that aren't
......@@ -541,7 +537,6 @@ GitLab uses [factory_bot] as a test fixture replacement.
[See example](https://gitlab.com/gitlab-org/gitlab-foss/commit/0b8cefd3b2385a21cfed779bd659978c0402766d).
[factory_bot]: https://github.com/thoughtbot/factory_bot
[traits]: http://www.rubydoc.info/gems/factory_bot/file/GETTING_STARTED.md#Traits
### Fixtures
......
......@@ -16,14 +16,14 @@ a black-box testing framework for the API and the UI.
### Testing nightly builds
We run scheduled pipeline each night to test nightly builds created by Omnibus.
You can find these nightly pipelines at [gitlab-org/quality/nightly/pipelines][quality-nightly-pipelines].
Results are reported in the `#qa-nightly` Slack channel.
You can find these nightly pipelines at `https://gitlab.com/gitlab-org/quality/nightly/pipelines`
(need Developer access permissions). Results are reported in the `#qa-nightly` Slack channel.
### Testing staging
We run scheduled pipeline each night to test staging.
You can find these nightly pipelines at [gitlab-org/quality/staging/pipelines][quality-staging-pipelines].
Results are reported in the `#qa-staging` Slack channel.
You can find these nightly pipelines at `https://gitlab.com/gitlab-org/quality/staging/pipelines`
(need developer access permissions). Results are reported in the `#qa-staging` Slack channel.
### Testing code in merge requests
......@@ -141,8 +141,6 @@ you can find an issue you would like to work on in
[omnibus-gitlab]: https://gitlab.com/gitlab-org/omnibus-gitlab
[gitlab-qa]: https://gitlab.com/gitlab-org/gitlab-qa
[gitlab-qa-readme]: https://gitlab.com/gitlab-org/gitlab-qa/tree/master/README.md
[quality-nightly-pipelines]: https://gitlab.com/gitlab-org/quality/nightly/pipelines
[quality-staging-pipelines]: https://gitlab.com/gitlab-org/quality/staging/pipelines
[review-apps]: ../review_apps.md
[gitlab-qa-architecture]: https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/architecture.md
[gitlab-qa-issues]: https://gitlab.com/gitlab-org/gitlab-qa/issues?label_name%5B%5D=new+scenario
......
......@@ -19,7 +19,7 @@ integration testing.
Following are two great articles that everyone should read to understand what
automated testing means, and what are its principles:
- [Five Factor Testing](https://www.devmynd.com/blog/five-factor-testing): Why do we need tests?
- [Five Factor Testing](https://madeintandem.com/blog/five-factor-testing/): Why do we need tests?
- [Principles of Automated Testing](http://www.lihaoyi.com/post/PrinciplesofAutomatedTesting.html): Levels of testing. Prioritize tests. Cost of tests.
## [Testing levels](testing_levels.md)
......
......@@ -232,7 +232,7 @@ using `v232`.
For the record, the debugging steps to find out this issue were:
1. Switch kubectl context to review-apps-ce (we recommend using [kubectx](https://kubectx.dev/))
1. Switch kubectl context to review-apps-ce (we recommend using [kubectx](https://github.com/ahmetb/kubectx/))
1. `kubectl get pods | grep dns`
1. `kubectl describe pod <pod name>` & confirm exact error message
1. Web search for exact error message, following rabbit hole to [a relevant kubernetes bug report](https://github.com/kubernetes/kubernetes/issues/57345)
......
......@@ -87,5 +87,5 @@ The following relate to Git Large File Storage:
- [Migrate an existing Git repo with Git LFS](migrate_to_git_lfs/index.md)
- [GitLab Git LFS user documentation](../../workflow/lfs/manage_large_binaries_with_git_lfs.md)
- [GitLab Git LFS admin documentation](../../workflow/lfs/lfs_administration.md)
- [Git-Annex to Git-LFS migration guide](../../workflow/lfs/migrate_from_git_annex_to_git_lfs.md)
- [git-annex to Git-LFS migration guide](../../workflow/lfs/migrate_from_git_annex_to_git_lfs.md)
- [Towards a production quality open source Git LFS server](https://about.gitlab.com/2015/08/13/towards-a-production-quality-open-source-git-lfs-server/)
......@@ -102,7 +102,8 @@ enabled on the Git server:
1. *Create a new Git repository and fetch.* Support for `--filter=sparse:oid`
using the clone command is incomplete, so we will emulate the clone command
by hand, using `git init` and `git fetch`. Follow
[gitaly#1769](https://gitlab.com/gitlab-org/gitaly/issues/1769) for updates.
[issue tracking support for `--filter=sparse:oid`](https://gitlab.com/gitlab-org/git/issues/4)
for updates.
```bash
# Create a new directory for the Git repository
......@@ -133,7 +134,7 @@ enabled on the Git server:
1. **Sparse checkout** must be enabled and configured to prevent objects from
other paths being downloaded automatically when checking out branches. Follow
[gitaly#1765](https://gitlab.com/gitlab-org/gitaly/issues/1765) for updates.
[issue proposing automating sparse checkouts](https://gitlab.com/gitlab-org/git/issues/5) for updates.
```bash
# Enable sparse checkout
......
......@@ -8,7 +8,7 @@ Sometimes things don't work the way they should or as you might expect when
you're using Git. Here are some tips on troubleshooting and resolving issues
with Git.
## Broken pipe errors on git push
## Broken pipe errors on `git push`
'Broken pipe' errors can occur when attempting to push to a remote repository.
When pushing you will usually see:
......@@ -68,7 +68,7 @@ ClientAliveInterval 60
ClientAliveCountMax 5
```
### Running a git repack
### Running a `git repack`
**If 'pack-objects' type errors are also being displayed**, you can try to
run a `git repack` before attempting to push to the remote repository again:
......@@ -110,7 +110,7 @@ MaxStartups 100
Restart SSHD for the change to take effect.
## Timeout during git push/pull
## Timeout during `git push` / `git pull`
If pulling/pushing from/to your repository ends up taking more than 50 seconds,
a timeout will be issued with a log of the number of operations performed
......
......@@ -108,7 +108,7 @@ git reflog
### Check the Git history of a file
The basic command to check the git history of a file:
The basic command to check the Git history of a file:
```sh
git log <file>
......@@ -147,7 +147,7 @@ gitk --follow <file>
## Debugging
### Use a custom SSH key for a git command
### Use a custom SSH key for a Git command
```sh
GIT_SSH_COMMAND="ssh -i ~/.ssh/gitlabadmin" git <command>
......@@ -183,7 +183,7 @@ git rebase -i master
git rebase --continue
```
### Use git rerere
### Use `git rerere`
To _reuse_ recorded solutions to the same problems when repeated:
......
......@@ -52,7 +52,7 @@ The GitLab University curriculum is composed of GitLab videos, screencasts, pres
### 1.5. Migrating from other Source Control
1. [Migrating from BitBucket/Stash](../user/project/import/bitbucket.md)
1. [Migrating from Bitbucket/Stash](../user/project/import/bitbucket.md)
1. [Migrating from GitHub](../user/project/import/github.md)
1. [Migrating from SVN](../user/project/import/svn.md)
1. [Migrating from Fogbugz](../user/project/import/fogbugz.md)
......
......@@ -6,6 +6,6 @@ comments: false
This page has been removed after an effort to ensure that all applicable GitLab-specific
terms are available in context on the relevant [GitLab Documentation](https://docs.gitlab.com/)
or [about.gitlab.com](https://about.gitlab.com/) pages.
or <https://about.gitlab.com/> pages.
If you are looking for a definition of a specific term, please search these sites.
......@@ -19,7 +19,7 @@ please submit a merge request to add an upcoming class, assign to
1. Don't make materials that are needlessly specific to one group of people, try
to keep the wording broad and inclusive (don't make things for only GitLab Inc.
people, only interns, only customers, etc.).
1. To allow people to contribute all content should be in git.
1. To allow people to contribute all content should be in Git.
1. The content can go in a subdirectory under `/doc/university/`.
1. To make, view or modify the slides of the classes use [Deckset](http://www.decksetapp.com/)
or [RevealJS](http://lab.hakim.se/reveal-js/). Do not use Powerpoint or Google
......
......@@ -109,11 +109,11 @@ cd ~/workspace
- GitLab is an application to code, test and deploy.
- Provides repository management with access controls, code reviews,
issue tracking, Merge Requests, and other features.
- The hosted version of GitLab is gitlab.com
- The hosted version of GitLab is <https://gitlab.com>
### New Project
- Sign in into your gitlab.com account
- Sign in into your <https://gitlab.com> account
- Create a project
- Choose to import from 'Any Repo by URL' and use <https://gitlab.com/gitlab-org/training-examples.git>
- On your machine clone the `training-examples` project
......@@ -126,7 +126,7 @@ cd ~/workspace
1. Stage the file
1. Commit
1. Push the commit to the remote
1. View the git log
1. View the Git log
```shell
# Edit `edit_this_file.rb`
......@@ -271,7 +271,7 @@ This will unstage the file but maintain the modifications. To revert the file ba
git checkout -- <file>
```
To remove a file from disk and repo use 'git rm' and to rm a dir use the '-r' flag:
To remove a file from disk and repo use `git rm` and to remove a directory use the `-r` flag:
```sh
git rm '*.txt'
......@@ -338,7 +338,7 @@ git pull origin master
git push origin master
```
### git revert vs git reset
### `git revert` vs `git reset`
Reset removes the commit while revert removes the changes but leaves the commit
Revert is safer considering we can revert a revert
......
......@@ -65,7 +65,7 @@ Modified files that have been marked to go in the next commit.
1. Stage the file
1. Commit
1. Push the commit to the remote
1. View the git log
1. View the Git log
```sh
# Edit `edit_this_file.rb`
......@@ -79,5 +79,5 @@ git log
## Note
- git fetch vs pull
- Pull is git fetch + git merge
- `git fetch` vs `git pull`
- Pull is `git fetch` + `git merge`
......@@ -60,7 +60,7 @@ git push origin conflicts_branch -f
## Note
- When to use 'git merge' and when to use 'git rebase'
- When to use `git merge` and when to use `git rebase`
- Rebase when updating your branch with master
- Merge when bringing changes from feature to master
- Reference: <https://www.atlassian.com/git/tutorials/merging-vs-rebasing/>
......@@ -62,7 +62,7 @@ git push origin master
## Note
- git revert vs git reset
- `git revert` vs `git reset`
- Reset removes the commit while revert removes the changes but leaves the commit
- Revert is safer considering we can revert a revert
......
......@@ -4,7 +4,7 @@ comments: false
# Git Stash
We use git stash to store our changes when they are not ready to be committed
We use `git stash` to store our changes when they are not ready to be committed
and we need to change to a different branch.
- Stash:
......
......@@ -16,7 +16,7 @@ comments: false
git checkout -- <file>
```
- To remove a file from disk and repo use 'git rm' and to rm a dir use the '-r' flag:
- To remove a file from disk and repo use `git rm` and to remove a directory use the `-r` flag:
```sh
git rm '*.txt'
......
......@@ -140,7 +140,7 @@ Modified files that have been marked to go in the next commit.
1. Stage the file.
1. Commit.
1. Push the commit to the remote.
1. View the git log.
1. View the Git log.
## Commands (committing)
......
......@@ -53,7 +53,7 @@ to offload local hard disk R/W operations, and free up disk space significantly.
GitLab is tightly integrated with `Fog`, so you can refer to its [documentation](http://fog.io/about/provider_documentation.html)
to check which storage services can be integrated with GitLab.
You can also use external object storage in a private local network. For example,
[Minio](https://min.io/) is a standalone object storage service, is easy to set up, and works well with GitLab instances.
[MinIO](https://min.io/) is a standalone object storage service, is easy to set up, and works well with GitLab instances.
GitLab provides two different options for the uploading mechanism: "Direct upload" and "Background upload".
......@@ -93,7 +93,7 @@ Here is a configuration example with S3.
| `enable_signature_v4_streaming` | Set to true to enable HTTP chunked transfers with [AWS v4 signatures](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html). Oracle Cloud S3 needs this to be false | true |
| `region` | AWS region | us-east-1 |
| `host` | S3 compatible host for when not using AWS, e.g. `localhost` or `storage.example.com` | s3.amazonaws.com |
| `endpoint` | Can be used when configuring an S3 compatible service such as [Minio](https://www.minio.io), by entering a URL such as `http://127.0.0.1:9000` | (optional) |
| `endpoint` | Can be used when configuring an S3 compatible service such as [MinIO](https://www.minio.io), by entering a URL such as `http://127.0.0.1:9000` | (optional) |
| `path_style` | Set to true to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as false for AWS S3 | false |
| `use_iam_profile` | Set to true to use IAM profile instead of access keys | false
......@@ -124,7 +124,7 @@ NOTE: **Note:**
Regardless of whether the container has public access enabled or disabled, Fog will
use the TempURL method to grant access to LFS objects. If you see errors in logs referencing
instantiating storage with a temp-url-key, ensure that you have set they key properly
on the Rackspace API and in gitlab.rb. You can verify the value of the key Rackspace
on the Rackspace API and in `gitlab.rb`. You can verify the value of the key Rackspace
has set by sending a GET request with token header to the service access endpoint URL
and comparing the output of the returned headers.
......@@ -235,7 +235,7 @@ and [projects APIs](../../api/projects.md).
## Troubleshooting: `Google::Apis::TransmissionError: execution expired`
If LFS integration is configred with Google Cloud Storage and background uploads (`background_upload: true` and `direct_upload: false`),
sidekiq workers may encouter this error. This is because the uploading timed out with very large files.
Sidekiq workers may encouter this error. This is because the uploading timed out with very large files.
LFS files up to 6Gb can be uploaded without any extra steps, otherwise you need to use the following workaround.
```shell
......
......@@ -70,7 +70,7 @@ git add .gitattributes
```
Cloning the repository works the same as before. Git automatically detects the
LFS-tracked files and clones them via HTTP. If you performed the git clone
LFS-tracked files and clones them via HTTP. If you performed the `git clone`
command with a SSH URL, you have to enter your GitLab credentials for HTTP
authentication.
......@@ -172,7 +172,7 @@ Check if you have permissions to push to the project or fetch from the project.
LFS object you are trying to push to the project or fetch from the project is not
available to the project anymore. Probably the object was removed from the server.
- Local git repository is using deprecated LFS API
- Local Git repository is using deprecated LFS API
### Invalid status for `<url>` : 501
......@@ -250,7 +250,7 @@ GitLab checks files to detect LFS pointers on push. If LFS pointers are detected
Verify that LFS in installed locally and consider a manual push with `git lfs push --all`.
If you are storing LFS files outside of GitLab you can disable LFS on the project by setting `lfs_enabled: false` with the [projects api](../../api/projects.md#edit-project).
If you are storing LFS files outside of GitLab you can disable LFS on the project by setting `lfs_enabled: false` with the [projects API](../../api/projects.md#edit-project).
### Hosting LFS objects externally
......
......@@ -78,7 +78,7 @@ Below is the table of events users can be notified of:
| New email added | User | Security email, always sent. |
| Email changed | User | Security email, always sent. |
| Password changed | User | Security email, always sent. |
| New user created | User | Sent on user creation, except for omniauth (LDAP)|
| New user created | User | Sent on user creation, except for OmniAuth (LDAP)|
| User added to project | User | Sent when user is added to project |
| Project access level changed | User | Sent when user project access level is changed |
| User added to group | User | Sent when user is added to group |
......@@ -150,7 +150,7 @@ Notification emails include headers that provide extra content about the notific
| X-GitLab-Pipeline-Id | Only in pipeline emails, the ID of the pipeline the notification is for |
| X-GitLab-Reply-Key | A unique token to support reply by email |
| X-GitLab-NotificationReason | The reason for being notified. "mentioned", "assigned", etc |
| List-Id | The path of the project in a RFC 2919 mailing list identifier useful for email organization, for example, with GMail filters |
| List-Id | The path of the project in a RFC 2919 mailing list identifier useful for email organization, for example, with Gmail filters |
#### X-GitLab-NotificationReason
......
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Confidential Issue Sidebar Block renders for isConfidential = false and isEditable = false 1`] = `
<div
class="block issuable-sidebar-item confidentiality"
>
<div
class="sidebar-collapsed-icon"
data-boundary="viewport"
data-container="body"
data-original-title="Not confidential"
data-placement="left"
title=""
>
<icon-stub
aria-hidden="true"
cssclasses=""
name="eye"
size="16"
/>
</div>
<div
class="title hide-collapsed"
>
Confidentiality
<!---->
</div>
<div
class="value sidebar-item-value hide-collapsed"
>
<!---->
<div
class="no-value sidebar-item-value"
>
<icon-stub
aria-hidden="true"
class="sidebar-item-icon inline"
cssclasses=""
name="eye"
size="16"
/>
Not confidential
</div>
</div>
</div>
`;
exports[`Confidential Issue Sidebar Block renders for isConfidential = false and isEditable = true 1`] = `
<div
class="block issuable-sidebar-item confidentiality"
>
<div
class="sidebar-collapsed-icon"
data-boundary="viewport"
data-container="body"
data-original-title="Not confidential"
data-placement="left"
title=""
>
<icon-stub
aria-hidden="true"
cssclasses=""
name="eye"
size="16"
/>
</div>
<div
class="title hide-collapsed"
>
Confidentiality
<a
class="float-right confidential-edit"
data-track-event="click_edit_button"
data-track-label="right_sidebar"
data-track-property="confidentiality"
href="#"
>
Edit
</a>
</div>
<div
class="value sidebar-item-value hide-collapsed"
>
<!---->
<div
class="no-value sidebar-item-value"
>
<icon-stub
aria-hidden="true"
class="sidebar-item-icon inline"
cssclasses=""
name="eye"
size="16"
/>
Not confidential
</div>
</div>
</div>
`;
exports[`Confidential Issue Sidebar Block renders for isConfidential = true and isEditable = false 1`] = `
<div
class="block issuable-sidebar-item confidentiality"
>
<div
class="sidebar-collapsed-icon"
data-boundary="viewport"
data-container="body"
data-original-title="Confidential"
data-placement="left"
title=""
>
<icon-stub
aria-hidden="true"
cssclasses=""
name="eye-slash"
size="16"
/>
</div>
<div
class="title hide-collapsed"
>
Confidentiality
<!---->
</div>
<div
class="value sidebar-item-value hide-collapsed"
>
<!---->
<div
class="value sidebar-item-value hide-collapsed"
>
<icon-stub
aria-hidden="true"
class="sidebar-item-icon inline is-active"
cssclasses=""
name="eye-slash"
size="16"
/>
This issue is confidential
</div>
</div>
</div>
`;
exports[`Confidential Issue Sidebar Block renders for isConfidential = true and isEditable = true 1`] = `
<div
class="block issuable-sidebar-item confidentiality"
>
<div
class="sidebar-collapsed-icon"
data-boundary="viewport"
data-container="body"
data-original-title="Confidential"
data-placement="left"
title=""
>
<icon-stub
aria-hidden="true"
cssclasses=""
name="eye-slash"
size="16"
/>
</div>
<div
class="title hide-collapsed"
>
Confidentiality
<a
class="float-right confidential-edit"
data-track-event="click_edit_button"
data-track-label="right_sidebar"
data-track-property="confidentiality"
href="#"
>
Edit
</a>
</div>
<div
class="value sidebar-item-value hide-collapsed"
>
<!---->
<div
class="value sidebar-item-value hide-collapsed"
>
<icon-stub
aria-hidden="true"
class="sidebar-item-icon inline is-active"
cssclasses=""
name="eye-slash"
size="16"
/>
This issue is confidential
</div>
</div>
</div>
`;
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`SidebarTodo template renders component container element with proper data attributes 1`] = `
<button
aria-label="Mark as done"
class="btn btn-default btn-todo issuable-header-btn float-right"
data-boundary="viewport"
data-container="body"
data-issuable-id="1"
data-issuable-type="epic"
data-original-title=""
data-placement="left"
title=""
type="button"
>
<icon-stub
cssclasses="todo-undone"
name="todo-done"
size="16"
style="display: none;"
/>
<span
class="issuable-todo-inner"
>
Mark as done
</span>
<glloadingicon-stub
color="orange"
inline="true"
label="Loading"
size="sm"
style="display: none;"
/>
</button>
`;
import Vue from 'vue';
import confidentialIssueSidebar from '~/sidebar/components/confidential/confidential_issue_sidebar.vue';
import { shallowMount } from '@vue/test-utils';
import ConfidentialIssueSidebar from '~/sidebar/components/confidential/confidential_issue_sidebar.vue';
import { mockTracking, triggerEvent } from 'helpers/tracking_helper';
import EditForm from '~/sidebar/components/confidential/edit_form.vue';
describe('Confidential Issue Sidebar Block', () => {
let vm1;
let vm2;
let wrapper;
beforeEach(() => {
const Component = Vue.extend(confidentialIssueSidebar);
const createComponent = propsData => {
const service = {
update: () => Promise.resolve(true),
};
vm1 = new Component({
wrapper = shallowMount(ConfidentialIssueSidebar, {
propsData: {
isConfidential: true,
isEditable: true,
service,
...propsData,
},
}).$mount();
vm2 = new Component({
propsData: {
isConfidential: false,
isEditable: false,
service,
},
}).$mount();
});
it('shows if confidential and/or editable', () => {
expect(vm1.$el.innerHTML.includes('Edit')).toBe(true);
expect(vm1.$el.innerHTML.includes('This issue is confidential')).toBe(true);
expect(vm2.$el.innerHTML.includes('Not confidential')).toBe(true);
sync: false,
});
};
it.each`
isConfidential | isEditable
${false} | ${false}
${false} | ${true}
${true} | ${false}
${true} | ${true}
`(
'renders for isConfidential = $isConfidential and isEditable = $isEditable',
({ isConfidential, isEditable }) => {
createComponent({
isConfidential,
isEditable,
});
expect(wrapper.element).toMatchSnapshot();
},
);
afterEach(() => {
wrapper.destroy();
});
it('displays the edit form when editable', () => {
expect(vm1.edit).toBe(false);
describe('if editable', () => {
beforeEach(() => {
createComponent({
isConfidential: true,
isEditable: true,
});
});
vm1.$el.querySelector('.confidential-edit').click();
it('displays the edit form when editable', () => {
wrapper.setData({ edit: false });
expect(vm1.edit).toBe(true);
wrapper.find({ ref: 'editLink' }).trigger('click');
return Vue.nextTick().then(() => {
expect(vm1.$el.innerHTML.includes('You are going to turn off the confidentiality.')).toBe(
true,
);
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(EditForm).exists()).toBe(true);
});
});
});
it('displays the edit form when opened from collapsed state', () => {
expect(vm1.edit).toBe(false);
vm1.$el.querySelector('.sidebar-collapsed-icon').click();
it('displays the edit form when opened from collapsed state', () => {
wrapper.setData({ edit: false });
expect(vm1.edit).toBe(true);
wrapper.find({ ref: 'collapseIcon' }).trigger('click');
return Vue.nextTick().then(() => {
expect(vm1.$el.innerHTML.includes('You are going to turn off the confidentiality.')).toBe(
true,
);
return wrapper.vm.$nextTick().then(() => {
expect(wrapper.find(EditForm).exists()).toBe(true);
});
});
});
it('tracks the event when "Edit" is clicked', () => {
const spy = mockTracking('_category_', vm1.$el, jest.spyOn);
triggerEvent('.confidential-edit');
it('tracks the event when "Edit" is clicked', () => {
const spy = mockTracking('_category_', wrapper.element, jest.spyOn);
const editLink = wrapper.find({ ref: 'editLink' });
triggerEvent(editLink.element);
expect(spy).toHaveBeenCalledWith('_category_', 'click_edit_button', {
label: 'right_sidebar',
property: 'confidentiality',
expect(spy).toHaveBeenCalledWith('_category_', 'click_edit_button', {
label: 'right_sidebar',
property: 'confidentiality',
});
});
});
});
import { shallowMount } from '@vue/test-utils';
import { GlLoadingIcon } from '@gitlab/ui';
import SidebarTodos from '~/sidebar/components/todo_toggle/todo.vue';
import Icon from '~/vue_shared/components/icon.vue';
const defaultProps = {
issuableId: 1,
issuableType: 'epic',
};
describe('SidebarTodo', () => {
let wrapper;
const createComponent = (props = {}) => {
wrapper = shallowMount(SidebarTodos, {
sync: false,
propsData: {
...defaultProps,
...props,
},
});
};
afterEach(() => {
wrapper.destroy();
});
it.each`
state | classes
${false} | ${['btn', 'btn-default', 'btn-todo', 'issuable-header-btn', 'float-right']}
${true} | ${['btn-blank', 'btn-todo', 'sidebar-collapsed-icon', 'dont-change-state']}
`('returns todo button classes for when `collapsed` prop is `$state`', ({ state, classes }) => {
createComponent({ collapsed: state });
expect(wrapper.find('button').classes()).toStrictEqual(classes);
});
it.each`
isTodo | iconClass | label | icon
${false} | ${''} | ${'Add a To Do'} | ${'todo-add'}
${true} | ${'todo-undone'} | ${'Mark as done'} | ${'todo-done'}
`(
'renders proper button when `isTodo` prop is `$isTodo`',
({ isTodo, iconClass, label, icon }) => {
createComponent({ isTodo });
expect(wrapper.find(Icon).props('cssClasses')).toStrictEqual(iconClass);
expect(wrapper.find(Icon).props('name')).toStrictEqual(icon);
expect(wrapper.find('button').text()).toBe(label);
},
);
describe('template', () => {
it('emits `toggleTodo` event when clicked on button', () => {
createComponent();
wrapper.find('button').trigger('click');
expect(wrapper.emitted().toggleTodo).toBeTruthy();
});
it('renders component container element with proper data attributes', () => {
createComponent({
issuableId: 1,
issuableType: 'epic',
});
expect(wrapper.element).toMatchSnapshot();
});
it('renders button label element when `collapsed` prop is `false`', () => {
createComponent({ collapsed: false });
expect(wrapper.find('span.issuable-todo-inner').text()).toBe('Mark as done');
});
it('renders button icon when `collapsed` prop is `true`', () => {
createComponent({ collapsed: true });
expect(wrapper.find(Icon).props('name')).toBe('todo-done');
});
it('renders loading icon when `isActionActive` prop is true', () => {
createComponent({ isActionActive: true });
expect(wrapper.find(GlLoadingIcon).exists()).toBe(true);
});
});
});
import Vue from 'vue';
import SidebarTodos from '~/sidebar/components/todo_toggle/todo.vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
const createComponent = ({
issuableId = 1,
issuableType = 'epic',
isTodo,
isActionActive,
collapsed,
}) => {
const Component = Vue.extend(SidebarTodos);
return mountComponent(Component, {
issuableId,
issuableType,
isTodo,
isActionActive,
collapsed,
});
};
describe('SidebarTodo', () => {
let vm;
beforeEach(() => {
vm = createComponent({});
});
afterEach(() => {
vm.$destroy();
});
describe('computed', () => {
describe('buttonClasses', () => {
it('returns todo button classes for when `collapsed` prop is `false`', () => {
expect(vm.buttonClasses).toBe('btn btn-default btn-todo issuable-header-btn float-right');
});
it('returns todo button classes for when `collapsed` prop is `true`', done => {
vm.collapsed = true;
Vue.nextTick()
.then(() => {
expect(vm.buttonClasses).toBe(
'btn-blank btn-todo sidebar-collapsed-icon dont-change-state',
);
})
.then(done)
.catch(done.fail);
});
});
describe('buttonLabel', () => {
it('returns todo button text for marking todo as done when `isTodo` prop is `true`', () => {
expect(vm.buttonLabel).toBe('Mark as done');
});
it('returns todo button text for add todo when `isTodo` prop is `false`', done => {
vm.isTodo = false;
Vue.nextTick()
.then(() => {
expect(vm.buttonLabel).toBe('Add a To Do');
})
.then(done)
.catch(done.fail);
});
});
describe('collapsedButtonIconClasses', () => {
it('returns collapsed button icon class when `isTodo` prop is `true`', () => {
expect(vm.collapsedButtonIconClasses).toBe('todo-undone');
});
it('returns empty string when `isTodo` prop is `false`', done => {
vm.isTodo = false;
Vue.nextTick()
.then(() => {
expect(vm.collapsedButtonIconClasses).toBe('');
})
.then(done)
.catch(done.fail);
});
});
describe('collapsedButtonIcon', () => {
it('returns button icon name when `isTodo` prop is `true`', () => {
expect(vm.collapsedButtonIcon).toBe('todo-done');
});
it('returns button icon name when `isTodo` prop is `false`', done => {
vm.isTodo = false;
Vue.nextTick()
.then(() => {
expect(vm.collapsedButtonIcon).toBe('todo-add');
})
.then(done)
.catch(done.fail);
});
});
});
describe('methods', () => {
describe('handleButtonClick', () => {
it('emits `toggleTodo` event on component', () => {
spyOn(vm, '$emit');
vm.handleButtonClick();
expect(vm.$emit).toHaveBeenCalledWith('toggleTodo');
});
});
});
describe('template', () => {
it('renders component container element', () => {
const dataAttributes = {
issuableId: '1',
issuableType: 'epic',
originalTitle: '',
placement: 'left',
container: 'body',
boundary: 'viewport',
};
expect(vm.$el.nodeName).toBe('BUTTON');
const elDataAttrs = vm.$el.dataset;
Object.keys(elDataAttrs).forEach(attr => {
expect(elDataAttrs[attr]).toBe(dataAttributes[attr]);
});
});
it('check button label computed property', () => {
expect(vm.buttonLabel).toEqual('Mark as done');
});
it('renders button label element when `collapsed` prop is `false`', () => {
const buttonLabelEl = vm.$el.querySelector('span.issuable-todo-inner');
expect(buttonLabelEl).not.toBeNull();
expect(buttonLabelEl.innerText.trim()).toBe('Mark as done');
});
it('renders button icon when `collapsed` prop is `true`', done => {
vm.collapsed = true;
Vue.nextTick()
.then(() => {
const buttonIconEl = vm.$el.querySelector('svg');
expect(buttonIconEl).not.toBeNull();
expect(buttonIconEl.querySelector('use').getAttribute('xlink:href')).toContain(
'todo-done',
);
})
.then(done)
.catch(done.fail);
});
it('renders loading icon when `isActionActive` prop is true', done => {
vm.isActionActive = true;
Vue.nextTick()
.then(() => {
const loadingEl = vm.$el.querySelector('span.loading-container');
expect(loadingEl).not.toBeNull();
})
.then(done)
.catch(done.fail);
});
});
});
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