Skip to content

Commit

Permalink
Login before tests
Browse files Browse the repository at this point in the history
  • Loading branch information
andrzejewsky committed Oct 3, 2024
1 parent eb5ccbb commit 371f327
Show file tree
Hide file tree
Showing 43 changed files with 442 additions and 76 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,5 @@
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unused-vars": "off"
},
"ignorePatterns": ["node_modules/", "**/types/**/*", "type-policies.ts"]
"ignorePatterns": ["node_modules/", "**/types/**/*", "type-policies.ts", "playwright/auth.js"]
}
18 changes: 17 additions & 1 deletion .github/actions/run-pw-tests/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ inputs:
description: "Project name form playwright config"
required: false
default: "e2e"
ACCOUNTS:
description: "Accounts hash"
required: true
E2E_ENCODE_PASS:
description: "Accounts hash"
required: true

runs:
using: "composite"
Expand All @@ -47,6 +53,16 @@ runs:
shell: bash
run: npm ci

- name: Restore accounts
shell: bash
env:
E2E_ENCODE_PASS: ${{ inputs.E2E_ENCODE_PASS }}
ACCOUNTS: ${{ inputs.ACCOUNTS }}
API_URL: ${{ inputs.API_URL }}
BASE_URL: ${{ inputs.BASE_URL }}
run: |
node playwright/auth.js restore $ACCOUNTS
- name: Install Playwright Browsers
shell: bash
run: npx playwright install --with-deps
Expand Down Expand Up @@ -82,4 +98,4 @@ runs:
with:
name: all-blob-reports
path: blob-report
retention-days: 1
retention-days: 1
19 changes: 18 additions & 1 deletion .github/workflows/pr-automation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ jobs:
deploy-dashboard:
if: github.event.pull_request.head.repo.full_name == 'saleor/saleor-dashboard'
outputs:
ACCOUNTS: ${{ steps.accounts.outputs.ACCOUNTS }}
runs-on: ubuntu-22.04
needs: initialize-cloud
permissions:
Expand Down Expand Up @@ -150,6 +152,18 @@ jobs:
env_url: ${{ needs.initialize-cloud.outputs.BASE_URL }}
deployment_id: ${{ steps.deployment.outputs.deployment_id }}
env: ${{ needs.initialize-cloud.outputs.POOL_NAME }}
- name: Prepare accounts
id: accounts
env:
BASE_URL: ${{ needs.initialize-cloud.outputs.BASE_URL }}
API_URL: ${{ needs.initialize-cloud.outputs.API_URL }}
E2E_USER_NAME: ${{ secrets.E2E_USER_NAME }}
E2E_USER_PASSWORD: ${{ secrets.E2E_USER_PASSWORD }}
E2E_ENCODE_PASS: ${{ secrets.E2E_ENCODE_PASS }}
E2E_PERMISSIONS_USERS_PASSWORD: ${{ secrets.E2E_PERMISSIONS_USERS_PASSWORD }}
run: |
ACCOUNTS=$(node playwright/auth.js login)
echo "ACCOUNTS=${ACCOUNTS}" >> "$GITHUB_OUTPUT"
run-tests:
if: ${{ contains(github.event.pull_request.labels.*.name, 'run pw-e2e') }}
Expand All @@ -159,6 +173,7 @@ jobs:
fail-fast: false
matrix:
shard: ${{ fromJson(needs.initialize-cloud.outputs.SHARD_MATRIX) }}

steps:
- uses: actions/checkout@v4

Expand All @@ -174,6 +189,8 @@ jobs:
MAILPITURL: ${{ secrets.MAILPITURL }}
PW_WORKERS: ${{ vars.PW_WORKERS }}
PW_RETRIES: ${{ vars.PW_RETRIES }}
ACCOUNTS: ${{ needs.deploy-dashboard.outputs.ACCOUNTS }}
E2E_ENCODE_PASS: ${{ secrets.E2E_ENCODE_PASS }}

merge-reports:
if: "!cancelled() && contains(github.event.pull_request.labels.*.name, 'run pw-e2e')"
Expand All @@ -184,4 +201,4 @@ jobs:
- uses: actions/checkout@v4

- name: Merge playwright reports
uses: ./.github/actions/merge-pw-reports
uses: ./.github/actions/merge-pw-reports
184 changes: 184 additions & 0 deletions playwright/auth.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
/* eslint-disable */

const { request } = require("@playwright/test");
const dotenv = require("dotenv");
const process = require("process");
const crypto = require("crypto");
const path = require("path");
const fs = require("fs");

dotenv.config();

