Skip to content

Commit

Permalink
fix: add ios appium tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kobenguyent committed Nov 2, 2023
1 parent fec2c29 commit f24f568
Show file tree
Hide file tree
Showing 4 changed files with 264 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Appium V2 Tests
name: Appium V2 Tests - Android

on:
push:
Expand Down
59 changes: 59 additions & 0 deletions .github/workflows/appiumV2_iOS.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
name: Appium V2 Tests - iOS

on:
push:
branches:
- 3.x
- appium-v1-deprecation

env:
CI: true
# Force terminal colors. @see https://www.npmjs.com/package/colors
FORCE_COLOR: 1

jobs:
appium1:
runs-on: ubuntu-20.04

strategy:
matrix:
node-version: [16.x]

steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm install --legacy-peer-deps
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: true
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true
- run: 'npm run test:ios:appium-quick'
env: # Or as an environment variable
SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}


appium2:

runs-on: ubuntu-20.04

strategy:
matrix:
node-version: [16.x]

steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm install --legacy-peer-deps
env:
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: true
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: true
- run: 'npm run test:ios:appium-other'
env: # Or as an environment variable
SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
"test": "npm run test:unit && npm run test:runner",
"test:appium-quick": "mocha test/helper/AppiumV2_test.js --grep 'quick'",
"test:appium-other": "mocha test/helper/AppiumV2_test.js --grep 'second'",
"test:ios:appium-quick": "mocha test/helper/AppiumV2_ios_test.js --grep 'quick'",
"test:ios:appium-other": "mocha test/helper/AppiumV2_ios_test.js --grep 'second'",
"test-app:start": "php -S 127.0.0.1:8000 -t test/data/app",
"test-app:stop": "kill -9 $(lsof -t -i:8000)",
"test:unit:webbapi:playwright": "mocha test/helper/Playwright_test.js",
Expand Down
202 changes: 202 additions & 0 deletions test/helper/AppiumV2_ios_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
const assert = require('assert');
const path = require('path');

const Appium = require('../../lib/helper/Appium');
const AssertionFailedError = require('../../lib/assert/error');
const fileExists = require('../../lib/utils').fileExists;
global.codeceptjs = require('../../lib');

let app;
// iOS test app is built from https://github.com/appium/ios-test-app and uploaded to Saucelabs
const apk_path = 'storage:filename=TestApp-iphonesimulator.zip';
const smallWait = 3;

