Skip to content

Commit

Permalink
test(e2e): Setup BDD and add first scenario
Browse files Browse the repository at this point in the history
  • Loading branch information
JalilArfaoui committed May 22, 2019
1 parent c4f7475 commit 76bb143
Show file tree
Hide file tree
Showing 17 changed files with 644 additions and 77 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
test/screenshots
.awcache/
node_modules
npm-debug.log
Expand Down
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ yarn build:dev

```bash
# test everything
yarn test
yarn test:unit
```

## Lint
Expand Down Expand Up @@ -151,6 +151,22 @@ yarn lint:css

Inspect the extension _background_ to get its console and run `window.integrationTest()`.

### Integration tests (New)

Integration tests run a series of real world (staging) scenarios to validate the BDD features described in ./features folder.

Run

```
yarn start
```

and then concurrently:

```
yarn test:e2e
```

## LICENSE

[GNU GPL v3](LICENSE)
Expand Down
12 changes: 12 additions & 0 deletions cucumber.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
var common = [
`--format ${
process.env.CI || !process.stdout.isTTY ? 'progress' : 'progress-bar'
}`,
'--parallel 20',
'--require ./features/support/**/*.ts',
'--require ./features/step_definitions/**/*.ts'
].join(' ');

module.exports = {
default: common
};
9 changes: 9 additions & 0 deletions features/MatchingContext.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Feature: Matching context
In order to read relevant notice
As a user
I want to see notices that match my current tab context

Scenario: Open Pixmania homepage
When I open the url "https://pixmania.fr"
Then I see the notification within 10 seconds
And The first notice has text "Que choisir signale que de nombreux clients mécontents"
16 changes: 16 additions & 0 deletions features/step_definitions/navigating.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { When } from 'cucumber';
import { BubbleWorld, InitializedBubbleWorld } from '../support/setup';
import expect from 'expect';

When(/^I open the url "(.+)"$/, async function(this: BubbleWorld, url: string) {
let error = null;
try {
await (this as InitializedBubbleWorld).page.goto(url, {
waitUntil: 'networkidle0'
});
} catch (e) {
error = e;
}

expect(error).toBeNull();
});
34 changes: 34 additions & 0 deletions features/step_definitions/notices.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Then } from 'cucumber';
import { BubbleWorld, InitializedBubbleWorld } from '../support/setup';
import expect from 'expect';
import { findIframe } from '../support/iframe';

Then(/^The first notice has text "(.+)"$/, async function(
this: BubbleWorld,
text: string
) {
let error = null;
try {
const frame = findIframe((this as InitializedBubbleWorld).page);
expect(frame).toBeDefined();

if (frame) {
const firstNoticeP = await frame.$(
"article p[data-test-type='noticeTitle']"
);
expect(firstNoticeP).toBeDefined();

if (firstNoticeP) {
const firstNoticeText = await frame.evaluate(
e => e.textContent,
firstNoticeP
);
expect(firstNoticeText).toMatch(new RegExp(`^${text}`));
}
}
} catch (e) {
error = e;
}

expect(error).toBeNull();
});
27 changes: 27 additions & 0 deletions features/step_definitions/notification.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Then } from 'cucumber';
import { BubbleWorld, InitializedBubbleWorld } from '../support/setup';
import expect from 'expect';
import { findIframe } from '../support/iframe';

Then(/^I see the notification within (\d+) seconds$/, async function(
this: BubbleWorld,
delay: number
) {
let error = null;
try {
const frame = findIframe((this as InitializedBubbleWorld).page);
expect(frame).toBeDefined();

if (frame) {
await frame.waitForSelector(
`section[data-test-id="bubble-notification"]`,
{ timeout: delay * 1000 }
);
}
} catch (e) {
error = e;
}

expect(error).toBeNull();
});
// document.querySelectorAll('body section[data-test-id="bubble-notification"]');
7 changes: 7 additions & 0 deletions features/support/iframe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Page } from 'puppeteer';

export const findIframe = (page: Page) =>
page
.mainFrame()
.childFrames()
.find(frame => frame.name() === 'BubbleIONotification');
51 changes: 51 additions & 0 deletions features/support/setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { After, Before, Status, setDefaultTimeout, World } from 'cucumber';
import puppeteer, { Browser, Page } from 'puppeteer';
import path from 'path';

setDefaultTimeout(60 * 1000);

const CRX_PATH = path.resolve(process.cwd(), 'build', 'dev');

const config = {
screenshotPath: path.resolve(process.cwd(), 'test', 'screenshots')
};

export interface BubbleWorld extends World {
browser?: Browser;
page?: Page;
}

export interface InitializedBubbleWorld extends BubbleWorld {
browser: Browser;
page: Page;
}

Before(async function(this: BubbleWorld) {
this.browser = await puppeteer.launch({
headless: false,
args: [
'--no-sandbox',
'--disable-dev-shm-usage',
`--disable-extensions-except=${CRX_PATH}`,
`--load-extension=${CRX_PATH}`
],
ignoreHTTPSErrors: true
});
const background = await this.browser.newPage();
await background.goto(
'chrome-extension://iddjnlppdcfkhliebhkhbidlhemoncon/background.html',
{ waitUntil: 'networkidle0' }
);

this.page = await this.browser.newPage();
await background.close();
});

