Skip to content

Commit 283ce0e

Browse files
Merge branch 'main' into sdk
2 parents bc57d6b + d1d329c commit 283ce0e

File tree

5 files changed

+919
-1114
lines changed

5 files changed

+919
-1114
lines changed

.github/workflows/sanity-workflow.yml

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# This job is to test different maven profiles in sdk branch against full commit-id provided
2+
# This workflow targets Playwright execution
3+
4+
name: NodeJS SDK Test workflow on workflow_dispatch
5+
6+
on:
7+
workflow_dispatch:
8+
inputs:
9+
commit_sha:
10+
description: 'The full commit id to build'
11+
required: true
12+
package_url:
13+
description: 'Staging package url'
14+
required: false
15+
16+
jobs:
17+
comment-run:
18+
runs-on: ${{ matrix.os }}
19+
strategy:
20+
fail-fast: false
21+
max-parallel: 3
22+
matrix:
23+
node: ['14', '16', '18', '20']
24+
os: [ macos-latest, windows-latest, ubuntu-latest ]
25+
name: NodeJS Playwright Repo ${{ matrix.node }} - ${{ matrix.os }} Sample
26+
env:
27+
BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
28+
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
29+
PACKAGE_URL: ${{ github.event.inputs.package_url }}
30+
31+
steps:
32+
- uses: actions/checkout@v3
33+
with:
34+
ref: ${{ github.event.inputs.commit_sha }}
35+
- uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975
36+
id: status-check-in-progress
37+
env:
38+
job_name: NodeJS Playwright Repo ${{ matrix.node }} - ${{ matrix.os }} Sample
39+
commit_sha: ${{ github.event.inputs.commit_sha }}
40+
with:
41+
github-token: ${{ github.token }}
42+
script: |
43+
const result = await github.rest.checks.create({
44+
owner: context.repo.owner,
45+
repo: context.repo.repo,
46+
name: process.env.job_name,
47+
head_sha: process.env.commit_sha,
48+
status: 'in_progress'
49+
}).catch((err) => ({status: err.status, response: err.response}));
50+
console.log(`The status-check response : ${result.status} Response : ${JSON.stringify(result.response)}`)
51+
if (result.status !== 201) {
52+
console.log('Failed to create check run')
53+
}
54+
- name: Setup node
55+
uses: actions/setup-node@v3
56+
with:
57+
node-version: ${{ matrix.node }}
58+
59+
- name: Setup staging npm package
60+
if: ${{ github.event.inputs.package_url != '' }}
61+
run: |
62+
echo 'Publishing tar.gz to local registry'
63+
curl -o staging_package.tgz "$PACKAGE_URL"
64+
npm install [email protected] -g
65+
verdaccio &
66+
npm config set registry http://localhost:4873
67+
npm install -g npm-cli-adduser && npm-cli-adduser -u dummy -p dummy -e [email protected] -r http://localhost:4873
68+
npm publish staging_package.tgz --registry http://localhost:4873/
69+
shell: bash
70+
71+
- name: Install dependencies
72+
run: npm install
73+
74+
- name: Run sample tests
75+
run: npm run sample-test
76+
77+
- name: Run local tests
78+
run: npm run sample-local-test
79+
80+
- if: always()
81+
uses: actions/github-script@98814c53be79b1d30f795b907e553d8679345975
82+
id: status-check-completed
83+
env:
84+
conclusion: ${{ job.status }}
85+
job_name: NodeJS Playwright Repo ${{ matrix.node }} - ${{ matrix.os }} Sample
86+
commit_sha: ${{ github.event.inputs.commit_sha }}
87+
with:
88+
github-token: ${{ github.token }}
89+
script: |
90+
const result = await github.rest.checks.create({
91+
owner: context.repo.owner,
92+
repo: context.repo.repo,
93+
name: process.env.job_name,
94+
head_sha: process.env.commit_sha,
95+
status: 'completed',
96+
conclusion: process.env.conclusion
97+
}).catch((err) => ({status: err.status, response: err.response}));
98+
console.log(`The status-check response : ${result.status} Response : ${JSON.stringify(result.response)}`)
99+
if (result.status !== 201) {
100+
console.log('Failed to create check run')
101+
}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ node_modules
22
playwright-report
33
test-results
44
log/
5+
package-lock.json
56
local.log

