Skip to content

Commit

Permalink
feat: add new subject type, implement window and document query
Browse files Browse the repository at this point in the history
  • Loading branch information
Solant committed Oct 17, 2024
1 parent e203553 commit be41e60
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 17 deletions.
6 changes: 3 additions & 3 deletions COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
| [.children()](https://docs.cypress.io/api/commands/children) || - | [3](#3-timeouts) |
| [.closest()](https://docs.cypress.io/api/commands/closest) | 🕓 | 🕓 | |
| [.contains()](https://docs.cypress.io/api/commands/contains) | ⚠️ | ⚠️ | selectors are not implemented, `includeShadowDom` option is not implemented, [3](#3-timeouts) |
| [.document()](https://docs.cypress.io/api/commands/document) | 🕓 | 🕓 | |
| [.document()](https://docs.cypress.io/api/commands/document) | | - | [3](#3-timeouts) |
| [.eq()](https://docs.cypress.io/api/commands/eq) || - | [3](#3-timeouts) |
| [.filter()](https://docs.cypress.io/api/commands/filter) || - | [3](#3-timeouts) |
| [.find()](https://docs.cypress.io/api/commands/find) || ⚠️ | `includeShadowDom` option is not implemented, [3](#3-timeouts) |
Expand Down Expand Up @@ -41,7 +41,7 @@
| [.siblings()](https://docs.cypress.io/api/commands/siblings) | ⚠️ | 🕓 | selector argument is not implemented, [3](#3-timeouts) |
| [.title()](https://docs.cypress.io/api/commands/title) || - | [3](#3-timeouts) |
| [.url()](https://docs.cypress.io/api/commands/url) || ⚠️ | `decode` option is not implemented, [3](#3-timeouts) |
| [.window()](https://docs.cypress.io/api/commands/window) | 🕓 | 🕓 | |
| [.window()](https://docs.cypress.io/api/commands/window) | | - | [3](#3-timeouts) |

## Assertions

Expand Down Expand Up @@ -156,7 +156,7 @@ the target element. Thus, in some cases, playwright action with `force` flag ena

### 2. Assertions

`.should()` assertions are supported (some of them might be missing), but there are just too many of them for this
`.should()` assertions are supported (some of them are missing), but there are just too many of them for this
list (the whole chai BDD list).

`expect()` assertions are not supported because their chained API is trickier to reimplement and as they rely too much
Expand Down
63 changes: 51 additions & 12 deletions src/actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { expect, Locator, Page } from '@playwright/test';
import {
expect, JSHandle, Locator, Page,
} from '@playwright/test';

export type SpecialSelector = { modifier: 'first' } | { modifier: 'last' } | {
modifier: 'contains',
Expand Down Expand Up @@ -93,6 +95,9 @@ export type Action = AssertActions | {
| 'port'
| 'protocol'
| 'search'
} | {
type: 'handle',
global: 'window' | 'document',
};

let queue: Array<Action> = [];
Expand All @@ -115,7 +120,10 @@ function resolveSelectorItem(parent: Locator | Page, selector: Selector[number])
}
}

export type Subject = { type: 'locator', value: Locator } | { type: 'value', value: unknown };
export type Subject =
{ type: 'locator', value: Locator }
| { type: 'value', value: unknown }
| { type: 'handle', value: JSHandle };

export async function evaluateAction(
page: Page,
Expand All @@ -124,6 +132,16 @@ export async function evaluateAction(
aliasMap: Record<string, Subject>,
): Promise<Subject> {
switch (action.type) {
case 'handle': {
switch (action.global) {
case 'window':
return { type: 'handle', value: await page.evaluateHandle(() => window) };
case 'document':
return { type: 'handle', value: await page.evaluateHandle(() => window.document) };
default:
throw new Error('Unknown handle value');
}
}
case 'alias': {
// eslint-disable-next-line no-param-reassign
aliasMap[action.name] = subject;
Expand Down Expand Up @@ -195,13 +213,30 @@ export async function evaluateAction(
} else {
expect(subject.value).toContain(action.value);
}
} else if (action.negation) {
await expect(subject.value).not.toContainText(action.value);
} else {
await expect(subject.value).toContainText(action.value);
}
break;
if (subject.type === 'locator') {
if (action.negation) {
await expect(subject.value).not.toContainText(action.value);
} else {
await expect(subject.value).toContainText(action.value);
}
break;
}
throw new Error('Handle subject is not implemented');
case 'property':
if (subject.type === 'handle') {
const result = await page.evaluate(
(ctx) => Object.prototype.hasOwnProperty.call(ctx.subject, ctx.property),
{ subject: subject.value, property: action.value },
);
if (action.negation) {
expect(result).not.toBe(true);
} else {
expect(result).toBe(true);
}
break;
}

if (action.negation) {
expect(subject.value).not.toHaveProperty(action.value);
} else {
Expand Down Expand Up @@ -229,13 +264,17 @@ export async function evaluateAction(
expect(Object.keys(subject.value as any)).not.toHaveLength(0);
break;
}
} else if (action.negation) {
await expect(subject.value).not.toBeEmpty();
}
if (subject.type === 'locator') {
if (action.negation) {
await expect(subject.value).not.toBeEmpty();
break;
} else {
await expect(subject.value).toBeEmpty();
}
break;
} else {
await expect(subject.value).toBeEmpty();
}
break;
throw new Error('Handle subject is not implemented');
case 'equal':
if (action.negation) {
expect(subject.value).not.toBe(action.value);
Expand Down
10 changes: 10 additions & 0 deletions src/cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,16 @@ class Cy {
return this.selfOrChild();
}

window() {
pushQueue({ type: 'handle', global: 'window' });
return this.selfOrChild();
}

document() {
pushQueue({ type: 'handle', global: 'document' });
return this.selfOrChild();
}

hash() {
return this.location('hash');
}
Expand Down
3 changes: 1 addition & 2 deletions tests/2-advanced-examples/window.cy.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import { setup } from '../../src';

setup();

context('Window', () => {
beforeEach(() => {
cy.visit('https://example.cypress.io/commands/window')
})

/*
it('cy.window() - get the global window object', () => {
// https://on.cypress.io/window
cy.window().should('have.property', 'top')
})
*/

/*
it('cy.document() - get the document object', () => {
Expand Down

0 comments on commit be41e60

Please sign in to comment.