Skip to content

[ENHANCEMENT] [MER-5670] Playwright test for Adaptive Lesson: BB Unit 7: Our Blue Planet - #6762

Merged
simonchoxx merged 6 commits into
masterfrom
MER-5670/automation-tests/our-blue-planet
Aug 18, 2026
Merged

[ENHANCEMENT] [MER-5670] Playwright test for Adaptive Lesson: BB Unit 7: Our Blue Planet#6762
simonchoxx merged 6 commits into
masterfrom
MER-5670/automation-tests/our-blue-planet

Conversation

@manelli

@manelli manelli commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds Playwright coverage for the BioBeyond Unit 7: Blue Planet → Our Blue Planet adaptive lesson.

The test imports the full course, navigates to the correct lesson, and completes all lesson screens twice:

  1. The first page attempt intentionally submits configured incorrect answers before correcting them, verifying attempt-based scoring reduces the score.
  2. The second page attempt answers everything correctly on the first try and verifies the score resets and reaches 100.

A lesson-specific driver handles the lesson’s navigation and evaluation behavior without modifying the shared AdaptiveDeckPO or AdaptiveHappyPathTask helpers. It also waits for fill-in-the-blank values to persist before submission and prevents actions from leaking into the following screen.

Assets

The following assets must exist in the Playwright asset bucket:

bio_beyond-our_blue_planet/course.zip
bio_beyond-our_blue_planet/answers.json

How to run locally

Start Torus locally, then run the following from assets/automation:

export PLAYWRIGHT_BASE_URL=http://127.0.0.1
export PLAYWRIGHT_SCENARIO_TOKEN=my-token
export PLAYWRIGHT_AUTOMATION_API_KEY='<your-api-key>'

npx playwright test our-blue-planet-adaptive.spec.ts

The automation API key must be a valid locally generated key. Without it, Playwright will report the test as skipped.


video.webm

See: https://eliterate.atlassian.net/browse/MER-5670

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor
Warnings
⚠️ PR is large (982 LOC changed). Consider splitting.

Risk score: 3 → risk/low

Generated by 🚫 dangerJS against e41648a

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

AI Review —

No issues found

- OurBluePlanetTask.ts: Made lesson interactions more reliable by handling screens without feedback, waiting for stable inputs, and avoiding intentional wrong answers on completion-scored screens.
- our-blue-planet-adaptive.spec.ts: Increased teardown timeouts and removed the previous 15-second timeout cap.
- automation_setup.ex: Deletes every section belonging to the disposable project before deleting its resources, preventing foreign-key failures from sections included in the imported archive.
- sections.ex: Clears a section’s root-resource reference before deleting the section, all within one transaction.
- automation_setup_controller.ex: Extends Cowboy’s idle timeout specifically for teardown requests so large-course cleanup can finish.
- sections_test.exs: Verifies deleting a section also removes its section resources.
- automation_setup_controller_test.exs: Verifies project teardown also removes sections imported with the course archive.
@github-actions

Copy link
Copy Markdown
Contributor

AI Review — performance

No issues found

@github-actions

Copy link
Copy Markdown
Contributor

AI Review — security

No issues found

@github-actions

Copy link
Copy Markdown
Contributor

AI Review — elixir

No issues found

@simonchoxx simonchoxx left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was able to run the spec and it passed for me, and teardown seems to be working fine — I checked the DB afterwards and it came out clean.

One thing I noticed: if the server has been running for a while, the test starts failing, and not always in the same place. If I restart Phoenix right before, it passes. My guess is that when the server responds slower, the test retries clicks that had actually gone through and ends up submitting twice — sometimes it skips a screen, sometimes it re-submits the same one, and the score ends up below 100 without anything being raised.

Leaving it here mainly so it's on your radar.

Comment thread assets/automation/.gitignore Outdated
# resources
tests/resources/login.env No newline at end of file
tests/resources/login.env
local-assets/

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think local-assets/ isn't referenced anywhere in the repo. Should we drop it, or is it a local workflow worth documenting?

