Create the usual setup (package.json
, build scripts and so on). Take the chess-queen exercise as a base but instead of using xt-sc-chess-queen
, you will use xt-sc-bookmarks
.
Here is the HTML code of your src/index.html
:
<!DOCTYPE html>
<html>
<head>
<title>Bookmarks</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<header>
<form method="get" class="columns">
<div class="grow rows">
<div>
<input required type="url" name="link" placeholder="https://devdocs.io" />
</div>
<div>
<textarea name="notes" placeholder="Some notes about the link"></textarea>
</div>
</div>
<div class="rows">
<button class="grow">Save</button>
</div>
</form>
</header>
<main>
<ul class="bookmarks">
<!-- <li class="bookmark">
<div>
<a href="https://devdocs.io">https://devdocs.io</a>
<p>Works offline</p>
</div>
<button class="remove">X</button>
</li> -->
</ul>
<script type="text/javascript" src="bundle.js"></script>
</main>
</body>
</html>
In order to pass the tests it is a requirement that Chrome runs in headless mode which means that your test/wdio.conf.js
must have the following code in the capabilities
// ...
chromeOptions: {
args: ['--headless', '--disable-gpu', '--window-size=1280,800']
}
// ...
Then create a file test/bookmarks.spec.js
const assert = require('assert');
const checkStyle = require('xt-sc-bookmarks');
describe('Bookmarks tool', function() {
var elements;
const headless = ((browser.desiredCapabilities.chromeOptions || {}).args || []).indexOf('--headless') > -1;
before(function() {
browser.url('http://localhost:9090');
browser.execute(function() {
localStorage.removeItem('bookmraks');
});
});
describe('normal design', function() {
Object.keys(checkStyle.resolutions).forEach(key => {
(headless ? it : xit)('has the right styles for ' + key.split('-').join(' '), function () {
checkStyle(browser, key, null, './docs/image-diffs', 5);
});
});
});
describe('saving a bookmark', function() {
var bookmarks;
it('requires a url', function() {
// by not giving the url before the first click of the 3 clicks
// and checking
$('[name=notes]').setValue('My personal website');
$('form button').click();
$('[name=link]').setValue('https://irata.ch');
$('form button').click();
$('[name=link]').setValue('https://devdocs.io');
$('[name=notes]').setValue('Offline available documention for development');
$('form button').click();
});
it('writes in the localStorage bookmarks', function() {
bookmarks = browser.execute(function() {
return localStorage.bookmarks;
}).value;
assert(typeof bookmarks, 'string');
});
it('has written valid JSON', function() {
// JSON.parse throws an Error if the string cannot be parsed
// (which makes the test fail)
bookmarks = JSON.parse(bookmarks);
});
it('has 2 bookmarks', function() {
assert(Array.isArray(bookmarks));
assert(bookmarks.length === 2);
});
});
describe('removing a bookmark', function() {
var bookmarks;
it('can be done by clicking the remove button', function() {
$('.bookmarks button').click();
});
it('writes in the localStorage bookmarks', function() {
bookmarks = browser.execute(function() {
return localStorage.bookmarks;
}).value;
assert(typeof bookmarks, 'string');
});
it('has written valid JSON', function() {
bookmarks = JSON.parse(bookmarks);
});
it('has 1 bookmark', function() {
assert(Array.isArray(bookmarks));
assert(bookmarks.length === 1);
});
});
});
You can make the test run on travis-ci by adding the following .travis.yml
file at the root of your repository.
sudo: required
dist: trusty
language: node_js
addons:
firefox: latest
node_js:
- 8
before_install:
- export CHROME_BIN=/usr/bin/google-chrome
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- sleep 3 # give xvfb some time to start
- sudo apt-get update
- sudo apt-get install -y libappindicator1 fonts-liberation libcairo2-dev libjpeg8-dev libpango1.0-dev libgif-dev build-essential g++
- wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
- sudo dpkg -i google-chrome*.deb
Based on the test screenshots (whih you can find under node_modules/xt-sc-bookmarks/sc
), recreate the design.
CSS without values
*,
*:before,
*:after {
box-sizing: /* ... */;
}
body {
margin: /* ... */;
padding: /* ... */;
display: /* ... */;
flex-direction: /* ... */;
font-family: /* ... */;
background-color: /* ... */;
color: /* ... */;
}
body > header {
background-color: /* ... */;
}
form,
.bookmarks {
min-width: /* ... */;
max-width: /* ... */;
margin: /* ... */;
padding: /* ... */;
}
form {
input,
textarea,
button {
font-size: /* ... */;
border: /* ... */;
}
input,
textarea {
width: /* ... */;
margin: /* ... */;
padding: /* ... */;
font-family: /* ... */;
display: /* ... */;
}
input {
border-radius: /* ... */;
}
textarea {
border-radius: /* ... */;
border-top: /* ... */;
}
button {
border-left: /* ... */;
border-radius: /* ... */;
}
}
.columns,
.rows {
display: /* ... */;
}
.columns {
flex-direction: /* ... */;
}
.rows {
flex-direction: /* ... */;
}
.grow {
flex-grow: /* ... */;
}
.bookmarks {
list-style: /* ... */;
> li {
border: /* ... */;
border-radius: /* ... */;
background-color: /* ... */;
padding: /* ... */;
margin: /* ... */;
position: /* ... */;
}
a {
font-size: /* ... */;
text-decoration: /* ... */;
color: /* ... */;
}
}
.remove {
display: /* ... */;
text-align: /* ... */;
width: /* ... */;
height: /* ... */;
padding: /* ... */;
border-radius: /* ... */;
border: /* ... */;
position: /* ... */;
right: /* ... */;
top: /* ... */;
}
The exercise is not finished yet...