describe('Appium iOS Tests', function () {
this.timeout(0);

before(async () => {
global.codecept_dir = path.join(__dirname, '/../data');
app = new Appium({
app: apk_path,
appiumV2: true,
desiredCapabilities: {
'sauce:options': {
appiumVersion: '2.0.0',
},
browserName: '',
recordVideo: 'false',
recordScreenshots: 'false',
platformName: 'iOS',
platformVersion: '12.2',
deviceName: 'iPhone 8 Simulator',
androidInstallTimeout: 90000,
appWaitDuration: 300000,
},
restart: true,
protocol: 'http',
host: 'ondemand.saucelabs.com',
port: 80,
user: process.env.SAUCE_USERNAME,
key: process.env.SAUCE_ACCESS_KEY,
});
await app._beforeSuite();
app.isWeb = false;
await app._before();
});

after(async () => {
await app._after();
});

describe('app installation : #removeApp', () => {
describe(
'#grabAllContexts, #grabContext, #grabOrientation, #grabSettings',
() => {
it('should grab all available contexts for screen', async () => {
await app.resetApp();
const val = await app.grabAllContexts();
assert.deepEqual(val, ['NATIVE_APP']);
});

it('should grab current context', async () => {
const val = await app.grabContext();
assert.equal(val, 'NATIVE_APP');
});

it('should grab custom settings', async () => {
const val = await app.grabSettings();
assert.deepEqual(val, { imageElementTapStrategy: 'w3cActions' });
});
},
);
});

describe('device orientation : #seeOrientationIs #setOrientation', () => {
it('should return correct status about device orientation', async () => {
await app.seeOrientationIs('PORTRAIT');
try {
await app.seeOrientationIs('LANDSCAPE');
} catch (e) {
e.should.be.instanceOf(AssertionFailedError);
e.inspect().should.include('expected orientation to be LANDSCAPE');
}
});
});

describe('#hideDeviceKeyboard', () => {
it('should hide device Keyboard @quick', async () => {
await app.resetApp();
await app.click('~IntegerA');
try {
await app.click('~locationStatus');
} catch (e) {
e.message.should.include('element');
}
await app.hideDeviceKeyboard('pressKey', 'Done');
await app.click('~locationStatus');
});

it('should assert if no keyboard', async () => {
try {
await app.hideDeviceKeyboard('pressKey', 'Done');
} catch (e) {
e.message.should.include('An unknown server-side error occurred while processing the command. Original error: Soft keyboard not present, cannot hide keyboard');
}
});
});

describe('see text : #see', () => {
it('should work inside elements @second', async () => {
await app.resetApp();
await app.see('Compute Sum', '~ComputeSumButton');
});
});

describe('#appendField', () => {
it('should be able to send special keys to element @second', async () => {
await app.resetApp();
await app.waitForElement('~IntegerA', smallWait);
await app.click('~IntegerA');
await app.appendField('~IntegerA', '1');
await app.hideDeviceKeyboard('pressKey', 'Done');
await app.see('1', '~IntegerA');
});
});

describe('#waitForText', () => {
it('should return error if not present', async () => {
try {
await app.waitForText('Nothing here', 1, '~IntegerA');
} catch (e) {
e.message.should.contain('element (~IntegerA) is not in DOM or there is no element(~IntegerA) with text "Nothing here" after 1 sec');
}
});
});

describe('#seeNumberOfElements @second', () => {
it('should return 1 as count', async () => {
await app.resetApp();
await app.seeNumberOfElements('~IntegerA', 1);
});
});

describe('see element : #seeElement, #dontSeeElement', () => {
it('should check visible elements on page @quick', async () => {
await app.resetApp();
await app.seeElement('~IntegerA');
await app.dontSeeElement('#something-beyond');
await app.dontSeeElement('//input[@id="something-beyond"]');
});
});

describe('#click @quick', () => {
it('should click by accessibility id', async () => {
await app.resetApp();
await app.tap('~ComputeSumButton');
await app.see('0');
});
});

describe('#fillField @second', () => {
it('should fill field by accessibility id', async () => {
await app.resetApp();
await app.waitForElement('~IntegerA', smallWait);
await app.click('~IntegerA');
await app.fillField('~IntegerA', '1');
await app.hideDeviceKeyboard('pressKey', 'Done');
await app.see('1', '~IntegerA');
});
});

describe('#grabTextFrom, #grabValueFrom, #grabAttributeFrom @quick', () => {
it('should grab text from page', async () => {
await app.resetApp();
const val = await app.grabTextFrom('~ComputeSumButton');
assert.equal(val, 'Compute Sum');
});

it('should grab attribute from element', async () => {
await app.resetApp();
const val = await app.grabAttributeFrom('~ComputeSumButton', 'label');
assert.equal(val, 'Compute Sum');
});

it('should be able to grab elements', async () => {
await app.resetApp();
const id = await app.grabNumberOfVisibleElements('~ComputeSumButton');
assert.strictEqual(1, id);
});
});

describe('#saveScreenshot', () => {
beforeEach(() => {
global.output_dir = path.join(global.codecept_dir, 'output');
});

it('should create a screenshot file in output dir', async () => {
const sec = (new Date()).getUTCMilliseconds();
await app.saveScreenshot(`screenshot_${sec}.png`);
assert.ok(fileExists(path.join(global.output_dir, `screenshot_${sec}.png`)), null, 'file does not exists');
});
});
});

0 comments on commit f24f568

Please sign in to comment.