Skip to content

Commit 8f121a9

Browse files
committed
Added iframe mocks support.
1 parent d87b11e commit 8f121a9

File tree

10 files changed

+224
-5
lines changed

10 files changed

+224
-5
lines changed

lib/testcase/visualdiff.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Page } from '@playwright/test';
12
export declare function defineVisualDiffConfig(cases: VisualDiffUrlConfig): VisualDiffTestCases;
23
export declare function defaultTestFunction(testCase: VisualDiff, group: VisualDiffGroup): ({ page, context }: {
34
page: any;
@@ -40,6 +41,9 @@ export type VisualDiffGroup = BaseVisualDiff & {
4041
pathPrefix?: string;
4142
testCases: VisualDiff[];
4243
};
44+
export interface Mockable {
45+
mock(page: Page): Promise<void>;
46+
}
4347
/**
4448
* An individual test case.
4549
*/
@@ -51,6 +55,7 @@ export type BaseVisualDiff = {
5155
description?: string;
5256
representativeUrl?: string;
5357
skip?: SkipTest;
58+
mockClass?: Mockable | void;
5459
};
5560
/**
5661
* A declaration that a test should be skipped.

lib/testcase/visualdiff.js

+8-2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ function defaultTestFunction(testCase, group) {
5353
return __generator(this, function (_c) {
5454
switch (_c.label) {
5555
case 0:
56+
if (!(testCase.mockClass != undefined)) return [3 /*break*/, 2];
57+
return [4 /*yield*/, testCase.mockClass.mock(page)];
58+
case 1:
59+
_c.sent();
60+
_c.label = 2;
61+
case 2:
5662
// Log any errors to the Playwright console too.
5763
context.on('weberror', function (webError) { return console.log(webError.error()); });
5864
testInfo.annotations.push({
@@ -77,10 +83,10 @@ function defaultTestFunction(testCase, group) {
7783
path = group.pathPrefix + path;
7884
}
7985
return [4 /*yield*/, page.goto(path)];
80-
case 1:
86+
case 3:
8187
_c.sent();
8288
return [4 /*yield*/, (0, util_1.takeAccessibleScreenshot)(page, testInfo, { fullPage: true })];
83-
case 2:
89+
case 4:
8490
_c.sent();
8591
return [2 /*return*/];
8692
}

lib/util/mock/mock.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { Page } from '@playwright/test';
2+
import { Mockable } from "../../testcase";
3+
export declare class Mock implements Mockable {
4+
mock(page: Page): Promise<void>;
5+
}

lib/util/mock/mock.js

+63
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"use strict";
2+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4+
return new (P || (P = Promise))(function (resolve, reject) {
5+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8+
step((generator = generator.apply(thisArg, _arguments || [])).next());
9+
});
10+
};
11+
var __generator = (this && this.__generator) || function (thisArg, body) {
12+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14+
function verb(n) { return function (v) { return step([n, v]); }; }
15+
function step(op) {
16+
if (f) throw new TypeError("Generator is already executing.");
17+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
18+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19+
if (y = 0, t) op = [op[0] & 2, t.value];
20+
switch (op[0]) {
21+
case 0: case 1: t = op; break;
22+
case 4: _.label++; return { value: op[1], done: false };
23+
case 5: _.label++; y = op[1]; op = [0]; continue;
24+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
25+
default:
26+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30+
if (t[2]) _.ops.pop();
31+
_.trys.pop(); continue;
32+
}
33+
op = body.call(thisArg, _);
34+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36+
}
37+
};
38+
Object.defineProperty(exports, "__esModule", { value: true });
39+
exports.Mock = void 0;
40+
var youtube_1 = require("./youtube");
41+
var Mock = /** @class */ (function () {
42+
function Mock() {
43+
}
44+
Mock.prototype.mock = function (page) {
45+
var _this = this;
46+
var f = function (page) { return __awaiter(_this, void 0, void 0, function () {
47+
var youtube;
48+
return __generator(this, function (_a) {
49+
switch (_a.label) {
50+
case 0:
51+
youtube = new youtube_1.Youtube();
52+
return [4 /*yield*/, youtube.mock(page)];
53+
case 1:
54+
_a.sent();
55+
return [2 /*return*/];
56+
}
57+
});
58+
}); };
59+
return f(page);
60+
};
61+
return Mock;
62+
}());
63+
exports.Mock = Mock;

lib/util/mock/youtube.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { Page } from '@playwright/test';
2+
import { Mockable } from "../../testcase";
3+
export declare class Youtube implements Mockable {
4+
mock(page: Page): Promise<void>;
5+
}

lib/util/mock/youtube.js

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
"use strict";
2+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4+
return new (P || (P = Promise))(function (resolve, reject) {
5+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8+
step((generator = generator.apply(thisArg, _arguments || [])).next());
9+
});
10+
};
11+
var __generator = (this && this.__generator) || function (thisArg, body) {
12+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
13+
return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
14+
function verb(n) { return function (v) { return step([n, v]); }; }
15+
function step(op) {
16+
if (f) throw new TypeError("Generator is already executing.");
17+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
18+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
19+
if (y = 0, t) op = [op[0] & 2, t.value];
20+
switch (op[0]) {
21+
case 0: case 1: t = op; break;
22+
case 4: _.label++; return { value: op[1], done: false };
23+
case 5: _.label++; y = op[1]; op = [0]; continue;
24+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
25+
default:
26+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
27+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
28+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
29+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
30+
if (t[2]) _.ops.pop();
31+
_.trys.pop(); continue;
32+
}
33+
op = body.call(thisArg, _);
34+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
35+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
36+
}
37+
};
38+
Object.defineProperty(exports, "__esModule", { value: true });
39+
exports.Youtube = void 0;
40+
var Youtube = /** @class */ (function () {
41+
function Youtube() {
42+
}
43+
Youtube.prototype.mock = function (page) {
44+
return __awaiter(this, void 0, void 0, function () {
45+
var ytEmbedUrl;
46+
var _this = this;
47+
return __generator(this, function (_a) {
48+
switch (_a.label) {
49+
case 0:
50+
ytEmbedUrl = new RegExp('www\.youtube\.com', 'i');
51+
return [4 /*yield*/, page.route(ytEmbedUrl, function (route) { return __awaiter(_this, void 0, void 0, function () {
52+
return __generator(this, function (_a) {
53+
switch (_a.label) {
54+
case 0: return [4 /*yield*/, route.fulfill({
55+
contentType: 'text/html',
56+
body: "\n<html>\n<head>\n <title>Youtube Video Mock</title>\n <style>\n body {\n color: white;\n background-color: darkred;\n }\n div {\n position: absolute;\n top: 50%;\n left: 50%;\n margin: 0;\n transform: translate(-50%, -50%);\n font-size: xxx-large;\n text-align: center;\n }\n </style>\n</head>\n<body>\n <div>Youtube Video Mock</div>\n</body>\n</html>\n",
57+
})];
58+
case 1:
59+
_a.sent();
60+
return [2 /*return*/];
61+
}
62+
});
63+
}); })];
64+
case 1:
65+
_a.sent();
66+
return [2 /*return*/];
67+
}
68+
});
69+
});
70+
};
71+
return Youtube;
72+
}());
73+
exports.Youtube = Youtube;

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@
1717
},
1818
"devDependencies": {
1919
"typescript": "^5.2.2"
20-
}
20+
},
21+
"packageManager": "[email protected]+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
2122
}

