feat: mobile app package (#1075)
This commit is contained in:
58
packages/mobile/e2e/Helpers.ts
Normal file
58
packages/mobile/e2e/Helpers.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const faker = require('faker')
|
||||
import { by, device, element, expect, waitFor } from 'detox'
|
||||
|
||||
export const expectToBeVisible = async (testedElement: Detox.IndexableNativeElement) => {
|
||||
try {
|
||||
await expect(testedElement).toBeVisible()
|
||||
return true
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
const checkAfterReinstall = async () => {
|
||||
if (device.getPlatform() === 'ios') {
|
||||
const alertElement = element(
|
||||
by.label('Delete Local Data').and(by.type('_UIAlertControllerActionView'))
|
||||
)
|
||||
const alertVisible = await expectToBeVisible(alertElement)
|
||||
if (alertVisible) {
|
||||
await element(
|
||||
by.label('Delete Local Data').and(by.type('_UIAlertControllerActionView'))
|
||||
).tap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const openSettingsScreen = async () => {
|
||||
await checkAfterReinstall()
|
||||
await device.reloadReactNative()
|
||||
|
||||
// Opens the settings screen
|
||||
await waitFor(element(by.id('rootView')))
|
||||
.toBeVisible()
|
||||
.withTimeout(2000)
|
||||
await element(by.id('headerButton')).tap()
|
||||
await element(by.id('settingsButton')).tap()
|
||||
}
|
||||
|
||||
export const openComposeNewNoteScreen = async () => {
|
||||
await device.reloadReactNative()
|
||||
|
||||
// Opens the screen to compose a new note
|
||||
await waitFor(element(by.id('rootView')))
|
||||
.toBeVisible()
|
||||
.withTimeout(2000)
|
||||
await waitFor(element(by.id('newNoteButton')))
|
||||
.toBeVisible()
|
||||
.withTimeout(2000)
|
||||
|
||||
await element(by.id('newNoteButton')).tap()
|
||||
}
|
||||
|
||||
export const randomCredentials = {
|
||||
email: faker.internet.exampleEmail(),
|
||||
password: faker.internet.password(),
|
||||
syncServerUrl: 'https://app-dev.standardnotes.com',
|
||||
}
|
||||
103
packages/mobile/e2e/Screens/Settings/Account.spec.ts
Normal file
103
packages/mobile/e2e/Screens/Settings/Account.spec.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const helpers = require('../../Helpers')
|
||||
import { by, device, element, expect, waitFor } from 'detox'
|
||||
import { openSettingsScreen } from '../../Helpers'
|
||||
console.log('aaaa is', helpers)
|
||||
// console.log('bbbb is', helpers2)
|
||||
console.log('cccc is', helpers.openSettingsScreen === openSettingsScreen)
|
||||
|
||||
fdescribe('Account section', () => {
|
||||
describe('Form', () => {
|
||||
beforeAll(async () => {
|
||||
await helpers.openSettingsScreen()
|
||||
})
|
||||
|
||||
it('should have the "Email" and "Password" fields visible', async () => {
|
||||
await expect(element(by.id('emailField'))).toBeVisible()
|
||||
await expect(element(by.id('passwordField'))).toBeVisible()
|
||||
})
|
||||
|
||||
it('should have the "Sign In" button visible', async () => {
|
||||
await expect(element(by.id('signInButton'))).toBeVisible()
|
||||
})
|
||||
|
||||
it('should have the "Register" button visible', async () => {
|
||||
await expect(element(by.id('registerButton'))).toBeVisible()
|
||||
})
|
||||
|
||||
it('should have the "Other Options" button visible', async () => {
|
||||
await expect(element(by.id('otherOptionsButton'))).toBeVisible()
|
||||
})
|
||||
|
||||
it('should have the "Sync Server" field visible when "Other Options" button is pressed', async () => {
|
||||
await element(by.id('otherOptionsButton')).tap()
|
||||
await expect(element(by.id('syncServerField'))).toBeVisible()
|
||||
})
|
||||
})
|
||||
|
||||
describe('Register', () => {
|
||||
beforeAll(async () => {
|
||||
await helpers.openSettingsScreen()
|
||||
})
|
||||
|
||||
it('should work when valid data is provided', async () => {
|
||||
await element(by.id('emailField')).typeText(helpers.randomCredentials.email)
|
||||
await element(by.id('passwordField')).typeText(helpers.randomCredentials.password)
|
||||
await element(by.id('otherOptionsButton')).tap()
|
||||
await element(by.id('syncServerField')).clearText()
|
||||
await element(by.id('syncServerField')).typeText(
|
||||
helpers.randomCredentials.syncServerUrl + '\n'
|
||||
)
|
||||
// wait for buttons to be visible after closing keyboard on smaller devices
|
||||
await waitFor(element(by.id('registerButton')))
|
||||
.toBeVisible()
|
||||
.withTimeout(1000)
|
||||
await element(by.id('registerButton')).tap()
|
||||
|
||||
// A confirmation screen is shown after we click the register button...
|
||||
await expect(element(by.id('passwordConfirmationField'))).toBeVisible()
|
||||
await expect(element(by.id('registerConfirmButton'))).toBeVisible()
|
||||
|
||||
// Password confirmation is required...
|
||||
await element(by.id('passwordConfirmationField')).typeText(helpers.randomCredentials.password)
|
||||
await element(by.id('registerConfirmButton')).tap()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await helpers.openSettingsScreen()
|
||||
|
||||
// Account is created and we now proceed to sign out...
|
||||
await expect(element(by.id('signOutButton'))).toBeVisible()
|
||||
await element(by.id('signOutButton')).tap()
|
||||
|
||||
// Confirmation button in the dialog...
|
||||
if (device.getPlatform() === 'ios') {
|
||||
await element(by.label('Sign Out').and(by.type('_UIAlertControllerActionView'))).tap()
|
||||
} else {
|
||||
await expect(element(by.text('SIGN OUT'))).toBeVisible()
|
||||
await element(by.text('SIGN OUT')).tap()
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe('Sign In', () => {
|
||||
beforeAll(async () => {
|
||||
await helpers.openSettingsScreen()
|
||||
})
|
||||
|
||||
it('should work when valid data is provided', async () => {
|
||||
await element(by.id('emailField')).typeText(helpers.randomCredentials.email)
|
||||
await element(by.id('passwordField')).typeText(helpers.randomCredentials.password)
|
||||
await element(by.id('otherOptionsButton')).tap()
|
||||
await element(by.id('syncServerField')).clearText()
|
||||
await element(by.id('syncServerField')).typeText(
|
||||
helpers.randomCredentials.syncServerUrl + '\n'
|
||||
)
|
||||
// wait for button to be visible after keyboard close
|
||||
await waitFor(element(by.id('signInButton')))
|
||||
.toBeVisible()
|
||||
.withTimeout(1000)
|
||||
await element(by.id('signInButton')).tap()
|
||||
})
|
||||
})
|
||||
})
|
||||
36
packages/mobile/e2e/Screens/Settings/Options.spec.ts
Normal file
36
packages/mobile/e2e/Screens/Settings/Options.spec.ts
Normal file
@@ -0,0 +1,36 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const helpers = require('../../Helpers')
|
||||
import { by, device, element, expect } from 'detox'
|
||||
|
||||
describe('Options section', () => {
|
||||
beforeAll(async () => {
|
||||
await helpers.openSettingsScreen()
|
||||
})
|
||||
|
||||
describe('Export Data', () => {
|
||||
it('should have the option visible', async () => {
|
||||
await expect(element(by.id('exportData'))).toBeVisible()
|
||||
await expect(element(by.id('exportData-title'))).toHaveText('Export Data')
|
||||
})
|
||||
|
||||
it('should restore to "Export Data" if dialog is dismissed', async () => {
|
||||
await expect(element(by.id('exportData-option-decrypted'))).toBeVisible()
|
||||
if (device.getPlatform() === 'android') {
|
||||
await element(by.id('exportData-option-decrypted')).tap()
|
||||
await device.pressBack()
|
||||
await expect(element(by.id('exportData-title'))).toHaveText('Export Data')
|
||||
}
|
||||
})
|
||||
|
||||
it('should export decrypted notes', async () => {
|
||||
await expect(element(by.id('exportData-option-decrypted'))).toBeVisible()
|
||||
if (device.getPlatform() === 'android') {
|
||||
await element(by.id('exportData-option-decrypted')).tap()
|
||||
await element(by.text('SAVE TO DISK')).tap()
|
||||
|
||||
await element(by.text('DONE')).tap()
|
||||
await expect(element(by.id('exportData-title'))).toHaveText('Export Data')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
7
packages/mobile/e2e/config.json
Normal file
7
packages/mobile/e2e/config.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"setupFilesAfterEnv": ["./init.js"],
|
||||
"testEnvironment": "detox/runners/jest/JestCircusEnvironment",
|
||||
"testRunner": "jest-circus/runner",
|
||||
"reporters": ["detox/runners/jest/streamlineReporter"],
|
||||
"verbose": true
|
||||
}
|
||||
37
packages/mobile/e2e/init.js
Normal file
37
packages/mobile/e2e/init.js
Normal file
@@ -0,0 +1,37 @@
|
||||
/* eslint-disable no-undef */
|
||||
const detox = require('detox');
|
||||
const config = require('../package.json').detox;
|
||||
const adapter = require('detox/runners/jest/adapter');
|
||||
const specReporter = require('detox/runners/jest/specReporter');
|
||||
const assignReporter = require('detox/runners/jest/assignReporter');
|
||||
|
||||
// Set the default timeout
|
||||
jest.setTimeout(120000);
|
||||
|
||||
detoxCircus.getEnv().addEventsListener(adapter);
|
||||
detoxCircus.getEnv().addEventsListener(specReporter);
|
||||
detoxCircus.getEnv().addEventsListener(assignReporter);
|
||||
|
||||
beforeAll(async () => {
|
||||
await detox.init(config);
|
||||
}, 600000);
|
||||
|
||||
// beforeEach(async () => {
|
||||
// try {
|
||||
// await adapter.beforeEach();
|
||||
// } catch (err) {
|
||||
// // Workaround for the 'jest-jasmine' runner (default one): if 'beforeAll' hook above fails with a timeout,
|
||||
// // unfortunately, 'jest' might continue running other hooks and test suites. To prevent that behavior,
|
||||
// // adapter.beforeEach() will throw if detox.init() is still running; that allows us to run detox.cleanup()
|
||||
// // in that emergency case and disable calling 'device', 'element', 'expect', 'by' and other Detox globals.
|
||||
// // If you switch to 'jest-circus' runner, you can omit this try-catch workaround at all.
|
||||
|
||||
// await detox.cleanup();
|
||||
// throw err;
|
||||
// }
|
||||
// });
|
||||
|
||||
afterAll(async () => {
|
||||
await adapter.afterAll();
|
||||
await detox.cleanup();
|
||||
});
|
||||
Reference in New Issue
Block a user