Skip to content
This repository was archived by the owner on Sep 13, 2023. It is now read-only.

Commit 9eab9b3

Browse files
authored
Migrate cypress tests (#203)
* Add basic auth authentication method for cypress tests * Remove all cypress & integration test code * Remove noisy ls from dockerfile
1 parent d678b4c commit 9eab9b3

21 files changed

+86
-859
lines changed

.circleci/config.yml

-37
Original file line numberDiff line numberDiff line change
@@ -35,35 +35,6 @@ jobs:
3535
key: v1-dependencies-{{ checksum "yarn.lock" }}
3636
- run: yarn test:unit
3737

38-
# TODO: Integration tests do not work anymore as Bitbucket is only accessible behind VPN.
39-
# Refer to TESTING.md at the root of the repository.
40-
# integration_test:
41-
# docker:
42-
# - image: cypress/base:12
43-
# working_directory: ~/repo
44-
# steps:
45-
# - checkout
46-
# # - restore_cache:
47-
# # keys:
48-
# # - v1-dependencies-{{ checksum "yarn.lock" }}
49-
# # - v1-dependencies-
50-
# - run: yarn
51-
# - save_cache:
52-
# paths:
53-
# - node_modules
54-
# - .cache
55-
# key: v1-dependencies-{{ checksum "yarn.lock" }}`
56-
# - run:
57-
# name: Cypress tests
58-
# command: |
59-
# node ./.circleci/create-cypress-env.js
60-
# yarn test:integration:staging
61-
# no_output_timeout: 30m
62-
# - store_test_results:
63-
# path: ./tests/integration/junit-reports
64-
# - store_artifacts:
65-
# path: ./tests/integration/screenshots
66-
6738
workflows:
6839
version: 2
6940
build:
@@ -72,11 +43,3 @@ workflows:
7243
unit_test:
7344
jobs:
7445
- unit_test
75-
# See comment above
76-
# integration_test:
77-
# jobs:
78-
# - hold:
79-
# type: approval
80-
# - integration_test:
81-
# requires:
82-
# - hold

.circleci/create-cypress-env.js

-12
This file was deleted.

.gitignore

-3
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,5 @@ db.sqlite
1010
env
1111
env.sh
1212
.logs
13-
cypress.env.json
14-
tests/integration/screenshots/
15-
tests/integration/junit-reports/
1613
config.js
1714
rules/

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ COPY webpack.*.js README.md /opt/service/
2626
COPY tools /opt/service/tools
2727

2828
# Build
29-
RUN ls node_modules && NODE_ENV=production yarn build
29+
RUN NODE_ENV=production yarn build
3030

3131
# Retain only dependencies
3232
RUN yarn --production --cache-folder ../ycache && rm -rf ../ycache

TESTING.md

+1-49
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,3 @@
11
# Integration Testing for Landkid
22

3-
This document describes how to run the integration tests for Landkid on the dev instance.
4-
5-
The integration tests for Landkid are setup to target a Bitbucket repository, only available to Atlassian employees.
6-
7-
Currently, those integration tests cannot run in CircleCI because the Bitbucket repository they access is only accessible through VPN.
8-
9-
Developers would need to run the tests locally to validate their changes.
10-
11-
## Deploy to dev instance
12-
13-
For testing purposes, we recommend to use the [dev](https://atlassian-frontend-landkid.dev.services.atlassian.com/current-state/) instance.
14-
15-
16-
(For strict local dev loop, see this [document](https://bitbucket.org/atlassian/atlassian-frontend-landkid-deployment/src/master/development.md) )
17-
18-
### Workflow
19-
20-
1. Push your changes to CircleCI
21-
2. Grab the image number from the `publish` step in CircleCI build from your PR in GitHub - for example: https://app.circleci.com/pipelines/github/atlassian/landkid/396/workflows/4445d64a-b96d-4f2c-bec4-f0d8d4a6b251/jobs/1499 -> `circle-1499`
22-
3. Access the [atlassian-frontend-landkid-deployment repository](https://bitbucket.org/atlassian/atlassian-frontend-landkid-deployment/src/master/)
23-
4. Create a branch and replace `LANDKID_VERSION` var in this [file](https://bitbucket.org/atlassian/atlassian-frontend-landkid-deployment/src/HEAD/build/vars.sh#lines-5) by the image number from step 2.
24-
5. Commit and push your changes
25-
6. Deployment to `dev` environment would need to be manually from the latest pipeline / your latest change.
26-
27-
## Setup environment variables
28-
29-
In this repository:
30-
31-
1. Create your own copy of `cypress.env.json` - the file is `.gitignore` but make sure it is not committed by mistake.
32-
2. Ask access to the folder `Landkid credentials for testing` in LastPass
33-
3. Fill out the environment variables required
34-
35-
```
36-
{
37-
"BITBUCKET_APP_PASSWORD": "bitbucket app password",
38-
"LANDKID_SESSION_ID": "landkid.sid cookie from https://atlassian-frontend-landkid.dev.services.atlassian.com/current-state/, this is used by circleCI",
39-
"LANDKID_DEV_SESSION_ID"; "this is used in the local dev loop, use the LANDKID_SESSION_ID value to test a dev deployment locally otherwise use the landkid.sid cookie in your local instance of landkid",
40-
"LANDKID_DEV_URL": "https://atlassian-frontend-landkid.dev.services.atlassian.com/current-state/ to test a dev deployment or https://[basurl]/current-state for local testing",
41-
"CUSTOM_TOKEN": "token for specific endpoints - use the HASHED_CUSTOM_TOKEN"
42-
}
43-
```
44-
45-
To get the `LANDKID_SESSION_ID`, you would need to visit the [dev instance](https://atlassian-frontend-landkid.dev.services.atlassian.com/current-state/) and grab the `landkid.sid` from your browser in chrome://settings/siteData and look for `atlassian-frontend-landkid.dev`.
46-
47-
This environment variable is required to be authenticated while running the tests.
48-
49-
4. Run `yarn test:integration:watch` to watch and debug the tests or `yarn test:integration` to run it in `headless` mode.
50-
51-
_Note_: if you need to see any logs when running in `headless` mode, add `ELECTRON_ENABLE_LOGGING=1` to the command `yarn test:integration`.
3+
Integration testing via cypress has now moved to https://go.atlassian.com/af-landkid-deployment-repo

config.example.js

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ module.exports = {
2626
key: process.env.oauth_key,
2727
secret: process.env.oauth_secret,
2828
},
29+
enableBasicAuth: false,
2930
},
3031
maxConcurrentBuilds: 3,
3132
widgetSettings: {

cypress.env.example.json

-7
This file was deleted.

cypress.json

-11
This file was deleted.

package.json

+3-6
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,13 @@
1818
"scripts": {
1919
"clean": "rimraf dist",
2020
"test:unit": "jest",
21-
"pretest:integration": "node tools/test-local.js",
22-
"posttest:integration": "node tools/test-local.js --revert",
23-
"test:integration": "cypress run --browser chrome --reporter junit",
24-
"test:integration:watch": "cypress open",
2521
"format": "prettier --write src/**/*.ts src/**/*.tsx",
2622
"build": "yarn clean && yarn build:server && yarn build:ui",
2723
"build:server": "tsc",
2824
"build:ui": "cross-env OUTPUT_PATH=dist/static webpack --mode=production",
2925
"start": "cross-env NODE_ENV=production node ./dist",
3026
"dev": "yarn build:server && concurrently \"webpack-dev-server\" \"tsc -w\" \"nodemon ./dist --watch dist --watch config.js --watch rules --delay 1\"",
31-
"precommit": "node tools/test-local.js --revert && lint-staged",
27+
"precommit": "lint-staged",
3228
"migrate": "ts-node src/db/MigrationService.ts",
3329
"tunnel": "./tools/tunnel.sh",
3430
"storybook": "start-storybook -p 6006",
@@ -56,6 +52,7 @@
5652
"@types/node": "^15.0.2",
5753
"@types/p-retry": "^2.0.0",
5854
"@types/passport": "^1.0.6",
55+
"@types/passport-http": "^0.3.9",
5956
"@types/passport-oauth2": "^1.4.10",
6057
"@types/react": "^16.8.0",
6158
"@types/react-dom": "^16.8.0",
@@ -66,7 +63,6 @@
6663
"cache-loader": "^4.1.0",
6764
"concurrently": "^4.1.0",
6865
"css-loader": "^6.7.1",
69-
"cypress": "^8.3.1",
7066
"faker": "^4.1.0",
7167
"html-webpack-plugin": "^5.5.0",
7268
"httplease-asap": "^0.3.2",
@@ -112,6 +108,7 @@
112108
"mime": "^3.0.0",
113109
"p-limit": "^3.1.0",
114110
"passport": "^0.4.1",
111+
"passport-http": "^0.3.0",
115112
"passport-oauth2": "^1.5.0",
116113
"pg": "^8.2.1",
117114
"react": "^16.8.0",

src/auth/bitbucket.ts

+43-25
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,41 @@
11
import axios from 'axios';
22
import passport from 'passport';
3+
import { BasicStrategy } from 'passport-http';
34
import { Strategy, VerifyCallback } from 'passport-oauth2';
45
import { Logger } from '../lib/Logger';
56
import { config } from '../lib/Config';
67
import { OAuthConfig } from '../types';
78

9+
async function verifyBitbucketUser(
10+
authHeader: string,
11+
verified: (err?: Error | null, user?: Express.User) => void,
12+
) {
13+
let userInfo: ISessionUser;
14+
try {
15+
const userResponse = await axios.get('https://api.bitbucket.org/2.0/user', {
16+
headers: {
17+
Authorization: authHeader,
18+
},
19+
});
20+
21+
userInfo = {
22+
aaid: userResponse.data.uuid,
23+
username: userResponse.data.username,
24+
displayName: userResponse.data.display_name,
25+
accountId: userResponse.data.account_id,
26+
};
27+
28+
Logger.info('User logged in', {
29+
namespace: 'auth:bitbucket',
30+
aaid: userInfo.aaid,
31+
});
32+
} catch (err) {
33+
return verified(err);
34+
}
35+
36+
verified(null, userInfo);
37+
}
38+
839
export function initializePassport(oAuthConfig: OAuthConfig) {
940
passport.serializeUser<string>((user, done) => {
1041
done(null, JSON.stringify(user));
@@ -14,6 +45,7 @@ export function initializePassport(oAuthConfig: OAuthConfig) {
1445
done(null, JSON.parse(serialized));
1546
});
1647

48+
// Bitbucket OAuth2
1749
passport.use(
1850
'bitbucket',
1951
new Strategy(
@@ -24,32 +56,18 @@ export function initializePassport(oAuthConfig: OAuthConfig) {
2456
clientID: oAuthConfig.key,
2557
clientSecret: oAuthConfig.secret,
2658
},
27-
async (accessToken: string, refreshToken: string, profile: any, verified: VerifyCallback) => {
28-
let userInfo: ISessionUser;
29-
try {
30-
const userResponse = await axios.get('https://api.bitbucket.org/2.0/user', {
31-
headers: {
32-
Authorization: `Bearer ${accessToken}`,
33-
},
34-
});
35-
36-
userInfo = {
37-
aaid: userResponse.data.uuid,
38-
username: userResponse.data.username,
39-
displayName: userResponse.data.display_name,
40-
accountId: userResponse.data.account_id,
41-
};
42-
43-
Logger.info('User logged in', {
44-
namespace: 'auth:bitbucket',
45-
aaid: userInfo.aaid,
46-
});
47-
} catch (err) {
48-
return verified(err);
49-
}
50-
51-
verified(null, userInfo);
59+
(accessToken: string, refreshToken: string, profile: any, verified: VerifyCallback) => {
60+
verifyBitbucketUser(`Bearer ${accessToken}`, verified);
5261
},
5362
),
5463
);
64+
65+
// Allow programmatic Bitbucket login for tests
66+
passport.use(
67+
'basic',
68+
new BasicStrategy((username, password, done) => {
69+
const token = Buffer.from(`${username}:${password}`).toString('base64');
70+
verifyBitbucketUser(`Basic ${token}`, done);
71+
}),
72+
);
5573
}

src/routes/auth/index.ts

+8-2
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@ import passport from 'passport';
33
import { permissionService } from '../../lib/PermissionService';
44
import { wrap } from '../middleware';
55
import { Logger } from '../../lib/Logger';
6+
import { Config } from '../../types';
67

7-
export function authRoutes() {
8+
export function authRoutes(config: Config) {
89
const router = express();
910

10-
router.get('/', passport.authenticate('bitbucket'));
11+
const authStrategies = config.deployment.enableBasicAuth ? ['basic', 'bitbucket'] : 'bitbucket';
12+
13+
router.get('/', passport.authenticate(authStrategies), (req, res) => {
14+
res.redirect('/current-state');
15+
});
16+
1117
router.get(
1218
'/callback',
1319
passport.authenticate('bitbucket', { failureRedirect: '/auth' }),

src/routes/index.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ export async function routes(server: express.Application, client: BitbucketClien
4747
res.header('Access-Control-Allow-Origin', '*').json(bitbucketAddonDescriptor);
4848
});
4949
router.use('/api', apiRoutes(runner, client, config));
50-
router.use('/auth', authRoutes());
50+
router.use('/auth', authRoutes(config));
5151
router.use('/bitbucket', bitbucketRoutes(runner, client));
5252

5353
if (process.env.NODE_ENV === 'production') {

src/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export type DeploymentConfig = {
6868
port: number;
6969
};
7070
oAuth: OAuthConfig;
71+
enableBasicAuth?: boolean;
7172
};
7273

7374
export type OAuthConfig = {

tests/integration/all-success.spec.ts

-26
This file was deleted.

tests/integration/cypress.d.ts

-8
This file was deleted.

0 commit comments

Comments
 (0)