Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
7f665f8757
commit
707b5c82a5
|
|
@ -2,7 +2,7 @@
|
|||
include:
|
||||
- local: .gitlab/ci/cng/main.gitlab-ci.yml
|
||||
- project: 'gitlab-org/quality/pipeline-common'
|
||||
ref: '8.18.3'
|
||||
ref: '8.18.4'
|
||||
file: ci/base.gitlab-ci.yml
|
||||
|
||||
stages:
|
||||
|
|
|
|||
|
|
@ -125,7 +125,6 @@ Performance/StringIdentifierArgument:
|
|||
- 'lib/gitlab/utils/lazy_attributes.rb'
|
||||
- 'lib/kramdown/parser/atlassian_document_format.rb'
|
||||
- 'lib/sidebars/context.rb'
|
||||
- 'qa/qa/flow/purchase.rb'
|
||||
- 'qa/qa/page/component/ci_icon.rb'
|
||||
- 'qa/qa/page/component/note.rb'
|
||||
- 'qa/qa/resource/base.rb'
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
028b25396b2c27c0b994fed07e513e4eaa3f3c0c
|
||||
3907ef1a1fc3655cc376db339ae19cb1f0f1ccf6
|
||||
|
|
|
|||
|
|
@ -107,7 +107,9 @@ export default {
|
|||
}
|
||||
},
|
||||
onInputValidationStateChange(inputId, value) {
|
||||
this.$set(this.inputValidStates, inputId, value);
|
||||
const copy = [...this.inputValidStates];
|
||||
copy[inputId] = value;
|
||||
this.inputValidStates = copy;
|
||||
},
|
||||
onHighlight(path) {
|
||||
this.$emit('update:highlight', path);
|
||||
|
|
|
|||
|
|
@ -75,6 +75,13 @@ class PoolRepository < ApplicationRecord
|
|||
|
||||
def create_object_pool
|
||||
object_pool.create
|
||||
rescue GRPC::AlreadyExists
|
||||
# The object pool already exists. Nothing to do here.
|
||||
rescue GRPC::FailedPrecondition => e
|
||||
# This rescue is temporary until gitaly returns the correct error code for
|
||||
# "repo exists already". Gitaly error messages are not guaranteed to match
|
||||
# and so should not typically be used to determine error type.
|
||||
raise unless e.message.include?('repository exists already')
|
||||
end
|
||||
|
||||
# The members of the pool should have fetched the missing objects to their own
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.gl-ml-auto.gl-mr-auto{ class: 'sm:gl-w-1/2' }
|
||||
.gl-justify-content-left.gl-items-center
|
||||
.gl-items-center
|
||||
.gl-font-size-h1
|
||||
= html_escape(_('%{client_name} is requesting access to your account on %{title}.')) % { title: brand_title.html_safe, client_name: "<strong>#{html_escape(@pre_auth.client.name)}</strong>".html_safe }
|
||||
.gl-flex.gl-items-center.gl-gap-2.gl-py-5
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
= _("To continue, please update your password. After you update, you'll be directed to sign in again.")
|
||||
.info-well
|
||||
.well-segment
|
||||
.gl-justify-content-left.gl-display-flex.gl-align-items-center
|
||||
.gl-display-flex.gl-align-items-center
|
||||
= render Pajamas::AvatarComponent.new(current_user, size: 24, avatar_options: { data: { qa_selector: 'user_avatar_content' }, title: current_user.username })
|
||||
.gl-pl-4.gl-break-all
|
||||
%span= _('Signed in as %{username}') % { username: '@' + current_user.username }
|
||||
|
|
|
|||
|
|
@ -40,7 +40,22 @@ made to your repositories. There's two ways you can accomplish that:
|
|||
Project.all.find_each { |project| project.update!(repository_read_only: true) }
|
||||
```
|
||||
|
||||
When you're ready to revert this, you can do so with the following command:
|
||||
To set only a subset of repositories to read-only, run the following:
|
||||
|
||||
```ruby
|
||||
# List of project IDs of projects to set to read-only.
|
||||
projects = [1,2,3]
|
||||
|
||||
projects.each do |p|
|
||||
project = Project.find p
|
||||
project.update!(repository_read_only: true)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
puts "Project ID #{p} not found"
|
||||
|
||||
end
|
||||
```
|
||||
|
||||
When you're ready to revert this, change `repository_read_only` to `false` on the projects. For example, run the following:
|
||||
|
||||
```ruby
|
||||
Project.all.find_each { |project| project.update!(repository_read_only: false) }
|
||||
|
|
|
|||
|
|
@ -74,24 +74,29 @@ set of widgets for them.
|
|||
|---|---|---|---|---|
|
||||
| [WorkItemWidgetAssignees](../../../api/graphql/reference/index.md#workitemwidgetassignees) | List of work item assignees | |`Guest`|Yes|
|
||||
| [WorkItemWidgetAwardEmoji](../../../api/graphql/reference/index.md#workitemwidgetawardemoji) | Emoji reactions added to work item, including support for upvote/downvote counts | |Anyone who can view|No|
|
||||
| [WorkItemWidgetColor](../../../api/graphql/reference/index.md#workitemwidgetcolor) | Set color of a work item. **Note:** Color is available only for epics. | |`Reporter`|No|
|
||||
| [WorkItemWidgetCurrentUserTodos](../../../api/graphql/reference/index.md#workitemwidgetcurrentusertodos) | User todo state of work item | |Anyone who can view|No|
|
||||
| [WorkItemWidgetDescription](../../../api/graphql/reference/index.md#workitemwidgetdescription) | Description of work item, including support for edited state, timestamp, and author | |`Reporter`|No|
|
||||
| [WorkItemWidgetDesigns](../../../api/graphql/reference/index.md#workitemwidgetdesigns) | Uploaded images and designs | |`Reporter`|No|
|
||||
| [WorkItemWidgetDesigns](../../../api/graphql/reference/index.md#workitemwidgetdesigns) | Design attachments for work items | |`Reporter`|No|
|
||||
| [WorkItemWidgetDevelopment](../../../api/graphql/reference/index.md#workitemwidgetdevelopment) | Show related branches and merge requests for work items | |`Reporter`|No|
|
||||
| [WorkItemWidgetHealthStatus](../../../api/graphql/reference/index.md#workitemwidgethealthstatus) | Health status assignment support for work item | |`Reporter`|No|
|
||||
| [WorkItemWidgetHierarchy](../../../api/graphql/reference/index.md#workitemwidgethierarchy) | Hierarchy of work items, including support for boolean representing presence of children. **Note:** Hierarchy is currently available only for OKRs. | `okrs_mvc` |`Guest`|No|
|
||||
| [WorkItemWidgetHierarchy](../../../api/graphql/reference/index.md#workitemwidgethierarchy) | Hierarchy of work items, including support for boolean representing presence of children. | |`Guest`|No|
|
||||
| [WorkItemWidgetIteration](../../../api/graphql/reference/index.md#workitemwidgetiteration) | Iteration assignment support for work item | |`Reporter`|No|
|
||||
| [WorkItemWidgetLabels](../../../api/graphql/reference/index.md#workitemwidgetlabels) | List of labels added to work items, including support for checking whether scoped labels are supported | |`Reporter`|Yes|
|
||||
| [WorkItemWidgetLinkedItems](../../../api/graphql/reference/index.md#workitemwidgetlinkeditems) | List of work items added as related to a given work item, with possible relationship types being `relates_to`, `blocks`, and `blocked_by`. Includes support for individual counts of blocked status, blocked by, blocking, and related to. | |`Guest`|No|
|
||||
| [WorkItemWidgetMilestone](../../../api/graphql/reference/index.md#workitemwidgetmilestone) | Milestone assignment support for work item | |`Reporter`|No|
|
||||
| [WorkItemWidgetNotes](../../../api/graphql/reference/index.md#workitemwidgetnotes) | List of discussions within a work item | |`Guest`|Yes|
|
||||
| [WorkItemWidgetNotifications](../../../api/graphql/reference/index.md#workitemwidgetnotifications) | Notifications subscription status of a work item for current user | |Anyone who can view|No|
|
||||
| [WorkItemWidgetParticipants](../../../api/graphql/reference/index.md#workitemwidgetparticipants) | Participants of a work item | |Anyone who can view|No|
|
||||
| [WorkItemWidgetProgress](../../../api/graphql/reference/index.md#workitemwidgetprogress) | Progress value of a work item. **Note:** Progress is currently available only for OKRs. | `okrs_mvc` |`Reporter`|No|
|
||||
| [WorkItemWidgetRequirementLegacy](../../../api/graphql/reference/index.md#workitemwidgetrequirementlegacy) | Legacy requirements | | |No|
|
||||
| [WorkItemWidgetRolledupDates](../../../api/graphql/reference/index.md#workitemwidgetrolledupdates) | Set the start date and due date for epic work items, and roll up the start date and due date from child work items | |`Reporter`|No|
|
||||
| [WorkItemWidgetStartAndDueDate](../../../api/graphql/reference/index.md#workitemwidgetstartandduedate) | Set start and due dates for a work item | |`Reporter`|No|
|
||||
| [WorkItemWidgetStatus](../../../api/graphql/reference/index.md#workitemwidgetstatus) | Status of a work item when type is Requirement, with possible status types being `unverified`, `satisfied`, or `failed` | | |No|
|
||||
| [WorkItemWidgetTestReports](../../../api/graphql/reference/index.md#workitemwidgettestreports) | Test reports associated with a work item | | | |
|
||||
| [WorkItemWidgetTimeTracking](../../../api/graphql/reference/index.md#workitemwidgettimetracking) | Track total time spent on a work item | |`Reporter`|No|
|
||||
| [WorkItemWidgetWeight](../../../api/graphql/reference/index.md#workitemwidgetweight) | Set weight of a work item | |`Reporter`|No|
|
||||
| WorkItemWidgetLock | Lock/Unlock a work item | |`Reporter`|No|
|
||||
| [WorkItemWidgetColor](../../../api/graphql/reference/index.md#workitemwidgetcolor) | Set color of a work item. **Note:** Color is currently available only for epics. | |`Reporter`|No|
|
||||
|
||||
#### Widget availability (updating)
|
||||
|
||||
|
|
@ -99,23 +104,28 @@ set of widgets for them.
|
|||
|---|---|---|---|---|---|
|
||||
| [WorkItemWidgetAssignees](../../../api/graphql/reference/index.md#workitemwidgetassignees) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| [WorkItemWidgetAwardEmoji](../../../api/graphql/reference/index.md#workitemwidgetawardemoji) | ✅ | ✔️ | ✅ | ✅ | ✅ |
|
||||
| [WorkItemWidgetColor](../../../api/graphql/reference/index.md#workitemwidgetcolor) | ✅ | ❌ | ❌ | ❌ | ❌ |
|
||||
| [WorkItemWidgetCurrentUserTodos](../../../api/graphql/reference/index.md#workitemwidgetcurrentusertodos) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| [WorkItemWidgetDescription](../../../api/graphql/reference/index.md#workitemwidgetdescription) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| [WorkItemWidgetDesigns](../../../api/graphql/reference/index.md#workitemwidgetdesigns) | ❌ | ✅ | ❌ | ❌ | ❌ |
|
||||
| [WorkItemWidgetDesigns](../../../api/graphql/reference/index.md#workitemwidgetdesigns) | ✔️ | ✅ | ❌ | ❌ | ❌ |
|
||||
| [WorkItemWidgetDevelopment](../../../api/graphql/reference/index.md#workitemwidgetdevelopment) | ❌ | ✅ | ❌ | ❌ | ❌ |
|
||||
| [WorkItemWidgetHealthStatus](../../../api/graphql/reference/index.md#workitemwidgethealthstatus) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| [WorkItemWidgetHierarchy](../../../api/graphql/reference/index.md#workitemwidgethierarchy) | ✔ | ✔️ | ❌ | ✅ | ❌ |
|
||||
| [WorkItemWidgetHierarchy](../../../api/graphql/reference/index.md#workitemwidgethierarchy) | ✅ | ✅ | ❌ | ✅ | ❌ |
|
||||
| [WorkItemWidgetIteration](../../../api/graphql/reference/index.md#workitemwidgetiteration) | ❌ | ✅ | ✅ | ❌ | ❌ |
|
||||
| [WorkItemWidgetLabels](../../../api/graphql/reference/index.md#workitemwidgetlabels) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| [WorkItemWidgetLinkedItems](../../../api/graphql/reference/index.md#workitemwidgetlinkeditems) | ✔️ | ✔️ | ✔️ | ✅ | ✅ |
|
||||
| [WorkItemWidgetMilestone](../../../api/graphql/reference/index.md#workitemwidgetmilestone) | 🔍 | ✅ | ✅ | ✅ | ❌ |
|
||||
| [WorkItemWidgetLinkedItems](../../../api/graphql/reference/index.md#workitemwidgetlinkeditems) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| [WorkItemWidgetMilestone](../../../api/graphql/reference/index.md#workitemwidgetmilestone) | ❌ | ✅ | ✅ | ✅ | ❌ |
|
||||
| [WorkItemWidgetNotes](../../../api/graphql/reference/index.md#workitemwidgetnotes) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| [WorkItemWidgetNotifications](../../../api/graphql/reference/index.md#workitemwidgetnotifications) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| [WorkItemWidgetParticipants](../../../api/graphql/reference/index.md#workitemwidgetparticipants) | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||
| [WorkItemWidgetProgress](../../../api/graphql/reference/index.md#workitemwidgetprogress) | ❌ | ❌ | ❌ | ✅ | ✅ |
|
||||
| [WorkItemWidgetStartAndDueDate](../../../api/graphql/reference/index.md#workitemwidgetstartandduedate) | 🔍 | ✅ | ✅ | ❌ | ✅ |
|
||||
| [WorkItemWidgetRequirementLegacy](../../../api/graphql/reference/index.md#workitemwidgetrequirementlegacy) | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||
| [WorkItemWidgetRolledupDates](../../../api/graphql/reference/index.md#workitemwidgetrolledupdates) | ✅ | ❌ | ❌ | ❌ | ❌ |
|
||||
| [WorkItemWidgetStartAndDueDate](../../../api/graphql/reference/index.md#workitemwidgetstartandduedate) | ❌ | ✅ | ✅ | ❌ | ✅ |
|
||||
| [WorkItemWidgetStatus](../../../api/graphql/reference/index.md#workitemwidgetstatus) | ❓ | ❓ | ❓ | ❓ | ❓ |
|
||||
| [WorkItemWidgetTestReports](../../../api/graphql/reference/index.md#workitemwidgettestreports) | ❌ | ❌ | ❌ | ❌ | ❌ |
|
||||
| [WorkItemWidgetWeight](../../../api/graphql/reference/index.md#workitemwidgetweight) | 🔍 | ✅ | ✅ | ❌ | ❌ |
|
||||
| [WorkItemWidgetColor](../../../api/graphql/reference/index.md#workitemwidgettestreports) | ✅ | ❌ | ❌ | ❌ | ❌ |
|
||||
| [WorkItemWidgetTimeTracking](../../../api/graphql/reference/index.md#workitemwidgettimetracking) | ✅ | ✅ | ✅ | ❌ | ❌ |
|
||||
| [WorkItemWidgetWeight](../../../api/graphql/reference/index.md#workitemwidgetweight) | ❌ | ✅ | ✅ | ❌ | ❌ |
|
||||
|
||||
##### Legend
|
||||
|
||||
|
|
|
|||
|
|
@ -230,6 +230,14 @@ To resolve the issue:
|
|||
|
||||
1. If the error persists, try using a different web browser or an incognito/private browsing window.
|
||||
|
||||
#### Error: `Attempt_Exceed_Limitation - Attempt exceed the limitation, refresh page to try again`
|
||||
|
||||
You might get the error `Attempt_Exceed_Limitation - Attempt exceed the limitation, refresh page to try again.` when purchasing compute minutes.
|
||||
|
||||
This issue occurs when the credit card form is re-submitted too quickly within a specific timeframe (3 submissions in 1 minute or 6 submissions in 1 hour).
|
||||
|
||||
To resolve this issue, wait a few minutes and try the purchase process again.
|
||||
|
||||
## How compute usage is calculated
|
||||
|
||||
GitLab uses this formula to calculate the compute usage of a job:
|
||||
|
|
|
|||
|
|
@ -147,13 +147,41 @@ Enable all feature flags maintained by "group::ai framework" by running this com
|
|||
bundle exec rake gitlab:duo:enable_feature_flags
|
||||
```
|
||||
|
||||
### Recommended: Run GDK in SaaS mode and enable AI features for a test group
|
||||
### Recommended: Run `gitlab:duo:setup` Rake task to prepare the environment
|
||||
|
||||
**Why:** By default, GDK runs GitLab as a self-managed instance. But, the Duo
|
||||
licensing setup for self-managed is more complex than it is for GitLab.com. If
|
||||
the feature you are working on available on GitLab.com, you should
|
||||
run GDK in "SaaS" mode so that you can skip the
|
||||
[customersDot setup](#option-2-use-your-customersdot-instance-as-a-provider).
|
||||
This Rake task ensures that the local environment is ready to run GitLab Duo.
|
||||
The task can be run in either SaaS or Self-Managed modes, depending on which installation you currently imitate in GDK.
|
||||
|
||||
If you currently run you local GDK as SaaS (imitating GitLab.com), you need to provide the argument to the task:
|
||||
`GITLAB_SIMULATE_SAAS=1 bundle exec 'rake gitlab:duo:setup[<test-group-name>]'`
|
||||
|
||||
Replace `<test-group-name>` with the name of any top-level group. Duo will be configured for that group. If the
|
||||
group doesn't exist, it creates a new one. Make sure the script succeeded. It prints error messages with links
|
||||
on how to resolve the error. You can re-run the script until it succeeds.
|
||||
|
||||
If you currently run you local GDK as Self-Managed (default for GDK), no arguments for Rake task are expected:
|
||||
`GITLAB_SIMULATE_SAAS=0 bundle exec 'rake gitlab:duo:setup'`
|
||||
|
||||
It's recommended to run `gdk restart` after the task succeeded.
|
||||
|
||||
### Recommended: Set `CLOUD_CONNECTOR_SELF_SIGN_TOKENS` environment variable
|
||||
|
||||
If you plan to run you local GDK as Self-Managed (for GDK), it is recommended to set this environment variable.
|
||||
It has no effect if you run you local GDK as SaaS, so you can always keep it set.
|
||||
|
||||
Setting this environment variable will allow the local GL instance to issue tokens itself, without syncing with CustomersDot first.
|
||||
This is similar how GitLab.com operates, and we allow it for development purposes to simplify the setup.
|
||||
With it you can skip the [CustomersDot setup](#option-2-use-your-customersdot-instance-as-a-provider).
|
||||
This can done by either:
|
||||
|
||||
- setting it in the `env.runit` file in your GDK root
|
||||
- executing `export CLOUD_CONNECTOR_SELF_SIGN_TOKENS=1` in your shell (but you need to repeat it for every new session)
|
||||
|
||||
You need to restart GDK to apply the change.
|
||||
|
||||
If you plan to use local CustomersDot or test cross-service integration, you may want to unset this variable.
|
||||
|
||||
### Option A: Run GDK in SaaS mode and enable AI features for a test group
|
||||
|
||||
**How:** the following should be set in the `env.runit` file in your GDK root:
|
||||
|
||||
|
|
@ -163,24 +191,22 @@ run GDK in "SaaS" mode so that you can skip the
|
|||
export GITLAB_SIMULATE_SAAS=1
|
||||
```
|
||||
|
||||
Run `gdk restart rails` after you update the file so that the value
|
||||
is picked up by your local instance.
|
||||
or, just for a current session:
|
||||
|
||||
If you are running GDK in SaaS mode, you also need to enable Duo
|
||||
features for at least one group. To do this, run this command in your `/gitlab` directory:
|
||||
```shell
|
||||
export CLOUD_CONNECTOR_SELF_SIGN_TOKENS=1 && gdk restart
|
||||
```
|
||||
|
||||
Make sure you run `gitlab:duo:setup` Rake task `/gitlab` directory:
|
||||
|
||||
```shell
|
||||
GITLAB_SIMULATE_SAAS=1 RAILS_ENV=development bundle exec rake 'gitlab:duo:setup[<test-group-name>]'
|
||||
```
|
||||
|
||||
Replace `<test-group-name>` with the name of any top-level group. If the
|
||||
group doesn't exist, it creates a new one. You might need to
|
||||
re-run the script multiple times; it prints error messages with links
|
||||
on how to resolve the error.
|
||||
|
||||
Membership to a group with Duo features enabled is what enables many AI
|
||||
features. To enable AI feature access locally, make sure that your test user is
|
||||
a member of the group with Duo features enabled.
|
||||
a member of the group with Duo features enabled (`<test-group-name>`)
|
||||
and (for some features) have a [seat assigned](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/subscriptions/subscription-add-ons.md#for-gitlabcom).
|
||||
|
||||
Finally, you must clear the GitLab-Rails Redis cache. User access to GitLab Duo
|
||||
features in SaaS mode is cached in Redis. This cache expires every 60 minutes.
|
||||
|
|
@ -192,6 +218,37 @@ bundle exec rake cache:clear
|
|||
|
||||
**Troubleshooting:** If you have problems with your setup at this point, double-check your admin settings. When GDK is running, go to admin settings (Navigation -> Admin), then go to general settings (Settings -> General), and expand the "Account and limit" section. Scroll to the bottom of this section to make sure the setting "Allow use of licensed EE features" is toggled on.
|
||||
|
||||
### Option B: Run GDK in Self-Managed mode and enable AI features for the instance
|
||||
|
||||
**How:** This is the default for GDK. To set it explicitly, the following should be set in the `env.runit` file in your GDK root:
|
||||
|
||||
```shell
|
||||
# <GDK-root>/env.runit
|
||||
|
||||
export GITLAB_SIMULATE_SAAS=0
|
||||
```
|
||||
|
||||
or, just for a current session:
|
||||
|
||||
```shell
|
||||
export CLOUD_CONNECTOR_SELF_SIGN_TOKENS=0 && gdk restart
|
||||
```
|
||||
|
||||
Make sure you executed `gitlab:duo:setup` Rake task in `/gitlab` directory:
|
||||
|
||||
```shell
|
||||
GITLAB_SIMULATE_SAAS=0 RAILS_ENV=development bundle exec rake 'gitlab:duo:setup'
|
||||
```
|
||||
|
||||
and it succeeded.
|
||||
|
||||
Some AI features requires a [seat to be assigned](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/subscriptions/subscription-add-ons.md#for-self-managed) to a user to have access.
|
||||
If you use `CLOUD_CONNECTOR_SELF_SIGN_TOKENS=1` you need to assign `root`/`admin` user to a seat,
|
||||
to receive a "Code completion test was successful" notification from the Health Check
|
||||
on the `http://localhost:3000/admin/code_suggestions` page.
|
||||
|
||||
Our customers (production environment) do not need to do that to run a Code Suggestions Health Check.
|
||||
|
||||
### Recommended: Test clients in Rails console
|
||||
|
||||
**Why:** you've completed all of the setup steps, now it's time to confirm that
|
||||
|
|
|
|||
|
|
@ -591,3 +591,16 @@ Once Product Analytics services are running and are connected to your GDK, the t
|
|||
```shell
|
||||
bundle exec rspec qa/specs/features/ee/browser_ui/8_monitor/product_analytics/onboarding_spec.rb
|
||||
```
|
||||
|
||||
## Tests that require a global server hook
|
||||
|
||||
The [`tag_revision_trigger_prereceive_hook_spec`](https://gitlab.com/gitlab-org/gitlab/-/blob/c3342dac0c6c8e9e11ec049b910eac832600b0bf/qa/qa/specs/features/api/3_create/repository/tag_revision_trigger_prereceive_hook_spec.rb) requires a global server hook to be pre-configured in the target test environment. When running this tests against a local GDK, the server hook will need to be configured with:
|
||||
|
||||
```shell
|
||||
# From the gdk directory
|
||||
mkdir -p gitaly-custom-hooks/pre-receive.d
|
||||
cp gitlab/qa/gdk/pre-receive gitaly-custom-hooks/pre-receive.d
|
||||
chmod +x gitaly-custom-hooks/pre-receive.d/pre-receive
|
||||
```
|
||||
|
||||
More information on global server hooks can be found in the [server hooks documentation](../../../administration/server_hooks.md#create-the-global-server-hook)
|
||||
|
|
|
|||
|
|
@ -519,6 +519,14 @@ If your credit card is declined when purchasing a GitLab subscription, possible
|
|||
Check with your financial institution to confirm if any of these reasons apply. If they don't
|
||||
apply, contact [GitLab Support](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293).
|
||||
|
||||
### Error: `Attempt_Exceed_Limitation - Attempt exceed the limitation, refresh page to try again`
|
||||
|
||||
You might get the error `Attempt_Exceed_Limitation - Attempt exceed the limitation, refresh page to try again.` when purchasing a GitLab subscription.
|
||||
|
||||
This issue occurs when the credit card form is re-submitted too quickly within a specific timeframe (3 submissions in 1 minute or 6 submissions in 1 hour).
|
||||
|
||||
To resolve this issue, wait a few minutes and try the purchase process again.
|
||||
|
||||
### Unable to link subscription to namespace
|
||||
|
||||
If you cannot link a subscription to your namespace, ensure that you have the Owner role
|
||||
|
|
|
|||
|
|
@ -500,6 +500,14 @@ If your credit card is declined when purchasing a GitLab subscription, possible
|
|||
Check with your financial institution to confirm if any of these reasons apply. If they don't
|
||||
apply, contact [GitLab Support](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293).
|
||||
|
||||
### Error: `Attempt_Exceed_Limitation - Attempt exceed the limitation, refresh page to try again`
|
||||
|
||||
You might get the error `Attempt_Exceed_Limitation - Attempt exceed the limitation, refresh page to try again.` when purchasing a GitLab subscription.
|
||||
|
||||
This issue occurs when the credit card form is re-submitted too quickly within a specific timeframe (3 submissions in 1 minute or 6 submissions in 1 hour).
|
||||
|
||||
To resolve this issue, wait a few minutes and try the purchase process again.
|
||||
|
||||
### Check daily and historical billable users
|
||||
|
||||
Administrators can get a list of daily and historical billable users in your GitLab instance.
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ GitLab self-managed administrators can reduce their attack surface by disabling
|
|||
|
||||
1. On the left sidebar, at the bottom, select **Admin Area**.
|
||||
1. Select **Settings > General**.
|
||||
1. Expand **Visibility and access controls**.
|
||||
1. Expand **Import and export settings**.
|
||||
1. Scroll to **Import sources**.
|
||||
1. Clear checkboxes for importers that are not required.
|
||||
|
||||
|
|
|
|||
|
|
@ -19522,12 +19522,12 @@ msgstr ""
|
|||
msgid "DuoProTrial|You have successfully created a trial subscription for GitLab Duo Pro. It will expire on %{exp_date}.%{new_line}To get started, enable the GitLab Duo Pro add-on for team members on this page by turning on the toggle for each team member. The subscription may take a minute to sync, so refresh the page if it's not visible yet."
|
||||
msgstr ""
|
||||
|
||||
msgid "DuoProTrial|You've got %{daysRemaining} day remaining on your GitLab Duo Pro trial!"
|
||||
msgid_plural "DuoProTrial|You've got %{daysRemaining} days remaining on your GitLab Duo Pro trial!"
|
||||
msgid "DuoProTrial|You've got %{daysRemaining} day left in your GitLab Duo Pro trial"
|
||||
msgid_plural "DuoProTrial|You've got %{daysRemaining} days left in your GitLab Duo Pro trial"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "DuoProTrial|Your trial ends on %{strongStart}%{trialEndDate}%{strongEnd}. We hope you’re enjoying the features of GitLab Duo Pro. To continue using your AI-powered assistant after you trial ends, you'll need to buy an add-on subscription."
|
||||
msgid "DuoProTrial|Your trial ends on %{strongStart}%{trialEndDate}%{strongEnd}. To continue using features in GitLab Duo Pro, purchase a subscription add-on."
|
||||
msgstr ""
|
||||
|
||||
msgid "Duplicate page: A page with that title already exists in the file %{file}"
|
||||
|
|
|
|||
|
|
@ -35,12 +35,8 @@ module Gitlab
|
|||
#
|
||||
# @param plan [Hash] Name of the plan
|
||||
# @option plan [Hash] Support::Helpers::FREE
|
||||
# @option plan [Hash] Support::Helpers::PREMIUM
|
||||
# @option plan [Hash] Support::Helpers::PREMIUM_SELF_MANAGED
|
||||
# @option plan [Hash] Support::Helpers::ULTIMATE
|
||||
# @option plan [Hash] Support::Helpers::ULTIMATE_SELF_MANAGED
|
||||
# @option plan [Hash] Support::Helpers::COMPUTE_MINUTES
|
||||
# @option plan [Hash] Support::Helpers::STORAGE
|
||||
# @param users_in_license [Integer] Number of users in license
|
||||
# @param license_type [Hash] Type of the license
|
||||
# @option license_type [String] 'license file'
|
||||
|
|
|
|||
|
|
@ -7,30 +7,6 @@ module Gitlab
|
|||
class Billing < Chemlab::Page
|
||||
h4 :billing_plan_header
|
||||
link :start_your_free_trial
|
||||
link :upgrade_to_premium
|
||||
link :upgrade_to_ultimate
|
||||
|
||||
# Subscription details
|
||||
button :refresh_seats
|
||||
|
||||
def refresh_subscription_seats
|
||||
refresh_seats
|
||||
::QA::Support::WaitForRequests.wait_for_requests
|
||||
end
|
||||
|
||||
# Waits for subscription to be synced and UI to be updated
|
||||
#
|
||||
# @param subscription_plan [String]
|
||||
def wait_for_subscription(subscription_plan)
|
||||
::QA::Support::Waiter.wait_until(
|
||||
max_duration: ::QA::Support::Helpers::Zuora::ZUORA_TIMEOUT,
|
||||
sleep_interval: 2,
|
||||
reload_page: Chemlab.configuration.browser.session,
|
||||
message: "Subscription plan '#{subscription_plan}' failed to appear"
|
||||
) do
|
||||
billing_plan_header.match?(/currently using the #{subscription_plan} saas plan/i)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -52,78 +52,6 @@ module Gitlab
|
|||
def start_your_free_trial?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +link :upgrade_to_premium+
|
||||
# Clicks +upgrade_to_premium+
|
||||
def upgrade_to_premium
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::Billing.perform do |billing|
|
||||
# expect(billing.upgrade_to_premium_element).to exist
|
||||
# end
|
||||
# @return [Watir::Link] The raw +Link+ element
|
||||
def upgrade_to_premium_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::Billing.perform do |billing|
|
||||
# expect(billing).to be_upgrade_to_premium
|
||||
# end
|
||||
# @return [Boolean] true if the +upgrade_to_premium+ element is present on the page
|
||||
def upgrade_to_premium?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +link :upgrade_to_ultimate+
|
||||
# Clicks +upgrade_to_ultimate+
|
||||
def upgrade_to_ultimate
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::Billing.perform do |billing|
|
||||
# expect(billing.upgrade_to_ultimate_element).to exist
|
||||
# end
|
||||
# @return [Watir::Link] The raw +Link+ element
|
||||
def upgrade_to_ultimate_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::Billing.perform do |billing|
|
||||
# expect(billing).to be_upgrade_to_ultimate
|
||||
# end
|
||||
# @return [Boolean] true if the +upgrade_to_ultimate+ element is present on the page
|
||||
def upgrade_to_ultimate?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +button :refresh_seats+
|
||||
# Clicks +refresh_seats+
|
||||
def refresh_seats
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::Billing.perform do |billing|
|
||||
# expect(billing.refresh_seats_element).to exist
|
||||
# end
|
||||
# @return [Watir::Button] The raw +Button+ element
|
||||
def refresh_seats_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::Billing.perform do |billing|
|
||||
# expect(billing).to be_refresh_seats
|
||||
# end
|
||||
# @return [Boolean] true if the +refresh_seats+ element is present on the page
|
||||
def refresh_seats?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,27 +5,11 @@ module Gitlab
|
|||
module Group
|
||||
module Settings
|
||||
class UsageQuotas < Chemlab::Page
|
||||
# Seats section
|
||||
div :seats_in_use
|
||||
p :seats_used
|
||||
p :seats_owed
|
||||
table :subscription_users
|
||||
|
||||
# Pipelines section
|
||||
link :pipelines_tab
|
||||
link :buy_compute_minutes
|
||||
div :plan_compute_minutes
|
||||
div :additional_compute_minutes
|
||||
div :ci_purchase_successful_alert, text: /You have successfully purchased compute minutes/
|
||||
|
||||
# Storage section
|
||||
link :storage_tab
|
||||
link :purchase_more_storage
|
||||
div :namespace_usage_total
|
||||
span :group_usage_message
|
||||
span :dependency_proxy_size
|
||||
div :storage_purchased
|
||||
div :storage_purchase_successful_alert, text: /You have successfully purchased a storage/
|
||||
span :project_repository_size
|
||||
span :project_wiki_size
|
||||
span :project_snippets_size
|
||||
|
|
@ -35,57 +19,6 @@ module Gitlab
|
|||
div :pending_members
|
||||
button :approve_member
|
||||
button :confirm_member_approval, text: /^OK$/
|
||||
|
||||
def plan_ci_limits
|
||||
plan_compute_minutes[/(\d+){2}/]
|
||||
end
|
||||
|
||||
def additional_ci_limits
|
||||
additional_compute_minutes[/(\d+){2}/]
|
||||
end
|
||||
|
||||
def additional_compute_minutes_added?
|
||||
# When opening the Usage quotas page, Seats quota tab is opened briefly even when url is to a different tab
|
||||
::QA::Support::WaitForRequests.wait_for_requests
|
||||
additional_compute_minutes?
|
||||
end
|
||||
|
||||
# Returns total purchased storage value once it's ready on page
|
||||
#
|
||||
# @return [Float] Total purchased storage value in GiB
|
||||
def total_purchased_storage
|
||||
::QA::Support::WaitForRequests.wait_for_requests
|
||||
|
||||
storage_purchased[/(\d+){2}.\d+/].to_f
|
||||
end
|
||||
|
||||
# Waits for additional compute minutes to be available on the page
|
||||
def wait_for_additional_compute_minutes_available
|
||||
::QA::Support::Waiter.wait_until(
|
||||
max_duration: ::QA::Support::Helpers::Zuora::ZUORA_TIMEOUT,
|
||||
sleep_interval: 2,
|
||||
reload_page: Chemlab.configuration.browser.session,
|
||||
message: 'Expected additional compute minutes but they did not appear.'
|
||||
) do
|
||||
additional_compute_minutes_added?
|
||||
end
|
||||
end
|
||||
|
||||
# Waits for additional compute minutes amount to match the expected number of minutes
|
||||
#
|
||||
# @param [String] minutes
|
||||
def wait_for_additional_compute_minute_limits(minutes)
|
||||
wait_for_additional_compute_minutes_available
|
||||
|
||||
::QA::Support::Waiter.wait_until(
|
||||
max_duration: ::QA::Support::Helpers::Zuora::ZUORA_TIMEOUT,
|
||||
sleep_interval: 2,
|
||||
reload_page: Chemlab.configuration.browser.session,
|
||||
message: "Expected additional compute minutes to equal #{minutes}"
|
||||
) do
|
||||
additional_ci_limits == minutes
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,222 +5,6 @@ module Gitlab
|
|||
module Group
|
||||
module Settings
|
||||
module UsageQuotas
|
||||
# @note Defined as +div :seats_in_use+
|
||||
# @return [String] The text content or value of +seats_in_use+
|
||||
def seats_in_use
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.seats_in_use_element).to exist
|
||||
# end
|
||||
# @return [Watir::Div] The raw +Div+ element
|
||||
def seats_in_use_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_seats_in_use
|
||||
# end
|
||||
# @return [Boolean] true if the +seats_in_use+ element is present on the page
|
||||
def seats_in_use?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +p :seats_used+
|
||||
# @return [String] The text content or value of +seats_used+
|
||||
def seats_used
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.seats_used_element).to exist
|
||||
# end
|
||||
# @return [Watir::P] The raw +P+ element
|
||||
def seats_used_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_seats_used
|
||||
# end
|
||||
# @return [Boolean] true if the +seats_used+ element is present on the page
|
||||
def seats_used?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +p :seats_owed+
|
||||
# @return [String] The text content or value of +seats_owed+
|
||||
def seats_owed
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.seats_owed_element).to exist
|
||||
# end
|
||||
# @return [Watir::P] The raw +P+ element
|
||||
def seats_owed_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_seats_owed
|
||||
# end
|
||||
# @return [Boolean] true if the +seats_owed+ element is present on the page
|
||||
def seats_owed?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +table :subscription_users+
|
||||
# @return [String] The text content or value of +subscription_users+
|
||||
def subscription_users
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.subscription_users_element).to exist
|
||||
# end
|
||||
# @return [Watir::Table] The raw +Table+ element
|
||||
def subscription_users_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_subscription_users
|
||||
# end
|
||||
# @return [Boolean] true if the +subscription_users+ element is present on the page
|
||||
def subscription_users?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +link :pipelines_tab+
|
||||
# Clicks +pipelines_tab+
|
||||
def pipelines_tab
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.pipelines_tab_element).to exist
|
||||
# end
|
||||
# @return [Watir::Link] The raw +Link+ element
|
||||
def pipelines_tab_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_pipelines_tab
|
||||
# end
|
||||
# @return [Boolean] true if the +pipelines_tab+ element is present on the page
|
||||
def pipelines_tab?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +link :buy_compute_minutes+
|
||||
# Clicks +buy_compute_minutes+
|
||||
def buy_compute_minutes
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.buy_compute_minutes_element).to exist
|
||||
# end
|
||||
# @return [Watir::Link] The raw +Link+ element
|
||||
def buy_compute_minutes_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_buy_compute_minutes
|
||||
# end
|
||||
# @return [Boolean] true if the +buy_compute_minutes+ element is present on the page
|
||||
def buy_compute_minutes?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +div :plan_compute_minutes+
|
||||
# @return [String] The text content or value of +plan_compute_minutes+
|
||||
def plan_compute_minutes
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.plan_compute_minutes_element).to exist
|
||||
# end
|
||||
# @return [Watir::Div] The raw +Div+ element
|
||||
def plan_compute_minutes_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_plan_compute_minutes
|
||||
# end
|
||||
# @return [Boolean] true if the +plan_compute_minutes+ element is present on the page
|
||||
def plan_compute_minutes?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +div :additional_compute_minutes+
|
||||
# @return [String] The text content or value of +additional_compute_minutes+
|
||||
def additional_compute_minutes
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.additional_compute_minutes_element).to exist
|
||||
# end
|
||||
# @return [Watir::Div] The raw +Div+ element
|
||||
def additional_compute_minutes_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_additional_compute_minutes
|
||||
# end
|
||||
# @return [Boolean] true if the +additional_compute_minutes+ element is present on the page
|
||||
def additional_compute_minutes?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +div :ci_purchase_successful_alert+
|
||||
# @return [String] The text content or value of +ci_purchase_successful_alert+
|
||||
def ci_purchase_successful_alert
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.ci_purchase_successful_alert_element).to exist
|
||||
# end
|
||||
# @return [Watir::Div] The raw +Div+ element
|
||||
def ci_purchase_successful_alert_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_ci_purchase_successful_alert
|
||||
# end
|
||||
# @return [Boolean] true if the +ci_purchase_successful_alert+ element is present on the page
|
||||
def ci_purchase_successful_alert?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +link :storage_tab+
|
||||
# Clicks +storage_tab+
|
||||
def storage_tab
|
||||
|
|
@ -245,54 +29,6 @@ module Gitlab
|
|||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +link :purchase_more_storage+
|
||||
# Clicks +purchase_more_storage+
|
||||
def purchase_more_storage
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.purchase_more_storage_element).to exist
|
||||
# end
|
||||
# @return [Watir::Link] The raw +Link+ element
|
||||
def purchase_more_storage_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_purchase_more_storage
|
||||
# end
|
||||
# @return [Boolean] true if the +purchase_more_storage+ element is present on the page
|
||||
def purchase_more_storage?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +div :used_storage_message+
|
||||
# @return [String] The text content or value of +used_storage_message+
|
||||
def used_storage_message
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.used_storage_message_element).to exist
|
||||
# end
|
||||
# @return [Watir::Div] The raw +Div+ element
|
||||
def used_storage_message_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_used_storage_message
|
||||
# end
|
||||
# @return [Boolean] true if the +used_storage_message+ element is present on the page
|
||||
def used_storage_message?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +span :group_usage_message+
|
||||
# @return [String] The text content or value of +group_usage_message+
|
||||
def group_usage_message
|
||||
|
|
@ -340,126 +76,6 @@ module Gitlab
|
|||
def dependency_proxy_size?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +div :project_storage_used+
|
||||
# @return [String] The text content or value of +project_storage_used+
|
||||
def project_storage_used
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.project_storage_used_element).to exist
|
||||
# end
|
||||
# @return [Watir::Div] The raw +Div+ element
|
||||
def project_storage_used_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_project_storage_used
|
||||
# end
|
||||
# @return [Boolean] true if the +project_storage_used+ element is present on the page
|
||||
def project_storage_used?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +div :project+
|
||||
# @return [String] The text content or value of +project+
|
||||
def project
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.project_element).to exist
|
||||
# end
|
||||
# @return [Watir::Div] The raw +Div+ element
|
||||
def project_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_project
|
||||
# end
|
||||
# @return [Boolean] true if the +project+ element is present on the page
|
||||
def project?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +div :storage_purchased+
|
||||
# @return [String] The text content or value of +storage_purchased+
|
||||
def storage_purchased
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.storage_purchased_element).to exist
|
||||
# end
|
||||
# @return [Watir::Div] The raw +Div+ element
|
||||
def storage_purchased_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_storage_purchased
|
||||
# end
|
||||
# @return [Boolean] true if the +storage_purchased+ element is present on the page
|
||||
def storage_purchased?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +div :storage_purchase_successful_alert+
|
||||
# @return [String] The text content or value of +storage_purchase_successful_alert+
|
||||
def storage_purchase_successful_alert
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.storage_purchase_successful_alert_element).to exist
|
||||
# end
|
||||
# @return [Watir::Div] The raw +Div+ element
|
||||
def storage_purchase_successful_alert_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_storage_purchase_successful_alert
|
||||
# end
|
||||
# @return [Boolean] true if the +storage_purchase_successful_alert+ element is present on the page
|
||||
def storage_purchase_successful_alert?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +h2 :storage_available_alert+
|
||||
# @return [String] The text content or value of +storage_available_alert+
|
||||
def storage_available_alert
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas.storage_available_alert_element).to exist
|
||||
# end
|
||||
# @return [Watir::H2] The raw +H2+ element
|
||||
def storage_available_alert_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quotas|
|
||||
# expect(usage_quotas).to be_storage_available_alert
|
||||
# end
|
||||
# @return [Boolean] true if the +storage_available_alert+ element is present on the page
|
||||
def storage_available_alert?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,67 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Page
|
||||
module Subscriptions
|
||||
class New < Chemlab::Page
|
||||
path '/subscriptions/new'
|
||||
|
||||
# Purchase Details
|
||||
select :plan_name
|
||||
select :group_name
|
||||
text_field :number_of_users
|
||||
text_field :quantity
|
||||
button :continue_to_billing, text: /Continue to billing/
|
||||
|
||||
# Billing address
|
||||
select :country
|
||||
text_field :street_address_1
|
||||
text_field :street_address_2
|
||||
text_field :city
|
||||
select :state
|
||||
text_field :zip_code
|
||||
button :continue_to_payment, text: /Continue to payment/
|
||||
|
||||
# Payment method
|
||||
# TODO: Revisit when https://gitlab.com/gitlab-org/quality/chemlab/-/issues/6 is closed
|
||||
iframe :payment_form, id: 'z_hppm_iframe'
|
||||
|
||||
text_field(:name_on_card) { payment_form_element.text_field(id: 'input-creditCardHolderName') }
|
||||
text_field(:card_number) { payment_form_element.text_field(id: 'input-creditCardNumber') }
|
||||
select(:expiration_month) { payment_form_element.select(id: 'input-creditCardExpirationMonth') }
|
||||
select(:expiration_year) { payment_form_element.select(id: 'input-creditCardExpirationYear') }
|
||||
text_field(:cvv) { payment_form_element.text_field(id: 'input-cardSecurityCode') }
|
||||
link(:review_your_order) { payment_form_element.link(text: /Review your order/) }
|
||||
# ENDTODO
|
||||
|
||||
# ToS Acceptance
|
||||
div :privacy_and_terms_confirm
|
||||
|
||||
# Confirmation
|
||||
button :confirm_purchase, text: /Confirm purchase/
|
||||
|
||||
# Order Summary
|
||||
div :selected_plan
|
||||
div :total_amount
|
||||
|
||||
# Alerts
|
||||
div :lock_competition_error, text: /Operation failed due to a lock competition, please retry later./
|
||||
|
||||
def purchase
|
||||
::QA::Support::Retrier.retry_until(
|
||||
max_duration: 80,
|
||||
sleep_interval: 10,
|
||||
message: 'Expected no Zuora lock competition error'
|
||||
) do
|
||||
::QA::Runtime::Logger.debug('Attempting to purchase subscription')
|
||||
|
||||
privacy_and_terms_confirm_element.click
|
||||
confirm_purchase
|
||||
::QA::Support::WaitForRequests.wait_for_requests
|
||||
!lock_competition_error?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,651 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Page
|
||||
module Subscriptions
|
||||
module New
|
||||
# @note Defined as +select :plan_name+
|
||||
# @return [String] The text content or value of +plan_name+
|
||||
def plan_name
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.plan_name_element).to exist
|
||||
# end
|
||||
# @return [Watir::Select] The raw +Select+ element
|
||||
def plan_name_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_plan_name
|
||||
# end
|
||||
# @return [Boolean] true if the +plan_name+ element is present on the page
|
||||
def plan_name?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +select :group_name+
|
||||
# @return [String] The text content or value of +group_name+
|
||||
def group_name
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.group_name_element).to exist
|
||||
# end
|
||||
# @return [Watir::Select] The raw +Select+ element
|
||||
def group_name_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_group_name
|
||||
# end
|
||||
# @return [Boolean] true if the +group_name+ element is present on the page
|
||||
def group_name?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +text_field :number_of_users+
|
||||
# @return [String] The text content or value of +number_of_users+
|
||||
def number_of_users
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# Set the value of number_of_users
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# new.number_of_users = 'value'
|
||||
# end
|
||||
# @param value [String] The value to set.
|
||||
def number_of_users=(value)
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.number_of_users_element).to exist
|
||||
# end
|
||||
# @return [Watir::TextField] The raw +TextField+ element
|
||||
def number_of_users_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_number_of_users
|
||||
# end
|
||||
# @return [Boolean] true if the +number_of_users+ element is present on the page
|
||||
def number_of_users?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +text_field :quantity+
|
||||
# @return [String] The text content or value of +quantity+
|
||||
def quantity
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# Set the value of quantity
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# new.quantity = 'value'
|
||||
# end
|
||||
# @param value [String] The value to set.
|
||||
def quantity=(value)
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.quantity_element).to exist
|
||||
# end
|
||||
# @return [Watir::TextField] The raw +TextField+ element
|
||||
def quantity_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_quantity
|
||||
# end
|
||||
# @return [Boolean] true if the +quantity+ element is present on the page
|
||||
def quantity?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +button :continue_to_billing+
|
||||
# Clicks +continue_to_billing+
|
||||
def continue_to_billing
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.continue_to_billing_element).to exist
|
||||
# end
|
||||
# @return [Watir::Button] The raw +Button+ element
|
||||
def continue_to_billing_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_continue_to_billing
|
||||
# end
|
||||
# @return [Boolean] true if the +continue_to_billing+ element is present on the page
|
||||
def continue_to_billing?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +select :country+
|
||||
# @return [String] The text content or value of +country+
|
||||
def country
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.country_element).to exist
|
||||
# end
|
||||
# @return [Watir::Select] The raw +Select+ element
|
||||
def country_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_country
|
||||
# end
|
||||
# @return [Boolean] true if the +country+ element is present on the page
|
||||
def country?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +text_field :street_address_1+
|
||||
# @return [String] The text content or value of +street_address_1+
|
||||
def street_address_1
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# Set the value of street_address_1
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# new.street_address_1 = 'value'
|
||||
# end
|
||||
# @param value [String] The value to set.
|
||||
def street_address_1=(value)
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.street_address_1_element).to exist
|
||||
# end
|
||||
# @return [Watir::TextField] The raw +TextField+ element
|
||||
def street_address_1_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_street_address_1
|
||||
# end
|
||||
# @return [Boolean] true if the +street_address_1+ element is present on the page
|
||||
def street_address_1?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +text_field :street_address_2+
|
||||
# @return [String] The text content or value of +street_address_2+
|
||||
def street_address_2
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# Set the value of street_address_2
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# new.street_address_2 = 'value'
|
||||
# end
|
||||
# @param value [String] The value to set.
|
||||
def street_address_2=(value)
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.street_address_2_element).to exist
|
||||
# end
|
||||
# @return [Watir::TextField] The raw +TextField+ element
|
||||
def street_address_2_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_street_address_2
|
||||
# end
|
||||
# @return [Boolean] true if the +street_address_2+ element is present on the page
|
||||
def street_address_2?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +text_field :city+
|
||||
# @return [String] The text content or value of +city+
|
||||
def city
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# Set the value of city
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# new.city = 'value'
|
||||
# end
|
||||
# @param value [String] The value to set.
|
||||
def city=(value)
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.city_element).to exist
|
||||
# end
|
||||
# @return [Watir::TextField] The raw +TextField+ element
|
||||
def city_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_city
|
||||
# end
|
||||
# @return [Boolean] true if the +city+ element is present on the page
|
||||
def city?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +select :state+
|
||||
# @return [String] The text content or value of +state+
|
||||
def state
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.state_element).to exist
|
||||
# end
|
||||
# @return [Watir::Select] The raw +Select+ element
|
||||
def state_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_state
|
||||
# end
|
||||
# @return [Boolean] true if the +state+ element is present on the page
|
||||
def state?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +text_field :zip_code+
|
||||
# @return [String] The text content or value of +zip_code+
|
||||
def zip_code
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# Set the value of zip_code
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# new.zip_code = 'value'
|
||||
# end
|
||||
# @param value [String] The value to set.
|
||||
def zip_code=(value)
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.zip_code_element).to exist
|
||||
# end
|
||||
# @return [Watir::TextField] The raw +TextField+ element
|
||||
def zip_code_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_zip_code
|
||||
# end
|
||||
# @return [Boolean] true if the +zip_code+ element is present on the page
|
||||
def zip_code?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +button :continue_to_payment+
|
||||
# Clicks +continue_to_payment+
|
||||
def continue_to_payment
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.continue_to_payment_element).to exist
|
||||
# end
|
||||
# @return [Watir::Button] The raw +Button+ element
|
||||
def continue_to_payment_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_continue_to_payment
|
||||
# end
|
||||
# @return [Boolean] true if the +continue_to_payment+ element is present on the page
|
||||
def continue_to_payment?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +iframe :payment_form+
|
||||
# @return [String] The text content or value of +payment_form+
|
||||
def payment_form
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.payment_form_element).to exist
|
||||
# end
|
||||
# @return [Watir::Iframe] The raw +Iframe+ element
|
||||
def payment_form_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_payment_form
|
||||
# end
|
||||
# @return [Boolean] true if the +payment_form+ element is present on the page
|
||||
def payment_form?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +text_field :name_on_card+
|
||||
# @return [String] The text content or value of +name_on_card+
|
||||
def name_on_card
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# Set the value of name_on_card
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# new.name_on_card = 'value'
|
||||
# end
|
||||
# @param value [String] The value to set.
|
||||
def name_on_card=(value)
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.name_on_card_element).to exist
|
||||
# end
|
||||
# @return [Watir::TextField] The raw +TextField+ element
|
||||
def name_on_card_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_name_on_card
|
||||
# end
|
||||
# @return [Boolean] true if the +name_on_card+ element is present on the page
|
||||
def name_on_card?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +text_field :card_number+
|
||||
# @return [String] The text content or value of +card_number+
|
||||
def card_number
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# Set the value of card_number
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# new.card_number = 'value'
|
||||
# end
|
||||
# @param value [String] The value to set.
|
||||
def card_number=(value)
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.card_number_element).to exist
|
||||
# end
|
||||
# @return [Watir::TextField] The raw +TextField+ element
|
||||
def card_number_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_card_number
|
||||
# end
|
||||
# @return [Boolean] true if the +card_number+ element is present on the page
|
||||
def card_number?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +select :expiration_month+
|
||||
# @return [String] The text content or value of +expiration_month+
|
||||
def expiration_month
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.expiration_month_element).to exist
|
||||
# end
|
||||
# @return [Watir::Select] The raw +Select+ element
|
||||
def expiration_month_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_expiration_month
|
||||
# end
|
||||
# @return [Boolean] true if the +expiration_month+ element is present on the page
|
||||
def expiration_month?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +select :expiration_year+
|
||||
# @return [String] The text content or value of +expiration_year+
|
||||
def expiration_year
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.expiration_year_element).to exist
|
||||
# end
|
||||
# @return [Watir::Select] The raw +Select+ element
|
||||
def expiration_year_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_expiration_year
|
||||
# end
|
||||
# @return [Boolean] true if the +expiration_year+ element is present on the page
|
||||
def expiration_year?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +text_field :cvv+
|
||||
# @return [String] The text content or value of +cvv+
|
||||
def cvv
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# Set the value of cvv
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# new.cvv = 'value'
|
||||
# end
|
||||
# @param value [String] The value to set.
|
||||
def cvv=(value)
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.cvv_element).to exist
|
||||
# end
|
||||
# @return [Watir::TextField] The raw +TextField+ element
|
||||
def cvv_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_cvv
|
||||
# end
|
||||
# @return [Boolean] true if the +cvv+ element is present on the page
|
||||
def cvv?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +link :review_your_order+
|
||||
# Clicks +review_your_order+
|
||||
def review_your_order
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.review_your_order_element).to exist
|
||||
# end
|
||||
# @return [Watir::Link] The raw +Link+ element
|
||||
def review_your_order_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_review_your_order
|
||||
# end
|
||||
# @return [Boolean] true if the +review_your_order+ element is present on the page
|
||||
def review_your_order?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +button :confirm_purchase+
|
||||
# Clicks +confirm_purchase+
|
||||
def confirm_purchase
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.confirm_purchase_element).to exist
|
||||
# end
|
||||
# @return [Watir::Button] The raw +Button+ element
|
||||
def confirm_purchase_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_confirm_purchase
|
||||
# end
|
||||
# @return [Boolean] true if the +confirm_purchase+ element is present on the page
|
||||
def confirm_purchase?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +div :selected_plan+
|
||||
# @return [String] The text content or value of +selected_plan+
|
||||
def selected_plan
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.selected_plan_element).to exist
|
||||
# end
|
||||
# @return [Watir::Div] The raw +Div+ element
|
||||
def selected_plan_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_selected_plan
|
||||
# end
|
||||
# @return [Boolean] true if the +selected_plan+ element is present on the page
|
||||
def selected_plan?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +div :total_amount+
|
||||
# @return [String] The text content or value of +total_amount+
|
||||
def total_amount
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.total_amount_element).to exist
|
||||
# end
|
||||
# @return [Watir::Div] The raw +Div+ element
|
||||
def total_amount_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_total_amount
|
||||
# end
|
||||
# @return [Boolean] true if the +total_amount+ element is present on the page
|
||||
def total_amount?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @note Defined as +div :lock_competition_error+
|
||||
# @return [String] The text content or value of +lock_competition_error+
|
||||
def lock_competition_error
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new.lock_competition_error_element).to exist
|
||||
# end
|
||||
# @return [Watir::Div] The raw +Div+ element
|
||||
def lock_competition_error_element
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
|
||||
# @example
|
||||
# Gitlab::Page::Subscriptions::New.perform do |new|
|
||||
# expect(new).to be_lock_competition_error
|
||||
# end
|
||||
# @return [Boolean] true if the +lock_competition_error+ element is present on the page
|
||||
def lock_competition_error?
|
||||
# This is a stub, used for indexing. The method is dynamically generated.
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
module Flow
|
||||
module Purchase
|
||||
include Support::Helpers::Plan
|
||||
|
||||
extend self
|
||||
|
||||
def upgrade_subscription(plan: PREMIUM, skip_contact: false)
|
||||
Page::Group::Menu.perform(&:go_to_billing)
|
||||
Gitlab::Page::Group::Settings::Billing.perform do |billing|
|
||||
billing.send("upgrade_to_#{plan[:name].downcase}")
|
||||
end
|
||||
|
||||
Gitlab::Page::Subscriptions::New.perform do |new_subscription|
|
||||
new_subscription.continue_to_billing
|
||||
fill_in_default_info(skip_contact)
|
||||
new_subscription.purchase
|
||||
end
|
||||
end
|
||||
|
||||
def purchase_compute_minutes(quantity: 1, skip_contact: false)
|
||||
Page::Group::Menu.perform(&:go_to_usage_quotas)
|
||||
Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quota|
|
||||
usage_quota.pipelines_tab
|
||||
usage_quota.buy_compute_minutes
|
||||
end
|
||||
|
||||
Gitlab::Page::Subscriptions::New.perform do |compute_minutes|
|
||||
compute_minutes.quantity = quantity
|
||||
compute_minutes.continue_to_billing
|
||||
|
||||
fill_in_default_info(skip_contact)
|
||||
|
||||
compute_minutes.purchase
|
||||
end
|
||||
end
|
||||
|
||||
def purchase_storage(quantity: 1, skip_contact: false)
|
||||
Page::Group::Menu.perform(&:go_to_usage_quotas)
|
||||
Gitlab::Page::Group::Settings::UsageQuotas.perform do |usage_quota|
|
||||
usage_quota.storage_tab
|
||||
usage_quota.purchase_more_storage
|
||||
end
|
||||
|
||||
# Purchase checkout opens a new tab but buying additional storage does not
|
||||
session = Chemlab.configuration.browser.session.engine
|
||||
session.switch_window if session.windows.size == 2
|
||||
|
||||
Gitlab::Page::Subscriptions::New.perform do |storage|
|
||||
storage.quantity = quantity
|
||||
storage.continue_to_billing
|
||||
|
||||
fill_in_default_info(skip_contact)
|
||||
|
||||
storage.purchase
|
||||
end
|
||||
end
|
||||
|
||||
def fill_in_customer_info
|
||||
Gitlab::Page::Subscriptions::New.perform do |subscription|
|
||||
subscription.country = user_billing_info[:country]
|
||||
subscription.street_address_1 = user_billing_info[:address_1]
|
||||
subscription.street_address_2 = user_billing_info[:address_2]
|
||||
subscription.city = user_billing_info[:city]
|
||||
subscription.state = user_billing_info[:state]
|
||||
subscription.zip_code = user_billing_info[:zip]
|
||||
end
|
||||
end
|
||||
|
||||
def fill_in_payment_info
|
||||
Gitlab::Page::Subscriptions::New.perform do |subscription|
|
||||
subscription.name_on_card = credit_card_info[:name]
|
||||
subscription.card_number = credit_card_info[:number]
|
||||
subscription.expiration_month = credit_card_info[:month]
|
||||
subscription.expiration_year = credit_card_info[:year]
|
||||
subscription.cvv = credit_card_info[:cvv]
|
||||
subscription.review_your_order
|
||||
end
|
||||
end
|
||||
|
||||
def fill_in_default_info(skip_contact)
|
||||
Gitlab::Page::Subscriptions::New.perform do |subscription|
|
||||
fill_in_customer_info unless skip_contact
|
||||
subscription.continue_to_payment
|
||||
fill_in_payment_info
|
||||
end
|
||||
end
|
||||
|
||||
def credit_card_info
|
||||
{
|
||||
name: 'QA Test',
|
||||
number: '4111111111111111',
|
||||
month: '01',
|
||||
year: '2025',
|
||||
cvv: '232'
|
||||
}.freeze
|
||||
end
|
||||
|
||||
def user_billing_info
|
||||
{
|
||||
country: 'United States of America',
|
||||
address_1: 'Address 1',
|
||||
address_2: 'Address 2',
|
||||
city: 'San Francisco',
|
||||
state: 'California',
|
||||
zip: '94102'
|
||||
}.freeze
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
QA::Flow::Purchase.prepend_mod_with('Flow::Purchase', namespace: QA)
|
||||
|
|
@ -16,8 +16,7 @@ module QA
|
|||
:name,
|
||||
:full_path,
|
||||
# Add visibility to enable create private group
|
||||
:visibility,
|
||||
:shared_with_groups
|
||||
:visibility
|
||||
|
||||
# Get group projects
|
||||
#
|
||||
|
|
@ -181,7 +180,6 @@ module QA
|
|||
:require_two_factor_authentication,
|
||||
:share_with_group_lock,
|
||||
:subgroup_creation_level,
|
||||
:shared_with_groups,
|
||||
:two_factor_grace_period
|
||||
# TODO: Add back visibility comparison once https://gitlab.com/gitlab-org/gitlab/-/issues/331252 is fixed
|
||||
# :visibility
|
||||
|
|
|
|||
|
|
@ -3,6 +3,11 @@
|
|||
module QA
|
||||
RSpec.describe 'Create' do
|
||||
describe 'Prereceive hook', product_group: :source_code do
|
||||
# NOTE: this test requires a global server hook to be configured in the target test environment.
|
||||
# If running this test against a local GDK installation, please follow the instructions in the
|
||||
# following guide to set up the hook:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md#tests-that-require-a-global-server-hook
|
||||
|
||||
let(:project) { create(:project, :with_readme) }
|
||||
|
||||
context 'when creating a tag for a ref' do
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ module QA
|
|||
Flow::Login.sign_in
|
||||
end
|
||||
|
||||
it 'by adding a home page to the wiki',
|
||||
it 'by adding a home page to the wiki', :blocking,
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347809' do
|
||||
project.visit!
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
it 'by adding a second page to the wiki',
|
||||
it 'by adding a second page to the wiki', :blocking,
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347808' do
|
||||
wiki.visit!
|
||||
|
||||
|
|
@ -91,7 +91,7 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
it 'by adding a wiki page with spaces in the path using git push',
|
||||
it 'by adding a wiki page with spaces in the path using git push', :blocking,
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/442387' do
|
||||
Resource::Repository::WikiPush.fabricate! do |push|
|
||||
push.file_name = "#{new_wiki_page_with_spaces_in_the_path}.md"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ module QA
|
|||
Flow::Login.sign_in
|
||||
end
|
||||
|
||||
it 'by manipulating content on the page',
|
||||
it 'by manipulating content on the page', :blocking,
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347810' do
|
||||
wiki.visit!
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ module QA
|
|||
end
|
||||
|
||||
context 'with Wiki Sidebar' do
|
||||
it 'has all expected links that work',
|
||||
it 'has all expected links that work', :blocking,
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347814' do
|
||||
small_wiki.visit!
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ module QA
|
|||
end
|
||||
|
||||
context 'with Wiki Page List' do
|
||||
it 'has all expected links that work',
|
||||
it 'has all expected links that work', :blocking,
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347813' do
|
||||
large_wiki.visit!
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ module QA
|
|||
context 'when a file with the same name already exists' do
|
||||
let(:file_name) { 'README.md' }
|
||||
|
||||
it 'throws an error', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/390005' do
|
||||
it 'throws an error', :blocking, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/390005' do
|
||||
Page::Project::WebIDE::VSCode.perform do |ide|
|
||||
ide.upload_file(file_path)
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ module QA
|
|||
it_behaves_like 'upload a file'
|
||||
end
|
||||
|
||||
context 'when the file is an image',
|
||||
context 'when the file is an image', :blocking,
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/390007' do
|
||||
let(:file_name) { 'dk.png' }
|
||||
|
||||
|
|
|
|||
|
|
@ -6,15 +6,6 @@ module QA
|
|||
module Plan
|
||||
FREE = { name: 'free', price: 0, yearly_price: 0, compute_minutes: 400 }.freeze
|
||||
|
||||
PREMIUM = {
|
||||
plan_id: '2c92a00d76f0d5060176f2fb0a5029ff',
|
||||
rate_charge_id: '2c92a00d76f0d5060176f2fb0a672a02',
|
||||
name: 'premium',
|
||||
price: 19,
|
||||
yearly_price: 228,
|
||||
compute_minutes: 10000
|
||||
}.freeze
|
||||
|
||||
PREMIUM_SELF_MANAGED = {
|
||||
plan_id: '2c92a01176f0d50a0176f3043c4d4a53',
|
||||
rate_charge_id: '2c92a01176f0d50a0176f3043c6a4a58',
|
||||
|
|
@ -23,15 +14,6 @@ module QA
|
|||
yearly_price: 228
|
||||
}.freeze
|
||||
|
||||
ULTIMATE = {
|
||||
plan_id: '2c92a0ff76f0d5250176f2f8c86f305a',
|
||||
rate_charge_id: '2c92a0ff76f0d5250176f2f8c896305c',
|
||||
name: 'ultimate',
|
||||
price: 99,
|
||||
yearly_price: 1188,
|
||||
compute_minutes: 50000
|
||||
}.freeze
|
||||
|
||||
ULTIMATE_SELF_MANAGED = {
|
||||
plan_id: '2c92a00c76f0c6c20176f2f9328b33c9',
|
||||
rate_charge_id: '2c92a00c76f0c6c20176f2fcbb645b5f',
|
||||
|
|
@ -40,22 +22,6 @@ module QA
|
|||
yearly_price: 1188
|
||||
}.freeze
|
||||
|
||||
COMPUTE_MINUTES = {
|
||||
plan_id: '2c92a0086a07f4a8016a2c0a1f7b4b4c',
|
||||
rate_charge_id: '2c92a0fd6a07f4c6016a2c0af07c3f21',
|
||||
name: 'compute_minutes',
|
||||
price: 10,
|
||||
compute_minutes: 1000
|
||||
}.freeze
|
||||
|
||||
STORAGE = {
|
||||
plan_id: '2c92a00f7279a6f5017279d299d01cf9',
|
||||
rate_charge_id: '2c92a0ff7279a74f017279d5bea71fc5',
|
||||
name: 'storage',
|
||||
price: 60,
|
||||
storage: 10
|
||||
}.freeze
|
||||
|
||||
LICENSE_TYPE = {
|
||||
legacy_license: 'legacy license',
|
||||
online_cloud: 'online license',
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
module Support
|
||||
module Helpers
|
||||
module Zuora
|
||||
ZUORA_TIMEOUT = 60
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -44,7 +44,8 @@ module QA
|
|||
quarantine: example.metadata[:quarantine],
|
||||
screenshot: example.metadata[:screenshot],
|
||||
product_group: example.metadata[:product_group],
|
||||
ci_job_url: QA::Runtime::Env.ci_job_url
|
||||
ci_job_url: QA::Runtime::Env.ci_job_url,
|
||||
level: 'E2E'
|
||||
}
|
||||
|
||||
e = example.exception
|
||||
|
|
|
|||
|
|
@ -74,21 +74,17 @@ describe('Pipelines stage component', () => {
|
|||
createComponent({ updateDropdown: true });
|
||||
|
||||
mock.onGet(dropdownPath).reply(HTTP_STATUS_OK, legacyStageReply);
|
||||
|
||||
await openStageDropdown();
|
||||
await findDropdownToggle().trigger('click');
|
||||
});
|
||||
|
||||
it('displays loading state while jobs are being fetched', async () => {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
wrapper.setData({ isLoading: true });
|
||||
await waitForPromises();
|
||||
|
||||
it('displays loading state while jobs are being fetched', () => {
|
||||
expect(findLoadingState().exists()).toBe(true);
|
||||
expect(findLoadingState().text()).toBe(LegacyPipelineStage.i18n.loadingText);
|
||||
});
|
||||
|
||||
it('does not display loading state after jobs have been fetched', async () => {
|
||||
await waitForPromises();
|
||||
await nextTick();
|
||||
|
||||
expect(findLoadingState().exists()).toBe(false);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -125,9 +125,9 @@ describe('IDE Terminal', () => {
|
|||
canScrollDown: false,
|
||||
});
|
||||
|
||||
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
wrapper.setData({ canScrollUp: true, canScrollDown: true });
|
||||
const terminalInstance = GLTerminal.mock.instances[0];
|
||||
const scrollHandler = terminalInstance.addScrollListener.mock.calls[0][0];
|
||||
scrollHandler({ canScrollUp: true, canScrollDown: true });
|
||||
|
||||
return nextTick().then(() => {
|
||||
expect(wrapper.findComponent(TerminalControls).props()).toEqual({
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import { nextTick } from 'vue';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { trimText } from 'helpers/text_helper';
|
||||
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
|
|
@ -66,11 +67,14 @@ const defaultMrProps = () => ({
|
|||
});
|
||||
|
||||
const getStatusText = () => wrapper.findByTestId('statusText').text();
|
||||
const findCancelAutoMergeButton = () => wrapper.find('[data-testid="cancelAutomaticMergeButton"]');
|
||||
|
||||
describe('MRWidgetAutoMergeEnabled', () => {
|
||||
let oldWindowGl;
|
||||
let mock;
|
||||
|
||||
beforeEach(() => {
|
||||
mock = new MockAdapter(axios);
|
||||
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
|
||||
|
||||
oldWindowGl = window.gl;
|
||||
|
|
@ -82,6 +86,7 @@ describe('MRWidgetAutoMergeEnabled', () => {
|
|||
});
|
||||
|
||||
afterEach(() => {
|
||||
mock.restore();
|
||||
window.gl = oldWindowGl;
|
||||
});
|
||||
|
||||
|
|
@ -130,13 +135,8 @@ describe('MRWidgetAutoMergeEnabled', () => {
|
|||
factory({
|
||||
...defaultMrProps(),
|
||||
});
|
||||
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
wrapper.setData({
|
||||
isCancellingAutoMerge: true,
|
||||
});
|
||||
|
||||
await nextTick();
|
||||
await findCancelAutoMergeButton().trigger('click');
|
||||
|
||||
expect(wrapper.find('.js-cancel-auto-merge').props('loading')).toBe(true);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import { useLocalStorageSpy } from 'helpers/local_storage_helper';
|
|||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
|
||||
import RecentSearchesService from '~/filtered_search/services/recent_searches_service';
|
||||
import RecentSearchesStore from '~/filtered_search/stores/recent_searches_store';
|
||||
import {
|
||||
FILTERED_SEARCH_TERM,
|
||||
TOKEN_TYPE_AUTHOR,
|
||||
|
|
@ -37,6 +36,27 @@ jest.mock('~/vue_shared/components/filtered_search_bar/filtered_search_utils', (
|
|||
).filterEmptySearchTerm,
|
||||
}));
|
||||
|
||||
const mockFetch = jest.fn().mockResolvedValue([]);
|
||||
const mockServiceResults = (results) => {
|
||||
mockFetch.mockResolvedValueOnce(results);
|
||||
};
|
||||
|
||||
jest.mock('~/filtered_search/services/recent_searches_service', () => {
|
||||
const ServiceMock = jest.fn(function ServiceMock() {
|
||||
Object.assign(this, {
|
||||
fetch: mockFetch,
|
||||
save: jest.fn(),
|
||||
isAvailable: () => true,
|
||||
});
|
||||
});
|
||||
ServiceMock.isAvailable = () => true;
|
||||
|
||||
return {
|
||||
__esModule: true,
|
||||
default: ServiceMock,
|
||||
};
|
||||
});
|
||||
|
||||
const defaultProps = {
|
||||
namespace: 'gitlab-org/gitlab-test',
|
||||
recentSearchesStorageKey: 'issues',
|
||||
|
|
@ -140,17 +160,9 @@ describe('FilteredSearchBarRoot', () => {
|
|||
});
|
||||
|
||||
describe('filteredRecentSearches', () => {
|
||||
beforeEach(() => {
|
||||
createComponent();
|
||||
});
|
||||
|
||||
it('returns array of recent searches filtering out any string type (unsupported) items', async () => {
|
||||
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
wrapper.setData({
|
||||
recentSearches: [{ foo: 'bar' }, 'foo'],
|
||||
});
|
||||
|
||||
mockServiceResults([{ foo: 'bar' }, 'foo']);
|
||||
createComponent();
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.filteredRecentSearches).toHaveLength(1);
|
||||
|
|
@ -158,15 +170,11 @@ describe('FilteredSearchBarRoot', () => {
|
|||
});
|
||||
|
||||
it('returns array of recent searches sanitizing any duplicate token values', async () => {
|
||||
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
wrapper.setData({
|
||||
recentSearches: [
|
||||
[tokenValueAuthor, tokenValueLabel, tokenValueMilestone, tokenValueLabel],
|
||||
[tokenValueAuthor, tokenValueMilestone],
|
||||
],
|
||||
});
|
||||
|
||||
mockServiceResults([
|
||||
[tokenValueAuthor, tokenValueLabel, tokenValueMilestone, tokenValueLabel],
|
||||
[tokenValueAuthor, tokenValueMilestone],
|
||||
]);
|
||||
createComponent();
|
||||
await nextTick();
|
||||
|
||||
expect(wrapper.vm.filteredRecentSearches).toHaveLength(2);
|
||||
|
|
@ -174,6 +182,7 @@ describe('FilteredSearchBarRoot', () => {
|
|||
});
|
||||
|
||||
it('returns undefined when recentSearchesStorageKey prop is not set on component', async () => {
|
||||
createComponent();
|
||||
wrapper.setProps({
|
||||
recentSearchesStorageKey: '',
|
||||
});
|
||||
|
|
@ -209,31 +218,16 @@ describe('FilteredSearchBarRoot', () => {
|
|||
|
||||
describe('methods', () => {
|
||||
describe('setupRecentSearch', () => {
|
||||
it('initializes `recentSearchesService` and `recentSearchesStore` props when `recentSearchesStorageKey` is available', () => {
|
||||
createComponent();
|
||||
expect(wrapper.vm.recentSearchesService instanceof RecentSearchesService).toBe(true);
|
||||
expect(wrapper.vm.recentSearchesStore instanceof RecentSearchesStore).toBe(true);
|
||||
});
|
||||
|
||||
it('initializes `recentSearchesPromise` prop with a promise by using `recentSearchesService.fetch()`', () => {
|
||||
expect(localStorage.setItem).not.toHaveBeenCalled();
|
||||
createComponent();
|
||||
|
||||
expect(localStorage.setItem).toHaveBeenCalledWith('canUseLocalStorage', 'true');
|
||||
expect(wrapper.vm.recentSearchesPromise instanceof Promise).toBe(true);
|
||||
});
|
||||
|
||||
describe('when `recentSearchesStorageKey` is changed', () => {
|
||||
it('gets new items from local storage', async () => {
|
||||
it('reinitializes storage service', async () => {
|
||||
createComponent();
|
||||
|
||||
expect(localStorage.getItem).toHaveBeenCalledWith(
|
||||
expect(RecentSearchesService).toHaveBeenLastCalledWith(
|
||||
'gitlab-org/gitlab-test-issue-recent-searches',
|
||||
);
|
||||
|
||||
await wrapper.setProps({ recentSearchesStorageKey: RECENT_SEARCHES_STORAGE_KEY_GROUPS });
|
||||
|
||||
expect(localStorage.getItem).toHaveBeenCalledWith(
|
||||
expect(RecentSearchesService).toHaveBeenLastCalledWith(
|
||||
'gitlab-org/gitlab-test-groups-recent-searches',
|
||||
);
|
||||
});
|
||||
|
|
@ -305,16 +299,9 @@ describe('FilteredSearchBarRoot', () => {
|
|||
it('clears search history from recent searches store', () => {
|
||||
createComponent();
|
||||
jest.spyOn(wrapper.vm.recentSearchesStore, 'setRecentSearches').mockReturnValue([]);
|
||||
|
||||
expect(localStorage.setItem).toHaveBeenCalledTimes(2);
|
||||
findGlFilteredSearch().vm.$emit('clear-history');
|
||||
|
||||
expect(wrapper.vm.recentSearchesStore.setRecentSearches).toHaveBeenCalledWith([]);
|
||||
expect(localStorage.setItem).toHaveBeenCalledTimes(4);
|
||||
expect(localStorage.setItem).toHaveBeenLastCalledWith(
|
||||
'gitlab-org/gitlab-test-issue-recent-searches',
|
||||
'[]',
|
||||
);
|
||||
expect(wrapper.vm.recentSearches).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
|
@ -323,14 +310,7 @@ describe('FilteredSearchBarRoot', () => {
|
|||
const mockFilters = [tokenValueAuthor, 'foo'];
|
||||
|
||||
beforeEach(async () => {
|
||||
createComponent();
|
||||
|
||||
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
wrapper.setData({
|
||||
filterValue: mockFilters,
|
||||
});
|
||||
|
||||
createComponent({ propsData: { initialFilterValue: mockFilters } });
|
||||
await nextTick();
|
||||
});
|
||||
|
||||
|
|
@ -353,27 +333,11 @@ describe('FilteredSearchBarRoot', () => {
|
|||
});
|
||||
|
||||
it('calls `recentSearchesService.save` with array of searches', async () => {
|
||||
expect(localStorage.setItem).toHaveBeenCalledTimes(4);
|
||||
findGlFilteredSearch().vm.$emit('submit');
|
||||
await waitForPromises();
|
||||
|
||||
expect(localStorage.setItem).toHaveBeenCalledTimes(6);
|
||||
expect(localStorage.setItem).toHaveBeenLastCalledWith(
|
||||
'gitlab-org/gitlab-test-issue-recent-searches',
|
||||
JSON.stringify([mockFilters]),
|
||||
);
|
||||
});
|
||||
|
||||
it('sets `recentSearches` data prop with array of searches', async () => {
|
||||
expect(localStorage.setItem).toHaveBeenCalledTimes(4);
|
||||
findGlFilteredSearch().vm.$emit('submit');
|
||||
await waitForPromises();
|
||||
|
||||
expect(localStorage.setItem).toHaveBeenCalledTimes(6);
|
||||
expect(localStorage.setItem).toHaveBeenLastCalledWith(
|
||||
'gitlab-org/gitlab-test-issue-recent-searches',
|
||||
JSON.stringify([mockFilters]),
|
||||
);
|
||||
const { save } = RecentSearchesService.mock.instances.at(-1);
|
||||
expect(save).toHaveBeenLastCalledWith([mockFilters]);
|
||||
});
|
||||
|
||||
it('calls `blurSearchInput` method to remove focus from filter input field', () => {
|
||||
|
|
@ -396,12 +360,10 @@ describe('FilteredSearchBarRoot', () => {
|
|||
|
||||
describe('template', () => {
|
||||
it('renders gl-filtered-search component', async () => {
|
||||
mockServiceResults(mockHistoryItems);
|
||||
createComponent();
|
||||
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
await wrapper.setData({
|
||||
recentSearches: mockHistoryItems,
|
||||
});
|
||||
await nextTick();
|
||||
await nextTick();
|
||||
|
||||
const glFilteredSearchEl = wrapper.findComponent(GlFilteredSearch);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,20 +11,23 @@ RSpec.describe Gitlab::GitalyClient::ObjectPoolService, feature_category: :sourc
|
|||
subject { described_class.new(object_pool) }
|
||||
|
||||
before do
|
||||
subject.create(raw_repository) # rubocop:disable Rails/SaveBang
|
||||
subject.create(raw_repository) # rubocop:disable Rails/SaveBang -- This is a gitaly call
|
||||
::Gitlab::GitalyClient.clear_stubs!
|
||||
end
|
||||
|
||||
describe '#create' do
|
||||
it 'exists on disk' do
|
||||
expect(object_pool.repository.exists?).to be(true)
|
||||
end
|
||||
it 'sends a create_object_pool message' do
|
||||
expected_request = Gitaly::CreateObjectPoolRequest.new(
|
||||
object_pool: object_pool.gitaly_object_pool,
|
||||
origin: raw_repository.gitaly_repository)
|
||||
|
||||
context 'when the pool already exists' do
|
||||
it 'returns an error' do
|
||||
expect do
|
||||
subject.create(raw_repository) # rubocop:disable Rails/SaveBang
|
||||
end.to raise_error(GRPC::FailedPrecondition)
|
||||
expect_next_instance_of(Gitaly::ObjectPoolService::Stub) do |stub|
|
||||
expect(stub)
|
||||
.to receive(:create_object_pool)
|
||||
.with(expected_request, kind_of(Hash))
|
||||
end
|
||||
|
||||
subject.create(raw_repository) # rubocop:disable Rails/SaveBang -- This is a gitaly call
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,10 @@ RSpec.describe ObjectPool::CreateWorker, feature_category: :shared do
|
|||
pool.create_object_pool
|
||||
end
|
||||
|
||||
it 'cleans up the pool' do
|
||||
expect do
|
||||
subject.perform(pool.id)
|
||||
end.to raise_error(GRPC::FailedPrecondition)
|
||||
it 'marks the pool as ready' do
|
||||
subject.perform(pool.id)
|
||||
|
||||
expect(pool.reload.failed?).to be(true)
|
||||
expect(pool.reload).to be_ready
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -40,7 +38,7 @@ RSpec.describe ObjectPool::CreateWorker, feature_category: :shared do
|
|||
subject.perform(pool.id)
|
||||
end.to raise_error(GRPC::Internal)
|
||||
|
||||
expect(pool.reload.failed?).to be(true)
|
||||
expect(pool.reload).to be_failed
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue