Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Micro: bit selenium test code refactor #5745

Merged
merged 31 commits into from
Jul 31, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift click to select a range
1096f7f
ui test initial import
Helen09 May 23, 2019
74a4d96
add README.md file
Helen09 May 27, 2019
2cafc85
Change of dependencies and refactor
jieliu2000 May 30, 2019
eba6ebf
Changes of framwork
jieliu2000 Jun 1, 2019
2bf94c3
Remove useless code
jieliu2000 Jun 9, 2019
2c4487e
Refactor of new project testing (uncompleted)
jieliu2000 Jun 9, 2019
a6f2325
Update of newProject.js
jieliu2000 Jun 9, 2019
07c6e86
Refactor of the code structure
jieliu2000 Jun 13, 2019
e430bb4
Fix errors of tests
jieliu2000 Jun 13, 2019
8e8700d
Refactor and clean code
jieliu2000 Jun 13, 2019
fd330ae
Fix errors
jieliu2000 Jun 13, 2019
cf66721
Renaming files
jieliu2000 Jun 13, 2019
078e55a
refactor and remove useless code
jieliu2000 Jun 13, 2019
6045924
Merge pull request #2 from jieliu2000/refactor
jieliu2000 Jun 13, 2019
f242be7
Send keys to inpur
jieliu2000 Jun 13, 2019
2ec1d96
Merge pull request #3 from jieliu2000/refactor
jieliu2000 Jun 13, 2019
5082457
Remove useless code
jieliu2000 Jun 13, 2019
75e8493
Merge pull request #5 from jieliu2000/refactor
jieliu2000 Jun 13, 2019
aedf8cb
Modified the file's format and update new-project.js
StevenH8 Jul 5, 2019
6319549
pxt ui test initial import
Helen09 Jul 11, 2019
ab9c5e8
delete extra files
Helen09 Jul 11, 2019
93ec2c9
update new-project
Helen09 Jul 11, 2019
66d0f29
Refactor and clean code
jieliu2000 Jul 11, 2019
15205d4
Change test description
jieliu2000 Jul 11, 2019
f494ba0
Update screenshots capture related code
jieliu2000 Jul 11, 2019
172d7c6
Refactor and clean code
jieliu2000 Jul 11, 2019
3398ecf
update description in package.json
Helen09 Jul 11, 2019
e16eaec
Update console debug information
jieliu2000 Jul 11, 2019
d304e1c
Merge branch 'selenium-test' of https://github.com/Helen09/pxt into s…
jieliu2000 Jul 11, 2019
08e2769
delete useless code in dom-object.js
Helen09 Jul 18, 2019
48e2655
Merge branch 'selenium-test' of https://github.com/Helen09/pxt into s…
Helen09 Jul 18, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 24,10 @@ paper.fls
paper.fdb_latexmk
paper.aux
tests/**/*.local.*
package-lock.json
package-lock.json
tests/ui-test/node_modules
tests/ui-test/.vs
tests/ui-test/package-lock.json
tests/ui-test/debug.log
tests/ui-test/chromedriver.exe
tests/ui-test/screenshot/**
2 changes: 2 additions & 0 deletions tests/ui-test/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 1,2 @@
node_modules
screenshots
24 changes: 24 additions & 0 deletions tests/ui-test/.vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 1,24 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Mocha Tests",
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
"args": [
"${workspaceFolder}/src/index.js",
"--require",
"@babel/register",
"--require",
"@babel/polyfill",
"--colors",
"--no-timeouts"
],
"internalConsoleOptions": "openOnSessionStart"
}
]
}
30 changes: 30 additions & 0 deletions tests/ui-test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 1,30 @@
# Micro:bit UI test

This is the selenium UI test for Micro:bit.

## Download and Build

1. Clone the PXT git repository
2. Install Chrome browser if you don't have it on your computer.
3. Download ChromeDriver from https://sites.google.com/a/chromium.org/chromedriver/downloads. The downloaded file is a zip file. Extract it and place the executable in a folder in your PATH. Please note that there are multiple versions of ChromeDriver in download list. You need to make sure your ChromeDriver's version matches your Chrome version.
4. Open folder tests/ui-test
5. Install required node.js modules for the selenium test

```
npm install
```

## Run in command line

```
npm test
```

## Run and Debug in VS Code

1. Open VS Code
2. Open project `ui-test` folder in VS Code
3. Click `Debug`
4. Choose `Mocha Tests` in Debug
5. Click `Start Debugging`

26 changes: 26 additions & 0 deletions tests/ui-test/package.json
Original file line number Diff line number Diff line change
@@ -0,0 1,26 @@
{
"name": "pxt-ui-test",
"version": "1.0.0",
"description": "Selenium ui test for Micro:bit",
"main": "Main.js",
"scripts": {
"test": "node_modules/.bin/mocha ./src/index.js --require @babel/register --require @babel/polyfill --timeout 100000"
},
"type": "module",
"author": "Helen Ma",
"license": "MIT",
"dependencies": {
"chromedriver": "^2.46.0",
"dateformat": "^3.0.3",
"selenium-webdriver": "^4.0.0-alpha.1"
},
"devDependencies": {
"@babel/cli": "^7.4.4",
"@babel/core": "^7.4.5",
"@babel/polyfill": "^7.4.4",
"@babel/preset-env": "^7.4.5",
"@babel/preset-es2015": "^7.0.0-beta.53",
"@babel/register": "^7.4.4",
"mocha": "^6.1.4"
}
}
3 changes: 3 additions & 0 deletions tests/ui-test/src/.jshintrc
Original file line number Diff line number Diff line change
@@ -0,0 1,3 @@
{
"esversion": 8
}
7 changes: 7 additions & 0 deletions tests/ui-test/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 1,7 @@
// Transpile all code following this line with babel and use '@babel/preset-env' (aka ES6) preset.
require("@babel/register")({
presets: ["@babel/preset-env"]
});

// Import the rest of our application.
module.exports = require('./main.js');
80 changes: 80 additions & 0 deletions tests/ui-test/src/lib/dom-object.js
Original file line number Diff line number Diff line change
@@ -0,0 1,80 @@
import { By } from 'selenium-webdriver';
import fs from 'fs';
import dateformat from 'dateformat';

const screenshotsFolder = './screenshots';

export class DomObject {

async actionForAll(actionName, findBys) {
for (let criteria of findBys) {
if (criteria) {
console.debug(`Try to click the element by criteria: ${criteria}`);

let findBy = this.findBy(criteria);

//wait until the element can be located
let element = await this.waitforElementLocated(findBy);

//Sleep for 2 seconds to make sure the element's state is stable for interactions
await driver.sleep(2000);

await element[actionName]();
}
}
return true;
}

async waitforElementLocated(criteria) {
let findBy = this.findBy(criteria);

let element = await driver.wait(until.elementLocated(findBy));
return element;
}

findBy(criteria) {
if (typeof criteria === 'string') {
return By.css(criteria);
}
return criteria;
}

async getText(criteria) {
let element = await this.waitforElementLocated(this.findBy(criteria));
return await element.getText();
}

async sendKeys(criteria, keys) {

let element = await driver.findElement(this.findBy(criteria));
await element.sendKeys(keys);
return true;
}


async click(...findBys) {
return await this.actionForAll('click', findBys);
}

async takeScreenshot(name) {
if (!fs.existsSync(screenshotsFolder)) {
fs.mkdirSync(screenshotsFolder);
}

let base64String = await driver.takeScreenshot();
let fileName = name "-" dateformat(new Date(), "yyyymmddHHMMssl");

fs.writeFile(`${screenshotsFolder}/${fileName}.png`, base64String, 'base64', function (err) {
if (!err) {
console.error(err);
}
});

return true;
}

async getAttribute(criteria, attributeName) {
let element = await this.waitforElementLocated(this.findBy(criteria));
return element.getAttribute(attributeName);
}
}
42 changes: 42 additions & 0 deletions tests/ui-test/src/lib/website.js
Original file line number Diff line number Diff line change
@@ -0,0 1,42 @@
import { Builder, until } from 'selenium-webdriver';
import { chrome } from 'selenium-webdriver/chrome';


const WEBSITE_URL = "https://makecode.microbit.org"

class Website {

constructor(rootURL = WEBSITE_URL) {
this.rootURL = rootURL;
}

async open(path = "") {
var fullPath = this.getUrl(path);
console.info(`Open url ${fullPath}`);

await driver.get(fullPath);

console.info(`Opened URL ${fullPath}`);
return await driver.manage().window().maximize();
}

getUrl(path) {
if (!path.startsWith("/")) {
path = "/" path;
}
return this.rootURL path;
}

close() {
console.info("Close webstie...");
driver.quit();
}
}

global.driver = new Builder()
.forBrowser('chrome')
.build();
global.until = until;


export let website = new Website();
16 changes: 16 additions & 0 deletions tests/ui-test/src/main.js
Original file line number Diff line number Diff line change
@@ -0,0 1,16 @@
import { website } from "./lib/website";
import webdriver from 'selenium-webdriver';
import { chrome } from 'selenium-webdriver/chrome';

import { newProjectPage } from './new-project'

describe('Micro:bit Test', function () {
before(async () => {
return await website.open("beta");
});
after(function () {
website.close();
});

newProjectPage.test();
});
46 changes: 46 additions & 0 deletions tests/ui-test/src/new-project.js
Original file line number Diff line number Diff line change
@@ -0,0 1,46 @@
import { DomObject } from './lib/dom-object';
import assert from 'assert';


class NewProjectPage extends DomObject {

async testCreateNewProject() {

console.debug("Start testCreateNewProject()");

//Create a new project
await this.click('.newprojectcard', '.openproject');

//Close the new project name input popup
await this.click('.closeIcon');

await this.takeScreenshot('editorPage1');

//Assert the title is correct
assert.equal(await this.getAttribute('.openproject', 'title'), 'Home');

//Open the project name input popup again
await this.click('.openproject');
//Name the new project to "Project1"
await this.sendKeys('input#projectNameInput', 'Project1');

//Confirm the changes
await this.click('.button.positive');

//Validate the project is correctly created
let text = await this.getText("[aria-label='My Projects'] .carouselitem:nth-child(2) .header");
console.debug(`The header text in the first DIV of 'My Projects' is "${text}"`);

assert.equal(text, "Project1");

return true;
}

test() {
it('Creae a new project and open it', async () => {
return await this.testCreateNewProject();
});
}
}

export let newProjectPage = new NewProjectPage();