├── .editorconfig
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── feature_request.md
│ └── user-story.md
├── PULL_REQUEST_TEMPLATE.md
├── SauceLabsLogo.png
├── dependabot.yml
├── issue-branch.yml
└── workflows
│ ├── codeql-analysis.yml
│ ├── dependency-review.yml
│ ├── issue-branch.yml
│ ├── java-ci.yml
│ ├── release.yml
│ ├── setup-sauce-connect-tunnels.yml
│ └── upload_my_demo_app.yml
├── .gitignore
├── .gitpod.yml
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── saucelabs
│ │ └── saucerest
│ │ ├── AutomationBackend.java
│ │ ├── DataCenter.java
│ │ ├── ErrorExplainers.java
│ │ ├── HttpMethod.java
│ │ ├── JobSource.java
│ │ ├── JobVisibility.java
│ │ ├── LogEntry.java
│ │ ├── SauceException.java
│ │ ├── SauceREST.java
│ │ ├── SauceShareableLink.java
│ │ ├── TestAsset.java
│ │ ├── Unfinished.java
│ │ ├── api
│ │ ├── AbstractEndpoint.java
│ │ ├── AccountsEndpoint.java
│ │ ├── BuildsEndpoint.java
│ │ ├── HttpClientConfig.java
│ │ ├── InsightsEndpoint.java
│ │ ├── JobsEndpoint.java
│ │ ├── PerformanceEndpoint.java
│ │ ├── PlatformEndpoint.java
│ │ ├── RealDevicesEndpoint.java
│ │ ├── ResponseHandler.java
│ │ ├── SauceConnectEndpoint.java
│ │ └── StorageEndpoint.java
│ │ └── model
│ │ ├── accounts
│ │ ├── Allowed.java
│ │ ├── Concurrency.java
│ │ ├── CreateTeam.java
│ │ ├── CreateUser.java
│ │ ├── Current.java
│ │ ├── Group.java
│ │ ├── Links.java
│ │ ├── LookupTeams.java
│ │ ├── LookupUsers.java
│ │ ├── LookupUsersParameter.java
│ │ ├── Organization.java
│ │ ├── Organizations.java
│ │ ├── ResetAccessKeyForTeam.java
│ │ ├── Result.java
│ │ ├── Role.java
│ │ ├── Roles.java
│ │ ├── SetTeam.java
│ │ ├── Settings.java
│ │ ├── Team.java
│ │ ├── TeamMembers.java
│ │ ├── UpdateTeam.java
│ │ ├── UpdateUser.java
│ │ ├── User.java
│ │ ├── UserConcurrency.java
│ │ └── UsersTeam.java
│ │ ├── builds
│ │ ├── Build.java
│ │ ├── JobInBuild.java
│ │ ├── Jobs.java
│ │ ├── JobsInBuild.java
│ │ ├── LookupBuildsParameters.java
│ │ ├── LookupJobsParameters.java
│ │ ├── Sort.java
│ │ ├── State.java
│ │ └── Status.java
│ │ ├── insights
│ │ ├── Item.java
│ │ ├── Meta.java
│ │ ├── TestResult.java
│ │ └── TestResultParameter.java
│ │ ├── jobs
│ │ ├── BaseConfig.java
│ │ ├── CommandCounts.java
│ │ ├── CustomData.java
│ │ ├── GetJobsParameters.java
│ │ ├── GoogChromeOptions.java
│ │ ├── Job.java
│ │ ├── JobAssets.java
│ │ ├── SauceOptions.java
│ │ └── UpdateJobParameter.java
│ │ ├── platform
│ │ ├── AppiumVersion.java
│ │ ├── EndOfLifeAppiumVersions.java
│ │ ├── Platform.java
│ │ ├── SupportedPlatforms.java
│ │ └── TestStatus.java
│ │ ├── realdevices
│ │ ├── ApplicationSummary.java
│ │ ├── AvailableDevices.java
│ │ ├── BaseConfig.java
│ │ ├── Concurrency.java
│ │ ├── Device.java
│ │ ├── DeviceDescriptor.java
│ │ ├── DeviceJob.java
│ │ ├── DeviceJobs.java
│ │ ├── Entity.java
│ │ ├── MetaData.java
│ │ └── Organization.java
│ │ ├── sauceconnect
│ │ ├── Downloads.java
│ │ ├── Instance.java
│ │ ├── JobsForATunnel.java
│ │ ├── Linux.java
│ │ ├── LinuxArm64.java
│ │ ├── Metadata.java
│ │ ├── Osx.java
│ │ ├── StopTunnel.java
│ │ ├── Tags.java
│ │ ├── TunnelDefault.java
│ │ ├── TunnelInformation.java
│ │ ├── Versions.java
│ │ └── Win32.java
│ │ └── storage
│ │ ├── Access.java
│ │ ├── DeleteAppFile.java
│ │ ├── DeleteAppGroupFiles.java
│ │ ├── EditAppGroupSettings.java
│ │ ├── EditFileDescription.java
│ │ ├── GetAppFiles.java
│ │ ├── GetAppStorageGroupSettings.java
│ │ ├── GetAppStorageGroups.java
│ │ ├── GetAppStorageGroupsParameters.java
│ │ ├── Instrumentation.java
│ │ ├── Item.java
│ │ ├── ItemInteger.java
│ │ ├── Links.java
│ │ ├── Metadata.java
│ │ ├── Owner.java
│ │ ├── Proxy.java
│ │ ├── Recent.java
│ │ ├── Resigning.java
│ │ ├── Settings.java
│ │ ├── StorageParameter.java
│ │ └── UploadFileApp.java
└── resources
│ ├── .properties
│ └── com
│ └── saucelabs
│ └── saucerest
│ └── BuildUtils.template
└── test
├── java
└── com
│ └── saucelabs
│ └── saucerest
│ ├── Helper.java
│ ├── integration
│ ├── AccountsEndpointTest.java
│ ├── BuildsEndpointTest.java
│ ├── InsightsEndpointTest.java
│ ├── JobsEndpointTest.java
│ ├── PlatformEndpointTest.java
│ ├── RealDevicesEndpointTest.java
│ ├── SauceConnectEndpointTest.java
│ ├── StorageEndpointTest.java
│ ├── StorageTestHelper.java
│ └── TeamDeletionHelper.java
│ └── unit
│ ├── AbstractEndpointTest.java
│ ├── AutomationBackendTest.java
│ ├── CreateUserTest.java
│ ├── DataCenterTest.java
│ ├── EditAppGroupSettingsTest.java
│ ├── ErrorExplainerTest.java
│ ├── HelperTest.java
│ ├── HttpMethodTest.java
│ ├── JobSourceTest.java
│ ├── LogEntryTest.java
│ ├── LookupBuildsParametersTest.java
│ ├── ResponseHandlerTest.java
│ ├── SauceConnectEndpointTest.java
│ ├── SauceExceptionTest.java
│ ├── SauceRESTTest.java
│ ├── SauceShareableLinkTest.java
│ ├── StorageEndpointParameterTest.java
│ └── TestAssetTest.java
└── resources
├── AppFiles
├── Android-MyDemoAppNative.apk
├── Android-MyDemoAppRN.apk
├── iOS-Real-Device-MyNativeDemoApp.ipa
├── iOS-Real-Device-MyRNDemoApp.ipa
└── iOS-Simulator-MyRNDemoApp.zip
├── appium-server.log
├── appium.json
├── assets.json
├── buildsResponse.json
├── buildsResponses.json
├── junit-platform.properties
├── sauce-connect-config-apac-southeast.yaml
├── sauce-connect-config-eu-central.yaml
├── sauce-connect-config-us-west.yaml
├── selenium-server.log
├── testfile.txt
├── tunnelsResponse.json
├── user_test.json
└── users_test_concurrency.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | [*]
2 | end_of_line = lf
3 | indent_style = space
4 | indent_size = 2
5 | insert_final_newline = false
6 | trim_trailing_whitespace = true
7 |
8 | [{pom.xml,*.jelly,*.html,*.java}]
9 | indent_size = 4
10 | max_line_length = 160
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## The problem
11 |
12 | Briefly describe the issue you are experiencing (or the feature you want to see added to Appium). Tell us what you were trying to do and what happened instead. Remember, this is _not_ a place to ask questions.
13 |
14 | ## Environment
15 |
16 | * Java JDK version that exhibits the issue:
17 | * saucerest-java version that exhibits the issue:
18 | * Operating System / version that exhibits the issue:
19 | * Last configuration (Java, saucerest-java, OS, OS version) that did not exhibit the issue (if applicable):
20 |
21 | ## Details
22 |
23 | If necessary, describe the problem you have been experiencing in more detail.
24 |
25 | ## Link to logs
26 |
27 | If your log files are really long consider creating a [GIST](https://gist.github.com) which is a paste of your _full_ logs, and link them here. Otherwise this report will be long and hard to read.
28 |
29 | ## Code To Reproduce Issue [ Good To Have ]
30 |
31 | Please remember that with sample code it's easier to reproduce the bug and it's much faster to fix it.
32 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/user-story.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: User story
3 | about: Template for intrinsic changes from Sauce Labs employees
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 |
11 |
12 | ## Description
13 |
14 |
15 |
16 | ## Motivation and Context
17 |
18 |
19 |
20 | ## Further comments
21 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Description
4 |
5 |
6 | ## Motivation and Context
7 |
8 |
9 |
10 | ## How Has This Been Tested?
11 |
12 |
13 |
14 |
15 | ## Types of changes
16 |
17 |
18 |
19 | - [ ] Bugfix (non-breaking change which fixes an issue)
20 | - [ ] New feature (non-breaking change which adds functionality)
21 | - [ ] Refactoring (change which improves current code base; please describe the change)
22 | - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected)
23 | - [ ] Documentation Update (if none of the other choices apply)
24 |
25 | ## Screenshots (if appropriate):
26 |
27 | ## Checklist
28 |
29 |
30 |
31 |
32 | - [ ] I have read the [CONTRIBUTING](https://github.com/saucelabs/saucerest-java/blob/master/CONTRIBUTING.md) doc
33 | - [ ] I have added tests that prove my fix is effective or that my feature works
34 | - [ ] All new and existing tests passed locally
35 | - [ ] I have added necessary documentation (if appropriate)
36 |
37 | ## Further comments
38 |
39 | If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc...
40 |
--------------------------------------------------------------------------------
/.github/SauceLabsLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/saucelabs/saucerest-java/04a21b292d74e2bdb4953b7664d7f895e8fa4979/.github/SauceLabsLogo.png
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: "maven"
4 | directory: "/"
5 | schedule:
6 | interval: "daily"
7 |
8 | - package-ecosystem: "github-actions"
9 | directory: "/"
10 | schedule:
11 | interval: "daily"
--------------------------------------------------------------------------------
/.github/issue-branch.yml:
--------------------------------------------------------------------------------
1 | gitSafeReplacementChar: '-'
2 | branchName: '${issue.number}-${issue.title}'
3 | defaultBranch: 'master'
4 | branches:
5 | - label: enhancement
6 | prefix: enhancement/
7 | - label: feature_request
8 | prefix: feature/
9 | - label: bug
10 | prefix: bugfix/
11 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | name: "Code Scanning - Action"
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | types: [ opened, reopened, synchronize ]
8 | schedule:
9 | # Run daily at 00:00
10 | - cron: '0 0 * * *'
11 |
12 | jobs:
13 | CodeQL-Build:
14 | runs-on: ubuntu-latest
15 |
16 | steps:
17 | - name: Checkout repository
18 | uses: actions/checkout@v4
19 | - name: Set up JDK 20
20 | uses: actions/setup-java@v4
21 | with:
22 | java-version: '20'
23 | distribution: 'temurin'
24 |
25 | - name: Initialize CodeQL
26 | uses: github/codeql-action/init@v3
27 | with:
28 | languages: java
29 |
30 | - name: Autobuild
31 | uses: github/codeql-action/autobuild@v3
32 |
33 | - name: Perform CodeQL Analysis
34 | uses: github/codeql-action/analyze@v3
35 |
--------------------------------------------------------------------------------
/.github/workflows/dependency-review.yml:
--------------------------------------------------------------------------------
1 | # Dependency Review Action
2 | #
3 | # This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.
4 | #
5 | # Source repository: https://github.com/actions/dependency-review-action
6 | # Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
7 | name: 'Dependency Review'
8 | on:
9 | push:
10 | branches: [ main ]
11 | pull_request:
12 | types: [ opened, reopened, synchronize ]
13 | schedule:
14 | # Run daily at 00:00
15 | - cron: '0 0 * * *'
16 |
17 | permissions:
18 | contents: read
19 |
20 | jobs:
21 | dependency-review:
22 | runs-on: ubuntu-latest
23 | steps:
24 | - name: 'Checkout Repository'
25 | uses: actions/checkout@v4
26 | - name: 'Dependency Review'
27 | uses: actions/dependency-review-action@v4
28 | with:
29 | base-ref: ${{ github.event.pull_request.base.sha || 'main' }}
30 | head-ref: ${{ github.event.pull_request.head.sha || github.ref }}
31 |
--------------------------------------------------------------------------------
/.github/workflows/issue-branch.yml:
--------------------------------------------------------------------------------
1 | name: Create Issue Branch
2 | on:
3 | issues:
4 | types: [assigned]
5 | issue_comment:
6 | types: [created]
7 |
8 | jobs:
9 | create_issue_branch_job:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: Create Issue Branch
13 | id: Create_Issue_Branch
14 | uses: robvanderleek/create-issue-branch@main
15 | env:
16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17 | - name: Echo branch name
18 | run: echo ${{ steps.Create_Issue_Branch.outputs.branchName }}
19 |
--------------------------------------------------------------------------------
/.github/workflows/java-ci.yml:
--------------------------------------------------------------------------------
1 | name: Java CI
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | types: [ opened, reopened, synchronize ]
8 | workflow_dispatch:
9 | schedule:
10 | # Run every 6 hours at minute 0: 06:00, 12:00, 18:00, 00:00
11 | - cron: '0 6,12,18,0 * * *'
12 |
13 | concurrency:
14 | group: ${{ github.workflow }}
15 |
16 | permissions:
17 | contents: write
18 |
19 | env:
20 | SAUCE_USERNAME: ${{secrets.SAUCE_USERNAME}}
21 | SAUCE_ACCESS_KEY: ${{secrets.SAUCE_ACCESS_KEY}}
22 |
23 | jobs:
24 |
25 | unit_tests_job:
26 | name: Unit Tests
27 | runs-on: ubuntu-latest
28 |
29 | steps:
30 | - uses: actions/checkout@v4
31 | - name: Set up JDK 21
32 | uses: actions/setup-java@v4
33 | with:
34 | java-version: '21'
35 | distribution: 'temurin'
36 | cache: 'maven'
37 | - name: Build with Maven
38 | run: mvn clean test -Dtest="com.saucelabs.saucerest.unit.**" -Dgpg.skip -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -V
39 | - name: Upload JaCoCo report to Codecov
40 | uses: codecov/codecov-action@v5
41 | with:
42 | flags: unittests,tests
43 |
44 | upload_apps_job:
45 | name: Upload My Demo Apps
46 | # Only proceed if unit tests pass
47 | needs: unit_tests_job
48 | uses: ./.github/workflows/upload_my_demo_app.yml
49 | secrets: inherit
50 |
51 | integration_tests_job:
52 | name: Integration Tests
53 | needs: [ unit_tests_job, upload_apps_job ]
54 | runs-on: ubuntu-latest
55 |
56 | steps:
57 | - name: Set env var for Integration Tests
58 | # Only run integration tests if the code is coming from this repo and not forks
59 | if: ${{ github.repository == github.event.pull_request.head.repo.full_name }} || ${{ github.event.push.head.repo.full_name == github.repository }}
60 | run: |
61 | echo "NOT_FROM_FORK=true" >> $GITHUB_ENV
62 |
63 | - name: Print env var
64 | run: |
65 | echo "NOT_FROM_FORK: ${{ env.NOT_FROM_FORK }}"
66 |
67 | - uses: actions/checkout@v4
68 | if: ${{ env.NOT_FROM_FORK }} == 'true'
69 |
70 | - name: Set up JDK 21
71 | uses: actions/setup-java@v4
72 | if: ${{ env.NOT_FROM_FORK }} == 'true'
73 | with:
74 | java-version: '21'
75 | distribution: 'temurin'
76 | cache: 'maven'
77 |
78 | - name: Setup Sauce Connect US-West
79 | uses: saucelabs/sauce-connect-action@v2
80 | with:
81 | username: ${{ secrets.SAUCE_USERNAME }}
82 | accessKey: ${{ secrets.SAUCE_ACCESS_KEY }}
83 | tunnelName: github-action-tunnel-us-west
84 | configFile: ${{ github.workspace }}/src/test/resources/sauce-connect-config-us-west.yaml
85 |
86 | - name: Setup Sauce Connect EU-Central
87 | uses: saucelabs/sauce-connect-action@v2
88 | with:
89 | username: ${{ secrets.SAUCE_USERNAME }}
90 | accessKey: ${{ secrets.SAUCE_ACCESS_KEY }}
91 | tunnelName: github-action-tunnel-eu-central
92 | configFile: ${{ github.workspace }}/src/test/resources/sauce-connect-config-eu-central.yaml
93 |
94 | - name: Build and Run Integration Tests
95 | if: ${{ env.NOT_FROM_FORK }} == 'true'
96 | uses: nick-invision/retry@v3.0.0
97 | with:
98 | timeout_minutes: 20
99 | max_attempts: 3
100 | command: |
101 | mvn clean test -Dtest="com.saucelabs.saucerest.integration.**" -Dgpg.skip -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -Dsurefire.rerunFailingTestsCount=2 -V
102 |
103 | - name: Upload JaCoCo report to Codecov
104 | uses: codecov/codecov-action@v5
105 | with:
106 | flags: integrationtests,tests
107 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release to Maven Central
2 |
3 | on:
4 | workflow_dispatch:
5 | inputs:
6 | releaseversion:
7 | description: 'Release version'
8 | required: true
9 | default: '2.1.0'
10 |
11 | permissions:
12 | contents: write
13 |
14 | env:
15 | SAUCE_USERNAME: ${{secrets.SAUCE_USERNAME}}
16 | SAUCE_ACCESS_KEY: ${{secrets.SAUCE_ACCESS_KEY}}
17 |
18 | jobs:
19 | publish:
20 | runs-on: ubuntu-latest
21 | steps:
22 | - run: echo "Will start a Maven Central upload with version ${{ github.event.inputs.releaseversion }}"
23 | - uses: actions/checkout@v4
24 |
25 | - name: Set up Maven Central Repository
26 | uses: actions/setup-java@v4
27 | with:
28 | java-version: '20'
29 | distribution: 'temurin'
30 | cache: 'maven'
31 | server-id: ossrh
32 | server-username: MAVEN_USERNAME
33 | server-password: MAVEN_PASSWORD
34 | gpg-private-key: ${{ secrets.OSSRH_GPG_SECRET_KEY }} # Value of the GPG private key to import
35 | gpg-passphrase: MAVEN_GPG_PASSPHRASE # env variable for GPG private key passphrase
36 |
37 | - name: Setup Sauce Connect US-West
38 | uses: saucelabs/sauce-connect-action@v2
39 | with:
40 | username: ${{ secrets.SAUCE_USERNAME }}
41 | accessKey: ${{ secrets.SAUCE_ACCESS_KEY }}
42 | tunnelName: github-action-tunnel-us-west
43 | configFile: ${{ github.workspace }}/src/test/resources/sauce-connect-config-us-west.yaml
44 |
45 | - name: Setup Sauce Connect EU-Central
46 | uses: saucelabs/sauce-connect-action@v2
47 | with:
48 | username: ${{ secrets.SAUCE_USERNAME }}
49 | accessKey: ${{ secrets.SAUCE_ACCESS_KEY }}
50 | tunnelName: github-action-tunnel-eu-central
51 | configFile: ${{ github.workspace }}/src/test/resources/sauce-connect-config-eu-central.yaml
52 |
53 | - name: Build with Maven
54 | run: mvn clean install -Dgpg.skip -B -Dorg.slf4j.simpleLogger.log.org.apache.maven.cli.transfer.Slf4jMavenTransferListener=warn -V
55 |
56 | - name: Upload JaCoCo report to Codecov
57 | uses: codecov/codecov-action@v5
58 | with:
59 | flags: tests,release
60 |
61 | - name: Set projects Maven version to GitHub Action GUI set version
62 | run: mvn versions:set "-DnewVersion=${{ github.event.inputs.releaseversion }}" -DgenerateBackupPoms=false -B --no-transfer-progress
63 |
64 | - name: Publish package
65 | run: mvn -B --no-transfer-progress clean deploy -DskipTests=true
66 | env:
67 | MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }}
68 | MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }}
69 | MAVEN_GPG_PASSPHRASE: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }}
70 |
71 | - name: Generate changelog
72 | id: changelog
73 | uses: metcalfc/changelog-generator@v4.3.1
74 | with:
75 | myToken: ${{ secrets.GITHUB_TOKEN }}
76 |
77 | - name: Create GitHub Release
78 | id: create_release
79 | uses: actions/create-release@v1
80 | env:
81 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
82 | with:
83 | tag_name: ${{ github.event.inputs.releaseversion }}
84 | release_name: ${{ github.event.inputs.releaseversion }}
85 | body: |
86 | ```
87 |
88 |
89 | com.saucelabs
90 | saucerest
91 | ${{ github.event.inputs.releaseversion }}
92 |
93 |
94 | ```
95 | ### Changelog
96 | ${{ steps.changelog.outputs.changelog }}
97 | draft: false
98 | prerelease: false
--------------------------------------------------------------------------------
/.github/workflows/setup-sauce-connect-tunnels.yml:
--------------------------------------------------------------------------------
1 | name: Setup Sauce Connect Tunnels
2 |
3 | on:
4 | workflow_call:
5 |
6 | env:
7 | SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
8 | SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
9 |
10 | jobs:
11 | setup_sauce_connect_tunnels:
12 | name: Setup Sauce Connect Tunnels
13 | runs-on: ubuntu-latest
14 | steps:
15 | - name: Checkout code
16 | uses: actions/checkout@v4
17 |
18 | - name: Setup Sauce Connect US-West
19 | uses: saucelabs/sauce-connect-action@v2
20 | with:
21 | username: ${{ secrets.SAUCE_USERNAME }}
22 | accessKey: ${{ secrets.SAUCE_ACCESS_KEY }}
23 | tunnelName: github-action-tunnel-us-west
24 | configFile: ${{ github.workspace }}/src/test/resources/sauce-connect-config-us-west.yaml
25 |
26 | - name: Setup Sauce Connect EU-Central
27 | uses: saucelabs/sauce-connect-action@v2
28 | with:
29 | username: ${{ secrets.SAUCE_USERNAME }}
30 | accessKey: ${{ secrets.SAUCE_ACCESS_KEY }}
31 | tunnelName: github-action-tunnel-eu-central
32 | configFile: ${{ github.workspace }}/src/test/resources/sauce-connect-config-eu-central.yaml
--------------------------------------------------------------------------------
/.github/workflows/upload_my_demo_app.yml:
--------------------------------------------------------------------------------
1 | name: Upload My Demo App monthly
2 |
3 | on:
4 | workflow_call:
5 | workflow_dispatch:
6 | schedule:
7 | - cron: '0 5 */30 * *'
8 |
9 | env:
10 | SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
11 | SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
12 |
13 | jobs:
14 | download_upload_apk_eu:
15 | name: Upload My Demo App apk to EU
16 | runs-on: ubuntu-latest
17 | steps:
18 | - name: Download My Demo App apk
19 | uses: wei/curl@v1.1.1
20 | with:
21 | args: -L -o Android-MyDemoAppRN.apk https://github.com/saucelabs/my-demo-app-rn/releases/download/v1.3.0/Android-MyDemoAppRN.1.3.0.build-244.apk
22 | - name: Upload My Demo App apk
23 | uses: wei/curl@v1.1.1
24 | with:
25 | args: -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" --location --request POST 'https://api.eu-central-1.saucelabs.com/v1/storage/upload' --form 'payload=@"Android-MyDemoAppRN.apk"' --form 'name="Android-MyDemoAppRN.apk"'
26 |
27 | download_upload_zip_eu:
28 | name: Upload My Demo App zip to EU
29 | runs-on: ubuntu-latest
30 | steps:
31 | - name: Download My Demo App zip
32 | uses: wei/curl@v1.1.1
33 | with:
34 | args: -L -o iOS-Simulator-MyRNDemoApp.zip https://github.com/saucelabs/my-demo-app-rn/releases/download/v1.3.0/iOS-Simulator-MyRNDemoApp.1.3.0-162.zip
35 | - name: Upload My Demo App zip
36 | uses: wei/curl@v1.1.1
37 | with:
38 | args: -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" --location --request POST 'https://api.eu-central-1.saucelabs.com/v1/storage/upload' --form 'payload=@"iOS-Simulator-MyRNDemoApp.zip"' --form 'name="iOS-Simulator-MyRNDemoApp.zip"'
39 |
40 | download_upload_ipa_eu:
41 | name: Upload My Demo App ipa to EU
42 | runs-on: ubuntu-latest
43 | steps:
44 | - name: Download My Demo App ipa
45 | uses: wei/curl@v1.1.1
46 | with:
47 | args: -L -o iOS-Real-Device-MyRNDemoApp.ipa https://github.com/saucelabs/my-demo-app-rn/releases/download/v1.3.0/iOS-Real-Device-MyRNDemoApp.1.3.0-162.ipa
48 | - name: Upload My Demo App ipa
49 | uses: wei/curl@v1.1.1
50 | with:
51 | args: -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" --location --request POST 'https://api.eu-central-1.saucelabs.com/v1/storage/upload' --form 'payload=@"iOS-Real-Device-MyRNDemoApp.ipa"' --form 'name="iOS-Real-Device-MyRNDemoApp.ipa"'
52 |
53 | download_upload_apk_us:
54 | name: Upload My Demo App apk to US
55 | runs-on: ubuntu-latest
56 | steps:
57 | - name: Download My Demo App apk
58 | uses: wei/curl@v1.1.1
59 | with:
60 | args: -L -o Android-MyDemoAppRN.apk https://github.com/saucelabs/my-demo-app-rn/releases/download/v1.3.0/Android-MyDemoAppRN.1.3.0.build-244.apk
61 | - name: Upload My Demo App apk
62 | uses: wei/curl@v1.1.1
63 | with:
64 | args: -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" --location --request POST 'https://api.us-west-1.saucelabs.com/v1/storage/upload' --form 'payload=@"Android-MyDemoAppRN.apk"' --form 'name="Android-MyDemoAppRN.apk"'
65 |
66 | download_upload_zip_us:
67 | name: Upload My Demo App zip to US
68 | runs-on: ubuntu-latest
69 | steps:
70 | - name: Download My Demo App zip
71 | uses: wei/curl@v1.1.1
72 | with:
73 | args: -L -o iOS-Simulator-MyRNDemoApp.zip https://github.com/saucelabs/my-demo-app-rn/releases/download/v1.3.0/iOS-Simulator-MyRNDemoApp.1.3.0-162.zip
74 | - name: Upload My Demo App zip
75 | uses: wei/curl@v1.1.1
76 | with:
77 | args: -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" --location --request POST 'https://api.us-west-1.saucelabs.com/v1/storage/upload' --form 'payload=@"iOS-Simulator-MyRNDemoApp.zip"' --form 'name="iOS-Simulator-MyRNDemoApp.zip"'
78 |
79 | download_upload_ipa_us:
80 | name: Upload My Demo App ipa to US
81 | runs-on: ubuntu-latest
82 | steps:
83 | - name: Download My Demo App ipa
84 | uses: wei/curl@v1.1.1
85 | with:
86 | args: -L -o iOS-Real-Device-MyRNDemoApp.ipa https://github.com/saucelabs/my-demo-app-rn/releases/download/v1.3.0/iOS-Real-Device-MyRNDemoApp.1.3.0-162.ipa
87 | - name: Upload My Demo App ipa
88 | uses: wei/curl@v1.1.1
89 | with:
90 | args: -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" --location --request POST 'https://api.us-west-1.saucelabs.com/v1/storage/upload' --form 'payload=@"iOS-Real-Device-MyRNDemoApp.ipa"' --form 'name="iOS-Real-Device-MyRNDemoApp.ipa"'
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | bin
2 | dist
3 | src/*.class
4 | target
5 |
6 | .idea/*
7 |
8 | .DS_Store
9 |
10 | .settings
11 | .classpath
12 | .project
13 |
14 | saucerest.iml
15 | atlassian-ide-plugin.xml
16 | src/main/java/com/saucelabs/saucerest/BuildUtils.java
17 |
--------------------------------------------------------------------------------
/.gitpod.yml:
--------------------------------------------------------------------------------
1 | # This configuration file was automatically generated by Gitpod.
2 | # Please adjust to your needs (see https://www.gitpod.io/docs/config-gitpod-file)
3 | # and commit this file to your remote git repository to share the goodness with others.
4 |
5 | github:
6 | prebuilds:
7 | master: true
8 | branches: true
9 | pullRequests: true
10 | pullRequestsFromForks: true
11 | addCheck: true
12 | addBadge: true
13 |
14 | vscode:
15 | extensions:
16 | - redhat.java
17 | - vscjava.vscode-java-debug
18 | - vscjava.vscode-java-pack
19 | - vscjava.vscode-maven
20 | - vscjava.vscode-java-dependency
21 | - vscjava.vscode-java-test
22 |
23 | tasks:
24 | - name: Install Java8
25 | init: |
26 | yes | sdk install java 8.0.345-tem
27 | sdk use java 8.0.345-tem
28 | gp sync-done java8install
29 |
30 | - name: Install Dependencies
31 | init: |
32 | gp sync-await java8install # Wait for Java to be installed before building
33 | mvn dependency:resolve
34 | gp sync-done dependencies
35 |
36 | - name: Build Code
37 | before: mvn clean
38 | init: |
39 | gp sync-await dependencies # Wait for Java to be installed before building
40 | mvn compile -DskipTests=true
41 | command: mvn test
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Thank You!
2 | We appreciate contributions from the community, helping to make this library better for everyone who uses it.
3 |
4 | # Developing new features and fixing bugs
5 | ## Step 1. Get You A Copy
6 | 1. Fork this repository
7 | 2. Clone your fork to your local machine
8 | 3. (Optional but helpful) Create a branch for your changes with `git checkout -b branchname`. Make your branchname short but descriptive, eg `add_contribution_doc`
9 |
10 | ## Step 2. Set up your environment
11 | 1. Make sure you've a JDK installed, along with Maven, and all the appropriate ENV Vars set
12 |
13 | ## Step 3. Make your changes
14 | 1. Code Changes should be accompanied by documentation (if new features) and tests
15 | 2. Run the JUnit tests with `mvn test` if appropriate
16 | 3. Once they all pass, you're gold!
17 |
18 | ## Step 4. Commit
19 | 1. List changed files with `git status`
20 | 2. Add relevant changed files to your commit with `git add filename`
21 | 3. Start your commit with `git commit`
22 | 4. Write a good commit message. Good messages have a short title describing what changed, as well as a longer message summarising the changes with any context required. If fixing a lodged issue, mention this in the title
23 | 5. Try to commit atomic bug fixes or features, or at least a related set of features
24 |
25 | ## Step 5. Send a Pull Request
26 | 1. `git push` to send your commands back to Github
27 | 2. Visit your repo on Github and click then `Pull Request` button
28 | 3. If required, fill in a PR request. Treat it like a commit message; A short title describing what changed, as well as a longer message summarising changes with any context required. If fixing a lodged issue, include this in the title
29 | 4. Send the Pull Request
30 |
31 | # Using a locally build version for Development or to resolve a bug
32 | We highly encourage users to send PRs and updates that the community might find useful. However, you might want to use a personal release if you're waiting for fixes to be built into a release, to test complicated behaviour, or for company-specific changes.
33 |
34 | One way of doing this is to take a copy of the source and install it locally by doing
35 | `mvn install`
36 | from the repository root.
37 |
38 | You can then update the pom file for your target project so that you're checking out your build version:
39 |
40 | ```
41 |
42 |
43 | com.saucelabs
44 | saucerest
45 | 1.0.38-SNAPSHOT
46 |
47 |
48 | ```
49 |
50 | Get the value of the VERSION from the version key in the saucerest-java pom file. ATM it's on line 6: `1.0.38-SNAPSHOT`.
51 |
52 | You may need to give it a custom version.
53 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Sauce Labs
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | saucerest-java
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | A Java client for Sauce Labs REST API.
26 |
27 | Currently, this client only support the endpoints listed [here](https://docs.saucelabs.com/dev/api/).
28 |
29 | With version 2.x of SauceREST we have made code-breaking changes to this wrapper. It has been updated to be more
30 | future-proof and to also support the newest APIs from Sauce Labs.
31 |
32 | This is going to be continuous process which means we will release changes to SauceREST over time.
33 |
34 | If a function you're after isn't supported, we suggest either shelling out and using the curl version, _or_ sending a pull
35 | request! [Contribution Details Here](https://github.com/saucelabs/saucerest-java/blob/master/CONTRIBUTING.md).
36 |
37 |
38 |
39 | # How to use
40 |
41 |
42 | Creating a client object
43 |
44 | ```java
45 | SauceREST sauceREST = new SauceREST("username", "access-key", DataCenter.EU_CENTRAL);
46 | ```
47 |
48 |
49 |
50 | Parameters:
51 |
52 | | Name | Type | Details |
53 | |-------------|---------------------------------|--------------------------------|
54 | | username | String (required) | Your sauce labs username |
55 | | access-key | String (required) | Your sauce labs accesskey |
56 | | data_center | String or DataCenter (required) | One of `US_WEST`, `EU_CENTRAL` |
57 |
58 | ## Code examples
59 |
60 | The best way to find out how to use this library is to look at the tests. They are located in the `src/test/java` directory. Especially the integration tests
61 | will provide you with a good overview of how to use this library.
62 |
63 | # Maven
64 |
65 | ```xml
66 |
67 |
68 |
69 | com.saucelabs
70 | saucerest
71 | LATEST VERSION
72 | test
73 |
74 |
75 | ```
76 |
77 | For latest version please check the following link: [click](https://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22com.saucelabs%22%20AND%20a%3A%22saucerest%22).
78 |
79 | ## Contributing
80 |
81 | Check out our contribution guide [here](CONTRIBUTING.md) for details.
82 |
83 | Want a fast, setup dev
84 | environment? [](https://gitpod.io/#https://github.com/saucelabs/saucerest-java)
85 |
86 |
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/AutomationBackend.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest;
2 |
3 | public enum AutomationBackend {
4 | APPIUM("appium"),
5 | WEBDRIVER("webdriver");
6 |
7 | public final String label;
8 |
9 | AutomationBackend(String label) {
10 | this.label = label;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/DataCenter.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest;
2 |
3 | import java.util.stream.Stream;
4 |
5 | public enum DataCenter {
6 | US_WEST("https://saucelabs.com/", "https://api.us-west-1.saucelabs.com/", "https://app.saucelabs.com/"),
7 | EU_CENTRAL("https://eu-central-1.saucelabs.com/", "https://api.eu-central-1.saucelabs.com/", "https://app.eu-central-1.saucelabs.com/");
8 |
9 | public final String server;
10 | public final String apiServer;
11 | public final String appServer;
12 |
13 | DataCenter(String server, String apiServer, String appServer) {
14 | this.server = server;
15 | this.apiServer = apiServer;
16 | this.appServer = appServer;
17 | }
18 |
19 | public String server() {
20 | return server;
21 | }
22 |
23 | public String apiServer() {
24 | return apiServer;
25 | }
26 |
27 | public String edsServer() {
28 | return apiServer + "v1/eds/";
29 | }
30 |
31 | public String appServer() {
32 | return appServer;
33 | }
34 |
35 | public static DataCenter fromString(String dataCenter) {
36 | return Stream.of(values()).filter(dc -> dc.name().equalsIgnoreCase(dataCenter)).findFirst().orElse(null);
37 | }
38 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/HttpMethod.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest;
2 |
3 | public enum HttpMethod {
4 | GET("GET"),
5 | POST("POST"),
6 | PUT("PUT"),
7 | DELETE("DELETE"),
8 | PATCH("PATCH"),
9 | HEAD("HEAD"),
10 | OPTIONS("OPTIONS");
11 |
12 | public final String label;
13 |
14 | HttpMethod(String label) {
15 | this.label = label;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/JobSource.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest;
2 |
3 | public enum JobSource {
4 | RDC("rdc"),
5 | VDC("vdc");
6 |
7 | public final String value;
8 |
9 | JobSource(String value) {
10 | this.value = value;
11 | }
12 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/JobVisibility.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | public enum JobVisibility {
6 | @SerializedName("public")
7 | PUBLIC,
8 | @SerializedName("public restricted")
9 | PUBLIC_RESTRICTED,
10 | @SerializedName("share")
11 | SHARE,
12 | @SerializedName("team")
13 | TEAM,
14 | @SerializedName("private")
15 | PRIVATE
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/LogEntry.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest;
2 |
3 | public class LogEntry {
4 | private final String timestamp;
5 | private final String level;
6 | private final String message;
7 |
8 | public LogEntry(String time, String level, String message) {
9 | this.timestamp = time;
10 | this.level = level;
11 | this.message = message;
12 | }
13 |
14 | public String getTime() {
15 | return timestamp;
16 | }
17 |
18 | public String getLevel() {
19 | return level;
20 | }
21 |
22 | public String getMessage() {
23 | return message;
24 | }
25 |
26 | @Override
27 | public String toString() {
28 | return String.format("%s %s %s", timestamp, level, message);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/SauceException.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest;
2 | /*
3 | * TODO: 2020-02-27 Lets have all these take a message, yeah?
4 | * TODO: 2020-02-27 And also, we should make these IOExceptions, not Runtime.
5 | */
6 |
7 | /**
8 | * Created by gavinmogan on 2015-11-02.
9 | */
10 | public class SauceException extends RuntimeException {
11 | /**
12 | * Created by gavinmogan on 2015-11-02.
13 | * {@inheritDoc}
14 | */
15 | public SauceException(String message) {
16 | super(message);
17 | }
18 |
19 | /**
20 | * Default case.
21 | */
22 | public SauceException() {
23 | }
24 |
25 | public static class UnknownError extends SauceException {
26 |
27 | public UnknownError(String message) {
28 | super(message);
29 | }
30 |
31 | public UnknownError() {
32 | }
33 | }
34 |
35 | public static class NotAuthorized extends SauceException {
36 |
37 | public NotAuthorized(String message) {
38 | super(message);
39 | }
40 |
41 | public NotAuthorized() {
42 | }
43 | }
44 |
45 | public static class NotFound extends SauceException {
46 |
47 | public NotFound(String message) {
48 | super(message);
49 | }
50 |
51 | public NotFound() {
52 | }
53 | }
54 |
55 | public static class TooManyRequests extends SauceException {
56 | }
57 |
58 | public static class NotYetDone extends SauceException {
59 | public NotYetDone(String message) {
60 | super(message);
61 | }
62 |
63 | public NotYetDone() {
64 | }
65 | }
66 |
67 | public static class ResigningNotAllowed extends SauceException {
68 | public ResigningNotAllowed(String message) {
69 | super(message);
70 | }
71 |
72 | public ResigningNotAllowed() {
73 | }
74 | }
75 |
76 | public static class InstrumentationNotAllowed extends SauceException {
77 | public InstrumentationNotAllowed(String message) {
78 | super(message);
79 | }
80 |
81 | public InstrumentationNotAllowed() {
82 | }
83 | }
84 |
85 | public static class DeviceLockOnlyOnAndroid extends SauceException {
86 | public DeviceLockOnlyOnAndroid(String message) {
87 | super(message);
88 | }
89 |
90 | public DeviceLockOnlyOnAndroid() {
91 | }
92 | }
93 |
94 | public static class MissingCredentials extends SauceException {
95 | public MissingCredentials(String message) {
96 | super(message);
97 | }
98 |
99 | public MissingCredentials() {
100 | }
101 | }
102 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/SauceShareableLink.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest;
2 |
3 | import java.nio.charset.StandardCharsets;
4 | import java.security.InvalidKeyException;
5 | import java.security.NoSuchAlgorithmException;
6 | import java.util.Formatter;
7 | import javax.crypto.Mac;
8 | import javax.crypto.spec.SecretKeySpec;
9 |
10 | /**
11 | * Class providing a method to create a shareable test results link of a test executed on Sauce Labs.
12 | */
13 | public class SauceShareableLink {
14 | private SauceShareableLink() {
15 | throw new IllegalStateException("Utility class");
16 | }
17 |
18 | public static String getJobAuthDigest(String username, String accessKey, String sauceJobId) {
19 | try {
20 | String key = String.format("%s:%s", username, accessKey);
21 | SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.US_ASCII), "HmacMD5");
22 | Mac mac = Mac.getInstance("HmacMD5");
23 | mac.init(secretKeySpec);
24 | byte[] result = mac.doFinal(sauceJobId.getBytes(StandardCharsets.US_ASCII));
25 | return bytesToHex(result).toLowerCase();
26 | } catch (NoSuchAlgorithmException | InvalidKeyException e) {
27 | throw new IllegalStateException("Error calculating job auth digest", e);
28 | }
29 | }
30 |
31 | private static String bytesToHex(byte[] bytes) {
32 | StringBuilder hexStringBuilder = new StringBuilder();
33 | Formatter formatter = new Formatter(hexStringBuilder);
34 | for (byte b : bytes) {
35 | formatter.format("%02x", b);
36 | }
37 | return hexStringBuilder.toString();
38 | }
39 |
40 | /**
41 | * This method will use username and access key from the environment variables SAUCE_USERNAME and SAUCE_ACCESS_KEY.
42 | *
43 | * @param sauceJobId Sauce Labs job id
44 | * @param dataCenter Sauce Labs data center endpoint
45 | * @return A url of the test result with an authentication token, so it can be accessed without Sauce Labs credentials.
46 | */
47 | public static String getShareableLink(String sauceJobId, DataCenter dataCenter) {
48 | return getShareableLink(null, null, sauceJobId, dataCenter);
49 | }
50 |
51 | /**
52 | * Based on the code from here
53 | *
54 | * @param username Sauce Labs username
55 | * @param accessKey Sauce Labs access key
56 | * @param sauceJobId Sauce Labs job id
57 | * @param dataCenter Sauce Labs data center endpoint
58 | * @return A url of the test result with an authentication token, so it can be accessed without Sauce Labs credentials.
59 | */
60 | public static String getShareableLink(String username, String accessKey, String sauceJobId, DataCenter dataCenter) {
61 | String defaultUsername = System.getenv("SAUCE_USERNAME");
62 | String defaultAccessKey = System.getenv("SAUCE_ACCESS_KEY");
63 |
64 | if (username == null || username.isEmpty()) {
65 | if (defaultUsername == null || defaultUsername.isEmpty()) {
66 | throw new IllegalArgumentException("Sauce Labs username cannot be null or empty");
67 | } else {
68 | username = defaultUsername;
69 | }
70 | }
71 |
72 | if (accessKey == null || accessKey.isEmpty()) {
73 | if (defaultAccessKey == null || defaultAccessKey.isEmpty()) {
74 | throw new IllegalArgumentException("Sauce Labs access key cannot be null or empty");
75 | } else {
76 | accessKey = defaultAccessKey;
77 | }
78 | }
79 |
80 | if (sauceJobId == null || sauceJobId.isEmpty()) {
81 | throw new IllegalArgumentException("Sauce Labs job ID cannot be null or empty");
82 | }
83 |
84 | if (dataCenter == null) {
85 | throw new IllegalArgumentException("Sauce Labs data center endpoint cannot be null");
86 | }
87 |
88 | String digest = getJobAuthDigest(username, accessKey, sauceJobId);
89 | return dataCenter.appServer + "tests/" + sauceJobId + "?auth=" + digest;
90 | }
91 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/TestAsset.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest;
2 |
3 | import java.util.Arrays;
4 | import java.util.Optional;
5 |
6 | /**
7 | * The Sauce Labs test assets do not have consistent names, labels and JSON keys/values. There is a difference
8 | * between the displayed filename in the UI, the JSON key in a HTTP response and its value.
9 | * This enum aims to combine all of these into a single place.
10 | * The enums themselves are named after what makes the most sense and what describes the test asset the best.
11 | * The label is the displayed filename in the UI.
12 | * The jsonKey is the JSON key that is used in the HTTP response and is mapped against
13 | * {@link com.saucelabs.saucerest.model.realdevices.DeviceJob} and {@link com.saucelabs.saucerest.model.jobs.JobAssets}.
14 | */
15 | public enum TestAsset {
16 | SAUCE_LOG("log.json", "sauce-log"),
17 | VIDEO("video.mp4", "video_url"),
18 | SELENIUM_LOG("selenium-server.log", "log_url"),
19 | AUTOMATOR_LOG("automator.log", "automator.log"),
20 | LOGCAT_LOG("logcat.log", "logcat.log"),
21 | SYSLOG_LOG("ios-syslog.log", "ios-syslog.log"),
22 | HAR("network.har", "network_log_url"),
23 | PERFORMANCE("performance.json", "performance.json"),
24 | CONSOLE_LOG("console.json", "console.json"),
25 | // no JSON key because it's from the /asset/screenshots.zip endpoint
26 | SCREENSHOTS("screenshots.zip", null),
27 | APPIUM_LOG("appium-server.log", "framework_log_url"),
28 | INSIGHTS_LOG("insights.json", "testfairy_log_url"),
29 | CRASH_LOG("crash.json", "crash_log_url"),
30 | DEVICE_LOG("device.log", "device_log_url"),
31 | COMMANDS_LOG("commands.json", "requests_url");
32 |
33 | public final String label;
34 | public final String jsonKey;
35 |
36 | TestAsset(String label, String jsonKey) {
37 | this.label = label;
38 | this.jsonKey = jsonKey;
39 | }
40 |
41 | public static Optional get(String label) {
42 | return Arrays.stream(TestAsset.values())
43 | .filter(asset -> asset.label.equals(label))
44 | .findFirst();
45 | }
46 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/Unfinished.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest;
2 |
3 | public @interface Unfinished {
4 | String value();
5 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/api/HttpClientConfig.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.api;
2 |
3 | import okhttp3.Authenticator;
4 | import okhttp3.Interceptor;
5 |
6 | import java.net.Proxy;
7 | import java.time.Duration;
8 |
9 | public class HttpClientConfig {
10 |
11 | private final Duration connectTimeout;
12 | private final Duration readTimeout;
13 | private final Duration writeTimeout;
14 | private final Proxy proxy;
15 | private final Authenticator authenticator;
16 | private final Interceptor interceptor;
17 |
18 | protected HttpClientConfig(
19 | Duration connectTimeout,
20 | Duration readTimeout,
21 | Duration writeTimeout,
22 | Proxy proxy,
23 | Authenticator authenticator,
24 | Interceptor interceptor) {
25 | this.connectTimeout = connectTimeout;
26 | this.readTimeout = readTimeout;
27 | this.writeTimeout = writeTimeout;
28 | this.proxy = proxy;
29 | this.authenticator = authenticator;
30 | this.interceptor = interceptor;
31 | }
32 |
33 | public static HttpClientConfig defaultConfig() {
34 | return new HttpClientConfig(
35 | Duration.ofSeconds(300),
36 | Duration.ofSeconds(300),
37 | Duration.ofSeconds(300),
38 | null,
39 | null,
40 | null);
41 | }
42 |
43 | public HttpClientConfig connectTimeout(Duration connectTimeout) {
44 | return new HttpClientConfig(
45 | connectTimeout, readTimeout, writeTimeout, proxy, authenticator, interceptor);
46 | }
47 |
48 | public HttpClientConfig readTimeout(Duration readTimeout) {
49 | return new HttpClientConfig(
50 | connectTimeout, readTimeout, writeTimeout, proxy, authenticator, interceptor);
51 | }
52 |
53 | public HttpClientConfig writeTimeout(Duration writeTimeout) {
54 | return new HttpClientConfig(
55 | connectTimeout, readTimeout, writeTimeout, proxy, authenticator, interceptor);
56 | }
57 |
58 | public HttpClientConfig proxy(Proxy proxy) {
59 | return new HttpClientConfig(
60 | connectTimeout, readTimeout, writeTimeout, proxy, authenticator, interceptor);
61 | }
62 |
63 | public HttpClientConfig authenticator(Authenticator authenticator) {
64 | return new HttpClientConfig(
65 | connectTimeout, readTimeout, writeTimeout, proxy, authenticator, interceptor);
66 | }
67 |
68 | public HttpClientConfig interceptor(Interceptor interceptor) {
69 | return new HttpClientConfig(
70 | connectTimeout, readTimeout, writeTimeout, proxy, authenticator, interceptor);
71 | }
72 |
73 | public Duration getConnectTimeout() {
74 | return this.connectTimeout;
75 | }
76 |
77 | public Duration getReadTimeout() {
78 | return this.readTimeout;
79 | }
80 |
81 | public Duration getWriteTimeout() {
82 | return this.writeTimeout;
83 | }
84 |
85 | public Proxy getProxy() {
86 | return this.proxy;
87 | }
88 |
89 | public Authenticator getAuthenticator() {
90 | return this.authenticator;
91 | }
92 |
93 | public Interceptor getInterceptor() {
94 | return this.interceptor;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/api/InsightsEndpoint.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.api;
2 |
3 | import com.saucelabs.saucerest.DataCenter;
4 | import com.saucelabs.saucerest.HttpMethod;
5 | import com.saucelabs.saucerest.Unfinished;
6 | import com.saucelabs.saucerest.model.insights.TestResult;
7 | import com.saucelabs.saucerest.model.insights.TestResultParameter;
8 | import java.io.IOException;
9 | import java.util.Map;
10 |
11 | @Unfinished("This endpoint is not yet completely implemented")
12 | public class InsightsEndpoint extends AbstractEndpoint {
13 | public InsightsEndpoint(DataCenter dataCenter) {
14 | super(dataCenter);
15 | }
16 |
17 | public InsightsEndpoint(String apiServer) {
18 | super(apiServer);
19 | }
20 |
21 | public InsightsEndpoint(String username, String accessKey, DataCenter dataCenter) {
22 | super(username, accessKey, dataCenter);
23 | }
24 |
25 | public InsightsEndpoint(String username, String accessKey, String apiServer) {
26 | super(username, accessKey, apiServer);
27 | }
28 |
29 | public TestResult getTestResults(TestResultParameter parameter) throws IOException {
30 | String url = getBaseEndpoint() + "v1/analytics/tests";
31 | Map params;
32 | params = parameter.toMap();
33 |
34 | return deserializeJSONObject(requestWithQueryParameters(url, HttpMethod.GET, params), TestResult.class);
35 | }
36 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/api/PerformanceEndpoint.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.api;
2 |
3 | import com.saucelabs.saucerest.DataCenter;
4 | import com.saucelabs.saucerest.Unfinished;
5 |
6 | @Unfinished("This endpoint is not yet completely implemented")
7 | public class PerformanceEndpoint extends AbstractEndpoint {
8 | public PerformanceEndpoint(DataCenter dataCenter) {
9 | super(dataCenter);
10 | }
11 |
12 | public PerformanceEndpoint(String apiServer) {
13 | super(apiServer);
14 | }
15 |
16 | public PerformanceEndpoint(String username, String accessKey, DataCenter dataCenter) {
17 | super(username, accessKey, dataCenter);
18 | }
19 |
20 | public PerformanceEndpoint(String username, String accessKey, String apiServer) {
21 | super(username, accessKey, apiServer);
22 | }
23 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/api/PlatformEndpoint.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.api;
2 |
3 | import com.google.gson.reflect.TypeToken;
4 | import com.saucelabs.saucerest.DataCenter;
5 | import com.saucelabs.saucerest.HttpMethod;
6 | import com.saucelabs.saucerest.model.platform.AppiumVersion;
7 | import com.saucelabs.saucerest.model.platform.EndOfLifeAppiumVersions;
8 | import com.saucelabs.saucerest.model.platform.Platform;
9 | import com.saucelabs.saucerest.model.platform.SupportedPlatforms;
10 | import com.saucelabs.saucerest.model.platform.TestStatus;
11 | import java.io.IOException;
12 | import java.lang.reflect.Type;
13 | import java.util.Map;
14 | import java.util.stream.Collectors;
15 |
16 | public class PlatformEndpoint extends AbstractEndpoint {
17 |
18 | public PlatformEndpoint(DataCenter dataCenter) {
19 | super(dataCenter, false);
20 | }
21 |
22 | public PlatformEndpoint(String apiServer) {
23 | super(apiServer, false);
24 | }
25 |
26 | public PlatformEndpoint(String username, String accessKey, DataCenter dataCenter) {
27 | super(username, accessKey, dataCenter);
28 | }
29 |
30 | public PlatformEndpoint(String username, String accessKey, String apiServer) {
31 | super(username, accessKey, apiServer);
32 | }
33 |
34 | /**
35 | * Returns the status of Sauce Labs. Documentation is
36 | * here
37 | *
38 | * @return {@link TestStatus}
39 | * @throws IOException API request failed
40 | */
41 | public TestStatus getTestStatus() throws IOException {
42 | String url = getBaseEndpoint() + "/status";
43 |
44 | return deserializeJSONObject(request(url, HttpMethod.GET), TestStatus.class);
45 | }
46 |
47 | /**
48 | * Returns supported platforms. Valid values are 'all', 'appium' or 'webdriver'.
49 | * Documentation is
50 | * here
51 | *
52 | * @param automationApi Specified automation framework: all, appium or webdriver.
53 | * @return {@link SupportedPlatforms}
54 | */
55 | public SupportedPlatforms getSupportedPlatforms(String automationApi) throws IOException {
56 | String url = getBaseEndpoint() + "/platforms/" + automationApi;
57 |
58 | return new SupportedPlatforms(deserializeJSONArray(request(url, HttpMethod.GET), Platform.class));
59 | }
60 |
61 | /**
62 | * Returns all supported Appium versions on Sauce Labs and the expected end of life date of the version.
63 | * Documentation is
64 | * here
65 | *
66 | * @return {@link EndOfLifeAppiumVersions}
67 | */
68 | public EndOfLifeAppiumVersions getEndOfLifeAppiumVersions() throws IOException {
69 | String url = getBaseEndpoint() + "/platforms/appium/eol";
70 |
71 | Type type = TypeToken.getParameterized(Map.class, String.class, Integer.class).getType();
72 | Map mapOfVersions = deserializeJSON(request(url, HttpMethod.GET), type);
73 | return new EndOfLifeAppiumVersions(mapOfVersions.entrySet().stream()
74 | .map(entry -> new AppiumVersion(entry.getKey(), entry.getValue()))
75 | .collect(Collectors.toList())
76 | );
77 | }
78 |
79 | /**
80 | * The base endpoint of the Platform endpoint APIs.
81 | */
82 | @Override
83 | protected String getBaseEndpoint() {
84 | return super.getBaseEndpoint() + "rest/v1/info";
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/api/ResponseHandler.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.api;
2 |
3 | import static java.net.HttpURLConnection.*;
4 |
5 | import com.saucelabs.saucerest.ErrorExplainers;
6 | import com.saucelabs.saucerest.HttpMethod;
7 | import com.saucelabs.saucerest.SauceException;
8 | import okhttp3.Response;
9 |
10 | /**
11 | * Handle non-200 HTTP responses differently if needed per endpoint.
12 | * For example, provide endpoint specific context and error message.
13 | */
14 | public class ResponseHandler {
15 | private ResponseHandler() {
16 | throw new IllegalStateException("Utility class");
17 | }
18 |
19 | public static void responseHandler(AbstractEndpoint endpoint, Response response) {
20 | // TODO: refactor this to use Java 17 pattern matching in the future
21 | // TODO: add more specific error messages for each endpoint
22 | switch (response.code()) {
23 | case HTTP_NOT_FOUND:
24 | if (endpoint instanceof SauceConnectEndpoint) {
25 | if (response.request().method().equals(HttpMethod.DELETE.label)) {
26 | String tunnelID = getID(response);
27 | throw new SauceException.NotFound(String.join(System.lineSeparator(), ErrorExplainers.TunnelNotFound(tunnelID)));
28 | }
29 | } else if (endpoint instanceof StorageEndpoint) {
30 | String appFileID = getID(response);
31 | throw new SauceException.NotFound(String.join(System.lineSeparator(), ErrorExplainers.AppNotFound(appFileID)));
32 | } else if (endpoint instanceof AccountsEndpoint) {
33 | String accountID = getID(response);
34 | throw new SauceException.NotFound(String.join(System.lineSeparator(), ErrorExplainers.AccountNotFound(accountID)));
35 | }
36 | throw new SauceException.NotFound();
37 | case HTTP_UNAUTHORIZED:
38 | throw new SauceException.NotAuthorized(checkCredentials(endpoint));
39 | case HTTP_BAD_REQUEST:
40 | if (endpoint instanceof JobsEndpoint) {
41 | if (response.message().equalsIgnoreCase("Job hasn't finished running")) {
42 | throw new SauceException.NotYetDone(ErrorExplainers.JobNotYetDone());
43 | }
44 | }
45 | throw new RuntimeException("Unexpected code " + response);
46 | default:
47 | throw new RuntimeException("Unexpected code " + response);
48 | }
49 | }
50 |
51 | /**
52 | * Returns the ID of the resource from the URL.
53 | */
54 | private static String getID(Response response) {
55 | String ID = getLastPathSegment(response, 1);
56 |
57 | // if ID is not a UUID
58 | if (!ID.matches("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}") || !ID.matches("\\d+")) {
59 | return getLastPathSegment(response, 2);
60 | }
61 |
62 | return ID;
63 | }
64 |
65 | private static String getLastPathSegment(Response response, int offset) {
66 | if (offset == 0) {
67 | offset = 1;
68 | }
69 |
70 | return response.request().url().pathSegments().get(response.request().url().pathSegments().size() - offset);
71 | }
72 |
73 | private static String checkCredentials(AbstractEndpoint endpoint) {
74 | String username = endpoint.username;
75 | String accessKey = endpoint.accessKey;
76 |
77 | if ((username == null || username.isEmpty()) && (accessKey == null || accessKey.isEmpty())) {
78 | return String.join(System.lineSeparator(), "Your username and access key are empty or blank.", ErrorExplainers.missingCreds());
79 | }
80 |
81 | if (username == null || username.isEmpty()) {
82 | return String.join(System.lineSeparator(), "Your username is empty or blank.", ErrorExplainers.missingCreds());
83 | }
84 |
85 | if (accessKey == null || accessKey.isEmpty()) {
86 | return String.join(System.lineSeparator(), "Your access key is empty or blank.", ErrorExplainers.missingCreds());
87 | }
88 |
89 | return ErrorExplainers.incorrectCreds(username, accessKey);
90 | }
91 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/Allowed.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | public class Allowed {
4 |
5 | public Integer vms;
6 | public Integer rds;
7 | public Integer macVms;
8 |
9 | /**
10 | * No args constructor for use in serialization
11 | */
12 | public Allowed() {
13 | }
14 |
15 | /**
16 | * @param rds
17 | * @param macVms
18 | * @param vms
19 | */
20 | public Allowed(Integer vms, Integer rds, Integer macVms) {
21 | super();
22 | this.vms = vms;
23 | this.rds = rds;
24 | this.macVms = macVms;
25 | }
26 |
27 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/Concurrency.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | public class Concurrency {
4 |
5 | public Organization organization;
6 | public Team team;
7 |
8 | /**
9 | * No args constructor for use in serialization
10 | */
11 | public Concurrency() {
12 | }
13 |
14 | /**
15 | * @param organization
16 | * @param team
17 | */
18 | public Concurrency(Organization organization, Team team) {
19 | super();
20 | this.organization = organization;
21 | this.team = team;
22 | }
23 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/CreateTeam.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | public class CreateTeam {
4 |
5 | public String createdAt;
6 | public String description;
7 | public Group group;
8 | public String id;
9 | public Boolean isDefault;
10 | public String name;
11 | public String orgUuid;
12 | public Settings settings;
13 | public String updatedAt;
14 |
15 | /**
16 | * No args constructor for use in serialization
17 | */
18 | public CreateTeam() {
19 | }
20 |
21 | public CreateTeam(String createdAt, String description, Group group, String id, Boolean isDefault, String name, String orgUuid, Settings settings, String updatedAt) {
22 | super();
23 | this.createdAt = createdAt;
24 | this.description = description;
25 | this.group = group;
26 | this.id = id;
27 | this.isDefault = isDefault;
28 | this.name = name;
29 | this.orgUuid = orgUuid;
30 | this.settings = settings;
31 | this.updatedAt = updatedAt;
32 | }
33 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/Current.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | public class Current {
4 |
5 | public Integer vms;
6 | public Integer rds;
7 | public Integer macVms;
8 |
9 | /**
10 | * No args constructor for use in serialization
11 | */
12 | public Current() {
13 | }
14 |
15 | /**
16 | * @param rds
17 | * @param macVms
18 | * @param vms
19 | */
20 | public Current(Integer vms, Integer rds, Integer macVms) {
21 | super();
22 | this.vms = vms;
23 | this.rds = rds;
24 | this.macVms = macVms;
25 | }
26 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/Group.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | public class Group {
4 |
5 | public String id;
6 | public String name;
7 | public Integer virtualMachines;
8 | public Integer realDevices;
9 |
10 | /**
11 | * No args constructor for use in serialization
12 | */
13 | public Group() {
14 | }
15 |
16 | /**
17 | * @param realDevices
18 | * @param name
19 | * @param id
20 | * @param virtualMachines
21 | */
22 | public Group(String id, String name, Integer virtualMachines, Integer realDevices) {
23 | super();
24 | this.id = id;
25 | this.name = name;
26 | this.virtualMachines = virtualMachines;
27 | this.realDevices = realDevices;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/Links.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | public class Links {
4 |
5 | public Object next;
6 | public Object previous;
7 | public String first;
8 | public String last;
9 |
10 | /**
11 | * No args constructor for use in serialization
12 | */
13 | public Links() {
14 | }
15 |
16 | /**
17 | * @param next
18 | * @param previous
19 | * @param last
20 | * @param first
21 | */
22 | public Links(Object next, Object previous, String first, String last) {
23 | super();
24 | this.next = next;
25 | this.previous = previous;
26 | this.first = first;
27 | this.last = last;
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/LookupTeams.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | import java.util.List;
4 |
5 | public class LookupTeams {
6 |
7 | public Links links;
8 | public Integer count;
9 | public List results = null;
10 |
11 | /**
12 | * No args constructor for use in serialization
13 | */
14 | public LookupTeams() {
15 | }
16 |
17 | /**
18 | * @param count
19 | * @param links
20 | * @param results
21 | */
22 | public LookupTeams(Links links, Integer count, List results) {
23 | super();
24 | this.links = links;
25 | this.count = count;
26 | this.results = results;
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/LookupUsers.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | import java.util.List;
4 |
5 | public class LookupUsers {
6 |
7 | public Links links;
8 | public Integer count;
9 | public List results;
10 |
11 | /**
12 | * No args constructor for use in serialization
13 | */
14 | public LookupUsers() {
15 | }
16 |
17 | public LookupUsers(Links links, Integer count, List results) {
18 | super();
19 | this.links = links;
20 | this.count = count;
21 | this.results = results;
22 | }
23 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/Organization.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | public class Organization {
4 |
5 | public String id;
6 | public Settings settings;
7 | public Integer totalVmConcurrency;
8 | public String name;
9 | public String createdAt;
10 | public String updatedAt;
11 | public Current current;
12 | public Allowed allowed;
13 |
14 | /**
15 | * No args constructor for use in serialization
16 | */
17 | public Organization() {
18 | }
19 |
20 | public Organization(String id, Settings settings, Integer totalVmConcurrency, String name, String createdAt, String updatedAt, Current current, Allowed allowed) {
21 | super();
22 | this.id = id;
23 | this.settings = settings;
24 | this.totalVmConcurrency = totalVmConcurrency;
25 | this.name = name;
26 | this.createdAt = createdAt;
27 | this.updatedAt = updatedAt;
28 | this.current = current;
29 | this.allowed = allowed;
30 | }
31 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/Organizations.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | import java.util.List;
4 |
5 | public class Organizations {
6 |
7 | public Links links;
8 | public Integer count;
9 | public List results;
10 |
11 | /**
12 | * No args constructor for use in serialization
13 | */
14 | public Organizations() {
15 | }
16 |
17 | public Organizations(Links links, Integer count, List results) {
18 | super();
19 | this.links = links;
20 | this.count = count;
21 | this.results = results;
22 | }
23 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/ResetAccessKeyForTeam.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | public class ResetAccessKeyForTeam {
4 |
5 | public String id;
6 | public String username;
7 | public String accessKey;
8 |
9 | /**
10 | * No args constructor for use in serialization
11 | */
12 | public ResetAccessKeyForTeam() {
13 | }
14 |
15 | /**
16 | * @param accessKey
17 | * @param id
18 | * @param username
19 | */
20 | public ResetAccessKeyForTeam(String id, String username, String accessKey) {
21 | super();
22 | this.id = id;
23 | this.username = username;
24 | this.accessKey = accessKey;
25 | }
26 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/Result.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | import java.util.List;
4 |
5 | public class Result {
6 |
7 | public String id;
8 | public Settings settings;
9 | public Group group;
10 | public Boolean isDefault;
11 | public String name;
12 | public String orgUuid;
13 | public Integer userCount;
14 | public String email;
15 | public String firstName;
16 | public String lastName;
17 | public Boolean isActive;
18 | public Organization organization;
19 | public List roles;
20 | public List teams;
21 | public String username;
22 |
23 | /**
24 | * No args constructor for use in serialization
25 | */
26 | public Result() {
27 | }
28 |
29 | public Result(String id, Settings settings, Group group, Boolean isDefault, String name, String orgUuid, Integer userCount, String email, String firstName, String lastName, Boolean isActive, Organization organization, List roles, List teams, String username) {
30 | this.id = id;
31 | this.settings = settings;
32 | this.group = group;
33 | this.isDefault = isDefault;
34 | this.name = name;
35 | this.orgUuid = orgUuid;
36 | this.userCount = userCount;
37 | this.email = email;
38 | this.firstName = firstName;
39 | this.lastName = lastName;
40 | this.isActive = isActive;
41 | this.organization = organization;
42 | this.roles = roles;
43 | this.teams = teams;
44 | this.username = username;
45 | }
46 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/Role.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | public class Role {
4 |
5 | public String name;
6 | public Integer role;
7 |
8 | /**
9 | * No args constructor for use in serialization
10 | */
11 | public Role() {
12 | }
13 |
14 | public Role(String name, Integer role) {
15 | super();
16 | this.name = name;
17 | this.role = role;
18 | }
19 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/Roles.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | public enum Roles {
4 | ORGADMIN(1),
5 | TEAMADMIN(4),
6 | MEMBER(3);
7 |
8 | private final int value;
9 |
10 | Roles(int value) {
11 | this.value = value;
12 | }
13 |
14 | public int getValue() {
15 | return value;
16 | }
17 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/SetTeam.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | public class SetTeam {
4 |
5 | public String id;
6 | public User user;
7 | public Team team;
8 | public String createdAt;
9 | public String updatedAt;
10 |
11 | public SetTeam(String id, User user, Team team, String createdAt, String updatedAt) {
12 | this.id = id;
13 | this.user = user;
14 | this.team = team;
15 | this.createdAt = createdAt;
16 | this.updatedAt = updatedAt;
17 | }
18 |
19 | /**
20 | * No args constructor for use in serialization
21 | */
22 | public SetTeam() {
23 | }
24 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/Settings.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | public class Settings {
4 |
5 | public Boolean allowIntegrationsPage;
6 | public Boolean canUseTunnelsWithPublicRealDevices;
7 | public String country;
8 | public Boolean disableEmailVerification;
9 | public Boolean groupsEnabled;
10 | public Object jitDefaultTeam;
11 | public String jitUsernamePrefix;
12 | public Boolean jobsCrossTeamSharing;
13 | public Boolean liveOnly;
14 | public String logoutUrl;
15 | public Integer macVirtualMachines;
16 | public Boolean performanceEnabled;
17 | public Boolean rdcEnabled;
18 | public Integer realDevices;
19 | public Boolean ssoEnabled;
20 | public Boolean ssoOnly;
21 | public Integer teamLimit;
22 | public Boolean teamLimitReached;
23 | public Object toPlan;
24 | public Object trialPeriod;
25 | public Boolean tunnelsLockdown;
26 | public String userType;
27 | public Integer virtualMachines;
28 | public Boolean vmLockdown;
29 | public Boolean ssoLegacyEnabled;
30 |
31 | /**
32 | * No args constructor for use in serialization
33 | */
34 | public Settings() {
35 | }
36 |
37 | public Settings(Boolean allowIntegrationsPage, Boolean canUseTunnelsWithPublicRealDevices, String country, Boolean disableEmailVerification, Boolean groupsEnabled, Object jitDefaultTeam, String jitUsernamePrefix, Boolean jobsCrossTeamSharing, Boolean liveOnly, String logoutUrl, Integer macVirtualMachines, Boolean performanceEnabled, Boolean rdcEnabled, Integer realDevices, Boolean ssoEnabled, Boolean ssoOnly, Integer teamLimit, Boolean teamLimitReached, Object toPlan, Object trialPeriod, Boolean tunnelsLockdown, String userType, Integer virtualMachines, Boolean vmLockdown, Boolean ssoLegacyEnabled) {
38 | super();
39 | this.allowIntegrationsPage = allowIntegrationsPage;
40 | this.canUseTunnelsWithPublicRealDevices = canUseTunnelsWithPublicRealDevices;
41 | this.country = country;
42 | this.disableEmailVerification = disableEmailVerification;
43 | this.groupsEnabled = groupsEnabled;
44 | this.jitDefaultTeam = jitDefaultTeam;
45 | this.jitUsernamePrefix = jitUsernamePrefix;
46 | this.jobsCrossTeamSharing = jobsCrossTeamSharing;
47 | this.liveOnly = liveOnly;
48 | this.logoutUrl = logoutUrl;
49 | this.macVirtualMachines = macVirtualMachines;
50 | this.performanceEnabled = performanceEnabled;
51 | this.rdcEnabled = rdcEnabled;
52 | this.realDevices = realDevices;
53 | this.ssoEnabled = ssoEnabled;
54 | this.ssoOnly = ssoOnly;
55 | this.teamLimit = teamLimit;
56 | this.teamLimitReached = teamLimitReached;
57 | this.toPlan = toPlan;
58 | this.trialPeriod = trialPeriod;
59 | this.tunnelsLockdown = tunnelsLockdown;
60 | this.userType = userType;
61 | this.virtualMachines = virtualMachines;
62 | this.vmLockdown = vmLockdown;
63 | this.ssoLegacyEnabled = ssoLegacyEnabled;
64 | }
65 |
66 | private Settings(Builder builder) {
67 | virtualMachines = builder.virtualMachines;
68 | }
69 |
70 | public static final class Builder {
71 | private Integer virtualMachines;
72 |
73 | public Builder setVirtualMachines(Integer val) {
74 | virtualMachines = val;
75 | return this;
76 | }
77 |
78 | public Settings build() {
79 | return new Settings(this);
80 | }
81 | }
82 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/Team.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | public class Team {
4 |
5 | public String id;
6 | public Settings settings;
7 | public String createdAt;
8 | public String description;
9 | public Group group;
10 | public Boolean isDefault;
11 | public String name;
12 | public String orgUuid;
13 | public String updatedAt;
14 | public Current current;
15 | public Allowed allowed;
16 |
17 | /**
18 | * No args constructor for use in serialization
19 | */
20 | public Team() {
21 | }
22 |
23 | /**
24 | * @param settings
25 | * @param createdAt
26 | * @param isDefault
27 | * @param name
28 | * @param description
29 | * @param id
30 | * @param group
31 | * @param orgUuid
32 | * @param updatedAt
33 | */
34 | public Team(String id, Settings settings, String createdAt, String description, Group group, Boolean isDefault, String name, String orgUuid, String updatedAt, Current current, Allowed allowed) {
35 | super();
36 | this.id = id;
37 | this.settings = settings;
38 | this.createdAt = createdAt;
39 | this.description = description;
40 | this.group = group;
41 | this.isDefault = isDefault;
42 | this.name = name;
43 | this.orgUuid = orgUuid;
44 | this.updatedAt = updatedAt;
45 | this.current = current;
46 | this.allowed = allowed;
47 | }
48 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/TeamMembers.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | import java.util.List;
4 |
5 | public class TeamMembers {
6 |
7 | public Links links;
8 | public Integer count;
9 | public List results;
10 |
11 | /**
12 | * No args constructor for use in serialization
13 | */
14 | public TeamMembers() {
15 | }
16 |
17 | /**
18 | * @param count
19 | * @param links
20 | * @param results
21 | */
22 | public TeamMembers(Links links, Integer count, List results) {
23 | super();
24 | this.links = links;
25 | this.count = count;
26 | this.results = results;
27 | }
28 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/UpdateTeam.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | public class UpdateTeam {
4 |
5 | public String id;
6 | public Settings settings;
7 | public String createdAt;
8 | public String description;
9 | public Group group;
10 | public Boolean isDefault;
11 | public String name;
12 | public String orgUuid;
13 | public String updatedAt;
14 |
15 | /**
16 | * No args constructor for use in serialization
17 | */
18 | public UpdateTeam() {
19 | }
20 |
21 | /**
22 | * @param settings
23 | * @param createdAt
24 | * @param isDefault
25 | * @param name
26 | * @param description
27 | * @param id
28 | * @param group
29 | * @param orgUuid
30 | * @param updatedAt
31 | */
32 | public UpdateTeam(String id, Settings settings, String createdAt, String description, Group group, Boolean isDefault, String name, String orgUuid, String updatedAt) {
33 | super();
34 | this.id = id;
35 | this.settings = settings;
36 | this.createdAt = createdAt;
37 | this.description = description;
38 | this.group = group;
39 | this.isDefault = isDefault;
40 | this.name = name;
41 | this.orgUuid = orgUuid;
42 | this.updatedAt = updatedAt;
43 | }
44 |
45 | private UpdateTeam(Builder builder) {
46 | settings = builder.settings;
47 | description = builder.description;
48 | name = builder.name;
49 | }
50 |
51 | public static final class Builder {
52 | private Settings settings;
53 | private String description;
54 | private String name;
55 |
56 | public Builder setSettings(Settings val) {
57 | settings = val;
58 | return this;
59 | }
60 |
61 | public Builder setDescription(String val) {
62 | description = val;
63 | return this;
64 | }
65 |
66 | public Builder setName(String val) {
67 | name = val;
68 | return this;
69 | }
70 |
71 | public UpdateTeam build() {
72 | return new UpdateTeam(this);
73 | }
74 | }
75 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/UpdateUser.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | public class UpdateUser {
7 | private final String userID;
8 | private final String firstName;
9 | private final String lastName;
10 | private final String phone;
11 |
12 | private UpdateUser(Builder builder) {
13 | userID = builder.userID;
14 | firstName = builder.firstName;
15 | lastName = builder.lastName;
16 | phone = builder.phone;
17 | }
18 |
19 | public Map toMap() {
20 | Map parameters = new HashMap<>();
21 |
22 | if (this.firstName != null) {
23 | parameters.put("first_name", this.firstName);
24 | }
25 |
26 | if (this.lastName != null) {
27 | parameters.put("last_name", this.lastName);
28 | }
29 |
30 | if (this.phone != null) {
31 | parameters.put("phone", this.phone);
32 | }
33 |
34 | return parameters;
35 | }
36 |
37 | public String getUserID() {
38 | return userID;
39 | }
40 |
41 | public static final class Builder {
42 | private String userID;
43 | private String firstName;
44 | private String lastName;
45 | private String phone;
46 |
47 | public Builder setUserID(String val) {
48 | userID = val;
49 | return this;
50 | }
51 |
52 | public Builder setFirstName(String val) {
53 | firstName = val;
54 | return this;
55 | }
56 |
57 | public Builder setLastName(String val) {
58 | lastName = val;
59 | return this;
60 | }
61 |
62 | public Builder setPhone(String val) {
63 | phone = val;
64 | return this;
65 | }
66 |
67 | public UpdateUser build() {
68 | if (phone != null && !phone.matches("^\\+?1?\\d{8,15}$")) {
69 | throw new IllegalArgumentException("Phone number must be in international format, e.g. +1 1234567890");
70 | }
71 |
72 | return new UpdateUser(this);
73 | }
74 | }
75 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/User.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | import java.util.List;
4 |
5 | public class User {
6 |
7 | public String id;
8 | public String email;
9 | public String firstName;
10 | public String lastName;
11 | public String username;
12 | public String createdAt;
13 | public List groups;
14 | public Boolean isActive;
15 | public Boolean isOrganizationAdmin;
16 | public Boolean isTeamAdmin;
17 | public Boolean isStaff;
18 | public Boolean isSuperuser;
19 | public Organization organization;
20 | public String phone;
21 | public List roles;
22 | public List teams;
23 | public String updatedAt;
24 | public String userType;
25 | public String accessKey;
26 |
27 | /**
28 | * No args constructor for use in serialization
29 | */
30 | public User() {
31 | }
32 |
33 | public User(String id, String email, String firstName, String lastName, String username, String createdAt, List groups, Boolean isActive, Boolean isOrganizationAdmin, Boolean isTeamAdmin, Boolean isStaff, Boolean isSuperuser, Organization organization, String phone, List roles, List teams, String updatedAt, String userType, String accessKey) {
34 | super();
35 | this.id = id;
36 | this.email = email;
37 | this.firstName = firstName;
38 | this.lastName = lastName;
39 | this.username = username;
40 | this.createdAt = createdAt;
41 | this.groups = groups;
42 | this.isActive = isActive;
43 | this.isOrganizationAdmin = isOrganizationAdmin;
44 | this.isTeamAdmin = isTeamAdmin;
45 | this.isStaff = isStaff;
46 | this.isSuperuser = isSuperuser;
47 | this.organization = organization;
48 | this.phone = phone;
49 | this.roles = roles;
50 | this.teams = teams;
51 | this.updatedAt = updatedAt;
52 | this.userType = userType;
53 | this.accessKey = accessKey;
54 | }
55 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/UserConcurrency.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | public class UserConcurrency {
4 |
5 | public Float timestamp;
6 | public Concurrency concurrency;
7 |
8 | /**
9 | * No args constructor for use in serialization
10 | */
11 | public UserConcurrency() {
12 | }
13 |
14 | /**
15 | * @param timestamp
16 | * @param concurrency
17 | */
18 | public UserConcurrency(Float timestamp, Concurrency concurrency) {
19 | super();
20 | this.timestamp = timestamp;
21 | this.concurrency = concurrency;
22 | }
23 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/accounts/UsersTeam.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.accounts;
2 |
3 | import java.util.List;
4 |
5 | public class UsersTeam {
6 |
7 | public Links links;
8 | public Integer count;
9 | public List results;
10 |
11 | /**
12 | * No args constructor for use in serialization
13 | */
14 | public UsersTeam() {
15 | }
16 |
17 | /**
18 | * @param count
19 | * @param links
20 | * @param results
21 | */
22 | public UsersTeam(Links links, Integer count, List results) {
23 | super();
24 | this.links = links;
25 | this.count = count;
26 | this.results = results;
27 | }
28 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/builds/Build.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.builds;
2 |
3 | public class Build {
4 |
5 | public Integer creationTime;
6 |
7 | public Integer deletionTime;
8 |
9 | public Integer endTime;
10 |
11 | public String groupId;
12 |
13 | public String id;
14 |
15 | public Jobs jobs;
16 |
17 | public Integer modificationTime;
18 |
19 | public String name;
20 |
21 | public String orgId;
22 |
23 | public String ownerId;
24 |
25 | public Object passed;
26 |
27 | public Boolean _public;
28 |
29 | public Integer run;
30 |
31 | public String source;
32 |
33 | public Integer startTime;
34 |
35 | public String status;
36 |
37 | public String teamId;
38 |
39 | public Build() {}
40 |
41 | public Build(
42 | Integer creationTime,
43 | Integer deletionTime,
44 | Integer endTime,
45 | String groupId,
46 | String id,
47 | Jobs jobs,
48 | Integer modificationTime,
49 | String name,
50 | String orgId,
51 | String ownerId,
52 | Object passed,
53 | Boolean _public,
54 | Integer run,
55 | String source,
56 | Integer startTime,
57 | String status,
58 | String teamId) {
59 | super();
60 | this.creationTime = creationTime;
61 | this.deletionTime = deletionTime;
62 | this.endTime = endTime;
63 | this.groupId = groupId;
64 | this.id = id;
65 | this.jobs = jobs;
66 | this.modificationTime = modificationTime;
67 | this.name = name;
68 | this.orgId = orgId;
69 | this.ownerId = ownerId;
70 | this.passed = passed;
71 | this._public = _public;
72 | this.run = run;
73 | this.source = source;
74 | this.startTime = startTime;
75 | this.status = status;
76 | this.teamId = teamId;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/builds/JobInBuild.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.builds;
2 |
3 | public class JobInBuild {
4 |
5 | public Integer creationTime;
6 |
7 | public Integer deletionTime;
8 |
9 | public String id;
10 |
11 | public Integer modificationTime;
12 |
13 | public State state;
14 |
15 | /** No args constructor for use in serialization */
16 | public JobInBuild() {}
17 |
18 | public JobInBuild(
19 | Integer creationTime,
20 | Integer deletionTime,
21 | String id,
22 | Integer modificationTime,
23 | State state) {
24 | this.creationTime = creationTime;
25 | this.deletionTime = deletionTime;
26 | this.id = id;
27 | this.modificationTime = modificationTime;
28 | this.state = state;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/builds/Jobs.java:
--------------------------------------------------------------------------------
1 |
2 | package com.saucelabs.saucerest.model.builds;
3 |
4 | public class Jobs {
5 |
6 | public Integer completed;
7 | public Integer errored;
8 | public Integer failed;
9 | public Integer finished;
10 | public Integer passed;
11 | public Integer _public;
12 | public Integer queued;
13 | public Integer running;
14 |
15 | /**
16 | * No args constructor for use in serialization
17 | */
18 | public Jobs() {
19 | }
20 |
21 | public Jobs(Integer completed, Integer errored, Integer failed, Integer finished, Integer passed, Integer _public, Integer queued, Integer running) {
22 | super();
23 | this.completed = completed;
24 | this.errored = errored;
25 | this.failed = failed;
26 | this.finished = finished;
27 | this.passed = passed;
28 | this._public = _public;
29 | this.queued = queued;
30 | this.running = running;
31 | }
32 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/builds/JobsInBuild.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.builds;
2 |
3 | import java.util.List;
4 |
5 | public class JobsInBuild {
6 |
7 | public List jobs;
8 |
9 | /** No args constructor for use in serialization */
10 | public JobsInBuild() {}
11 |
12 | public JobsInBuild(List jobs) {
13 | this.jobs = jobs;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/builds/Sort.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.builds;
2 |
3 | public enum Sort {
4 | asc("asc"),
5 | desc("desc");
6 |
7 | public final String value;
8 |
9 | Sort(String value) {
10 | this.value = value;
11 | }
12 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/builds/State.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.builds;
2 |
3 | public class State {
4 |
5 | public Boolean completed;
6 |
7 | public Boolean errored;
8 |
9 | public Boolean failed;
10 |
11 | public Boolean finished;
12 |
13 | public Boolean _new;
14 |
15 | public Boolean passed;
16 |
17 | public Boolean _public;
18 |
19 | public Boolean queued;
20 |
21 | public Boolean running;
22 |
23 | /** No args constructor for use in serialization */
24 | public State() {}
25 |
26 | public State(
27 | Boolean completed,
28 | Boolean errored,
29 | Boolean failed,
30 | Boolean finished,
31 | Boolean _new,
32 | Boolean passed,
33 | Boolean _public,
34 | Boolean queued,
35 | Boolean running) {
36 | this.completed = completed;
37 | this.errored = errored;
38 | this.failed = failed;
39 | this.finished = finished;
40 | this._new = _new;
41 | this.passed = passed;
42 | this._public = _public;
43 | this.queued = queued;
44 | this.running = running;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/builds/Status.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.builds;
2 |
3 | public enum Status {
4 | running("running"),
5 | error("error"),
6 | failed("failed"),
7 | complete("complete"),
8 | success("success");
9 |
10 | public final String value;
11 |
12 | Status(String value) {
13 | this.value = value;
14 | }
15 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/insights/Item.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.insights;
2 |
3 | public class Item {
4 |
5 | public String ancestor;
6 | public String browser;
7 | public String browserNormalized;
8 | public String build;
9 | public String creationTime;
10 | public String detailsUrl;
11 | public Integer duration;
12 | public String endTime;
13 | public String error;
14 | public String id;
15 | public String name;
16 | public String os;
17 | public String osNormalized;
18 | public String owner;
19 | public String startTime;
20 | public String status;
21 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/insights/Meta.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.insights;
2 |
3 | public class Meta {
4 | public Integer status;
5 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/insights/TestResult.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.insights;
2 |
3 | import java.util.List;
4 |
5 | public class TestResult {
6 | public Boolean hasMore;
7 | public List- items;
8 | public Meta meta;
9 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/jobs/BaseConfig.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.jobs;
2 |
3 | public class BaseConfig {
4 |
5 | public GoogChromeOptions googChromeOptions;
6 | public SauceOptions sauceOptions;
7 | public String browserName;
8 | public String platformName;
9 | public String browserVersion;
10 |
11 | public BaseConfig() {
12 | }
13 |
14 | public BaseConfig(GoogChromeOptions googChromeOptions, SauceOptions sauceOptions, String browserName, String platformName, String browserVersion) {
15 | super();
16 | this.googChromeOptions = googChromeOptions;
17 | this.sauceOptions = sauceOptions;
18 | this.browserName = browserName;
19 | this.platformName = platformName;
20 | this.browserVersion = browserVersion;
21 | }
22 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/jobs/CommandCounts.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.jobs;
2 |
3 | public class CommandCounts {
4 |
5 | public Integer all;
6 | public Integer error;
7 |
8 | public CommandCounts() {
9 | }
10 |
11 | public CommandCounts(Integer all, Integer error) {
12 | super();
13 | this.all = all;
14 | this.error = error;
15 | }
16 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/jobs/CustomData.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.jobs;
2 |
3 | public class CustomData {
4 |
5 | public String tcd;
6 | public String editor;
7 |
8 | /**
9 | * No args constructor for use in serialization
10 | */
11 | public CustomData() {
12 | }
13 |
14 | /**
15 | * @param editor
16 | * @param tcd
17 | */
18 | public CustomData(String tcd, String editor) {
19 | super();
20 | this.tcd = tcd;
21 | this.editor = editor;
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/jobs/GetJobsParameters.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.jobs;
2 |
3 | import java.util.HashMap;
4 | import java.util.Map;
5 |
6 | public class GetJobsParameters {
7 | private final String username;
8 | private final int limit;
9 | private final int skip;
10 | private final int from;
11 | private final int to;
12 | private final Format format;
13 |
14 | public GetJobsParameters(String username, int limit, int skip, int from, int to, Format format) {
15 | this.username = username;
16 | this.limit = limit;
17 | this.skip = skip;
18 | this.from = from;
19 | this.to = to;
20 | this.format = format;
21 | }
22 |
23 | private GetJobsParameters(Builder builder) {
24 | username = builder.username;
25 | limit = builder.limit;
26 | skip = builder.skip;
27 | from = builder.from;
28 | to = builder.to;
29 | format = builder.format;
30 | }
31 |
32 | public Map toMap() {
33 | Map parameters = new HashMap<>();
34 |
35 | if (this.username != null) {
36 | parameters.put("username", this.username);
37 | }
38 |
39 | if (this.limit > 0) {
40 | parameters.put("limit", this.limit);
41 | }
42 |
43 | if (this.skip > 0) {
44 | parameters.put("skip", this.skip);
45 | }
46 |
47 | if (this.from > 0) {
48 | parameters.put("from", this.from);
49 | }
50 |
51 | if (this.to > 0) {
52 | parameters.put("to", this.to);
53 | }
54 |
55 | if (this.format != null) {
56 | parameters.put("format", this.format);
57 | }
58 |
59 | return parameters;
60 | }
61 |
62 | public enum Format {
63 | JSON("json"),
64 | CSV("csv");
65 |
66 | private final String value;
67 |
68 | Format(String value) {
69 | this.value = value;
70 | }
71 |
72 | public String getValue() {
73 | return value;
74 | }
75 | }
76 |
77 | public static final class Builder {
78 | private String username;
79 | private int limit;
80 | private int skip;
81 | private int from;
82 | private int to;
83 | private Format format;
84 |
85 | public Builder setUsername(String val) {
86 | username = val;
87 | return this;
88 | }
89 |
90 | public Builder setLimit(int val) {
91 | limit = val;
92 | return this;
93 | }
94 |
95 | public Builder setSkip(int val) {
96 | skip = val;
97 | return this;
98 | }
99 |
100 | public Builder setFrom(int val) {
101 | from = val;
102 | return this;
103 | }
104 |
105 | public Builder setTo(int val) {
106 | to = val;
107 | return this;
108 | }
109 |
110 | public Builder setFormat(Format val) {
111 | format = val;
112 | return this;
113 | }
114 |
115 | public GetJobsParameters build() {
116 | return new GetJobsParameters(this);
117 | }
118 | }
119 | }
--------------------------------------------------------------------------------
/src/main/java/com/saucelabs/saucerest/model/jobs/GoogChromeOptions.java:
--------------------------------------------------------------------------------
1 | package com.saucelabs.saucerest.model.jobs;
2 |
3 | import java.util.List;
4 |
5 | public class GoogChromeOptions {
6 |
7 | public List args;
8 | public List