Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ browserstack.err
**/.DS_Store
.vscode/
.env
**/package-lock.json
Binary file modified android/WikipediaSample.apk
Binary file not shown.
2 changes: 2 additions & 0 deletions android/browserstack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ buildIdentifier: '#${BUILD_NUMBER}' # Supports strings along with either/both ${

source: cucumber-js:appium-sample-master:v1.0

CUSTOM_TAG_1: "bstack_sample"

# Set `app` to define the app that is to be used for testing.
# It can either take the id of any uploaded app or the path of the app directly.
app: ./WikipediaSample.apk
Expand Down
3 changes: 3 additions & 0 deletions android/cucumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module.exports = {
default: '--require "features/step_definitions/module*.steps.js" --require features/support/*.js --retry 2 --retryTagFilter @retry'
};
48 changes: 48 additions & 0 deletions android/features/moduleA/moduleA.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
Feature: BStackDemo Tests Module A

#Background:
# Given I skip the Wikipedia onboarding for moduleA
#And I tap on the search bar for moduleA

@p1
Scenario: flaky test - random product selection
When I randomly select a search term and search in moduleA
Then there should be at least one result in moduleA

@regression
Scenario: always failing test - missing element 1
When I try to click a non-existent element "non-existent-1" in moduleA
# No Then step - this should fail on the When step

Scenario: always passing test - example C
Then true should be true in moduleA

Scenario: always failing test - same stacktrace 1
When I try to click a non-existent element "common-error" in moduleA
# No Then step - this should fail on the When step

@regression
Scenario: always failing test - same stacktrace 2
When I try to click a non-existent element "common-error" in moduleA
# No Then step - this should fail on the When step

@regression @must-pass
Scenario: always passing test - example D
Then true should be true in moduleA

@must-pass
Scenario: always passing test - example A
Then 1 plus 1 should be 2 in moduleA

@retry
Scenario: Test with framework-level retry - 2 retries configured
When I run a flaky test with retry in moduleA
Then it should eventually pass or fail in moduleA

@retry
Scenario: Another Test with framework-level retry - 2 retries configured
When I run a flaky test with retry in moduleA
Then it should eventually pass or fail in moduleA

Scenario: always passing test - example B
Then "Browser" plus "Stack" should be "BrowserStack" in moduleA
47 changes: 47 additions & 0 deletions android/features/moduleB/moduleB.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
Feature: BStackDemo Tests Module B

#Background:
# Given I skip the Wikipedia onboarding for moduleB
# And I tap on the search bar for moduleB

@regression @p1
Scenario: flaky test - random product selection
When I randomly select a search term and search in moduleB
Then there should be at least one result in moduleB

Scenario: always failing test - missing element 1
When I try to click a non-existent element "non-existent-1" in moduleB
# No Then step - this should fail on the When step

@regression
Scenario: always passing test - example C
Then true should be true in moduleB

Scenario: always failing test - same stacktrace 1
When I try to click a non-existent element "common-error" in moduleB
# No Then step - this should fail on the When step

Scenario: always failing test - same stacktrace 2
When I try to click a non-existent element "common-error" in moduleB
# No Then step - this should fail on the When step

@regression
Scenario: always passing test - example D
Then true should be true in moduleB

@regression
Scenario: always passing test - example A
Then 1 plus 1 should be 2 in moduleB

@retry
Scenario: Test with framework-level retry - 2 retries configured
When I run a flaky test with retry in moduleB
Then it should eventually pass or fail in moduleB

@retry
Scenario: Another Test with framework-level retry - 2 retries configured
When I run a flaky test with retry in moduleB
Then it should eventually pass or fail in moduleB

Scenario: always passing test - example B
Then "Browser" plus "Stack" should be "BrowserStack" in moduleB
47 changes: 47 additions & 0 deletions android/features/moduleC/moduleC.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
Feature: BStackDemo Tests Module C

#Background:
# Given I skip the Wikipedia onboarding for moduleC
# And I tap on the search bar for moduleC

@p1
Scenario: flaky test - random product selection
When I randomly select a search term and search in moduleC
Then there should be at least one result in moduleC

Scenario: always failing test - missing element 1
When I try to click a non-existent element "non-existent-1" in moduleC
# No Then step - this should fail on the When step

Scenario: always passing test - example C
Then true should be true in moduleC

@must-pass
Scenario: always passing test - example D
Then true should be true in moduleC

Scenario: always failing test - same stacktrace 1
When I try to click a non-existent element "common-error" in moduleC
# No Then step - this should fail on the When step

Scenario: always failing test - same stacktrace 2
When I try to click a non-existent element "common-error" in moduleC
# No Then step - this should fail on the When step

@p1 @must-pass
Scenario: always passing test - example A
Then 1 plus 1 should be 2 in moduleC

@retry
Scenario: Test with framework-level retry - 2 retries configured
When I run a flaky test with retry in moduleC
Then it should eventually pass or fail in moduleC

@retry
Scenario: Another Test with framework-level retry - 2 retries configured
When I run a flaky test with retry in moduleC
Then it should eventually pass or fail in moduleC

