forked from appium/appium-xcuitest-driver
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbasic-e2e-specs.js
270 lines (239 loc) · 9.17 KB
/
basic-e2e-specs.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
import chai from 'chai';
import chaiAsPromised from 'chai-as-promised';
import chaiSubset from 'chai-subset';
import B from 'bluebird';
import util from 'util';
import {retryInterval} from 'asyncbox';
import {amendCapabilities, UICATALOG_CAPS, UICATALOG_BUNDLE_ID} from '../desired';
import {initSession, deleteSession, getUsePrebuiltWDACaps, MOCHA_TIMEOUT} from '../helpers/session';
import {GUINEA_PIG_PAGE} from '../web/helpers';
import sharp from 'sharp';
chai.should();
chai.use(chaiAsPromised);
chai.use(chaiSubset);
describe('XCUITestDriver - basics -', function () {
this.timeout(MOCHA_TIMEOUT);
let driver;
before(async function () {
const caps = amendCapabilities(UICATALOG_CAPS, await getUsePrebuiltWDACaps());
driver = await initSession(caps);
});
after(async function () {
try {
await driver.terminateApp(UICATALOG_BUNDLE_ID);
} catch (e) {
// eslint-disable-next-line no-console
console.error(e);
}
await deleteSession();
});
describe('status -', function () {
it('should get the server status', async function () {
let status = await driver.status();
status.build.version.should.exist;
});
it('should return status immediately if another operation is in progress', async function () {
await driver.setImplicitTimeout(10000);
const findElementPromise = driver.$('#WrongLocator');
const status = await driver.status();
status.build.version.should.exist;
util.inspect(findElementPromise).includes('pending').should.be.true;
try {
await findElementPromise;
} catch (err) {
err.status.should.eql(7);
}
});
});
describe('source -', function () {
function checkSource(src) {
// should have full elements
src.should.include('<AppiumAUT>');
src.should.include('<XCUIElementTypeApplication');
// should not have any XCTest errors
src.should.not.include('AX error');
}
describe('plain -', function () {
it('should get the source for the page', async function () {
let src = await driver.getPageSource();
(typeof src).should.eql('string');
checkSource(src);
});
});
describe('json parsed -', function () {
it('should get source with useJSONSource', async function () {
await driver.updateSettings({useJSONSource: true});
let src = await driver.getPageSource();
checkSource(src);
});
});
});
describe('deactivate app -', function () {
it('should background the app for the specified time', async function () {
let before = Date.now();
await driver.background(4);
(Date.now() - before).should.be.above(4000);
(await driver.getPageSource()).indexOf('<AppiumAUT>').should.not.eql(-1);
});
});
describe('screenshot -', function () {
after(async function () {
try {
await driver.setOrientation('PORTRAIT');
} catch (ign) {}
});
it('should get an app screenshot', async function () {
let screenshot = await driver.takeScreenshot();
screenshot.should.exist;
screenshot.should.be.a('string');
// make sure WDA didn't crash, by using it again
let els = await driver.$$('~Alert Views');
els.length.should.eql(1);
});
it('should get an app screenshot in landscape mode', async function () {
let screenshot1 = await driver.takeScreenshot();
screenshot1.should.exist;
try {
await driver.setOrientation('LANDSCAPE');
} catch (ign) {}
// take a little pause while it orients, otherwise you get the screenshot
// on an angle
await B.delay(500);
let screenshot2 = await driver.takeScreenshot();
screenshot2.should.exist;
screenshot2.should.not.eql(screenshot1);
});
});
describe('viewportScreenshot -', function () {
it('should get a cropped screenshot of the viewport without statusbar', async function () {
const {statusBarSize, scale} = await driver.execute('mobile: deviceScreenInfo');
const viewportRect = await driver.execute('mobile: viewportRect');
const fullScreen = await driver.takeScreenshot();
const viewScreen = await driver.execute('mobile: viewportScreenshot');
const fullImg = sharp(Buffer.from(fullScreen, 'base64'));
const {width: fullImgWidth, height: fullImgHeight} = await fullImg.metadata();
const viewImg = sharp(Buffer.from(viewScreen, 'base64'));
const {width: viewImgWidth, height: viewImgHeight} = await viewImg.metadata();
if (
fullImgWidth === undefined ||
fullImgHeight === undefined ||
viewImgWidth === undefined ||
viewImgHeight === undefined
) {
throw new Error('Image dimensions must not be undefined');
}
// Viewport size can be smaller than the full image size + status bar on some devices.
fullImgHeight.should.be.gte(viewImgHeight + Math.round(scale * statusBarSize.height));
viewImgHeight.should.eql(viewportRect.height);
fullImgWidth.should.be.gte(viewImgWidth);
});
});
describe('logging -', function () {
describe('types -', function () {
it('should get the list of available logs', async function () {
const expectedTypes = ['syslog', 'crashlog', 'performance', 'server', 'safariConsole'];
const actualTypes = await driver.getLogTypes();
actualTypes.should.containSubset(expectedTypes);
});
});
describe('retrieval -', function () {
it('should throw an error when an invalid type is given', async function () {
await driver.getLogs('something-random').should.be.rejected;
});
it('should get system logs', async function () {
(await driver.getLogs('syslog')).should.be.an('array');
});
it('should get crash logs', async function () {
(await driver.getLogs('crashlog')).should.be.an('array');
});
});
});
describe('orientation -', function () {
beforeEach(async function () {
await driver.setOrientation('PORTRAIT');
});
afterEach(async function () {
await driver.setOrientation('PORTRAIT');
});
it('should get the current orientation', async function () {
let orientation = await driver.getOrientation();
['PORTRAIT', 'LANDSCAPE'].should.include(orientation);
});
it('should set the orientation', async function () {
await driver.setOrientation('LANDSCAPE');
(await driver.getOrientation()).should.eql('LANDSCAPE');
});
it('should be able to interact with an element in LANDSCAPE', async function () {
await driver.setOrientation('LANDSCAPE');
let el = await driver.$('#Buttons');
await el.click();
await driver.findElement('css selector', '#Button').should.not.be.rejected;
await driver.back();
});
});
describe('window size -', function () {
it('should be able to get the current window size', async function () {
let size = await driver.getWindowSize();
size.width.should.be.a('number');
size.height.should.be.a('number');
});
});
describe('get geo location -', function () {
it('should fail because of preference error', async function () {
await driver.getGeoLocation().should.be.rejectedWith('Location service must be');
});
});
describe('geo location -', function () {
it('should work on Simulator', async function () {
if (process.env.CI) {
// skip on Travis, since Appium process should have access to system accessibility
// in order to run this method successfully
return this.skip();
}
await driver.setGeoLocation({latitude: '30.0001', longitude: '21.0002'}).should.not.be
.rejected;
});
});
describe('shake -', function () {
it('should work on Simulator', async function () {
if (process.env.CI) {
// skip on Travis, since Appium process should have access to system accessibility
// in order to run this method successfully
return this.skip();
}
await driver.shake().should.not.be.rejected;
});
});
describe('lock -', function () {
it('should properly lock and unlock the device', async function () {
try {
await driver.lock();
(await driver.isLocked()).should.be.true;
} finally {
await driver.unlock();
}
(await driver.isLocked()).should.be.false;
});
});
describe('contexts -', function () {
before(async function () {
await driver.execute('mobile: scroll', {direction: 'down'});
await driver.$('~Web View').click();
});
after(async function () {
await driver.back();
await driver.execute('mobile: scroll', {direction: 'up'});
});
it('should start a session, navigate to url, get title', async function () {
// on some systems (like Travis) it takes a while to load the webview
const contexts = await driver.execute('mobile: getContexts', {waitForWebviewMs: 1000});
await driver.switchContext(contexts[1].id);
await driver.navigateTo(GUINEA_PIG_PAGE);
await retryInterval(100, 1000, async function () {
let title = await driver.getTitle();
title.should.equal('I am a page title');
});
await driver.switchContext(contexts[0].id);
});
});
});