fixture.js

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
const base = require("@playwright/test");
2+
const cp = require("child_process");
3+
const { _android } = require("playwright");
4+
const clientPlaywrightVersion = cp
5+
.execSync("npx playwright --version")
6+
.toString()
7+
.trim()
8+
.split(" ")[1];
9+
const BrowserStackLocal = require("browserstack-local");
10+
const util = require("util");
11+
12+
// BrowserStack Specific Capabilities.
13+
// Set 'browserstack.local:true For Local testing
14+
const caps = {
15+
osVersion: "13.0",
16+
deviceName: "Samsung Galaxy S23", // "Samsung Galaxy S22 Ultra", "Google Pixel 7 Pro", "OnePlus 9", etc.
17+
browserName: "chrome",
18+
realMobile: "true",
19+
name: "My android playwright test",
20+
build: "playwright-build-1",
21+
"browserstack.username": process.env.BROWSERSTACK_USERNAME || "<USERNAME>",
22+
"browserstack.accessKey":
23+
process.env.BROWSERSTACK_ACCESS_KEY || "<ACCESS_KEY>",
24+
"browserstack.local": process.env.BROWSERSTACK_LOCAL || false,
25+
};
26+
27+
exports.bsLocal = new BrowserStackLocal.Local();
28+
29+
// replace YOUR_ACCESS_KEY with your key. You can also set an environment variable - "BROWSERSTACK_ACCESS_KEY".
30+
exports.BS_LOCAL_ARGS = {
31+
key: process.env.BROWSERSTACK_ACCESS_KEY || "ACCESSKEY",
32+
};
33+
34+
// Patching the capabilities dynamically according to the project name.
35+
const patchMobileCaps = (name, title) => {
36+
let combination = name.split(/@browserstack/)[0];
37+
let [browerCaps, osCaps] = combination.split(/:/);
38+
let [browser, deviceName] = browerCaps.split(/@/);
39+
let osCapsSplit = osCaps.split(/ /);
40+
let os = osCapsSplit.shift();
41+
let osVersion = osCapsSplit.join(" ");
42+
caps.browser = browser ? browser : "chrome";
43+
caps.deviceName = deviceName ? deviceName : "Samsung Galaxy S22 Ultra";
44+
caps.osVersion = osVersion ? osVersion : "12.0";
45+
caps.name = title;
46+
caps.realMobile = "true";
47+
};
48+
49+
const patchCaps = (name, title) => {
50+
let combination = name.split(/@browserstack/)[0];
51+
let [browerCaps, osCaps] = combination.split(/:/);
52+
let [browser, browser_version] = browerCaps.split(/@/);
53+
let osCapsSplit = osCaps.split(/ /);
54+
let os = osCapsSplit.shift();
55+
let os_version = osCapsSplit.join(" ");
56+
caps.browser = browser ? browser : "chrome";
57+
caps.browser_version = browser_version ? browser_version : "latest";
58+
caps.os = os ? os : "osx";
59+
caps.os_version = os_version ? os_version : "catalina";
60+
caps.name = title;
61+
};
62+
63+
const isHash = (entity) =>
64+
Boolean(entity && typeof entity === "object" && !Array.isArray(entity));
65+
const nestedKeyValue = (hash, keys) =>
66+
keys.reduce((hash, key) => (isHash(hash) ? hash[key] : undefined), hash);
67+
const isUndefined = (val) => val === undefined || val === null || val === "";
68+
const evaluateSessionStatus = (status) => {
69+
if (!isUndefined(status)) {
70+
status = status.toLowerCase();
71+
}
72+
if (status === "passed") {
73+
return "passed";
74+
} else if (status === "failed" || status === "timedout") {
75+
return "failed";
76+
} else {
77+
return "";
78+
}
79+
};
80+
81+
exports.test = base.test.extend({
82+
page: async ({ page, playwright }, use, testInfo) => {
83+
if (testInfo.project.name.match(/browserstack/)) {
84+
let vBrowser, vContext, vDevice;
85+
const isMobile = testInfo.project.name.match(/browserstack-mobile/);
86+
if (isMobile) {
87+
patchMobileCaps(
88+
testInfo.project.name,
89+
`${testInfo.file} - ${testInfo.title}`
90+
);
91+
vDevice = await playwright._android.connect(
92+
`wss://cdp.browserstack.com/playwright?caps=${encodeURIComponent(
93+
JSON.stringify(caps)
94+
)}`
95+
);
96+
await vDevice.shell("am force-stop com.android.chrome");
97+
vContext = await vDevice.launchBrowser();
98+
} else {
99+
patchCaps(testInfo.project.name, `${testInfo.title}`);
100+
delete caps.osVersion;
101+
delete caps.deviceName;
102+
delete caps.realMobile;
103+
vBrowser = await playwright.chromium.connect({
104+
wsEndpoint:
105+
`wss://cdp.browserstack.com/playwright?caps=` +
106+
`${encodeURIComponent(JSON.stringify(caps))}`,
107+
});
108+
vContext = await vBrowser.newContext(testInfo.project.use);
109+
}
110+
const vPage = await vContext.newPage();
111+
await use(vPage);
112+
113+
await vPage.close();
114+
115+
if (isMobile) {
116+
await vDevice.close();
117+
} else {
118+
await vBrowser.close();
119+
}
120+
} else {
121+
use(page);
122+
}
123+
},
124+
125+
beforeEach: [
126+
async ({ page }, use) => {
127+
await page
128+
.context()
129+
.tracing.start({ screenshots: true, snapshots: true, sources: true });
130+
await use();
131+
},
132+
{ auto: true },
133+
],
134+
135+
afterEach: [
136+
async ({ page }, use, testInfo) => {
137+
await use();
138+
if (testInfo.status == "failed") {
139+
await page
140+
.context()
141+
.tracing.stop({ path: `${testInfo.outputDir}/trace.zip` });
142+
await page.screenshot({ path: `${testInfo.outputDir}/screenshot.png` });
143+
await testInfo.attach("screenshot", {
144+
path: `${testInfo.outputDir}/screenshot.png`,
145+
contentType: "image/png",
146+
});
147+
await testInfo.attach("trace", {
148+
path: `${testInfo.outputDir}/trace.zip`,
149+
contentType: "application/zip",
150+
});
151+
}
152+
},
153+
{ auto: true },
154+
],
155+
});

local.log

14.1 KB
Binary file not shown.

0 commit comments

Comments
 (0)