@must-pass
Scenario: always passing test - example B
Then "Browser" plus "Stack" should be "BrowserStack" in moduleC
83 changes: 83 additions & 0 deletions android/features/step_definitions/moduleA.steps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
const { Given, When, Then, setDefaultTimeout } = require('@cucumber/cucumber');
const { By, until } = require('selenium-webdriver');
const assert = require('assert');

// Increase timeout for Appium commands
setDefaultTimeout(60 * 1000);

// Background steps
Given('I skip the Wikipedia onboarding for moduleA', async function() {
const skipButton = await this.driver.wait(
until.elementLocated(By.id('org.wikipedia.alpha:id/fragment_onboarding_skip_button')),
30000
);
await skipButton.click();
});

Given('I tap on the search bar for moduleA', async function() {
const searchSelector = await this.driver.wait(
until.elementLocated(By.xpath("//*[@content-desc='Search Wikipedia']")),
30000
);
await searchSelector.click();
});

// Module A specific step implementations - will fail naturally without try/catch
When('I randomly select a search term and search in moduleA', async function() {
const useValidSelector = Math.random() > 0.5;
let searchField;

if (useValidSelector) {
searchField = await this.driver.wait(
until.elementLocated(By.id('org.wikipedia.alpha:id/search_src_text')),
30000
);
} else {
// This will fail naturally
searchField = await this.driver.wait(
until.elementLocated(By.id('falseSelector')),
5000
);
}

const randomTerm = Math.random() > 0.5 ? "BrowserStack" : "akjsdhfakjsdhf";
await searchField.sendKeys(randomTerm);
await this.driver.sleep(5000);
});

Then('there should be at least one result in moduleA', async function() {
const allResults = await this.driver.findElements(By.className('android.widget.TextView'));
assert(allResults.length > 0, 'Expected to find at least one result');
});

// This will fail naturally without try/catch
When('I try to click a non-existent element {string} in moduleA', async function(elementName) {
const nonExistent = await this.driver.wait(
until.elementLocated(By.xpath(`//*[@content-desc='${elementName}']`)),
3000
);
await nonExistent.click();
});

Then('true should be true in moduleA', function() {
assert.strictEqual(true, true);
});

Then('1 plus 1 should be 2 in moduleA', function() {
assert.strictEqual(1 + 1, 2);
});

When('I run a flaky test with retry in moduleA', function() {
const randomOutcome = Math.random() > 0.7;
if (!randomOutcome) {
throw new Error("Test failed, will retry...");
}
});

Then('it should eventually pass or fail in moduleA', function() {
// No-op
});

Then('{string} plus {string} should be {string} in moduleA', function(a, b, expected) {
assert.strictEqual(a + b, expected);
});
83 changes: 83 additions & 0 deletions android/features/step_definitions/moduleB.steps.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
const { Given, When, Then, setDefaultTimeout } = require('@cucumber/cucumber');
const { By, until } = require('selenium-webdriver');
const assert = require('assert');

// Increase timeout for Appium commands
setDefaultTimeout(60 * 1000);

// Background steps
Given('I skip the Wikipedia onboarding for moduleB', async function() {
const skipButton = await this.driver.wait(
until.elementLocated(By.id('org.wikipedia.alpha:id/fragment_onboarding_skip_button')),
30000
);
await skipButton.click();
});

Given('I tap on the search bar for moduleB', async function() {
const searchSelector = await this.driver.wait(
until.elementLocated(By.xpath("//*[@content-desc='Search Wikipedia']")),
30000
);
await searchSelector.click();
});

// Module B specific step implementations - will fail naturally without try/catch
When('I randomly select a search term and search in moduleB', async function() {
const useValidSelector = Math.random() > 0.5;
let searchField;

if (useValidSelector) {
searchField = await this.driver.wait(
until.elementLocated(By.id('org.wikipedia.alpha:id/search_src_text')),
30000
);
} else {
// This will fail naturally
searchField = await this.driver.wait(
until.elementLocated(By.id('falseSelector')),
5000
);
}

const randomTerm = Math.random() > 0.5 ? "BrowserStack" : "akjsdhfakjsdhf";
await searchField.sendKeys(randomTerm);
await this.driver.sleep(5000);
});

Then('there should be at least one result in moduleB', async function() {
const allResults = await this.driver.findElements(By.className('android.widget.TextView'));
assert(allResults.length > 0, 'Expected to find at least one result');
});

// This will fail naturally without try/catch
When('I try to click a non-existent element {string} in moduleB', async function(elementName) {
const nonExistent = await this.driver.wait(
until.elementLocated(By.xpath(`//*[@content-desc='${elementName}']`)),
3000
);
await nonExistent.click();
});

Then('true should be true in moduleB', function() {
assert.strictEqual(true, true);
});

Then('1 plus 1 should be 2 in moduleB', function() {
assert.strictEqual(1 + 1, 2);
});

When('I run a flaky test with retry in moduleB', function() {
const randomOutcome = Math.random() > 0.7;
if (!randomOutcome) {
throw new Error("Test failed, will retry...");
}
});

Then('it should eventually pass or fail in moduleB', function() {
// No-op
});

Then('{string} plus {string} should be {string} in moduleB', function(a, b, expected) {
assert.strictEqual(a + b, expected);
});
Loading