const PERMISSIONS = [
"admin",
"app",
"discount",
"order",
"channel",
"customer",
"giftCard",
"page",
"plugin",
"productTypeAndAttribute",
"product",
"settings",
"staff",
"shipping",
"translations",
]

const ACCOUNT_EMAILS = {
channel: "[email protected]",
shipping: "[email protected]",
giftCard: "[email protected]",
app: "[email protected]",
settings: "[email protected]",
page: "[email protected]",
order: "[email protected]",
translations: "[email protected]",
staff: "[email protected]",
customer: "[email protected]",
productTypeAndAttribute: "[email protected]",
discount: "[email protected]",
plugin: "[email protected]",
product: "[email protected]",
};

const createQuery = (email, password) => `mutation TokenAuth{
tokenCreate(email: "${email}", password: "${password}") {
token
refreshToken
errors: errors {
code
message
}
user {
id
}
}
}`;


const getEmailForPermission = (permission) => {
if (permission === "admin") {
return process.env.E2E_USER_NAME;
}

return ACCOUNT_EMAILS[permission];
};

const getPasswordForPermission = (permission) => {
if (permission === "admin") {
return process.env.E2E_USER_PASSWORD;
}

return process.env.E2E_PERMISSIONS_USERS_PASSWORD;
};

const getAuthForPermission = async (permissionName) => {
const apiRequestContext = await request.newContext({
baseURL: process.env.BASE_URL,
});

const email = getEmailForPermission(permissionName);
const password = getPasswordForPermission(permissionName);
const query = createQuery(email, password)

const response = await apiRequestContext.post(process.env.API_URL || "", {
data: { query },
});
const resposnseObj = await response.json()
const { errors } = resposnseObj.data.tokenCreate

if (errors && errors.length > 0) {
const errorMessages = errors
.map(e => e.message)
.join(", ");

throw new Error(`Login failed for permission ${permissionName}: ${errorMessages}`);
}

const loginJsonInfo = await apiRequestContext.storageState();

return loginJsonInfo
}

const encrypt = (password, text) => {
const algorithm = 'aes-256-ctr';
const key = Buffer.concat([Buffer.from(password), Buffer.alloc(32)], 32);
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv(algorithm, key, iv);
let encrypted = cipher.update(text);
encrypted = Buffer.concat([encrypted, cipher.final()]);
return iv.toString('hex') + encrypted.toString('hex');
}

const decrypt = (password, text) => {
const algorithm = 'aes-256-ctr';
const key = Buffer.concat([Buffer.from(password), Buffer.alloc(32)], 32);
const iv = Buffer.from(text.substring(0, 32), 'hex');
const encryptedText = Buffer.from(text.substring(32), 'hex');
const decipher = crypto.createDecipheriv(algorithm, key, iv);
let decrypted = decipher.update(encryptedText);
decrypted = Buffer.concat([decrypted, decipher.final()]);
return decrypted.toString();
}

(async () => {
const command = process.argv[2]

if (command == "login") {
let authString = ''

for (const permissionName of PERMISSIONS) {

const auth = await getAuthForPermission(permissionName)


authString = `${authString}${JSON.stringify(auth)}|`
}

const encodedString = encrypt(process.env.E2E_ENCODE_PASS, authString)

process.stdout.write(encodedString)
}


if (command == "restore") {
const tempDir = path.join(__dirname, "../playwright/.auth");

if (!fs.existsSync(tempDir)) {
fs.mkdirSync(tempDir, { recursive: true });
}


const encodedInput = process.argv[3]
console.log("Restoring...", encodedInput.length)


const decodedString = decrypt(process.env.E2E_ENCODE_PASS, encodedInput)
decodedString
.split("|")
.filter(Boolean)
.map(JSON.parse)
.map(obj => {
obj.origins.push({
origin: process.env.BASE_URL,
localStorage: [
{
name: "_saleorRefreshToken",
value: obj.cookies[0].value,
},
],
});

return obj
})
.map(JSON.stringify)
.map((str, index) => ({ name: PERMISSIONS[index], str }))
.forEach(token => {
const storageStatePath = path.join(tempDir, `${token.name}.json`);
fs.writeFileSync(storageStatePath, token.str);
})
}
})()
4 changes: 3 additions & 1 deletion playwright/data/userPermissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ export const USER_PERMISSION: UserPermissionType = {
product: "[email protected]",
};