src/testcase/visualdiff.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {test, WebError} from '@playwright/test';
1+
import {Page, test, WebError} from '@playwright/test';
22

33
import {takeAccessibleScreenshot} from "../util";
44

@@ -9,8 +9,11 @@ export function defineVisualDiffConfig(cases: VisualDiffUrlConfig) {
99
export function defaultTestFunction(testCase: VisualDiff, group: VisualDiffGroup) {
1010
// @ts-ignore
1111
return async ({page, context}, testInfo) => {
12-
// Log any errors to the Playwright console too.
12+
if (testCase.mockClass != undefined) {
13+
await testCase.mockClass.mock(page);
14+
}
1315

16+
// Log any errors to the Playwright console too.
1417
context.on('weberror', (webError: WebError) => console.log(webError.error()));
1518
testInfo.annotations.push({
1619
type: 'Description',
@@ -130,6 +133,10 @@ export type VisualDiffGroup = BaseVisualDiff & {
130133
testCases: VisualDiff[],
131134
}
132135

136+
export interface Mockable {
137+
mock(page: Page): Promise<void>
138+
}
139+
133140
/**
134141
* An individual test case.
135142
*/
@@ -147,6 +154,7 @@ export type BaseVisualDiff = {
147154
representativeUrl?: string,
148155
// Allow skipping of this test.
149156
skip?: SkipTest,
157+
mockClass?: Mockable | void
150158
}
151159

152160
/**

src/util/mock/mock.ts

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import {Page} from '@playwright/test';
2+
import {Mockable} from "../../testcase";
3+
import {Youtube} from "./youtube";
4+
5+
export class Mock implements Mockable{
6+
mock(page: Page): Promise<void> {
7+
const f = async(page: Page): Promise<void> => {
8+
const youtube = new Youtube();
9+
await youtube.mock(page);
10+
}
11+
return f(page);
12+
}
13+
14+
}

src/util/mock/youtube.ts

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {Page} from '@playwright/test';
2+
import {Mockable} from "../../testcase";
3+
4+
export class Youtube implements Mockable{
5+
public async mock(page: Page): Promise<void> {
6+
const ytEmbedUrl = new RegExp('www\.youtube\.com', 'i');
7+
await page.route(ytEmbedUrl, async route => {
8+
await route.fulfill({
9+
contentType: 'text/html',
10+
body: `
11+
<html>
12+
<head>
13+
<title>Youtube Video Mock</title>
14+
<style>
15+
body {
16+
color: white;
17+
background-color: darkred;
18+
}
19+
div {
20+
position: absolute;
21+
top: 50%;
22+
left: 50%;
23+
margin: 0;
24+
transform: translate(-50%, -50%);
25+
font-size: xxx-large;
26+
text-align: center;
27+
}
28+
</style>
29+
</head>
30+
<body>
31+
<div>Youtube Video Mock</div>
32+
</body>
33+
</html>
34+
`,
35+
});
36+
});
37+
}
38+
39+
}

0 commit comments

Comments
 (0)