reveal.js
repository·master·Indexed 43 days ago
https://github.com/cpp-testing/gunitAn HTML presentation framework for creating slides with nested layouts, Markdown support, and PDF export. Version 3.2.0 includes a JavaScript API for programmatic control, a system for custom Sass themes, and features for speaker notes and background configurations.
What's inside reveal.js
- reveal.js is a framework for creating HTML-based presentations. It supports features such as nested slides, Markdown content, PDF export, speaker notes, and provides a comprehensive JavaScript API for programmatic control. For users who prefer a visual interface over coding, presentations can be created using the slides.com online editor.
Use GUnit.GMock to automate mock generation
masterGUnit.GMock allows you to use GoogleMock features without manually writing and maintaining mock classes. It works by wrapping an abstract interface in a
GMock<T>template.Key Features
- Automatic Mocking: No need to define
MOCK_METHODfor every interface. - Compatibility: Works alongside traditional GoogleMock mocks.
- Mock Types: Supports
NaggyGMock(default),StrictGMock, andNiceGMock. - Syntax Note: When using
EXPECT_CALLorON_CALLwith GUnit.GMock, you must wrap the function name in additional parentheses to handle the macro expansion correctly.
Supported Macros
EXPECT_CALL(mock, (function)(args))ON_CALL(mock, (function)(args))EXPECT_INVOKE(mock, function, args)(Universal syntax that works with both GoogleMock and GUnit.GMock)
// GoogleMock style EXPECT_CALL(mock, function(42)).WillOnce(Return(true)); // GUnit.GMock style (requires extra parens) EXPECT_CALL(mock, (function)(42)).WillOnce(Return(true)); // Universal GUnit.GMock style EXPECT_INVOKE(mock, function, 42); // Works for both // ON_CALL style ON_CALL(mock, (function)()).WillByDefault(Return(true));- Automatic Mocking: No need to define
Use GStep table parameters
masterWhen a Gherkin step includes a data table, you can capture it in your lambda using the
Tabletype (which is an alias fortable<unordered_map<string, convertible>>).Each value in the table is wrapped in a
convertibleobject. You can:- Use
operator T()to implicitly convert the value to a specific type. - Call
.available()to check if a field was actually set in the table.
- Use
Implement BDD scenarios with GUnit.GSteps
masterGUnit.GSteps provides support for Gherkin-style Behaviour Driven Development (BDD). You define feature files in
.featureformat and implement the steps in C++ using theGSTEPSmacro. Steps are matched using string patterns (e.g.,{n}for numbers).// Test/Features/Calc/Steps/CalcSteps.cpp #include <GUnit.h> GSTEPS("Calc*") { auto result = 0; Given("I created a calculator with value {n}") = [&](int n) { Calculator calc{n}; Given("I have entered {n} into the calculator") = [&](int n) { calc.push(n); }; When("I press add") = [&] { result = calc.add(); }; Then("The result should be {expected}") = [&](int expected) { EXPECT_EQ(expected, result); }; }; }How Multiplexing works
masterThe Multiplex plugin allows an audience to follow a master presentation in real-time on their own devices. It requires three components:
- Master presentation: The controller (usually run locally by the presenter).
- Client presentations: The followers (hosted on a public static file server).
- Socket.io server: The broadcaster that relays events from the master to the clients.
To use it, you must generate a unique
secretandidfrom your Socket.io server's token endpoint (e.g.,http://your-server/token).Use GUnit.GMake to simplify SUT and mock creation
masterGUnit.GMake is a utility designed to remove boilerplate mock declarations and decouple tests from the System Under Test (SUT) constructor. It allows you to create the SUT and its required mocks in a single call, ensuring that if the SUT's constructor changes (e.g., argument order or type), your test cases do not need to be refactored.
Key Benefits
- Automatic Mock Creation: Required mocks are instantiated automatically based on the SUT's constructor requirements.
- Constructor Resilience: Tests remain valid even if the SUT constructor is refactored (e.g., changing from
shared_ptrto raw pointers or changing argument order). - Reduced Boilerplate: Eliminates the need to manually declare and inject mocks for every test.
// Example of the core pattern auto [sut, mocks] = testing::make<example, NaggyMock>();Use Speaker Notes
masterThe speaker notes plugin allows you to present per-slide notes in a separate browser window (opened via the
»S«key).Defining Notes:
- HTML
<aside>element: Append an<aside class="notes">inside a<section>. You can use thedata-markdownattribute on theasideto write notes in Markdown. data-notesattribute: Add notes directly to the section:<section data-notes="Your notes here"></section>.- Markdown delimiter: If using the external Markdown plugin, use a special delimiter (e.g.,
Note:) defined in yourdata-separator-notesconfiguration.
Configuration & Sharing:
showNotes: Set totruein the configuration to make notes visible to everyone at the bottom of the presentation. This also includes them in PDF exports.showNotes: "separate-page": When exporting to PDF, this prints notes on a separate page following the slide instead of in a semi-transparent box on top of the slide.- Pacing Timer: To enable a pacing timer in the speaker view, configure the
defaultTimingparameter in theRevealconfiguration block (value in seconds). You can also set per-slide timing using thedata-timingattribute on a<section>.
<section> <h2>Some Slide</h2> <aside class="notes"> Oh hey, these are some notes. They'll be hidden in your presentation, but you can see them if you open the speaker notes window (hit »S« on your keyboard). </aside> </section>- HTML
How to grant test access to private class members
masterIf you need to test private or protected members of a class using GUnit, you can use the
friendkeyword to grant the test class access. There are three primary ways to achieve this:- Using the class name directly: If your test is defined as
GTEST(SomeTest), you can declare the test as a friend using the template syntaxfriend struct GTEST<SomeTest, testing::detail::string<> >;. - Using string literals (cumbersome): You can declare friendship using the string-based test name, but this requires manually expanding the string into a
testing::detail::stringtype. - Using the
FRIEND_GTESTmacro: This is the recommended way to grant friendship using a string name. It uses GUnit's internal preprocessor magic to map the string name to the correctGTESTtype.
Note: Avoid the practice of using
#define private publicbefore including production headers, as it is considered bad practice.#include <GUnit/Detail/Preprocessor.h> #include <GUnit/Detail/StringUtils.h> #define FRIEND_GTEST(name) \ struct __GUNIT_CAT(GTEST_STRING_, __LINE__) { static constexpr const char* chrs = #name; }; \ friend struct GTEST<decltype(::make_string<__GUNIT_CAT(GTEST_STRING_, __LINE__), sizeof(#name)>::type()), ::string<>>; class SomeClass { FRIEND_GTEST("SomeTest") }; GTEST("SomeTest") { ... }- Using the class name directly: If your test is defined as
Create multiple sub-tests within a single GTEST block using SHOULD
masterInstead of defining multiple
TEST_Fmacros, you can use a singleGTESTblock with a fixture and define multiple sub-tests using theSHOULDmacro. This is particularly useful when testing multiple scenarios for the same System Under Test (SUT) and Mocks.Note: When using
SHOULD, the fixture'sSetUp()andTearDown()methods are called separately for eachSHOULDblock.Filtering sub-tests: To run a specific
SHOULDtest case via the command line, use a colon (:) in the--gtest_filterflag.FooTest*:Do A: RunsFooTestwhere theSHOULDclause matches "Do A".FooTest*:Do*: Runs allSHOULDclauses inFooTeststarting with "Do".FooTest.:Do*: Alternative syntax for matchingSHOULDclauses.
struct FooTest : testing::Test { void SetUp() override { /* setup logic */ } void TearDown() override { /* teardown logic */ } }; GTEST(FooTest) { // This is sub-test 1 SHOULD("call foo") { // ... } // This is sub-test 2 SHOULD("call foo and return 0") { // ... } }Understand the reveal.js folder structure
masterThe project follows this directory structure:
css/: Core styles required for the project to function.js/: Core JavaScript files required for the project to function.plugin/: Extensions and components developed for reveal.js.lib/: Third-party assets including JavaScript, CSS, and fonts.
How Multiplexing works in reveal.js
masterThe Multiplex plugin allows an audience to view slides on their own devices in real time as the presenter navigates. It requires three components:
- Master presentation: The presenter's controlled view.
- Client presentations: The audience's view that follows the master.
- Socket.io server: A central server that broadcasts
slideChangedevents from the master to all clients.
To use a hosted Socket.io server, you must generate a unique
secretandidby visiting[YOUR_SOCKET_IO_SERVER_URL]/token.// Concept: Master controls, Clients follow // Master needs: secret, id, url // Client needs: id, url (secret is null)Build libgherkin-cpp
masterBefore using GUnit.GSteps, you must build the underlying Gherkin library. Navigate to the library directory and run
make libto generate the static (.a) and shared (.so) libraries.$cd libs/gherkin-cpp && make lib $ls libs/gherkin-cpp libgherkin-cpp.a libgherkin-cpp.so