@manufac/general-tests 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/projects.d.ts +14 -21
- package/dist/config/projects.js +8 -11
- package/dist/fixtures/index.d.ts +1 -0
- package/dist/fixtures/index.js +3 -10
- package/dist/specs/loading-page.spec.js +84 -0
- package/dist/specs/responsive-layout.spec.js +17 -0
- package/package.json +1 -1
- package/dist/specs/shared/landing-page.spec.js +0 -31
- package/dist/specs/site-wide/landing-page.spec.js +0 -38
- /package/dist/specs/{shared/landing-page.spec.d.ts → loading-page.spec.d.ts} +0 -0
- /package/dist/specs/{site-wide/landing-page.spec.d.ts → responsive-layout.spec.d.ts} +0 -0
|
@@ -4,45 +4,38 @@ export interface Breakpoint {
|
|
|
4
4
|
height: number;
|
|
5
5
|
}
|
|
6
6
|
export declare const DesktopBreakpoints: {
|
|
7
|
-
readonly Laptop: {
|
|
8
|
-
readonly name: "Laptop";
|
|
9
|
-
readonly width: 1280;
|
|
10
|
-
readonly height: 800;
|
|
11
|
-
};
|
|
12
7
|
readonly Desktop: {
|
|
13
8
|
readonly name: "Desktop";
|
|
14
9
|
readonly width: 1440;
|
|
15
10
|
readonly height: 900;
|
|
16
11
|
};
|
|
17
|
-
readonly Wide: {
|
|
18
|
-
readonly name: "Wide";
|
|
19
|
-
readonly width: 1920;
|
|
20
|
-
readonly height: 1080;
|
|
21
|
-
};
|
|
22
12
|
};
|
|
23
|
-
export declare const
|
|
13
|
+
export declare const ResponsiveLayoutBreakpoints: {
|
|
24
14
|
readonly MobileS: {
|
|
25
|
-
readonly name: "
|
|
15
|
+
readonly name: "320";
|
|
26
16
|
readonly width: 320;
|
|
27
17
|
readonly height: 568;
|
|
28
18
|
};
|
|
29
|
-
readonly
|
|
30
|
-
readonly name: "
|
|
31
|
-
readonly width:
|
|
32
|
-
readonly height:
|
|
19
|
+
readonly MobileL: {
|
|
20
|
+
readonly name: "375";
|
|
21
|
+
readonly width: 375;
|
|
22
|
+
readonly height: 812;
|
|
33
23
|
};
|
|
34
24
|
readonly Tablet: {
|
|
35
|
-
readonly name: "
|
|
25
|
+
readonly name: "768";
|
|
36
26
|
readonly width: 768;
|
|
37
27
|
readonly height: 1024;
|
|
38
28
|
};
|
|
29
|
+
readonly Desktop: {
|
|
30
|
+
readonly name: "1440";
|
|
31
|
+
readonly width: 1440;
|
|
32
|
+
readonly height: 900;
|
|
33
|
+
};
|
|
39
34
|
};
|
|
40
35
|
export declare const ProjectTypes: {
|
|
41
36
|
readonly Mobile: "mobile";
|
|
42
37
|
readonly Desktop: "desktop";
|
|
43
38
|
readonly Shared: "shared";
|
|
44
39
|
};
|
|
45
|
-
export declare const
|
|
46
|
-
export declare const
|
|
47
|
-
export declare const MobileOnlyTestMatch = "mobile-only/**/*.spec.js";
|
|
48
|
-
export declare const SiteWideTestMatch = "site-wide/**/*.spec.js";
|
|
40
|
+
export declare const LoadingPageTestMatch = "loading-page.spec.ts";
|
|
41
|
+
export declare const ResponsiveLayoutTestMatch = "responsive-layout.spec.js";
|
package/dist/config/projects.js
CHANGED
|
@@ -1,23 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.ResponsiveLayoutTestMatch = exports.LoadingPageTestMatch = exports.ProjectTypes = exports.ResponsiveLayoutBreakpoints = exports.DesktopBreakpoints = void 0;
|
|
4
4
|
// Section 3 of the Landing Page Test Plan — breakpoints / viewports.
|
|
5
5
|
exports.DesktopBreakpoints = {
|
|
6
|
-
Laptop: { name: "Laptop", width: 1280, height: 800 },
|
|
7
6
|
Desktop: { name: "Desktop", width: 1440, height: 900 },
|
|
8
|
-
Wide: { name: "Wide", width: 1920, height: 1080 },
|
|
9
7
|
};
|
|
10
|
-
exports.
|
|
11
|
-
MobileS: { name: "
|
|
12
|
-
|
|
13
|
-
Tablet: { name: "
|
|
8
|
+
exports.ResponsiveLayoutBreakpoints = {
|
|
9
|
+
MobileS: { name: "320", width: 320, height: 568 },
|
|
10
|
+
MobileL: { name: "375", width: 375, height: 812 },
|
|
11
|
+
Tablet: { name: "768", width: 768, height: 1024 },
|
|
12
|
+
Desktop: { name: "1440", width: 1440, height: 900 },
|
|
14
13
|
};
|
|
15
14
|
exports.ProjectTypes = {
|
|
16
15
|
Mobile: "mobile",
|
|
17
16
|
Desktop: "desktop",
|
|
18
17
|
Shared: "shared",
|
|
19
18
|
};
|
|
20
|
-
exports.
|
|
21
|
-
exports.
|
|
22
|
-
exports.MobileOnlyTestMatch = "mobile-only/**/*.spec.js";
|
|
23
|
-
exports.SiteWideTestMatch = "site-wide/**/*.spec.js";
|
|
19
|
+
exports.LoadingPageTestMatch = "loading-page.spec.ts";
|
|
20
|
+
exports.ResponsiveLayoutTestMatch = "responsive-layout.spec.js";
|
package/dist/fixtures/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export interface PageTestOptions {
|
|
2
2
|
targetPage: string;
|
|
3
|
+
pages: string[];
|
|
3
4
|
consoleErrors: string[];
|
|
4
5
|
}
|
|
5
6
|
export declare const test: import("@playwright/test").TestType<import("@playwright/test").PlaywrightTestArgs & import("@playwright/test").PlaywrightTestOptions & PageTestOptions, import("@playwright/test").PlaywrightWorkerArgs & import("@playwright/test").PlaywrightWorkerOptions>;
|
package/dist/fixtures/index.js
CHANGED
|
@@ -6,20 +6,13 @@ const test_1 = require("@playwright/test");
|
|
|
6
6
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
7
7
|
exports.test = test_1.test.extend({
|
|
8
8
|
// Ref: https://playwright.dev/docs/test-fixtures#fixtures-options
|
|
9
|
-
/**
|
|
10
|
-
* Playwright's test.extend<Options>({ someOption: [defaultValue, { option: true }] })
|
|
11
|
-
* syntax declares targetPage as a fixture option — a configurable value with a
|
|
12
|
-
* default ("/" here), which any consumer can override via test.use({ targetPage: "..." }),
|
|
13
|
-
* either per spec file, per describe block, or per Playwright "project" in a config.
|
|
14
|
-
* Without { option: true }, it'd just be a fixed value baked into the fixture,
|
|
15
|
-
* not something a consumer could override.
|
|
16
|
-
*/
|
|
17
9
|
targetPage: ["/", { option: true }],
|
|
10
|
+
pages: [["/"], { option: true }],
|
|
18
11
|
consoleErrors: async ({ page }, use) => {
|
|
19
|
-
|
|
12
|
+
const errors = [];
|
|
20
13
|
page.on("console", (message) => {
|
|
21
14
|
if (message.type() === "error") {
|
|
22
|
-
errors
|
|
15
|
+
errors.push(message.text());
|
|
23
16
|
}
|
|
24
17
|
});
|
|
25
18
|
await use(errors);
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const fixtures_1 = require("../fixtures");
|
|
4
|
+
const test_1 = require("@playwright/test");
|
|
5
|
+
fixtures_1.test.describe("Page load and structure", () => {
|
|
6
|
+
(0, fixtures_1.test)("LP-01: Page loads without errors", async ({ page, consoleErrors, pages }) => {
|
|
7
|
+
// Loops over every page in one test, so the default 30s timeout doesn't leave enough time
|
|
8
|
+
// per page once there are more than a handful — triple it instead of hardcoding a number.
|
|
9
|
+
fixtures_1.test.slow();
|
|
10
|
+
for (const targetPage of pages) {
|
|
11
|
+
await fixtures_1.test.step(targetPage, async () => {
|
|
12
|
+
const consoleErrorsBeforeNavigation = consoleErrors.length;
|
|
13
|
+
let failedNetworkRequests = 0;
|
|
14
|
+
const onResponse = (response) => {
|
|
15
|
+
const status = response.status();
|
|
16
|
+
if (status >= 400) {
|
|
17
|
+
failedNetworkRequests += 1;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
page.on("response", onResponse);
|
|
21
|
+
try {
|
|
22
|
+
const response = await page.goto(targetPage);
|
|
23
|
+
(0, test_1.expect)(response?.ok()).toBe(true);
|
|
24
|
+
(0, test_1.expect)(consoleErrors.slice(consoleErrorsBeforeNavigation)).toHaveLength(0);
|
|
25
|
+
(0, test_1.expect)(failedNetworkRequests, "Page should load without any failed network requests (404/500)").toBe(0);
|
|
26
|
+
}
|
|
27
|
+
finally {
|
|
28
|
+
page.off("response", onResponse);
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
(0, fixtures_1.test)("LP-02: Correct page metadata", async ({ page, pages }) => {
|
|
34
|
+
// Loops over every page in one test, so the default 30s timeout doesn't leave enough time
|
|
35
|
+
// per page once there are more than a handful — triple it instead of hardcoding a number.
|
|
36
|
+
fixtures_1.test.slow();
|
|
37
|
+
for (const targetPage of pages) {
|
|
38
|
+
await fixtures_1.test.step(targetPage, async () => {
|
|
39
|
+
await page.goto(targetPage);
|
|
40
|
+
const title = await page.title();
|
|
41
|
+
const hasTitle = title.trim().length > 0;
|
|
42
|
+
(0, test_1.expect)(hasTitle, "Page title should not be empty").toBe(true);
|
|
43
|
+
(0, test_1.expect)(title).not.toMatch(/^http/i);
|
|
44
|
+
(0, test_1.expect)(title).not.toMatch(/untitled/i);
|
|
45
|
+
const favicon = page.locator('link[rel="icon"], link[rel="shortcut icon"]');
|
|
46
|
+
await (0, test_1.expect)(favicon.first()).toBeAttached();
|
|
47
|
+
const href = await favicon.first().getAttribute("href");
|
|
48
|
+
(0, test_1.expect)(href, "Favicon href should not be empty").toBeTruthy();
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
(0, fixtures_1.test)("LP-03: HTTPS enforced", async ({ page, targetPage, baseURL }) => {
|
|
53
|
+
const isLocalhost = baseURL?.includes("localhost");
|
|
54
|
+
const isLocalIP = baseURL?.includes("127.0.0.1");
|
|
55
|
+
const isLocalEnvironment = isLocalhost === true || isLocalIP === true;
|
|
56
|
+
if (isLocalEnvironment) {
|
|
57
|
+
fixtures_1.test.skip(true, "HTTPS redirection is only testable on remote staging/production environments");
|
|
58
|
+
}
|
|
59
|
+
let httpBaseURL = baseURL;
|
|
60
|
+
const isHTTPS = baseURL?.startsWith("https://");
|
|
61
|
+
const isHTTP = baseURL?.startsWith("http://");
|
|
62
|
+
if (isHTTPS === true && baseURL !== undefined) {
|
|
63
|
+
httpBaseURL = baseURL.replace("https://", "http://");
|
|
64
|
+
}
|
|
65
|
+
else if (isHTTP === false && baseURL !== undefined) {
|
|
66
|
+
httpBaseURL = `http://${baseURL}`;
|
|
67
|
+
}
|
|
68
|
+
const httpURL = new URL(targetPage, httpBaseURL).toString();
|
|
69
|
+
await page.goto(httpURL);
|
|
70
|
+
(0, test_1.expect)(page.url()).toMatch(/^https:\/\//);
|
|
71
|
+
});
|
|
72
|
+
(0, fixtures_1.test)("LP-04: 404/error handling", async ({ page, targetPage }) => {
|
|
73
|
+
// Avoid a doubled leading slash (e.g. "/" + "/x" -> "//x"), which browsers resolve as
|
|
74
|
+
// protocol-relative and treat "x" as a hostname instead of a path on this site.
|
|
75
|
+
const normalizedTargetPage = targetPage.endsWith("/") ? targetPage.slice(0, -1) : targetPage;
|
|
76
|
+
const notFoundURL = `${normalizedTargetPage}/thispagedoesnotexist`;
|
|
77
|
+
await page.goto(notFoundURL);
|
|
78
|
+
const content = await page.content();
|
|
79
|
+
(0, test_1.expect)(content).not.toMatch(/stack trace/i);
|
|
80
|
+
await (0, test_1.expect)(page.getByText("Page not found"), "404 page should show a branded message").toBeVisible();
|
|
81
|
+
await (0, test_1.expect)(page.getByRole("img", { name: /manufac|logo/i }), "404 page should show the company logo").toBeVisible();
|
|
82
|
+
await (0, test_1.expect)(page.getByRole("link", { name: /home|back|return/i }), "404 page should have a link back to the home page").toBeVisible();
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const utils_js_1 = require("./utils.js");
|
|
4
|
+
const fixtures_1 = require("../fixtures");
|
|
5
|
+
const test_1 = require("@playwright/test");
|
|
6
|
+
fixtures_1.test.describe("Responsive layout", () => {
|
|
7
|
+
(0, fixtures_1.test)("RS-01: No horizontal overflow at 320 / 375 / 768 / 1440", async ({ page, pages }) => {
|
|
8
|
+
fixtures_1.test.slow();
|
|
9
|
+
for (const targetPage of pages) {
|
|
10
|
+
await fixtures_1.test.step(targetPage, async () => {
|
|
11
|
+
await page.goto(targetPage);
|
|
12
|
+
const hasScrollbar = await (0, utils_js_1.hasHorizontalScrollbar)(page);
|
|
13
|
+
(0, test_1.expect)(hasScrollbar, "Page should not have a horizontal scrollbar").toBe(false);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
});
|
package/package.json
CHANGED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const fixtures_1 = require("../../fixtures");
|
|
4
|
-
const test_1 = require("@playwright/test");
|
|
5
|
-
fixtures_1.test.describe("Page load and structure", () => {
|
|
6
|
-
(0, fixtures_1.test)("LP-01: Page loads without errors", async ({ page, consoleErrors, targetPage }) => {
|
|
7
|
-
let failedNetworkRequests = 0;
|
|
8
|
-
page.on("response", (response) => {
|
|
9
|
-
const status = response.status();
|
|
10
|
-
if (status >= 400) {
|
|
11
|
-
failedNetworkRequests += 1;
|
|
12
|
-
}
|
|
13
|
-
});
|
|
14
|
-
const response = await page.goto(targetPage);
|
|
15
|
-
(0, test_1.expect)(response?.ok()).toBe(true);
|
|
16
|
-
(0, test_1.expect)(consoleErrors).toHaveLength(0);
|
|
17
|
-
(0, test_1.expect)(failedNetworkRequests, "Page should load without any failed network requests (404/500)").toBe(0);
|
|
18
|
-
});
|
|
19
|
-
(0, fixtures_1.test)("LP-02: Correct page metadata", async ({ page, targetPage }) => {
|
|
20
|
-
await page.goto(targetPage);
|
|
21
|
-
const title = await page.title();
|
|
22
|
-
const hasTitle = title.trim().length > 0;
|
|
23
|
-
(0, test_1.expect)(hasTitle, "Page title should not be empty").toBe(true);
|
|
24
|
-
(0, test_1.expect)(title).not.toMatch(/^http/i);
|
|
25
|
-
(0, test_1.expect)(title).not.toMatch(/untitled/i);
|
|
26
|
-
const favicon = page.locator('link[rel="icon"], link[rel="shortcut icon"]');
|
|
27
|
-
await (0, test_1.expect)(favicon.first()).toBeAttached();
|
|
28
|
-
const href = await favicon.first().getAttribute("href");
|
|
29
|
-
(0, test_1.expect)(href, "Favicon href should not be empty").toBeTruthy();
|
|
30
|
-
});
|
|
31
|
-
});
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const fixtures_1 = require("../../fixtures");
|
|
4
|
-
const test_1 = require("@playwright/test");
|
|
5
|
-
fixtures_1.test.describe("Page load and structure - site-wide", () => {
|
|
6
|
-
(0, fixtures_1.test)("LP-03: HTTPS enforced", async ({ page, targetPage, baseURL }) => {
|
|
7
|
-
const isLocalhost = baseURL?.includes("localhost");
|
|
8
|
-
const isLocalIP = baseURL?.includes("127.0.0.1");
|
|
9
|
-
const isLocalEnvironment = isLocalhost === true || isLocalIP === true;
|
|
10
|
-
if (isLocalEnvironment) {
|
|
11
|
-
fixtures_1.test.skip(true, "HTTPS redirection is only testable on remote staging/production environments");
|
|
12
|
-
}
|
|
13
|
-
let httpBaseURL = baseURL;
|
|
14
|
-
const isHTTPS = baseURL?.startsWith("https://");
|
|
15
|
-
const isHTTP = baseURL?.startsWith("http://");
|
|
16
|
-
if (isHTTPS === true && baseURL !== undefined) {
|
|
17
|
-
httpBaseURL = baseURL.replace("https://", "http://");
|
|
18
|
-
}
|
|
19
|
-
else if (isHTTP === false && baseURL !== undefined) {
|
|
20
|
-
httpBaseURL = `http://${baseURL}`;
|
|
21
|
-
}
|
|
22
|
-
const httpURL = new URL(targetPage, httpBaseURL).toString();
|
|
23
|
-
await page.goto(httpURL);
|
|
24
|
-
(0, test_1.expect)(page.url()).toMatch(/^https:\/\//);
|
|
25
|
-
});
|
|
26
|
-
(0, fixtures_1.test)("LP-04: 404/error handling", async ({ page, targetPage }) => {
|
|
27
|
-
// Avoid a doubled leading slash (e.g. "/" + "/x" -> "//x"), which browsers resolve as
|
|
28
|
-
// protocol-relative and treat "x" as a hostname instead of a path on this site.
|
|
29
|
-
const normalizedTargetPage = targetPage.endsWith("/") ? targetPage.slice(0, -1) : targetPage;
|
|
30
|
-
const notFoundURL = `${normalizedTargetPage}/thispagedoesnotexist`;
|
|
31
|
-
await page.goto(notFoundURL);
|
|
32
|
-
const content = await page.content();
|
|
33
|
-
(0, test_1.expect)(content).not.toMatch(/stack trace/i);
|
|
34
|
-
await (0, test_1.expect)(page.getByText("Page not found"), "404 page should show a branded message").toBeVisible();
|
|
35
|
-
await (0, test_1.expect)(page.getByRole("img", { name: /manufac|logo/i }), "404 page should show the company logo").toBeVisible();
|
|
36
|
-
await (0, test_1.expect)(page.getByRole("link", { name: /home|back|return/i }), "404 page should have a link back to the home page").toBeVisible();
|
|
37
|
-
});
|
|
38
|
-
});
|
|
File without changes
|
|
File without changes
|