morph 0.1.0
Asynchronous bridge between GUI thread and business models
Loading...
Searching...
No Matches
memory_history.hpp
Go to the documentation of this file.
1// SPDX-License-Identifier: Apache-2.0
2#pragma once
3
4#include <cstddef>
5#include <functional>
6#include <string>
7#include <utility>
8#include <vector>
9
10#include "../route_history.hpp"
11
12/// @file
13/// @brief `MemoryHistory`: an `IHistory` held in memory, which a test moves through as a user moves through a
14/// browser's history.
15
16namespace morph::ui::testing {
17
18/// @brief A history of routes in memory: the entries, the current one, and back, forward and an edited address.
19class MemoryHistory final : public IHistory {
20public:
21 /// @brief A history of one entry.
22 /// @param initial The route the first entry holds, as a reloaded page or a shared link has it; empty for none.
23 explicit MemoryHistory(std::string initial = {}) { _entries.push_back(std::move(initial)); }
24
25 [[nodiscard]] std::string current() const override { return _entries.at(_index); }
26
27 void push(std::string const& route) override {
28 _entries.resize(_index + 1);
29 _entries.push_back(route);
30 ++_index;
31 }
32
33 void replace(std::string const& route) override { _entries.at(_index) = route; }
34
35 void onPop(std::function<void(std::string const& route)> popped) override { _popped = std::move(popped); }
36
37 /// @brief Moves to the previous entry, as the browser's back does.
38 /// @return Whether there was one.
39 bool back() {
40 if (_index == 0) {
41 return false;
42 }
43 --_index;
44 pop();
45 return true;
46 }
47
48 /// @brief Moves to the next entry, as the browser's forward does.
49 /// @return Whether there was one.
50 bool forward() {
51 if (_index + 1 >= _entries.size()) {
52 return false;
53 }
54 ++_index;
55 pop();
56 return true;
57 }
58
59 /// @brief Follows an address the user typed: adds an entry for @p route and reports the change, unless it is the
60 /// current entry's.
61 /// @param route The route.
62 void follow(std::string const& route) {
63 if (route == current()) {
64 return; // a browser reports no change for the address it is already at
65 }
66 push(route);
67 pop();
68 }
69
70 /// @brief Every entry, oldest first.
71 /// @return They.
72 [[nodiscard]] std::vector<std::string> const& entries() const noexcept { return _entries; }
73
74 /// @brief The current entry's index.
75 /// @return It.
76 [[nodiscard]] std::size_t index() const noexcept { return _index; }
77
78private:
79 // A copy of the callback and of the route: the callback may replace either while it runs.
80 void pop() const {
81 if (auto const popped = _popped) {
82 popped(std::string{_entries.at(_index)});
83 }
84 }
85
86 std::vector<std::string> _entries;
87 std::size_t _index = 0;
88 std::function<void(std::string const&)> _popped;
89};
90
91} // namespace morph::ui::testing
void replace(std::string const &route) override
Replaces the route the current entry holds.
std::size_t index() const noexcept
The current entry's index.
bool back()
Moves to the previous entry, as the browser's back does.
void onPop(std::function< void(std::string const &route)> popped) override
Sets what is called when the current entry changes from outside: back, forward, or an address the use...
std::string current() const override
The route the current entry holds.
void follow(std::string const &route)
Follows an address the user typed: adds an entry for route and reports the change,...
MemoryHistory(std::string initial={})
A history of one entry.
std::vector< std::string > const & entries() const noexcept
Every entry, oldest first.
void push(std::string const &route) override
Adds an entry after the current one, dropping any entries forward of it, and makes it current.
bool forward()
Moves to the next entry, as the browser's forward does.
Route history (spec 3 §10, spec 6 §20): the route of the screen a shell shows, kept in a history the ...