From 3b6306885d222686f084a560c747a79809152324 Mon Sep 17 00:00:00 2001 From: michael-kerscher Date: Fri, 16 May 2025 10:59:47 +0200 Subject: [PATCH] tests: refactor slide style guide tests and add playground size checks (#2745) The previous slide-size.test.ts was refactored and a slide class was implemented for convenience. The test now checks the playground size (if available on that slide) by checking if scrollbars are visible. To make this test more efficient, the mocha before() hook is used to load the slide once and check with all relevant tests before loading the next slide. --- tests/src/objects/slide.ts | 52 +++++++++++++++ tests/src/slide-size.test.ts | 53 --------------- tests/src/slide-style-guide.test.ts | 80 +++++++++++++++++++++++ tests/src/slides/slide-exemptions.list.ts | 9 ++- 4 files changed, 140 insertions(+), 54 deletions(-) create mode 100644 tests/src/objects/slide.ts delete mode 100644 tests/src/slide-size.test.ts create mode 100644 tests/src/slide-style-guide.test.ts diff --git a/tests/src/objects/slide.ts b/tests/src/objects/slide.ts new file mode 100644 index 00000000..02e62749 --- /dev/null +++ b/tests/src/objects/slide.ts @@ -0,0 +1,52 @@ +import { $, browser } from "@wdio/globals"; + +export default class Slide { + /** + * convenience functions for interacting with a slide + **/ + + /** + * @returns the scrollbar of the provided type if available + */ + scrollbar_typed(scrollbar_type: string): ChainablePromiseElement { + return $("#content main div.ace_scrollbar-" + scrollbar_type); + } + + get scrollbar_v() { + return this.scrollbar_typed("v"); + } + + get scrollbar_h() { + return this.scrollbar_typed("h"); + } + + get main_content() { + return $("#content > main"); + } + + /** + * + * @param element the element to be checked + * @param height the maximum height + * @param width the maximum width + * @returns true if either height or width is higher than the provided numbers + */ + async violates_max_size( + element: ChainablePromiseElement, + height: number, + width: number, + ): Promise { + const main_element_size = await element.getSize(); + return ( + main_element_size.height >= height || main_element_size.width > width + ); + } + + async load(slide_path: string) { + // ensure this is prefixed with / + if (!slide_path.startsWith("/")) { + slide_path = "/" + slide_path; + } + return await browser.url(slide_path); + } +} diff --git a/tests/src/slide-size.test.ts b/tests/src/slide-size.test.ts deleted file mode 100644 index e5cf198e..00000000 --- a/tests/src/slide-size.test.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { describe, it } from "mocha"; -import { $, expect, browser } from "@wdio/globals"; -import { slides } from "./slides/slides.list"; -import { exemptions } from "./slides/slide-exemptions.list"; - -// these are empirically determined values in 16:9 ratio -const MAX_HEIGHT = 1333; -const MAX_WIDTH = 750; - -describe("Slide", () => { - for (const slide of slides) { - if (exemptions.includes(slide)) { - // This slide is exempted and violated rules before. - // It is expected to still do this and if not it should be removed from exemptions. - // This acts as a regression check - it( - " " + - slide + - " is on the exemption list but should be removed from slide-exemptions.list.ts", - async () => { - await browser.url("/" + slide); - const main_element = $("#content > main"); - const main_element_size = await main_element.getSize(); - console.info("slide " + slide + " is on the exemption list"); - // one of them (height, width) should fail - expect( - main_element_size.height >= MAX_HEIGHT || - main_element_size.width > MAX_WIDTH, - ).toBe(true); - }, - ); - } else { - it( - " " + - slide + - " should not be higher than " + - MAX_HEIGHT + - " pixels or wider than " + - MAX_WIDTH + - " pixels", - async () => { - await browser.url("/" + slide); - const main_element = $("#content > main"); - const main_element_size = await main_element.getSize(); - expect( - main_element_size.height < MAX_HEIGHT && - main_element_size.width <= MAX_WIDTH, - ).toBe(true); - }, - ); - } - } -}); diff --git a/tests/src/slide-style-guide.test.ts b/tests/src/slide-style-guide.test.ts new file mode 100644 index 00000000..98a6be4d --- /dev/null +++ b/tests/src/slide-style-guide.test.ts @@ -0,0 +1,80 @@ +/** + * This file contains tests that check the style of the slides. + * It checks that the slides are not too high or wide and that + * the code examples are not too wide or high based on the visibility of scrollbars. + * + * Slides that exist on the exemptions lists are tested for that violation + * and if they are not violating the style, this alerts and the author should remove + * the slide from the exemption list. This acts as a regression check. + */ +import { describe, it } from "mocha"; +import { expect } from "@wdio/globals"; +import { slides } from "./slides/slides.list.ts"; +import { + playground_size_exemptions, + size_exemptions, +} from "./slides/slide-exemptions.list.ts"; +import Slide from "./objects/slide.ts"; + +// these are empirically determined values in 16:9 ratio +const MAX_HEIGHT = 1333; +const MAX_WIDTH = 750; + +const slide = new Slide(); +slides.forEach((slide_path) => { + describe("Slide " + slide_path, () => { + before(async () => { + slide.load(slide_path); + }); + + // slide size evaluation + if (size_exemptions.includes(slide_path)) { + // This slide is exempted and violated rules before. + // It is expected to still do this and if not it should be removed from exemptions. + // This acts as a regression check + it("is on the exemption list but should be removed from size_exemptions in slide-exemptions.list.ts", async () => { + const main_element = slide.main_content; + console.info("slide " + slide_path + " is on the exemption list"); + expect( + await slide.violates_max_size(main_element, MAX_HEIGHT, MAX_WIDTH), + ).toBe(true); + }); + } else { + it( + "should not be higher than " + + MAX_HEIGHT + + " pixels or wider than " + + MAX_WIDTH + + " pixels", + async () => { + const main_element = slide.main_content; + expect( + await slide.violates_max_size(main_element, MAX_HEIGHT, MAX_WIDTH), + ).toBe(false); + }, + ); + } + + // playground code examples are not too wide + if (playground_size_exemptions.includes(slide_path)) { + it("is on the exemption list but should be removed from playground_size_exemptions in slide-exemptions.list.ts", async () => { + // This slide is exempted and violated rules before. + // It is expected to still do this and if not it should be removed from exemptions. + // This acts as a regression check + await Promise.any([ + expect(slide.scrollbar_h).toBeDisplayed(), + expect(slide.scrollbar_v).toBeDisplayed(), + ]); + }); + } else { + it("should not show a scrollbar", async () => { + if (await slide.has_code_example) { + await Promise.all([ + expect(slide.scrollbar_h).not.toBeDisplayed(), + expect(slide.scrollbar_v).not.toBeDisplayed(), + ]); + } + }); + } + }); +}); diff --git a/tests/src/slides/slide-exemptions.list.ts b/tests/src/slides/slide-exemptions.list.ts index d868ff41..42758387 100644 --- a/tests/src/slides/slide-exemptions.list.ts +++ b/tests/src/slides/slide-exemptions.list.ts @@ -1,7 +1,7 @@ // These slides are known to violate the slide style guide. // They are checked if they still violate and if not fail the test. // Please remove slides that become good so they don't regress. -export const exemptions = [ +export const size_exemptions = [ "android/interoperability/java.html", "android/testing.html", "bare-metal/aps/entry-point.html", @@ -16,3 +16,10 @@ export const exemptions = [ "concurrency/sync-exercises/solutions.html", "concurrency/sync-exercises/link-checker.html", ]; + +export const playground_size_exemptions = [ + "bare-metal/aps/better-uart/driver.html", + "bare-metal/microcontrollers/type-state.html", + "concurrency/async-pitfalls/cancellation.html", + "iterators/intoiterator.html", +];