Compare commits
1
Commits
develop
...
visual-jamie
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9810b08f21 |
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"testRunner": "jest",
|
||||||
|
"testRegex": "\\.visual\\.js$",
|
||||||
|
|
||||||
|
"devices": {
|
||||||
|
|
||||||
|
"simulator": {
|
||||||
|
"type": "ios.simulator",
|
||||||
|
"device": {
|
||||||
|
"type": "iPhone 11 Pro"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"apps": {
|
||||||
|
"ios.release": {
|
||||||
|
"name": "StatusIm",
|
||||||
|
"type": "ios.app",
|
||||||
|
"binaryPath": "ios/build/Build/Products/Release-iphonesimulator/StatusIm.app",
|
||||||
|
"build": "make release-ios"
|
||||||
|
},
|
||||||
|
"ios.debug": {
|
||||||
|
"name": "StatusIm",
|
||||||
|
"type": "ios.app",
|
||||||
|
"binaryPath": "/Users/erik/Library/Developer/Xcode/DerivedData/StatusIm-dkjkfsbgallhrnchhutvuvbicfsa/Build/Products/Debug-iphonesimulator/StatusIm.app",
|
||||||
|
"build": "make run-ios SIMULATOR='iPhone 11 Pro'"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"configurations": {
|
||||||
|
"ios.sim.release": {
|
||||||
|
"device": "simulator",
|
||||||
|
"app": "ios.release"
|
||||||
|
},
|
||||||
|
"ios.sim.debug": {
|
||||||
|
"device": "simulator",
|
||||||
|
"app": "ios.debug"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
const waitToNavigate = duration => new Promise(resolve => setTimeout(() => resolve(), duration));
|
||||||
|
|
||||||
|
describe('Example (hello)', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
if (device.getPlatform() === 'ios') {
|
||||||
|
await device.setStatusBar({ time: '12:34', dataNetwork: 'wifi', wifiBars: '3', batteryState: 'charging', batteryLevel: '100' });
|
||||||
|
}
|
||||||
|
await device.reloadReactNative();
|
||||||
|
|
||||||
|
await element(by.text('I accept Status Terms of Use')).tap();
|
||||||
|
// close alert
|
||||||
|
await element(by.text('Get started')).tap();
|
||||||
|
await waitToNavigate(200);
|
||||||
|
|
||||||
|
await element(by.text('Generate keys')).tap();
|
||||||
|
await waitToNavigate(200);
|
||||||
|
|
||||||
|
await element(by.text('Next')).tap();
|
||||||
|
await waitToNavigate(700);
|
||||||
|
await element(by.text('Next')).tap();
|
||||||
|
await waitToNavigate(700);
|
||||||
|
// await element(by.text('Password...')).typeText('infinitbility@gmail.com');
|
||||||
|
// await element(by.text('Confirm your password...')).typeText('infinitbility@gmail.com');
|
||||||
|
await element(by.text('Next')).tap();
|
||||||
|
await waitToNavigate(700);
|
||||||
|
await element(by.text('Maybe later')).tap();
|
||||||
|
await waitToNavigate(700);
|
||||||
|
await element(by.text("Let's go")).tap();
|
||||||
|
await waitToNavigate(700);
|
||||||
|
|
||||||
|
await element(by.text("1")).tap();
|
||||||
|
await waitToNavigate(400);
|
||||||
|
await element(by.text("Quo2.0 Preview")).tap();
|
||||||
|
await waitToNavigate(400);
|
||||||
|
})
|
||||||
|
beforeEach(async () => {
|
||||||
|
});
|
||||||
|
afterEach(async () => {
|
||||||
|
await element(by.text("1")).tap();
|
||||||
|
await waitToNavigate(200);
|
||||||
|
await element(by.text("Quo2.0 Preview")).tap();
|
||||||
|
await waitToNavigate(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it(`button page should match snapshot`, async () => {
|
||||||
|
await element(by.text(`:button`)).tap();
|
||||||
|
await waitToNavigate(200);
|
||||||
|
const res = await jestExpect(`default-render-button`).toMatchImageSnapshot();
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"globalSetup": "./global-setup.js",
|
||||||
|
"globalTeardown": "./global-teardown.js",
|
||||||
|
"setupFilesAfterEnv": ["./setup.js"],
|
||||||
|
"maxWorkers": 1,
|
||||||
|
"testEnvironment": "./environment",
|
||||||
|
"testRunner": "jest-circus/runner",
|
||||||
|
"testTimeout": 120000,
|
||||||
|
"testRegex": "\\.e2e\\.js$",
|
||||||
|
|
||||||
|
"reporters": ["detox/runners/jest/streamlineReporter"],
|
||||||
|
"verbose": true
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
const {
|
||||||
|
DetoxCircusEnvironment,
|
||||||
|
SpecReporter,
|
||||||
|
WorkerAssignReporter,
|
||||||
|
} = require('detox/runners/jest-circus');
|
||||||
|
|
||||||
|
class CustomDetoxEnvironment extends DetoxCircusEnvironment {
|
||||||
|
constructor(config, context) {
|
||||||
|
super(config, context);
|
||||||
|
|
||||||
|
// Can be safely removed, if you are content with the default value (=300000ms)
|
||||||
|
this.initTimeout = 300000;
|
||||||
|
|
||||||
|
// This takes care of generating status logs on a per-spec basis. By default, Jest only reports at file-level.
|
||||||
|
// This is strictly optional.
|
||||||
|
this.registerListeners({
|
||||||
|
SpecReporter,
|
||||||
|
WorkerAssignReporter,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = CustomDetoxEnvironment;
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
const fs = require('fs-extra');
|
||||||
|
const { execSync } = require('child_process');
|
||||||
|
const detox = require('detox');
|
||||||
|
|
||||||
|
async function globalSetup() {
|
||||||
|
const config = resolveSelectedConfiguration() || {};
|
||||||
|
downloadTestButlerAPKIfNeeded(config);
|
||||||
|
await detox.globalInit();
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadTestButlerAPKIfNeeded(config) {
|
||||||
|
if (isAndroidConfig(config)) {
|
||||||
|
downloadTestButlerAPK();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadTestButlerAPK() {
|
||||||
|
const version = '2.2.1';
|
||||||
|
const artifactUrl = `https://repo1.maven.org/maven2/com/linkedin/testbutler/test-butler-app/${version}/test-butler-app-${version}.apk`;
|
||||||
|
const filePath = `./cache/test-butler-app.apk`;
|
||||||
|
|
||||||
|
fs.ensureDirSync('./cache');
|
||||||
|
if (!fs.existsSync(filePath)) {
|
||||||
|
console.log(`\nDownloading Test-Butler APK v${version}...`);
|
||||||
|
execSync(`curl -f -o ${filePath} ${artifactUrl}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveSelectedConfiguration() {
|
||||||
|
const { configurations } = require('../.detoxrc.json');
|
||||||
|
const configName = process.env.DETOX_CONFIGURATION;
|
||||||
|
return configurations[configName];
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO eventually, this should be made available by Detox more explicitly
|
||||||
|
function isAndroidConfig(config) {
|
||||||
|
return [config.type, process.env.DETOX_CONFIGURATION, config.device].some(s => `${s}`.includes('android'));
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = globalSetup;
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
const detox = require('detox');
|
||||||
|
|
||||||
|
async function globalTeardown() {
|
||||||
|
await detox.globalCleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = globalTeardown;
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
const { configureToMatchImageSnapshot } = require('jest-image-snapshot');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const kebabCase = require('lodash/kebabCase');
|
||||||
|
const {expect} = require('expect');
|
||||||
|
|
||||||
|
|
||||||
|
const toMatchImage = configureToMatchImageSnapshot({
|
||||||
|
comparisonMethod: 'ssim', failureThreshold: 0.002, failureThresholdType: 'percent'
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
expect.extend({ toMatchImage });
|
||||||
|
|
||||||
|
expect.extend({
|
||||||
|
async toMatchImageSnapshot(screenName) {
|
||||||
|
const platform = await device.getPlatform();
|
||||||
|
const deviceName = await device.name.split(' ').slice(1).join ('') ;
|
||||||
|
const deviceType = 'iPhone 11 Pro' //JSON.parse(deviceName).type.replace(',','');
|
||||||
|
|
||||||
|
const SNAPSHOTS_DIR = `__image_snapshots__/${platform}/${deviceType}`;
|
||||||
|
|
||||||
|
const { testPath, currentTestName } = this;
|
||||||
|
|
||||||
|
const customSnapshotsDir = path.join(path.dirname(testPath), SNAPSHOTS_DIR);
|
||||||
|
const customSnapshotIdentifier = kebabCase(`${path.basename(testPath)}-${currentTestName}-${screenName}`)
|
||||||
|
|
||||||
|
const tempPath = await device.takeScreenshot(screenName);
|
||||||
|
const image = fs.readFileSync(tempPath);
|
||||||
|
expect(image).toMatchImage({ customSnapshotIdentifier, customSnapshotsDir });
|
||||||
|
|
||||||
|
return { pass: true }
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
global.jestExpect = expect
|
||||||
|
|
||||||
|
|
||||||
|
beforeAll(async () => {
|
||||||
|
await device.launchApp();
|
||||||
|
});
|
||||||
+1
-1
@@ -640,7 +640,7 @@ SPEC CHECKSUMS:
|
|||||||
FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e
|
FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e
|
||||||
FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e
|
FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e
|
||||||
Folly: b73c3869541e86821df3c387eb0af5f65addfab4
|
Folly: b73c3869541e86821df3c387eb0af5f65addfab4
|
||||||
glog: 36ce0530c6d2c3a5a4326885ef4069564887a1db
|
glog: 997518ea2aa2d8cd5df9797b641b758d52ecf2bc
|
||||||
HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352
|
HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352
|
||||||
Keycard: ac6df4d91525c3c82635ac24d4ddd9a80aca5fc8
|
Keycard: ac6df4d91525c3c82635ac24d4ddd9a80aca5fc8
|
||||||
libwebp: 60305b2e989864154bd9be3d772730f08fc6a59c
|
libwebp: 60305b2e989864154bd9be3d772730f08fc6a59c
|
||||||
|
|||||||
+9
-2
@@ -10,7 +10,11 @@
|
|||||||
"app:compile:android": "shadow-cljs compile android",
|
"app:compile:android": "shadow-cljs compile android",
|
||||||
"app:watch": "shadow-cljs watch android",
|
"app:watch": "shadow-cljs watch android",
|
||||||
"app:packager": "react-native start --host 0.0.0.0 --port 8081",
|
"app:packager": "react-native start --host 0.0.0.0 --port 8081",
|
||||||
"app:android": "react-native run-android"
|
"app:android": "react-native run-android",
|
||||||
|
"detox": "detox build --configuration ios.sim.debug",
|
||||||
|
"visual-test": "detox test --configuration ios.sim.debug --config e2e/config.json",
|
||||||
|
"help": "detox test -- --help"
|
||||||
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/preset-typescript": "^7.17.12",
|
"@babel/preset-typescript": "^7.17.12",
|
||||||
@@ -80,7 +84,10 @@
|
|||||||
"@babel/preset-env": "7.1.0",
|
"@babel/preset-env": "7.1.0",
|
||||||
"@babel/register": "7.0.0",
|
"@babel/register": "7.0.0",
|
||||||
"@mapbox/node-pre-gyp": "^1.0.9",
|
"@mapbox/node-pre-gyp": "^1.0.9",
|
||||||
"jest": "^25.1.0",
|
"@types/jest": "^28.1.6",
|
||||||
|
"detox": "^19.9.1",
|
||||||
|
"jest-image-snapshot": "^5.1.0",
|
||||||
|
"jest": "^28.1.3",
|
||||||
"nodemon": "^2.0.16",
|
"nodemon": "^2.0.16",
|
||||||
"nyc": "^14.1.1",
|
"nyc": "^14.1.1",
|
||||||
"process": "0.11.10",
|
"process": "0.11.10",
|
||||||
|
|||||||
@@ -0,0 +1,55 @@
|
|||||||
|
const data = require('./visual-tests.json')
|
||||||
|
|
||||||
|
const waitToNavigate = duration => new Promise(resolve => setTimeout(() => resolve(), duration));
|
||||||
|
|
||||||
|
describe('Example (hello)', () => {
|
||||||
|
beforeAll(async () => {
|
||||||
|
if (device.getPlatform() === 'ios') {
|
||||||
|
await device.setStatusBar({ time: '12:34', dataNetwork: 'wifi', wifiBars: '3', batteryState: 'charging', batteryLevel: '100' });
|
||||||
|
}
|
||||||
|
await device.reloadReactNative();
|
||||||
|
|
||||||
|
await element(by.text('I accept Status Terms of Use')).tap();
|
||||||
|
// close alert
|
||||||
|
await element(by.text('Get started')).tap();
|
||||||
|
await waitToNavigate(200);
|
||||||
|
|
||||||
|
await element(by.text('Generate keys')).tap();
|
||||||
|
await waitToNavigate(200);
|
||||||
|
|
||||||
|
await element(by.text('Next')).tap();
|
||||||
|
await waitToNavigate(700);
|
||||||
|
await element(by.text('Next')).tap();
|
||||||
|
await waitToNavigate(700);
|
||||||
|
// await element(by.text('Password...')).typeText('infinitbility@gmail.com');
|
||||||
|
// await element(by.text('Confirm your password...')).typeText('infinitbility@gmail.com');
|
||||||
|
await element(by.text('Next')).tap();
|
||||||
|
await waitToNavigate(700);
|
||||||
|
await element(by.text('Maybe later')).tap();
|
||||||
|
await waitToNavigate(700);
|
||||||
|
await element(by.text("Let's go")).tap();
|
||||||
|
await waitToNavigate(700);
|
||||||
|
|
||||||
|
await element(by.text("1")).tap();
|
||||||
|
await waitToNavigate(400);
|
||||||
|
await element(by.text("Quo2.0 Preview")).tap();
|
||||||
|
await waitToNavigate(400);
|
||||||
|
})
|
||||||
|
beforeEach(async () => {
|
||||||
|
});
|
||||||
|
afterEach(async () => {
|
||||||
|
await element(by.text("1")).tap();
|
||||||
|
await waitToNavigate(200);
|
||||||
|
await element(by.text("Quo2.0 Preview")).tap();
|
||||||
|
await waitToNavigate(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
const pages = Object.keys(data)
|
||||||
|
|
||||||
|
it(`button page should match snapshot`, async () => {
|
||||||
|
await element(by.text(`:button`)).tap();
|
||||||
|
await waitToNavigate(200);
|
||||||
|
const res = await jestExpect(`default-render-button`).toMatchImageSnapshot();
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user