podojo-cli 0.4.2__tar.gz → 0.4.4__tar.gz
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.
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/.github/workflows/publish.yml +4 -2
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/CHANGELOG.md +11 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/CLAUDE.md +1 -1
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/PKG-INFO +1 -1
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/pyproject.toml +1 -1
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/commands/usertests.py +38 -3
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/tests/test_usertests.py +9 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/uv.lock +1 -1
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/.gitignore +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/README.md +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/__init__.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/client.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/commands/__init__.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/commands/auth.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/commands/gdrive.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/commands/projects.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/commands/showreel.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/commands/transcripts.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/commands/videos.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/config.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/gdrive/__init__.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/gdrive/list.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/gdrive/upload.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/main.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/video/__init__.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/src/podojo_cli/video/showreel.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/tests/conftest.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/tests/test_auth.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/tests/test_gdrive.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/tests/test_projects.py +0 -0
- {podojo_cli-0.4.2 → podojo_cli-0.4.4}/tests/test_showreel.py +0 -0
|
@@ -14,10 +14,12 @@ jobs:
|
|
|
14
14
|
id-token: write
|
|
15
15
|
attestations: write
|
|
16
16
|
steps:
|
|
17
|
-
- uses: actions/checkout@
|
|
17
|
+
- uses: actions/checkout@v6
|
|
18
18
|
|
|
19
|
-
- uses: astral-sh/setup-uv@
|
|
19
|
+
- uses: astral-sh/setup-uv@v8.0.0
|
|
20
20
|
|
|
21
21
|
- run: uv build
|
|
22
22
|
|
|
23
23
|
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
24
|
+
with:
|
|
25
|
+
skip-existing: true
|
|
@@ -5,6 +5,17 @@ All notable changes to the Podojo CLI will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org).
|
|
7
7
|
|
|
8
|
+
## [0.4.4] - 2026-04-19
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `usertests snippet` command prints the recorder script to embed in self-hosted prototypes
|
|
12
|
+
- `usertests create` now hints at the snippet command so users know how to enable screen recording
|
|
13
|
+
|
|
14
|
+
## [0.4.3] - 2026-04-14
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- Support `instruction` step variant for usertests (briefing screen with a "Continue" button, useful before prototype steps)
|
|
18
|
+
|
|
8
19
|
## [0.4.2] - 2026-04-05
|
|
9
20
|
|
|
10
21
|
### Changed
|
|
@@ -39,7 +39,7 @@ podojo usertests validate usertest.yaml # validate without creating
|
|
|
39
39
|
|
|
40
40
|
User test configs are YAML files. Run `podojo usertests example` for the full template.
|
|
41
41
|
Required fields: `usertest_id`, `client`, `title`, `logo`, `prototype_url`, `steps`.
|
|
42
|
-
Each step needs `type` ("screen" or "prototype") and `title`. Screen steps should have `variant` ("question" or "
|
|
42
|
+
Each step needs `type` ("screen" or "prototype") and `title`. Screen steps should have `variant` ("question", "task", or "instruction" — instruction screens render a "Continue" button instead of "Done with Step", useful as a briefing before a prototype step).
|
|
43
43
|
|
|
44
44
|
## Configuration
|
|
45
45
|
|
|
@@ -13,9 +13,25 @@ console = Console()
|
|
|
13
13
|
|
|
14
14
|
REQUIRED_FIELDS = ["usertest_id", "title", "logo", "prototype_url", "steps"]
|
|
15
15
|
VALID_STEP_TYPES = {"screen", "prototype"}
|
|
16
|
-
VALID_STEP_VARIANTS = {"question", "task", "intro", "feedback"}
|
|
16
|
+
VALID_STEP_VARIANTS = {"question", "task", "intro", "feedback", "instruction"}
|
|
17
17
|
REQUIRED_STEP_FIELDS = ["type", "title"]
|
|
18
18
|
|
|
19
|
+
RECORDER_SNIPPET = """\
|
|
20
|
+
<script src="https://usertests.podojo.com/player.js"></script>
|
|
21
|
+
<script>
|
|
22
|
+
if (typeof rrweb === "undefined") {
|
|
23
|
+
console.error("[rrweb] failed to load — screen recording disabled");
|
|
24
|
+
} else {
|
|
25
|
+
rrweb.record({
|
|
26
|
+
emit(event) {
|
|
27
|
+
window.parent.postMessage({ type: "rrweb-event", event: event }, "*");
|
|
28
|
+
},
|
|
29
|
+
checkoutEveryNms: 30000,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
</script>
|
|
33
|
+
"""
|
|
34
|
+
|
|
19
35
|
EXAMPLE_YAML = """\
|
|
20
36
|
# Podojo Unmoderated User Test Configuration
|
|
21
37
|
#
|
|
@@ -53,7 +69,8 @@ project_name: checkout-redesign-q1
|
|
|
53
69
|
|
|
54
70
|
# Steps define what participants see and do
|
|
55
71
|
# Each step requires: type ("screen" or "prototype") and title
|
|
56
|
-
# Screen steps should have a variant: "question" (open-ended)
|
|
72
|
+
# Screen steps should have a variant: "question" (open-ended), "task" (action-based),
|
|
73
|
+
# or "instruction" (briefing screen shown before a prototype step — uses a "Continue" button)
|
|
57
74
|
# Optional per step: text (markdown), image (URL)
|
|
58
75
|
steps:
|
|
59
76
|
- type: screen
|
|
@@ -64,6 +81,13 @@ steps:
|
|
|
64
81
|
What stands out to you first?
|
|
65
82
|
image: https://example.com/screenshots/homepage.png
|
|
66
83
|
|
|
84
|
+
- type: screen
|
|
85
|
+
variant: instruction
|
|
86
|
+
title: Next, you'll try the prototype
|
|
87
|
+
text: |
|
|
88
|
+
On the next screen you'll see a working prototype.
|
|
89
|
+
Try to buy a pair of running shoes, and think aloud as you go.
|
|
90
|
+
|
|
67
91
|
- type: prototype
|
|
68
92
|
title: Complete a Purchase
|
|
69
93
|
text: |
|
|
@@ -115,7 +139,7 @@ def validate_usertest_data(data: dict) -> list[str]:
|
|
|
115
139
|
variant = step.get("variant")
|
|
116
140
|
if step_type == "screen" and variant is not None and variant not in VALID_STEP_VARIANTS:
|
|
117
141
|
errors.append(
|
|
118
|
-
f"Step {i}: 'variant' must be
|
|
142
|
+
f"Step {i}: 'variant' must be one of {sorted(VALID_STEP_VARIANTS)}, got '{variant}'"
|
|
119
143
|
)
|
|
120
144
|
return errors
|
|
121
145
|
|
|
@@ -249,6 +273,11 @@ def create_usertest(
|
|
|
249
273
|
if group:
|
|
250
274
|
console.print(f" Preview: https://usertests.podojo.com/preview/{group}/{usertest_id}")
|
|
251
275
|
console.print(f" Live: https://usertests.podojo.com/{group}?test={usertest_id}")
|
|
276
|
+
console.print(
|
|
277
|
+
"\n[dim]If your prototype is self-hosted, add the recorder script to its "
|
|
278
|
+
"[bold]<head>[/bold] to enable screen recording.\n"
|
|
279
|
+
"Run [bold]podojo usertests snippet[/bold] to print it.[/dim]"
|
|
280
|
+
)
|
|
252
281
|
|
|
253
282
|
|
|
254
283
|
@app.command("update")
|
|
@@ -315,3 +344,9 @@ def validate(
|
|
|
315
344
|
def example():
|
|
316
345
|
"""Print an example user test YAML template."""
|
|
317
346
|
print(EXAMPLE_YAML)
|
|
347
|
+
|
|
348
|
+
|
|
349
|
+
@app.command("snippet")
|
|
350
|
+
def snippet():
|
|
351
|
+
"""Print the recorder script to embed in self-hosted prototypes."""
|
|
352
|
+
print(RECORDER_SNIPPET)
|
|
@@ -126,6 +126,7 @@ def test_create_usertest(runner, httpx_mock, tmp_path):
|
|
|
126
126
|
assert "test-usertest-1" in result.output
|
|
127
127
|
assert "https://usertests.podojo.com/preview/test-group/test-usertest-1" in result.output
|
|
128
128
|
assert "https://usertests.podojo.com/test-group?test=test-usertest-1" in result.output
|
|
129
|
+
assert "podojo usertests snippet" in result.output
|
|
129
130
|
|
|
130
131
|
|
|
131
132
|
def test_create_usertest_file_not_found(runner):
|
|
@@ -280,3 +281,11 @@ def test_example(runner):
|
|
|
280
281
|
assert "steps:" in result.output
|
|
281
282
|
assert "prototype" in result.output
|
|
282
283
|
assert "screen" in result.output
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def test_snippet(runner):
|
|
287
|
+
result = runner.invoke(app, ["usertests", "snippet"])
|
|
288
|
+
|
|
289
|
+
assert result.exit_code == 0
|
|
290
|
+
assert "player.js" in result.output
|
|
291
|
+
assert "rrweb.record" in result.output
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|