Skip to content

Commit

Permalink
Merge pull request #8 from satueveliina/overlap-and-overflow-detection
Browse files Browse the repository at this point in the history
Overlap and overflow detection
  • Loading branch information
Matt Simpson committed Jun 19, 2020
2 parents f939c97 + 8c08127 commit efe0702
Show file tree
Hide file tree
Showing 10 changed files with 357 additions and 16 deletions.
13 changes: 13 additions & 0 deletions README.md
Expand Up @@ -103,6 +103,19 @@ before(() => {
| **element** | string | - | - |
| **edge** | string | `'left', 'right', 'centered', 'all'` | `'all'` |

#### `overflowing([, direction])`

| argument | type | options | default |
| ---------------- | ------ | -------------------------------------| ------- |
| **direction** | string | `'vertically', 'horizontally', 'any'`| `'any'` |


#### `overlapping(element)`

| argument | type | options | default |
| ----------- | ------ | ------------------------------------ | ------- |
| **element** | string | - | - |

### Dimensions

The following width and height assertions are chain-able and can be used with the .gt, .within and .lt methods
Expand Down
71 changes: 71 additions & 0 deletions cypress/fixtures/test-app/overflow.html
@@ -0,0 +1,71 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>cypress-layout-inspector Test Application</title>
<style>
*,
*::before,
*::after {
box-sizing: border-box;
}

.container {
position: relative;
height: 80px;
}
.container .outer {
color: red;
border: 1px solid red;
}
.container .inner {
color: blue;
border: 1px solid blue;
}
.block {
padding: 5px;
}
.outer {
height: 50px;
}
.overflow-2.outer {
width: 200px;
}
.overflow-2 .inner {
width: 210px;
}

</style>
</head>
<body>
<pre>no overflow 1</pre>
<div class="container">
<div class="no-overflow-1 outer">
<div class="block no-overflow inner">no-overflow-1-inner</div>
</div>
</div>

<pre>is overflowing vertically</pre>
<div class="container">
<div class="overflow-1 outer">
<div class="inner">
overflow-inner-1 <br/>
this content <br/>
is longer <br/>
is then outer height<br/>
</div>
</div>
</div>

<pre>is overflowing horizontally</pre>
<div class="container">
<div class="overflow-2 outer">
<div class="inner">
this overflow-inner-2 is wider then outer width <br/>
</div>
</div>
</div>

</body>
</html>
126 changes: 126 additions & 0 deletions cypress/fixtures/test-app/overlap.html
@@ -0,0 +1,126 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>cypress-layout-inspector Test Application</title>
<style>
*,
*::before,
*::after {
box-sizing: border-box;
}

.container {
position: relative;
height: 220px;
}

.container .block:nth-child(1) {
color: red;
border: 1px solid red;
}

.container .block:nth-child(2) {
color: blue;
border: 1px solid blue;
}

.block {
position: absolute;
width: 100px;
height: 100px;
padding: 5px;
}

.no-overlap-1 {
top: 0;
left: 0;
}
.no-overlap-2 {
top: 105px;
left: 105px;
}
.no-overlap-3 {
top: 0;
left: 0;
}
.no-overlap-4 {
top: 105px;
left: 0px;
}
.no-overlap-5 {
top: 0;
left: 0;
}
.no-overlap-6 {
top: 0px;
left: 105px;
}

.overlap-1 {
top: 0;
left: 0;
}
.overlap-2 {
top: 50px;
left: 0px;
}
.overlap-3 {
top: 0;
left: 0;
}
.overlap-4 {
top: 0px;
left: 50px;
}
.overlap-5 {
top: 0;
left: 0;
}
.overlap-6 {
top: 50px;
left: 50px;
}

</style>
</head>
<body>
<pre>no overlap 1 and 2</pre>
<div class="container">
<div class="block no-overlap-1">no-overlap-1</div>
<div class="block no-overlap-2">no-overlap-2</div>
</div>

<pre>no overlap 3 and 4</pre>
<div class="container">
<div class="block no-overlap-3">no-overlap-3</div>
<div class="block no-overlap-4">no-overlap-4</div>
</div>

<pre>no overlap 5 and 6</pre>
<div class="container">
<div class="block no-overlap-5">no-overlap-5</div>
<div class="block no-overlap-6">no-overlap-6</div>
</div>

<pre>overlap-1 overlaps vertically with overlap-2</pre>
<div class="container">
<div class="block overlap-1">overlap-1</div>
<div class="block overlap-2">overlap-2</div>
</div>

<pre>overlap-3 overlaps horizontally with overlap-4</pre>
<div class="container">
<div class="block overlap-3">overlap-3</div>
<div class="block overlap-4">overlap-4</div>
</div>

<pre>overlap-5 overlaps horizontally and vertically with overlap-6</pre>
<div class="container">
<div class="block overlap-5">overlap-5</div>
<div class="block overlap-6">overlap-6</div>
</div>

</body>
</html>
24 changes: 24 additions & 0 deletions cypress/integration/overflow.spec.js
@@ -0,0 +1,24 @@
describe('overflow testing commands', () => {

beforeEach(() => {
cy.visit('cypress/fixtures/test-app/overflow.html');
});

it('no-overflow-1 should not be overflowing', () => {
cy.get('.no-overflow-1.outer').should('not.be.overflowing');
});

it('overflow-1 should be overflowing vertically', () => {
cy.get('.overflow-1.outer').should('be.overflowing');
cy.get('.overflow-1.outer').should('not.be.overflowing', 'horizontally');
cy.get('.overflow-1.outer').should('be.overflowing', 'vertically');
});

it('overflow-2 should be overflowing horizontally', () => {
cy.get('.overflow-2.outer').should('be.overflowing');
cy.get('.overflow-2.outer').should('be.overflowing', 'horizontally');
cy.get('.overflow-2.outer').should('not.be.overflowing', 'vertically');
});

});

37 changes: 37 additions & 0 deletions cypress/integration/overlap.spec.js
@@ -0,0 +1,37 @@
describe('overlap testing commands', () => {
beforeEach(() => {
cy.visit('cypress/fixtures/test-app/overlap.html');
});

it('no-overlap-1 and no-overlap-2 should not be overlapping', () => {
cy.get('.no-overlap-2').should('not.be.overlapping', '.no-overlap-1');
cy.get('.no-overlap-1').should('not.be.overlapping', '.no-overlap-2');
});

it('no-overlap-3 and no-overlap-4 should not be overlapping', () => {
cy.get('.no-overlap-3').should('not.be.overlapping', '.no-overlap-4');
cy.get('.no-overlap-4').should('not.be.overlapping', '.no-overlap-3');
});

it('no-overlap-5 and no-overlap-6 should not be overlapping', () => {
cy.get('.no-overlap-5').should('not.be.overlapping', '.no-overlap-6');
cy.get('.no-overlap-6').should('not.be.overlapping', '.no-overlap-5');
});

it('overlap-1 and overlap-2 should be overlapping', () => {
cy.get('.overlap-1').should('be.overlapping', '.overlap-2');
cy.get('.overlap-2').should('be.overlapping', '.overlap-1');
});

it('overlap-3 and overlap-4 should be overlapping', () => {
cy.get('.overlap-3').should('be.overlapping', '.overlap-4');
cy.get('.overlap-4').should('be.overlapping', '.overlap-3');
});

it('overlap-5 and overlap-6 should be overlapping', () => {
cy.get('.overlap-5').should('be.overlapping', '.overlap-6');
cy.get('.overlap-6').should('be.overlapping', '.overlap-5');
});

});

4 changes: 4 additions & 0 deletions src/assertions/index.js
@@ -1,7 +1,11 @@
import alignment from './alignment';
import position from './position';
import style from './style';
import overlap from './overlap';
import overflow from './overflow';

chai.use(alignment);
chai.use(position);
chai.use(style);
chai.use(overlap);
chai.use(overflow);
29 changes: 29 additions & 0 deletions src/assertions/overflow.js
@@ -0,0 +1,29 @@
import getElement from '../utils/getElement';

export default _chai => {
function overflowing(direction = 'any') {
const el = getElement(this._obj);
const overflowVertical = el.scrollHeight > el.clientHeight;
const overflowHorizontal = el.scrollWidth > el.clientWidth;

let condition;

switch (direction) {
case 'horizontally':
condition = overflowHorizontal;
break;
case 'vertically':
condition = overflowVertical;
break;
default:
condition = overflowVertical || overflowHorizontal;
}

return this.assert(
condition,
`expected #{this} to overflow ${direction}`,
`expected #{this} not to overflow ${direction}`
);
}
_chai.Assertion.addMethod('overflowing', overflowing);
};
30 changes: 30 additions & 0 deletions src/assertions/overlap.js
@@ -0,0 +1,30 @@
import Rect from '../utils/rect';

const linesOverlap = (line1, line2) => {
const line2isBefore = line2.end < line1.start;
const line2isAfter = line2.start > line1.end;
return !(line2isBefore || line2isAfter);
};

export default _chai => {
function overlapping(element) {
const [rect1, rect2] = [new Rect(this._obj), new Rect(element)];

const overlapVertical = linesOverlap(
{ start: rect1.top, end: rect1.bottom },
{ start: rect2.top, end: rect2.bottom }
);
const overlapHorizontal = linesOverlap(
{ start: rect1.left, end: rect1.right },
{ start: rect2.left, end: rect2.right }
);
const condition = overlapVertical && overlapHorizontal;

return this.assert(
condition,
`expected #{this} to overlap with ${element} `,
`expected #{this} not to overlap with ${element}`
);
}
_chai.Assertion.addMethod('overlapping', overlapping);
};
21 changes: 21 additions & 0 deletions src/utils/getElement.js
@@ -0,0 +1,21 @@
function getElement(subject) {
let element;
if (subject == null) {
throw new Error(
`Expected to find element: \`${subject}\`, but never found it.`
);
}

if (typeof subject === 'string') [element] = Cypress.$(subject);
if (subject.constructor.name === 'jQuery') [element] = subject;

if (element === undefined) {
throw new Error(
`Expected to find element: \`${subject}\`, but never found it.`
);
}

return element;
}

export default getElement;

0 comments on commit efe0702

Please sign in to comment.