Skip to content

Commit 853684a

Browse files
Tugmarecar3
authored andcommitted
Release v1.10.0 (#1246)
1 parent a826307 commit 853684a

32 files changed

+1733
-1602
lines changed

.circleci/config.yml

+12-10
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ commands:
66
- restore_cache:
77
name: Restore Yarn Cache
88
keys:
9-
- yarn-i18n-v1-{{ .Environment.CIRCLE_JOB }}-{{ checksum "yarn.lock" }}
9+
- yarn-i18n-v3-{{ .Environment.CIRCLE_JOB }}-{{ checksum "yarn.lock" }}
1010
- run:
1111
name: Yarn Install
1212
command: yarn install --frozen-lockfile --prefer-offline
1313
- save_cache:
1414
name: Save Yarn Cache
15-
key: yarn-i18n-v1-{{ .Environment.CIRCLE_JOB }}-{{ checksum "yarn.lock" }}
15+
key: yarn-i18n-v3-{{ .Environment.CIRCLE_JOB }}-{{ checksum "yarn.lock" }}
1616
paths:
1717
- node_modules
1818
- i18n-cache/data
@@ -61,7 +61,7 @@ jobs:
6161
path: ./reports/test-results
6262
android-device-checks:
6363
docker:
64-
- image: circleci/android:api-28-node8-alpha
64+
- image: circleci/android:api-29-node
6565
steps:
6666
- checkout
6767
- run:
@@ -80,7 +80,8 @@ jobs:
8080
- run:
8181
name: Upload apk to sauce labs
8282
command: |
83-
curl -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" -X POST -H "Content-Type: application/octet-stream" https://saucelabs.com/rest/v1/storage/automattic/Gutenberg.apk?overwrite=true --data-binary @./android/app/build/outputs/apk/debug/app-debug.apk
83+
source bin/sauce-pre-upload.sh
84+
curl -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" -X POST -H "Content-Type: application/octet-stream" https://saucelabs.com/rest/v1/storage/automattic/Gutenberg-$SAUCE_FILENAME.apk?overwrite=true --data-binary @./android/app/build/outputs/apk/debug/app-debug.apk
8485
- run:
8586
name: Run Device Tests
8687
command: yarn device-tests
@@ -111,21 +112,21 @@ jobs:
111112
- restore_cache:
112113
name: Restore Dependencies Cache
113114
keys:
114-
- dependencies-{{ checksum "react-native-aztec/ios/Cartfile.resolved" }}-{{
115+
- dependencies-v2-{{ checksum "react-native-aztec/ios/Cartfile.resolved" }}-{{
115116
checksum "yarn.lock" }}
116-
- dependencies-{{ checksum "react-native-aztec/ios/Cartfile.resolved" }}
117-
- dependencies-
117+
- dependencies-v2-{{ checksum "react-native-aztec/ios/Cartfile.resolved" }}
118+
- dependencies-v2-
118119
- run:
119120
name: Yarn preios (if needed)
120121
command: test -e ios/build/gutenberg/Build/Products/Release-iphonesimulator/gutenberg.app || yarn preios
121122
- save_cache:
122123
name: Save Dependencies Cache
123-
key: dependencies-{{ checksum "react-native-aztec/ios/Cartfile.resolved" }}-{{
124+
key: dependencies-v2-{{ checksum "react-native-aztec/ios/Cartfile.resolved" }}-{{
124125
checksum "yarn.lock" }}
125126
paths:
126127
- react-native-aztec/ios/Carthage
127128
- ~/.rncache
128-
- run:
129+
- run:
129130
name: Build (if needed)
130131
command: test -e ios/build/gutenberg/Build/Products/Release-iphonesimulator/gutenberg.app || yarn react-native run-ios --configuration Release --no-packager
131132
- run:
@@ -137,7 +138,8 @@ jobs:
137138
- run:
138139
name: Upload .app to sauce labs
139140
command: |
140-
curl -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" -X POST -H "Content-Type: application/octet-stream" https://saucelabs.com/rest/v1/storage/automattic/Gutenberg.app.zip?overwrite=true --data-binary @./ios/Gutenberg.app.zip
141+
source bin/sauce-pre-upload.sh
142+
curl -u "$SAUCE_USERNAME:$SAUCE_ACCESS_KEY" -X POST -H "Content-Type: application/octet-stream" https://saucelabs.com/rest/v1/storage/automattic/Gutenberg-$SAUCE_FILENAME.app.zip?overwrite=true --data-binary @./ios/Gutenberg.app.zip
141143
- run:
142144
name: Run Device Tests
143145
command: |

.vscode/extensions.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"recommendations": [
33
"gcazaciuc.vscode-flow-ide",
4-
"vsmobile.vscode-react-native"
4+
"msjsdiag.vscode-react-native"
55
]
66
}

README.md

+1-7
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,6 @@ nvm install --latest-npm
4141
yarn install
4242
```
4343

44-
Note: using node v9.x currently produces the following error:
45-
```
46-
error sane@3.1.0: The engine "node" is incompatible with this module. Expected version "6.* || 8.* || >= 10.*".
47-
```
48-
To be revisited, as we don't need to impose a limit in version per se.
49-
5044
## Run
5145

5246
```
@@ -141,7 +135,7 @@ and for android run,
141135

142136
Note, you might experience problems that seem to be related to the tests starting the Appium server, for example errors that say `Connection Refused`, `Connection Reset` or `The requested environment is not available`. Sorry about that this is still a WIP, you can manually start the Appium server via [appium desktop](https://github.com/appium/appium-desktop) or the cli, then change the port number in the tests while optionally commenting out related code in the `beforeAll` and `afterAll` block.
143137

144-
For a more detailed outline of the UI tests and how to get started writing one please visit the [Project Wiki](https://github.com/wordpress-mobile/gutenberg-mobile/wiki/Getting-started-with-UI-tests)
138+
For a more detailed outline of the UI tests and how to get started writing one please visit the [UI Test documentation](https://github.com/wordpress-mobile/gutenberg-mobile/blob/develop/__device-tests__/README.md) and our [contributing guide](https://github.com/wordpress-mobile/gutenberg-mobile/blob/develop/__device-tests__/CONTRIBUTING.md).
145139

146140
## Static analysis and code style
147141

RELEASE-NOTES.txt

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
1.10.0
2+
------
3+
* Adding a block from the post title now shows the add block here indicator.
4+
* Deselect post title any time a block is added
5+
* Fix loss of center alignment in image captions on Android
6+
17
1.9.0
28
------
39
* Enable video block on Android platform

__device-tests__/CONTRIBUTING.md

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
Writing a UI test? Great! 😬 This guide is here to help fill in some of the blanks of how the tests are written now and how you can add a new one.
2+
3+
You can find our on-device UI tests in the `__device-tests__` folder and that's where all of the code for that really lives.
4+
The test suite follows a sort of [Page Object Pattern](https://webdriver.io/docs/pageobjects.html), the `__device-tests__/pages/editor-page.js` manages all interactions with the pages and the `__device-tests__/gutenberg-editor.test.js` actually uses the functions made available via the Page Object `EditorPage` to drive the test cases. At the time of writing this, all the tests live there but as the suite gets large it might be better to manage different classes of tests in different files.
5+
6+
So what does the process for writing a test look like? Here are some steps that I hope can help make this easier,
7+
8+
### First, define the scenario
9+
10+
- What are the actions that need to take place here? Walk through the scenario and manually to have an idea of what the test steps will need to do, the elements you'll need to interact with and how you're going to need to interact with them. I found it helps to properly define the steps taken in the scenario and the different user interactions that are needed to accomplish it.
11+
12+
You'd just add a new scenario to the test file as well that would look something like,
13+
14+
```javscript
15+
it( 'should be able to do something', async () => {
16+
// Code to do something...
17+
} );
18+
```
19+
20+
That first parameter in the block above is where you'd put a short description of the scenario while the next parameter is the code you'd like to execute.
21+
22+
### Second, figure out how to find the elements
23+
24+
- The UI tests rely on locator strategies to identify elements... There's a number of locator strategies available to use and [this blog post](https://saucelabs.com/blog/advanced-locator-strategies) describes in a little more detail what a few of these are and how to use them. You'll need to start thinking about what locator strategy you'll need to use to find the elements you need if it isn't already available.
25+
- The preferred strategy is the accessibility identifier and in a lot of cases this might not be possible and you'll have to resort to other less robust alternatives such as XPath.
26+
27+
There's a few tools you have available to figure out what you need.
28+
29+
For Android, you can fire up the app and then within Android Studio select `Tools -> Layout Inspector` which will then open up a `.li` file which you can then use to inspect various areas of the app, here's a [screenshot](https://d.pr/free/i/anU50R) of what that looks like.
30+
31+
For iOS, you can also fire up and use the accessibility inspector, which is an app that should come available on your OSX machine. From there you can choose the process running your simulator and inspect various areas of the app.
32+
33+
Alternative for both of these platforms and for an interface to simulate the commands I'd recommend [Appium Desktop](https://github.com/appium/appium-desktop/releases/tag/v1.12.1). A great tool for inspecting the view hierarchy and interacting with elements on screen as your test would. Here's a [screenshot](https://d.pr/free/i/GziQ5Q) of what that would look like.
34+
35+
Using one or a combination of these tools will make it much easier to identify what locator strategy you're going to use or which elements need accessibility identifiers to ease the search process without affecting VoiceOver features.
36+
37+
### Finally, once you've figured out how you're going to find the elements
38+
39+
- You'll write any functions needed to interact with the page in the `EditorPage` page object and then call those interactions within the test. The code you'll need to write to actually do the finding will use a combination of
40+
41+
- Appium's spec http://appium.io/docs/en/about-appium/intro/ which you can find examples of a variety of functions under the commands tab
42+
- WebDriver I/O Appium protocols https://webdriver.io/docs/api/appium.html which provides examples and descriptions of what those look like.
43+
44+
It takes some getting use to but looking at the existing code should be helpful in identifying common commands that it'd help to be familiar with.

__device-tests__/README.md

+56
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# Overview
2+
3+
We use [appium](http://appium.io/) combined with [SauceLabs](https://saucelabs.com/) as an on-device testing solution for covering writing flows using Gutenberg blocks.
4+
5+
Appium is built on the idea that testing native apps shouldn't require including an SDK or recompiling your app. And that you should be able to use your preferred test practices, frameworks, and tools. Appium is an open source project and has made design and tool decisions to encourage a vibrant contributing community.
6+
7+
SauceLabs is a cloud hosting platform that provides access to a variety of simulators, emulators and real devices.
8+
9+
## Getting set up to run the tests
10+
11+
### Emulators && Simulators
12+
13+
iOS: Once you've already set up XCode and the simulators you should be good to go to run the tests on an iOS simulator.
14+
15+
Android: You'll need to have created the emulator images and fired up the desired emulator before running the tests against an Android emulator.
16+
17+
### Real Devices
18+
19+
TBA
20+
21+
## Running the tests locally
22+
23+
TLDR; to run the tests locally ensure metro isn't running and then run `yarn test:e2e:ios:local` and `yarn test:e2e:android:local` for the desired platform.
24+
25+
Those commands include the process to build a testable version of the app, if it's the case you don't want to run the
26+
full suite and want to run a specific file or files you can use the e2e build commands that can be found in the package.json for the respective platform and then
27+
run `TEST_RN_PLATFORM=android yarn device-tests <pattern>` where the pattern can just be the file path.
28+
29+
### Starting the Appium Server
30+
31+
One of the Caveats to using Appium is the need for the Appium server to be running to interact with the Simulator or Device through Webdriver, as a result the appium server will need to be started before running the tests. To make the entire process easier in the `beforeAll` block of the tests an Appium instance is fired up on a default port of 4723. If you already have something running on that port and would rather not stop that you can change the port within the code that starts that up. At the moment that port number is referenced from the config located at `__device-tests__/helpers/serverConfigs.js`. The process is killed in the `afterAll` block but at the time of writing this there's a small chance some errors might cause it not to get there so it might be best to kill the process yourself if you think something is up. The server output when running the tests are written to `appium-out.log`, this can provide useful information when debugging the issues with the tests.
32+
33+
### WebDriver capabilities
34+
35+
Appium uses a config object that contains `capabilities` to define how it will connect to a simulator or device, this object is currently located in `__device-tests__/helpers/caps.js` and then referenced when firing up the driver. There are two values that I think are important to know and that's
36+
37+
- `platformVersion` which is the platform version of a connected adb device. e.g `9.0` for Android or `12.2` for iOS. The version used here is upper bounded by the max allowed on CI but feel free to change this value locally as needed.
38+
- `app` which is the absolute path to the `.app` or `.apk` file or the path relative to the **Appium root**. It's important to note that that when using the relative paths it's not to the project folder but to the appium server, since by default we start up appium in the project root when running the paths appear relative to the root but if you were using another instance of the Appium server the relative path would need to come from there.
39+
40+
A full spec on the capabilities can be found [here](http://appium.io/docs/en/writing-running-appium/caps/). If you'd like to change configurations like
41+
what port appium runs on or what device or emulator the tests should be executed on that file would be where you'd like to make that update.
42+
43+
## The run process
44+
45+
At the moment when running locally, the app attempts to fire up an appium server and then connects to it via webdriver. Then
46+
47+
* on Android, a debug version of the app is bundled, built, and used.
48+
* on iOS a release version is bundled built and used.
49+
50+
**It's important to ensure that **metro is not running.** This would cause the value of the `__DEV__` variable to be true and load up the sample blocks.**
51+
52+
After the build is complete, an appium server is fired up on port 4723 and the device tests are ran on the connected device/simulator.
53+
54+
-----
55+
56+
To read more about writing your own tests please read the [contributing guide](https://github.com/wordpress-mobile/gutenberg-mobile/blob/develop/__device-tests__/CONTRIBUTING.md)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/**
2+
* @format
3+
* */
4+
5+
/**
6+
* Internal dependencies
7+
*/
8+
import EditorPage from './pages/editor-page';
9+
import {
10+
setupDriver,
11+
isLocalEnvironment,
12+
stopDriver,
13+
isAndroid,
14+
clickMiddleOfElement,
15+
} from './helpers/utils';
16+
import testData from './helpers/test-data';
17+
18+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 300000;
19+
20+
describe( 'Gutenberg Editor tests for Block insertion', () => {
21+
let driver;
22+
let editorPage;
23+
let allPassed = true;
24+
25+
// Use reporter for setting status for saucelabs Job
26+
if ( ! isLocalEnvironment() ) {
27+
const reporter = {
28+
specDone: async ( result ) => {
29+
allPassed = allPassed && result.status !== 'failed';
30+
},
31+
};
32+
33+
jasmine.getEnv().addReporter( reporter );
34+
}
35+
36+
beforeAll( async () => {
37+
driver = await setupDriver();
38+
editorPage = new EditorPage( driver );
39+
} );
40+
41+
it( 'should be able to see visual editor', async () => {
42+
await expect( editorPage.getBlockList() ).resolves.toBe( true );
43+
} );
44+
45+
it( 'should be able to insert block into post', async () => {
46+
await editorPage.addNewParagraphBlock();
47+
let paragraphBlockElement = await editorPage.getParagraphBlockAtPosition( 1 );
48+
if ( isAndroid() ) {
49+
await paragraphBlockElement.click();
50+
}
51+
await editorPage.sendTextToParagraphBlockAtPosition( 1, testData.longText );
52+
// Should have 3 paragraph blocks at this point
53+
54+
paragraphBlockElement = await editorPage.getParagraphBlockAtPosition( 2 );
55+
await paragraphBlockElement.click();
56+
57+
await editorPage.addNewParagraphBlock();
58+
paragraphBlockElement = await editorPage.getParagraphBlockAtPosition( 3 );
59+
await paragraphBlockElement.click();
60+
await editorPage.sendTextToParagraphBlockAtPosition( 3, testData.mediumText );
61+
62+
await editorPage.verifyHtmlContent( testData.blockInsertionHtml );
63+
64+
// Workaround for now since deleting the first element causes a crash on CI for Android
65+
if ( isAndroid() ) {
66+
paragraphBlockElement = await editorPage.getParagraphBlockAtPosition( 3 );
67+
await paragraphBlockElement.click();
68+
await editorPage.removeParagraphBlockAtPosition( 3 );
69+
for ( let i = 3; i > 0; i-- ) {
70+
paragraphBlockElement = await editorPage.getParagraphBlockAtPosition( i );
71+
await paragraphBlockElement.click();
72+
await editorPage.removeParagraphBlockAtPosition( i );
73+
}
74+
} else {
75+
for ( let i = 4; i > 0; i-- ) {
76+
paragraphBlockElement = await editorPage.getParagraphBlockAtPosition( 1 );
77+
await clickMiddleOfElement( driver, paragraphBlockElement );
78+
await editorPage.removeParagraphBlockAtPosition( 1 );
79+
}
80+
}
81+
} );
82+
83+
it( 'should be able to insert block at the beginning of post from the title', async () => {
84+
await editorPage.addNewParagraphBlock();
85+
let paragraphBlockElement = await editorPage.getParagraphBlockAtPosition( 1 );
86+
if ( isAndroid() ) {
87+
await paragraphBlockElement.click();
88+
}
89+
await editorPage.sendTextToParagraphBlockAtPosition( 1, testData.longText );
90+
// Should have 3 paragraph blocks at this point
91+
92+
if ( isAndroid() ) {
93+
await driver.hideDeviceKeyboard();
94+
}
95+
96+
const titleElement = await editorPage.getTitleElement();
97+
await titleElement.click();
98+
await titleElement.click();
99+
100+
await editorPage.addNewParagraphBlock();
101+
paragraphBlockElement = await editorPage.getParagraphBlockAtPosition( 1 );
102+
await clickMiddleOfElement( driver, paragraphBlockElement );
103+
await editorPage.sendTextToParagraphBlockAtPosition( 1, testData.mediumText );
104+
await paragraphBlockElement.click();
105+
await editorPage.verifyHtmlContent( testData.blockInsertionHtmlFromTitle );
106+
} );
107+
108+
afterAll( async () => {
109+
if ( ! isLocalEnvironment() ) {
110+
driver.sauceJobStatus( allPassed );
111+
}
112+
await stopDriver( driver );
113+
} );
114+
} );

__device-tests__/gutenberg-editor-heading.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
} from './helpers/utils';
1515
import testData from './helpers/test-data';
1616

17-
jasmine.DEFAULT_TIMEOUT_INTERVAL = 240000;
17+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 300000;
1818

1919
describe( 'Gutenberg Editor tests', () => {
2020
let driver;

__device-tests__/gutenberg-editor-image.test.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
} from './helpers/utils';
1717
import testData from './helpers/test-data';
1818

19-
jasmine.DEFAULT_TIMEOUT_INTERVAL = 240000;
19+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 300000;
2020

2121
describe( 'Gutenberg Editor Image Block tests', () => {
2222
let driver;
@@ -63,6 +63,7 @@ describe( 'Gutenberg Editor Image Block tests', () => {
6363
await swipeUp( driver, imageBlock );
6464
await editorPage.enterCaptionToSelectedImageBlock( testData.imageCaption );
6565
await editorPage.dismissKeyboard();
66+
imageBlock = await editorPage.getImageBlockAtPosition( 1 );
6667
await imageBlock.click();
6768
}
6869
await editorPage.removeImageBlockAtPosition( 1 );

__device-tests__/gutenberg-editor-lists-end.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
} from './helpers/utils';
1515
import testData from './helpers/test-data';
1616

17-
jasmine.DEFAULT_TIMEOUT_INTERVAL = 240000;
17+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 300000;
1818

1919
describe( 'Gutenberg Editor tests for List block (end)', () => {
2020
let driver;

__device-tests__/gutenberg-editor-lists.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
} from './helpers/utils';
1515
import testData from './helpers/test-data';
1616

17-
jasmine.DEFAULT_TIMEOUT_INTERVAL = 240000;
17+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 300000;
1818

1919
describe( 'Gutenberg Editor tests for List block', () => {
2020
let driver;

__device-tests__/gutenberg-editor-paragraph.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
} from './helpers/utils';
1717
import testData from './helpers/test-data';
1818

19-
jasmine.DEFAULT_TIMEOUT_INTERVAL = 250000;
19+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 300000;
2020

2121
describe( 'Gutenberg Editor tests for Paragraph Block', () => {
2222
let driver;

__device-tests__/gutenberg-editor-paste.test.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import {
1818
} from './helpers/utils';
1919
import testData from './helpers/test-data';
2020

21-
jasmine.DEFAULT_TIMEOUT_INTERVAL = 240000;
21+
jasmine.DEFAULT_TIMEOUT_INTERVAL = 300000;
2222

2323
describe( 'Gutenberg Editor paste tests', () => {
2424
// skip iOS for now

0 commit comments

Comments
 (0)