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

Commit

Permalink
Migrate cypress tests (#203)
Browse files Browse the repository at this point in the history
* Add basic auth authentication method for cypress tests

* Remove all cypress & integration test code

* Remove noisy ls from dockerfile
  • Loading branch information
Blasz authored Jan 15, 2023
1 parent d678b4c commit 9eab9b3
Show file tree
Hide file tree
Showing 21 changed files with 86 additions and 859 deletions.
37 changes: 0 additions & 37 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,35 +35,6 @@ jobs:
key: v1-dependencies-{{ checksum "yarn.lock" }}
- run: yarn test:unit

# TODO: Integration tests do not work anymore as Bitbucket is only accessible behind VPN.
# Refer to TESTING.md at the root of the repository.
# integration_test:
# docker:
# - image: cypress/base:12
# working_directory: ~/repo
# steps:
# - checkout
# # - restore_cache:
# # keys:
# # - v1-dependencies-{{ checksum "yarn.lock" }}
# # - v1-dependencies-
# - run: yarn
# - save_cache:
# paths:
# - node_modules
# - .cache
# key: v1-dependencies-{{ checksum "yarn.lock" }}`
# - run:
# name: Cypress tests
# command: |
# node ./.circleci/create-cypress-env.js
# yarn test:integration:staging
# no_output_timeout: 30m
# - store_test_results:
# path: ./tests/integration/junit-reports
# - store_artifacts:
# path: ./tests/integration/screenshots

workflows:
version: 2
build:
Expand All @@ -72,11 +43,3 @@ workflows:
unit_test:
jobs:
- unit_test
# See comment above
# integration_test:
# jobs:
# - hold:
# type: approval
# - integration_test:
# requires:
# - hold
12 changes: 0 additions & 12 deletions .circleci/create-cypress-env.js

This file was deleted.

3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,5 @@ db.sqlite
env
env.sh
.logs
cypress.env.json
tests/integration/screenshots/
tests/integration/junit-reports/
config.js
rules/
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ COPY webpack.*.js README.md /opt/service/
COPY tools /opt/service/tools

# Build
RUN ls node_modules && NODE_ENV=production yarn build
RUN NODE_ENV=production yarn build

# Retain only dependencies
RUN yarn --production --cache-folder ../ycache && rm -rf ../ycache
Expand Down
50 changes: 1 addition & 49 deletions TESTING.md
Original file line number Diff line number Diff line change
@@ -1,51 +1,3 @@
# Integration Testing for Landkid

This document describes how to run the integration tests for Landkid on the dev instance.

The integration tests for Landkid are setup to target a Bitbucket repository, only available to Atlassian employees.

Currently, those integration tests cannot run in CircleCI because the Bitbucket repository they access is only accessible through VPN.

Developers would need to run the tests locally to validate their changes.

## Deploy to dev instance

For testing purposes, we recommend to use the [dev](https://atlassian-frontend-landkid.dev.services.atlassian.com/current-state/) instance.


(For strict local dev loop, see this [document](https://bitbucket.org/atlassian/atlassian-frontend-landkid-deployment/src/master/development.md) )

### Workflow

1. Push your changes to CircleCI
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`
3. Access the [atlassian-frontend-landkid-deployment repository](https://bitbucket.org/atlassian/atlassian-frontend-landkid-deployment/src/master/)
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.
5. Commit and push your changes
6. Deployment to `dev` environment would need to be manually from the latest pipeline / your latest change.

## Setup environment variables

In this repository:

1. Create your own copy of `cypress.env.json` - the file is `.gitignore` but make sure it is not committed by mistake.
2. Ask access to the folder `Landkid credentials for testing` in LastPass
3. Fill out the environment variables required

```
{
"BITBUCKET_APP_PASSWORD": "bitbucket app password",
"LANDKID_SESSION_ID": "landkid.sid cookie from https://atlassian-frontend-landkid.dev.services.atlassian.com/current-state/, this is used by circleCI",
"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",
"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",
"CUSTOM_TOKEN": "token for specific endpoints - use the HASHED_CUSTOM_TOKEN"
}
```

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`.

This environment variable is required to be authenticated while running the tests.

4. Run `yarn test:integration:watch` to watch and debug the tests or `yarn test:integration` to run it in `headless` mode.

_Note_: if you need to see any logs when running in `headless` mode, add `ELECTRON_ENABLE_LOGGING=1` to the command `yarn test:integration`.
Integration testing via cypress has now moved to https://go.atlassian.com/af-landkid-deployment-repo
1 change: 1 addition & 0 deletions config.example.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ module.exports = {
key: process.env.oauth_key,
secret: process.env.oauth_secret,
},
enableBasicAuth: false,
},
maxConcurrentBuilds: 3,
widgetSettings: {
Expand Down
7 changes: 0 additions & 7 deletions cypress.env.example.json

This file was deleted.

11 changes: 0 additions & 11 deletions cypress.json

This file was deleted.

9 changes: 3 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,13 @@
"scripts": {
"clean": "rimraf dist",
"test:unit": "jest",
"pretest:integration": "node tools/test-local.js",
"posttest:integration": "node tools/test-local.js --revert",
"test:integration": "cypress run --browser chrome --reporter junit",
"test:integration:watch": "cypress open",
"format": "prettier --write src/**/*.ts src/**/*.tsx",
"build": "yarn clean && yarn build:server && yarn build:ui",
"build:server": "tsc",
"build:ui": "cross-env OUTPUT_PATH=dist/static webpack --mode=production",
"start": "cross-env NODE_ENV=production node ./dist",
"dev": "yarn build:server && concurrently \"webpack-dev-server\" \"tsc -w\" \"nodemon ./dist --watch dist --watch config.js --watch rules --delay 1\"",
"precommit": "node tools/test-local.js --revert && lint-staged",
"precommit": "lint-staged",
"migrate": "ts-node src/db/MigrationService.ts",
"tunnel": "./tools/tunnel.sh",
"storybook": "start-storybook -p 6006",
Expand Down Expand Up @@ -56,6 +52,7 @@
"@types/node": "^15.0.2",
"@types/p-retry": "^2.0.0",
"@types/passport": "^1.0.6",
"@types/passport-http": "^0.3.9",
"@types/passport-oauth2": "^1.4.10",
"@types/react": "^16.8.0",
"@types/react-dom": "^16.8.0",
Expand All @@ -66,7 +63,6 @@
"cache-loader": "^4.1.0",
"concurrently": "^4.1.0",
"css-loader": "^6.7.1",
"cypress": "^8.3.1",
"faker": "^4.1.0",
"html-webpack-plugin": "^5.5.0",
"httplease-asap": "^0.3.2",
Expand Down Expand Up @@ -112,6 +108,7 @@
"mime": "^3.0.0",
"p-limit": "^3.1.0",
"passport": "^0.4.1",
"passport-http": "^0.3.0",
"passport-oauth2": "^1.5.0",
"pg": "^8.2.1",
"react": "^16.8.0",
Expand Down
68 changes: 43 additions & 25 deletions src/auth/bitbucket.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,41 @@
import axios from 'axios';
import passport from 'passport';
import { BasicStrategy } from 'passport-http';
import { Strategy, VerifyCallback } from 'passport-oauth2';
import { Logger } from '../lib/Logger';
import { config } from '../lib/Config';
import { OAuthConfig } from '../types';

async function verifyBitbucketUser(
authHeader: string,
verified: (err?: Error | null, user?: Express.User) => void,
) {
let userInfo: ISessionUser;
try {
const userResponse = await axios.get('https://api.bitbucket.org/2.0/user', {
headers: {
Authorization: authHeader,
},
});

userInfo = {
aaid: userResponse.data.uuid,
username: userResponse.data.username,
displayName: userResponse.data.display_name,
accountId: userResponse.data.account_id,
};

Logger.info('User logged in', {
namespace: 'auth:bitbucket',
aaid: userInfo.aaid,
});
} catch (err) {
return verified(err);
}

verified(null, userInfo);
}

export function initializePassport(oAuthConfig: OAuthConfig) {
passport.serializeUser<string>((user, done) => {
done(null, JSON.stringify(user));
Expand All @@ -14,6 +45,7 @@ export function initializePassport(oAuthConfig: OAuthConfig) {
done(null, JSON.parse(serialized));
});

// Bitbucket OAuth2
passport.use(
'bitbucket',
new Strategy(
Expand All @@ -24,32 +56,18 @@ export function initializePassport(oAuthConfig: OAuthConfig) {
clientID: oAuthConfig.key,
clientSecret: oAuthConfig.secret,
},
async (accessToken: string, refreshToken: string, profile: any, verified: VerifyCallback) => {
let userInfo: ISessionUser;
try {
const userResponse = await axios.get('https://api.bitbucket.org/2.0/user', {
headers: {
Authorization: `Bearer ${accessToken}`,
},
});

userInfo = {
aaid: userResponse.data.uuid,
username: userResponse.data.username,
displayName: userResponse.data.display_name,
accountId: userResponse.data.account_id,
};

Logger.info('User logged in', {
namespace: 'auth:bitbucket',
aaid: userInfo.aaid,
});
} catch (err) {
return verified(err);
}

verified(null, userInfo);
(accessToken: string, refreshToken: string, profile: any, verified: VerifyCallback) => {
verifyBitbucketUser(`Bearer ${accessToken}`, verified);
},
),
);

// Allow programmatic Bitbucket login for tests
passport.use(
'basic',
new BasicStrategy((username, password, done) => {
const token = Buffer.from(`${username}:${password}`).toString('base64');
verifyBitbucketUser(`Basic ${token}`, done);
}),
);
}
10 changes: 8 additions & 2 deletions src/routes/auth/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,17 @@ import passport from 'passport';
import { permissionService } from '../../lib/PermissionService';
import { wrap } from '../middleware';
import { Logger } from '../../lib/Logger';
import { Config } from '../../types';

export function authRoutes() {
export function authRoutes(config: Config) {
const router = express();

router.get('/', passport.authenticate('bitbucket'));
const authStrategies = config.deployment.enableBasicAuth ? ['basic', 'bitbucket'] : 'bitbucket';

router.get('/', passport.authenticate(authStrategies), (req, res) => {
res.redirect('/current-state');
});

router.get(
'/callback',
passport.authenticate('bitbucket', { failureRedirect: '/auth' }),
Expand Down
2 changes: 1 addition & 1 deletion src/routes/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export async function routes(server: express.Application, client: BitbucketClien
res.header('Access-Control-Allow-Origin', '*').json(bitbucketAddonDescriptor);
});
router.use('/api', apiRoutes(runner, client, config));
router.use('/auth', authRoutes());
router.use('/auth', authRoutes(config));
router.use('/bitbucket', bitbucketRoutes(runner, client));

if (process.env.NODE_ENV === 'production') {
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export type DeploymentConfig = {
port: number;
};
oAuth: OAuthConfig;
enableBasicAuth?: boolean;
};

export type OAuthConfig = {
Expand Down
26 changes: 0 additions & 26 deletions tests/integration/all-success.spec.ts

This file was deleted.

8 changes: 0 additions & 8 deletions tests/integration/cypress.d.ts

This file was deleted.

Loading

0 comments on commit 9eab9b3

Please sign in to comment.