export const permissions: Array<keyof UserPermissionType> = [
export type UserPermission = keyof UserPermissionType;

export const permissions: Array<UserPermission> = [
"app",
"discount",
"order",
Expand Down
5 changes: 3 additions & 2 deletions playwright/tests/apps.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { APPS } from "@data/e2eTestData";
import { AppInstallationPage } from "@pages/appInstallationPage";
import { AppPage } from "@pages/appPageThirdparty";
import { AppsPage } from "@pages/appsPage";
import { expect, test } from "@playwright/test";
import { expect } from "@playwright/test";
import { test } from "utils/testWithPermission";

test.use({ storageState: "./playwright/.auth/admin.json" });
test.use({ permissionName: "admin" });

let appsPage: AppsPage;
let installationPage: AppInstallationPage;
Expand Down
5 changes: 3 additions & 2 deletions playwright/tests/attributes.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { ATTRIBUTES } from "@data/e2eTestData";
import { AttributesPage } from "@pages/attributesPage";
import { ConfigurationPage } from "@pages/configurationPage";
import { expect, test } from "@playwright/test";
import { expect } from "@playwright/test";
import faker from "faker";
import { test } from "utils/testWithPermission";

test.use({ storageState: "./playwright/.auth/admin.json" });
test.use({ permissionName: "admin" });

let attributesPage: AttributesPage;
let configurationPage: ConfigurationPage;
Expand Down
5 changes: 3 additions & 2 deletions playwright/tests/categories.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { CATEGORIES } from "@data/e2eTestData";
import { CategoriesPage } from "@pages/categoriesPage";
import { expect, test } from "@playwright/test";
import { expect } from "@playwright/test";
import { test } from "utils/testWithPermission";

test.use({ storageState: "./playwright/.auth/admin.json" });
test.use({ permissionName: "admin" });

let categoriesPage: CategoriesPage;

Expand Down
5 changes: 3 additions & 2 deletions playwright/tests/channels.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { CHANNELS } from "@data/e2eTestData";
import { ChannelPage } from "@pages/channelsPage";
import { ConfigurationPage } from "@pages/configurationPage";
import { expect, test } from "@playwright/test";
import { expect } from "@playwright/test";
import { test } from "utils/testWithPermission";

test.use({ storageState: "./playwright/.auth/admin.json", locale: "en" });
test.use({ permissionName: "admin" });

let configurationPage: ConfigurationPage;
let channelPage: ChannelPage;
Expand Down
5 changes: 3 additions & 2 deletions playwright/tests/collections.spec.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { COLLECTIONS } from "@data/e2eTestData";
import { CollectionsPage } from "@pages/collectionsPage";
import { expect, test } from "@playwright/test";
import { expect } from "@playwright/test";
import { test } from "utils/testWithPermission";

test.use({ storageState: "./playwright/.auth/admin.json" });
test.use({ permissionName: "admin" });

let collectionsPage: CollectionsPage;

Expand Down
5 changes: 3 additions & 2 deletions playwright/tests/customers.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import { AddAddressDialog } from "@pages/dialogs/addAddressDialog";
import { DeleteAddressDialog } from "@pages/dialogs/deleteAddressDialog";
import { AddressForm } from "@pages/forms/addressForm";
import { GiftCardsPage } from "@pages/giftCardsPage";
import { expect, test } from "@playwright/test";
import { expect } from "@playwright/test";
import faker from "faker";
import { test } from "utils/testWithPermission";

test.use({ storageState: "./playwright/.auth/admin.json" });
test.use({ permissionName: "admin" });

let customersPage: CustomersPage;
let giftCardsPage: GiftCardsPage;
Expand Down
5 changes: 3 additions & 2 deletions playwright/tests/discounts.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { CATEGORIES, CHANNELS, COLLECTIONS, DISCOUNTS, PRODUCTS } from "@data/e2eTestData";
import { DiscountsPage } from "@pages/discountsPage";
import { expect, test } from "@playwright/test";
import { expect } from "@playwright/test";
import faker from "faker";
import { test } from "utils/testWithPermission";

test.use({ storageState: "./playwright/.auth/admin.json" });
test.use({ permissionName: "admin" });

let discounts: DiscountsPage;

Expand Down
5 changes: 3 additions & 2 deletions playwright/tests/giftCards.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { MailpitService } from "@api/mailpit";
import { GIFT_CARDS } from "@data/e2eTestData";
import { GiftCardsPage } from "@pages/giftCardsPage";
import { expect, test } from "@playwright/test";
import { expect } from "@playwright/test";
import { test } from "utils/testWithPermission";

test.use({ storageState: "./playwright/.auth/admin.json" });
test.use({ permissionName: "admin" });

let giftCardsPage: GiftCardsPage;
let mailpitService: MailpitService;
Expand Down
Loading

0 comments on commit 371f327

Please sign in to comment.