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

Update packages and add extended tests from non-typescript example #5

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
157 changes: 156 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# cypress-cucumber-typescript-example
Example of using Cypress with Cucumber and TypeScript
Example of using Cypress with Cucumber and TypeScript.

There are examples that are part of a Continuous Integration build in the main repo, that also showcase more advanced
usage, please refer there as well - https://github.com/TheBrainFamily/cypress-cucumber-preprocessor/tree/master/cypress

All the configuration is in [cypress/plugins/index.js](cypress/plugins/index.js)

Expand All @@ -8,3 +11,155 @@ TypeScript step definitions are in [cypress/integration/passWithTypescript](cypr
(I'm using the nonGlobalStepDefinitions configuration in the [package.json](package.json) )

You can also use our Cucumber plugin with TypeScript and webpack: [https://github.com/TheBrainFamily/cypress-cucumber-webpack-typescript-example/](https://github.com/TheBrainFamily/cypress-cucumber-webpack-typescript-example/)

# Run example tests

```
npm install
npm test
```

Or, you can run the tests using the Cypress GUI:

```
npm install
npm run cy:open
```

# Tags usage

### Tagging tests
You can use tags to select which test should run using [cucumber's tag expressions](https://github.com/cucumber/cucumber/tree/master/tag-expressions).
Keep in mind we are using newer syntax, eg. `'not @foo and (@bar or @zap)'`.
In order to initialize tests using tags you will have to run cypress and pass TAGS environment variable.

To make things faster and skip cypress opening a browser for every feature file (taking a couple seconds for each one), even the ones we want ignored, we use our own cypress-tags wrapper. It passes all the arguments to cypress, so use it the same way you would use cypress CLI. The only difference is it will first filter out the files we don't care about, based on the tags provided.

### Examples:

There are a few tagged tests in these files:

[Facebook.feature](https://github.com/TheBrainFamily/cypress-cucumber-example/blob/master/cypress/integration/socialNetworks/Facebook.feature)
```
@feature-tag
Feature: The Facebook

I want to open a social network page

@tag-to-include
Scenario: Opening a social network page
Given I open Facebook page
Then I see "Facebook" in the title

@another-tag-to-include @some-other-tag
Scenario: Different kind of opening
Given I kinda open Facebook page
Then I am very happy

```


[GitHub.feature](https://github.com/TheBrainFamily/cypress-cucumber-example/blob/master/cypress/integration/socialNetworks/GitHub.feature)
```
@feature-tag @github-tag
Feature: The GitHub

I want to tweet things

@tag-to-include
Scenario: Opening GitHub
Given I open GitHub page
Then I see "GitHub" in the title

@another-tag-to-include
Scenario: Opening GitHub again
Given I open GitHub page
Then I see "GitHub" in the title
```

###### Simple Example
Run ```./node_modules/.bin/cypress-tags run -e TAGS='@feature-tag'``` in this repo. As both `Facebook.feature` and `GitHub.feature`
have `@feature-tag` above the feature name, and `Google.feature` has no tags, the result should be:

```
Spec Tests Passing Failing Pending Skipped
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ✔ socialNetworks/Facebook.feature 00:04 2 2 - - - │
├────────────────────────────────────────────────────────────────────────────────────────────────┤
│ ✔ socialNetworks/GitHub.feature 00:05 2 2 - - - │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
All specs passed! 00:09 4 4 - - -
```

###### usage of `not`

Run ```./node_modules/.bin/cypress-tags run -e TAGS='not @github-tag'``` in this repo. `Facebook.feature` and `Google.feature` will run, as only `GitHub.feature` has the unwanted tag. The result should be:

```
Spec Tests Passing Failing Pending Skipped
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ✔ socialNetworks/Facebook.feature 00:05 2 2 - - - │
└────────────────────────────────────────────────────────────────────────────────────────────────┘
All specs passed! 00:05 2 2 - - -
```

###### usage of `and`

Run ```./node_modules/.bin/cypress-tags run -e TAGS='@another-tag-to-include and @some-other-tag'``` in this repo. There is only one scenario that has both the tags, in `Facebook.feature`. The result should be:

```
Spec Tests Passing Failing Pending Skipped
┌────────────────────────────────────────────────────────────────────────────────────────────────┐
│ ✔ socialNetworks/Facebook.feature 00:03 1 1 - - - │
├────────────────────────────────────────────────────────────────────────────────────────────────┤
All specs passed! 00:03 1 1 - - -

```

###### combinations

Keep in mind that order matters and use parentheses wisely. The following commands will yield different results:
```./node_modules/.bin/cypress-tags run -e TAGS='@tag-to-include or @another-tag-to-include and not @github-tag'```

```./node_modules/.bin/cypress-tags run -e TAGS='(@tag-to-include or @another-tag-to-include) and not @github-tag'```

The first one will include scenario tagged `@tag-to-include` from the [GitHub.feature](https://github.com/TheBrainFamily/cypress-cucumber-example/blob/master/cypress/integration/socialNetworks/GitHub.feature), while
the second one will skip all scenarios from it.

### Smart tagging
Start your tests without setting any tags. And then put a @focus on the scenario (or scenarios) you want to focus on while development or bug fixing.

For example:
```gherkin
Feature: Smart Tagging

As a cucumber cypress plugin which handles Tags
I want to allow people to select tests to run if focused
So they can work more efficiently and have a shorter feedback loop

Scenario: This scenario should not run if @focus is on another scenario
Then this unfocused scenario should not run

@focus
Scenario: This scenario is focused and should run
Then this focused scenario should run

@this-tag-affects-nothing
Scenario: This scenario should also not run
Then this unfocused scenario should not run

@focus
Scenario: This scenario is also focused and also should run
Then this focused scenario should run
```

# Scoped hooks:

Unfortunately, running all tests through GUI causes an unexpected behavior with hooks:

[TheBrainFamily/cypress-cucumber-preprocessor#139](https://github.com/TheBrainFamily/cypress-cucumber-preprocessor/issues/139)
which is an acknowledged bug in cypress itself:

[cypress-io/cypress#3323](https://github.com/cypress-io/cypress/issues/3323)

Our advice is to not use the "run all" in the GUI - which would be slow once you have enough .feature files anyway. Running through cypress run (for CI use) works as described.
6 changes: 6 additions & 0 deletions cypress/integration/common/I_see_STRING_in_the_title.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/// <reference path='../../support/index.d.ts' />
import { Then } from 'cypress-cucumber-preprocessor/steps';

Then(`I see {string} in the title`, title => {
cy.title().should("include", title);
});
6 changes: 6 additions & 0 deletions cypress/integration/common/globalBefore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/// <reference path='../../support/index.d.ts' />
before(() => {
cy.log(
"This will run once before all tests, you can use this to for example start up your server, if that's your thing"
);
});
11 changes: 11 additions & 0 deletions cypress/integration/news/Google.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
Feature: The Google

I want to open Google page

Scenario: Opening a Google network page
Given I open Google page
Then I see "Google" in the title

Scenario: Different kind of opening
Given I kinda open Google page
Then I am very happy
6 changes: 6 additions & 0 deletions cypress/integration/news/Google/beforeEach.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/// <reference path='../../../support/index.d.ts' />
beforeEach(() => {
cy.log(
"This will run before every scenario of Google.feature test, but NEVER for Facebook/Google feature files"
);
});
26 changes: 26 additions & 0 deletions cypress/integration/news/Google/different.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/// <reference path='../../../support/index.d.ts' />
import {
Before,
Given,
Then,
} from 'cypress-cucumber-preprocessor/steps';

const url = "https://google.com";

let myBeforeCount = 0;

// This verifies that the hooks work with bundling feature
// https://github.com/TheBrainFamily/cypress-cucumber-preprocessor/pull/234
Before(() => {
expect(myBeforeCount).to.be.lessThan(2);
myBeforeCount += 1;
});

Given(`I kinda open Google page`, () => {
cy.visit(url);
});

// This is the same step that we have in socialNetworks/Facebook/different.js, but you don't have to worry about collisions!
Then(`I am very happy`, () => {
cy.title().should("include", "Google");
});
8 changes: 8 additions & 0 deletions cypress/integration/news/Google/openingGoogle.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <reference path='../../../support/index.d.ts' />
import { Given } from 'cypress-cucumber-preprocessor/steps';

const url = "https://google.com";

Given(`I open Google page`, () => {
cy.visit(url);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/// <reference path='../../../support/index.d.ts' />
import { Given } from 'cypress-cucumber-preprocessor/steps';

const localFunctionWithTypes = (a: number, b: number): number => a + b;

Given(/I pass/, () => {
cy.pass("hello world");
console.log(localFunctionWithTypes(1, 2) === 2);
});
10 changes: 0 additions & 10 deletions cypress/integration/passWithTypescript/google.ts

This file was deleted.

3 changes: 0 additions & 3 deletions cypress/integration/passWithTypescript/someFile.ts

This file was deleted.

14 changes: 14 additions & 0 deletions cypress/integration/socialNetworks/Facebook.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@feature-tag
Feature: The Facebook

I want to open a social network page

@tag-to-include
Scenario: Opening a social network page
Given I open Facebook page
Then I see "Facebook" in the title

@another-tag-to-include @some-other-tag
Scenario: Different kind of opening
Given I kinda open Facebook page
Then I am very happy
16 changes: 16 additions & 0 deletions cypress/integration/socialNetworks/Facebook/different.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/// <reference path='../../../support/index.d.ts' />
import {
Given,
Then,
} from 'cypress-cucumber-preprocessor/steps';

const url = "https://facebook.com";

Given(`I kinda open Facebook page`, () => {
cy.visit(url);
});

// This is the same step that we have in news/Google/different.js, but you don't have to worry about collisions!
Then(`I am very happy`, () => {
cy.title().should("include", "Facebook");
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <reference path='../../../support/index.d.ts' />
import { Given } from 'cypress-cucumber-preprocessor/steps';

const url = "https://facebook.com";

Given(`I open Facebook page`, () => {
cy.visit(url);
});
14 changes: 14 additions & 0 deletions cypress/integration/socialNetworks/GitHub.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@feature-tag @github-tag
Feature: The Github

I want to GitHub Things

@tag-to-include
Scenario: Opening GitHub
Given I open GitHub page
Then I see "GitHub" in the title

@another-tag-to-include
Scenario: Opening GitHub again
Given I open GitHub page
Then I see "GitHub" in the title
8 changes: 8 additions & 0 deletions cypress/integration/socialNetworks/GitHub/openingTwitter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/// <reference path='../../../support/index.d.ts' />
import { When } from 'cypress-cucumber-preprocessor/steps';

const url = "https://github.com";

When(`I open GitHub page`, () => {
cy.visit(url);
});
18 changes: 9 additions & 9 deletions cypress/plugins/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
const cucumber = require("cypress-cucumber-preprocessor").default;
const browserify = require("@cypress/browserify-preprocessor");
const browserify = require('@cypress/browserify-preprocessor');
const cucumber = require('cypress-cucumber-preprocessor').default;
const resolve = require('resolve');

module.exports = (on) => {
const options = browserify.defaultOptions;
module.exports = (on, config) => {
const options = {
...browserify.defaultOptions,
typescript: resolve.sync('typescript', { baseDir: config.projectRoot }),
};

options.browserifyOptions.plugin.unshift(['tsify']);
// Or, if you need a custom tsconfig.json for your test files:
// options.browserifyOptions.plugin.unshift(['tsify', {project: 'path/to/other/tsconfig.json'}]);

on("file:preprocessor", cucumber(options));
on('file:preprocessor', cucumber(options));
};
25 changes: 0 additions & 25 deletions cypress/support/commands.js

This file was deleted.

5 changes: 5 additions & 0 deletions cypress/support/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/// <reference path='../support/index.d.ts' />

Cypress.Commands.add('pass', (somethingToSay: string) => {
console.log('HELLO', somethingToSay)
});
14 changes: 14 additions & 0 deletions cypress/support/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// in cypress/support/index.d.ts
// load type definitions that come with Cypress module
/// <reference types="cypress" />

declare namespace Cypress {
interface Chainable {
/**
* Custom command to select DOM element by data-cy attribute.
* @example cy.dataCy('greeting')
*/

pass(somethingToSay: string): Chainable<Element>
}
}
Loading