After(async function(this: BubbleWorld, scenario) {
if (scenario.result.status === Status.FAILED && this.page) {
const screenShotName = scenario.pickle.name.replace(/[\W_]+/g, '-');
await this.page.screenshot({
path: `${config.screenshotPath}/error/${screenShotName}.png`
});
}
});
15 changes: 6 additions & 9 deletions manifest/dev.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,13 @@ const base = require('./base');

module.exports = {
...base,
key: 'nfabbfkbbbcebdmnocndhdombaffkaog',
// resulting extension id: iddjnlppdcfkhliebhkhbidlhemoncon
name: 'LMEM - DEV',
'content_security_policy': csp({
'directives': {
'script-src': [
'\'self\'',
'\'unsafe-eval\'',
],
'object-src': [
'\'self\'',
]
content_security_policy: csp({
directives: {
'script-src': ["'self'", "'unsafe-eval'"],
'object-src': ["'self'"]
}
})
};
12 changes: 10 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
"build": "yarn build:staging && yarn build:production",
"release": "yarn release:staging && yarn release:production",
"clean": "rm -rf build",
"test": "LMEM_BACKEND_ORIGIN='' NODE_ENV=test ts-mocha --paths test/app/*.ts test/app/**/*.ts",
"test:unit": "LMEM_BACKEND_ORIGIN='' NODE_ENV=test ts-mocha --paths test/app/*.ts test/app/**/*.ts",
"test:e2e": "cucumber-js --require-module ts-node/register",
"test": "yarn test:unit && yarn test:e2e",
"typecheck": "tsc --noEmit",
"lint": "yarn lint:ts && yarn lint:css",
"lint:ts": "tslint -p .",
Expand Down Expand Up @@ -82,7 +84,10 @@
"@storybook/react": "^4.1.11",
"@types/chai": "^4.1.7",
"@types/chrome": "^0.0.81",
"@types/expect": "^1.20.4",
"@types/mocha": "^5.2.6",
"@types/node": "^12.0.2",
"@types/puppeteer": "^1.12.4",
"@types/redux-immutable-state-invariant": "^2.1.0",
"@types/redux-logger": "^3.0.7",
"@types/remote-redux-devtools": "^0.5.3",
Expand Down Expand Up @@ -116,7 +121,7 @@
"eslint-plugin-jsx-a11y": "^6.1.2",
"eslint-plugin-module-resolver": "^0.8.0",
"eslint-plugin-react": "^7.11.1",
"expect": "^1.15.2",
"expect": "^24.8.0",
"file-loader": "^2.0.0",
"html-webpack-plugin": "^3.2.0",
"husky": "^1.3.1",
Expand All @@ -129,6 +134,7 @@
"prettier": "^1.16.4",
"pug": "^2.0.3",
"pug-loader": "^2.4.0",
"puppeteer": "^1.16.0",
"raw-loader": "^0.5.1",
"redbox-react": "^1.6.0",
"redux-immutable-state-invariant": "^2.1.0",
Expand Down Expand Up @@ -163,6 +169,7 @@
"dependencies": {
"@babel/polyfill": "^7.2.5",
"@sentry/browser": "^5.1.1",
"@types/cucumber": "^4.0.5",
"@types/date-fns": "^2.6.0",
"@types/flat": "^0.0.28",
"@types/history": "^4.7.2",
Expand All @@ -182,6 +189,7 @@
"connected-react-router": "^6.3.1",
"content-security-policy-builder": "^1.1.0",
"crossmessaging": "^0.2.0",
"cucumber": "^5.1.0",
"date-fns": "^1.30.1",
"dompurify": "^0.8.4",
"es6-promise": "^3.2.1",
Expand Down
2 changes: 1 addition & 1 deletion src/app/background/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ fetchContentScript('/js/grabDraftNotices.js').then(contentCode =>
);

const state: BackgroundState = store.getState();
if (!getInstallationDetails(state).datetime) {
if (!getInstallationDetails(state).datetime && process.env.ONBOARDING_ORIGIN) {
onInstalled(process.env.ONBOARDING_ORIGIN)(store.dispatch);
}

Expand Down
1 change: 1 addition & 0 deletions src/app/content/extensionIframe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const create = (style: {
}): HTMLIFrameElement => {
const iframe = document.createElement('iframe');
iframe.id = 'lmemFrame';
iframe.name = 'BubbleIONotification';
iframe.width = '390px';
iframe.height = '423px';
iframe.srcdoc =
Expand Down
4 changes: 3 additions & 1 deletion src/components/organisms/Notice/Title.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import React from 'react';
import styled from 'styled-components';
import Truncated from '../../atoms/Truncated';

export const TitleContainer = styled.p`
export const TitleContainer = styled.p.attrs({
'data-test-type': 'noticeTitle'
})`
display: inline;
margin: 0 10px 0 0;
color: ${props => props.theme.activeColor};
Expand Down
4 changes: 3 additions & 1 deletion src/components/organisms/Notification/Container.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import styled from 'styled-components';

export const Section = styled.section`
export const Section = styled.section.attrs({
'data-test-id': 'bubble-notification'
})`
display: flex;
flex-direction: column;
max-width: 384px;
Expand Down
7 changes: 4 additions & 3 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@
// "typeRoots": [], /* List of folders to include type definitions from. */
"types": [
"chrome",
"mocha"
"mocha",
"node"
] /* Type declaration files to be included in compilation. */,
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */,
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */

/* Source Map Options */
"sourceRoot": "./src" /* Specify the location where debugger should locate TypeScript files instead of source locations. */
"sourceRoot": "./src" /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
Expand Down
Loading

0 comments on commit 76bb143

Please sign in to comment.