Comment thread lib/oli/delivery/sections.ex Outdated
Comment on lines +1673 to +1688
Multi.new()
# A section owns its section resources, but also points back to the root
# section resource. Clear that circular reference before deleting the
# section so the section_resources ON DELETE CASCADE can run safely.
|> Multi.update_all(
:clear_root_section_resource,
from(s in Section, where: s.id == ^section.id),
set: [root_section_resource_id: nil]
)
|> Multi.delete(:section, section)
|> Repo.transaction()
|> case do
{:ok, %{section: deleted_section}} -> {:ok, deleted_section}
{:error, :section, changeset, _changes} -> {:error, changeset}
{:error, _operation, reason, _changes} -> {:error, reason}
end

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried it: with just Repo.delete(section) the spec goes green, the DB comes out clean, and the new test passes the same. Do you think it makes sense to keep the change, or should we revert it?

Comment thread test/oli/sections_test.exs Outdated
Comment on lines +545 to +555
section_resource_ids =
SectionResource
|> where([sr], sr.section_id == ^section.id)
|> select([sr], sr.id)
|> Oli.Repo.all()

assert section.root_section_resource_id in section_resource_ids

assert {:ok, %Section{}} = Sections.delete_section(section)
refute Sections.get_section_by_slug(section.slug)
refute Oli.Repo.exists?(from sr in SectionResource, where: sr.id in ^section_resource_ids)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like these assertions, I'd keep them. Only thing: I ran them with and without the change and they pass the same, so for now they wouldn't quite cover the new bit.

Comment thread lib/oli/automation_setup.ex Outdated
end
rescue
e in Ecto.ConstraintError ->
e in [Ecto.ConstraintError, Postgrex.Error] ->

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you added Postgrex.Error here but teardown_section didn't get it, and that one runs first. If it failed there the request would stop and it wouldn't get to delete the project. Was that intentional?

Comment on lines +105 to +119
project_sections =
from(s in Section, where: s.base_project_id == ^project.id)

result =
Multi.new()
# Full-course archives can contain delivery sections in addition to the
# section created by automation setup. Release every section owned by
# this disposable project before revision deletion cascades into its
# section_resources.
|> Multi.update_all(
:clear_project_section_roots,
project_sections,
set: [root_section_resource_id: nil]
)
|> Multi.delete_all(:project_sections, project_sections)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked at the archive and didn't find sections inside it, so I'm not clear on when this cleanup would kick in. Could the case you hit have been a previous run leaving the section undeleted instead? If that's it the code still helps, but I'd tweak the comment.

Comment on lines +279 to +287
# Deleting a fully imported automation course can exceed Cowboy's default
# 60-second HTTP/1 idle timeout. Scope the longer timeout to this endpoint
# rather than holding every connection open longer application-wide.
defp extend_teardown_idle_timeout(
%Plug.Conn{adapter: {Plug.Cowboy.Conn, cowboy_request}} = conn
) do
:cowboy_req.cast({:set_options, %{idle_timeout: 300_000}}, cowboy_request)
conn
end

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I measured the teardown request across several runs and got around 3 seconds. The one getting close to the limit is setup, at 20–30. Had you hit a case where teardown hung? It may well have been slower before the other fixes in this PR.

Comment on lines +97 to +101
stale_automation_section =
insert(:section,
title: "Section imported with the project archive",
base_project: project
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same point I left on automation_setup.ex: the title says the section came with the archive, but I didn't find sections inside the zip. If the real case is that it was left over from a previous run, I'd put that in the title — it's what whoever lands here in a year is going to read.

@simonchoxx simonchoxx left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🚀🚀

@simonchoxx
simonchoxx merged commit f691fcb into master Aug 18, 2026
13 checks passed
@simonchoxx
simonchoxx deleted the MER-5670/automation-tests/our-blue-planet branch August 18, 2026 17:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants