The proper fix was to apply what has been reverted in
7558e2c7cd
but we would have to break the API to apply this fix so I will just skip
these specs for now.
I suspect the within is doing a memoization of the preview at a moment
where the emoji has not been rendered yet, when we render the emoji we
might have a different instance of the preview in the within which
doesn't have the emoji.
Im not super confident about this theory, but the within is useless here
so it seems like a good thing to try first.
The error we have is:
```
Failure/Error: super
Playwright::Error:
TypeError: Cannot read properties of null (reading 'namespaceURI')
at eval (eval at evaluate (:313:29), <anonymous>:17:12)
at UtilityScript.evaluate (<anonymous>:320:18)
at UtilityScript.<anonymous> (<anonymous>:1:44)
Call log:
[Screenshot Image]: /__w/discourse/discourse/tmp/capybara/failures_r_spec_example_groups_composer_using_review_media_does_not_flag_a_post_with_an_emoji_250.png
~~~~~~~ JS LOGS ~~~~~~~
ℹ️ Discourse v3.5.0.beta5-dev — https://github.com/discourse/discourse/commits/94932de163 — Ember v5.12.0
DEBUG: For more advanced debugging, install the Ember Inspector from https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi
Failed to load resource: net::ERR_CONNECTION_REFUSED
~~~~~ END JS LOGS ~~~~~
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/promises.rb:1268:in `raise'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/promises.rb:1268:in `wait_until_resolved!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/concurrent-ruby-1.3.5/lib/concurrent-ruby/concurrent/promises.rb:1482:in `value!'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/playwright-ruby-client-1.52.0/lib/playwright/connection.rb:121:in `send_message_to_server'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/playwright-ruby-client-1.52.0/lib/playwright/channel.rb:35:in `block in send_message_to_server_result'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/playwright-ruby-client-1.52.0/lib/playwright/channel.rb:67:in `with_logging'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/playwright-ruby-client-1.52.0/lib/playwright/channel.rb:34:in `send_message_to_server_result'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/playwright-ruby-client-1.52.0/lib/playwright/channel.rb:20:in `send_message_to_server'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/playwright-ruby-client-1.52.0/lib/playwright/javascript/expression.rb:10:in `evaluate'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/playwright-ruby-client-1.52.0/lib/playwright/channel_owners/js_handle.rb:19:in `evaluate'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/playwright-ruby-client-1.52.0/lib/playwright_api/js_handle.rb:46:in `evaluate'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-playwright-driver-0.5.6/lib/capybara/playwright/node.rb:885:in `block in path'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-playwright-driver-0.5.6/lib/capybara/playwright/node.rb:87:in `assert_element_not_stale'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-playwright-driver-0.5.6/lib/capybara/playwright/node.rb:884:in `path'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/node/element.rb:578:in `inspect'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/queries/selector_query.rb:106:in `description'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/queries/selector_query.rb:115:in `applied_description'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/queries/selector_query.rb:180:in `failure_message'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/result.rb:114:in `failure_message'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/node/matchers.rb:112:in `block in assert_selector'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/node/matchers.rb:869:in `block in _verify_selector_result'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/node/base.rb:84:in `synchronize'
./spec/rails_helper.rb:421:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/node/matchers.rb:868:in `_verify_selector_result'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/node/matchers.rb:110:in `assert_selector'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/session.rb:774:in `assert_selector'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/rspec/matchers/have_selector.rb:18:in `element_matches?'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/rspec/matchers/base.rb:52:in `matches?'
./spec/system/composer/review_media_unless_trust_level_spec.rb:20:in `block (3 levels) in <main>'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/session.rb:366:in `within'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/dsl.rb:52:in `call'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/dsl.rb:52:in `within_element'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/rspec/matcher_proxies.rb:15:in `within'
./spec/system/composer/review_media_unless_trust_level_spec.rb:20:in `block (2 levels) in <main>'
```
A spec could potentially go so fast that it would attempt to fill in the
input before we have gone through the various redirects resulting in an
error.
```
Failure/Error: super
Playwright::Error:
TypeError: Cannot read properties of null (reading 'namespaceURI')
at eval (eval at evaluate (:313:29), <anonymous>:17:12)
at UtilityScript.evaluate (<anonymous>:320:18)
at UtilityScript.<anonymous> (<anonymous>:1:44)
Call log:
```
Now that we ensure that we have the current final state path we should
avoid this error.
Detects the `redirect` queryParam on the /login route. If the user is
already logged in, navigates to that page. Otherwise, sets the
"destination_url" cookie so that the user will be redirected after
logging in.
If the param doesn't start with a single slash, ignore it and follow
previous behavior (navigate to "/" or log in then navigate there)
Respects subfolder configs.
This simplifies the admin search and adds some basic accessibility
Simplification:
* Removes the filters for now, both in the modal and full-screen
* Removes the link to full-screen from the modal
* Simpler input placeholder text
* Positioned to sit higher on the page, similar to a command palette
Accessibility:
* Results (or lack of) announced for screenreaders after query
Bonus:
* Makes the modal input sticky on scroll
* Combined some styles shared between this and the chat menu (modifier +
k) under a `--quick-palette` class
Before:

After:

---------
Co-authored-by: Krzysztof Kotlarek <kotlarek.krzysztof@gmail.com>
If user returns to the signup form with data from their social login,
then we shouldn't show the right side column, because it is confusing to
have buttons there that restart the social login flow. This PR makes it
so we only show the signup form.
Internal ticket: /t/154184
---------
Co-authored-by: Régis Hanol <regis@hanol.fr>
We want to merge the theme component that allows admins to display extra groups on the about page. The settings for this are now under About your site.
All the code is lift-and-shift, with some minor adjustments, e.g. theme components can't use the group_list setting type, but it has been converted to that here.
Also the system tests for the admin controls are new.
This whole thing is gated behind a hidden site setting to avoid double rendering while we deprecate the theme component.
We were not correctly relying on capybara matchers leading to test
flakiness
```
ailure/Error: super
Capybara::Playwright::Node::StaleReferenceError:
Element is not attached to the DOM
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-playwright-driver-0.5.6/lib/capybara/playwright/node.rb:91:in `rescue in assert_element_not_stale'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-playwright-driver-0.5.6/lib/capybara/playwright/node.rb:81:in `assert_element_not_stale'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-playwright-driver-0.5.6/lib/capybara/playwright/node.rb:124:in `visible_text'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/node/element.rb:60:in `block in text'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/node/base.rb:84:in `synchronize'
./spec/rails_helper.rb:421:in `synchronize'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/node/element.rb:60:in `text'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/result.rb:44:in `each'
/var/www/discourse/vendor/bundle/ruby/3.3.0/gems/capybara-3.40.0/lib/capybara/result.rb:44:in `each'
./spec/system/page_objects/modals/sidebar_edit_categories.rb:45:in `map'
./spec/system/page_objects/modals/sidebar_edit_categories.rb:45:in `has_categories?'
./spec/system/editing_sidebar_categories_navigation_spec.rb:161:in `block (2 levels) in <main>'
```
These reject/approve buttons were getting `btn-default` classes rather
than `btn-danger` or `btn-success`, which meant the styles for the
colors had to be applied separately to `.approve-post` and
`.reject-post`. This also meant the styles needed an additional override
in themes.
Moving to our common button classes helps centralize the styles and
avoids a manual override being needed in themes.
Button appearance is the same before/after

Doing a full page load in system test is expensive and takes about 1
second on average. Since this shared example is being run across 70
official
plugins, the additional time to execute these full page loads adds up.
Therefore, we are trading off some readability here for CI runtime.
Before:
```
Randomized with seed 7202
..................
Finished in 21.26 seconds (files took 1.72 seconds to load)
18 examples, 0 failures
```
After:
```
Randomized with seed 7202
........
Finished in 14.28 seconds (files took 1.74 seconds to load)
8 examples, 0 failures
```
## 🔍 Overview
This update adds the ability for users to manually add translations to
specific posts. It adds a 🌐 icon on the post menu where you can click to
add translations for posts.
It also introduces a new site setting:
`content_localization_debug_allowed_groups` which is convenient when
debugging localized posts. It adds a globe icon in the post meta data
area along with a number of how many languages the post is translated
in. Hovering over the icon will show a tooltip with access to editing
and deleting the translated posts.
## 📸 Screenshots
<img width="1234" alt="Screenshot 2025-05-07 at 13 26 09"
src="https://github.com/user-attachments/assets/9d65374d-ee3e-4e8b-b171-b98db6f90f23"
/>
<img width="300" alt="Screenshot 2025-05-07 at 13 26 41"
src="https://github.com/user-attachments/assets/6ee9c5e6-16ed-4dab-97ec-9401804a4ac8"
/>
This commit makes various changes and improvements to the new color palettes
page that was introduced in
https://github.com/discourse/discourse/pull/32379. Specifically, it:
* Removes the ‘Logos and fonts’ banner
* Removes the icon from the palette names in the list
* Moves the ‘new’ button to the top of the palette list
* Excludes theme-owned color palettes from the color palettes page since
these will be editable directly from the theme page
* Makes the name the primary text if a color has no description
* Adds a button next to the name field to save just the name
* Adds a ‘Delete’ button alongside the existing ‘Duplicate’ button
* Adds a ‘Revert’ button to change a modified color back to its default
value (based on the base palette of the palette)
We have had multiple issues while using the chrome channel:
- super slow start of the spec, I can confirm I don't have it on
chromium
- more risk of different failures between local dev machines and CI
There was a test not working on chromium, as it doesn't have mp4 codecs
out of the box. I changed the spec to use webm instead and it's now
working correctly.
This commit also fixes a bug with the video/trace paths which were
incorrect, and also makes another test less flakey with uploads event
though Im not very clear on what is going on here, we need to dig this.
We now need to figure out a way to have this on the test image, but this
is for now a better solution.
This commit is replacing the system specs driver (selenium) by
Playwright: https://playwright.dev/
We are still using Capybara to write the specs but they will now be run
by Playwright. To achieve this we are using the non official ruby
driver: https://github.com/YusukeIwaki/capybara-playwright-driver
### Notable changes
- `CHROME_DEV_TOOLS` has been removed, it's not working well with
playwright use `pause_test` and inspect browser for now.
- `fill_in` is not generating key events in playwright, use `send_keys`
if you need this.
### New spec options
#### trace
Allows to capture a trace in a zip file which you can load at
https://trace.playwright.dev or locally through `npx playwright
show-trace /path/to/trace.zip`
_Example usage:_
```ruby
it "shows bar", trace: true do
visit("/")
find(".foo").click
expect(page).to have_css(".bar")
end
```
#### video
Allows to capture a video of your spec.
_Example usage:_
```ruby
it "shows bar", video: true do
visit("/")
find(".foo").click
expect(page).to have_css(".bar")
end
```
### New env variable
#### PLAYWRIGHT_SLOW_MO_MS
Allow to force playwright to wait DURATION (in ms) at each action.
_Example usage:_
```
PLAYWRIGHT_SLOW_MO_MS=1000 rspec foo_spec.rb
```
#### PLAYWRIGHT_HEADLESS
Allow to be in headless mode or not. Default will be headless.
_Example usage:_
```
PLAYWRIGHT_HEADLESS=0 rspec foo_spec.rb # will show the browser
```
### New helpers
#### with_logs
Allows to access the browser logs and check if something specific has
been logged.
_Example usage:_
```ruby
with_logs do |logger|
# do something
expect(logger.logs.map { |log| log[:message] }).to include("foo")
end
```
#### add_cookie
Allows to add a cookie on the browser session.
_Example usage:_
```ruby
add_cookie(name: "destination_url", value: "/new")
```
#### get_style
Get the property style value of an element.
_Example usage:_
```ruby
expect(get_style(find(".foo"), "height")).to eq("200px")
```
#### get_rgb_color
Get the rgb color of an element.
_Example usage:_
```ruby
expect(get_rgb_color(find("html"), "backgroundColor")).to eq("rgb(170, 51, 159)")
```
Follow-up to https://github.com/discourse/discourse/pull/31742
This commit adds a color palettes list to the new color palette edit page
that was introduced in the linked PR to allow navigating between color
palettes. It reuses the same UI that we already have in the legacy color
palette UI (`/admin/customize/colors`), but we may redesign the page in
the future.
There are instances of posts being deleted by system_user where the context is left blank in the staff action logs, leading to confusion about why exactly they have been deleted.
This change deprecates using the PostDestroyer as system_user without providing a context, and adds a context to all call sites currently missing it in core. Plugins to be done after this is merged.
In this PR we hide search input.
https://github.com/discourse/discourse/pull/32485
However, search input is much more intuitive. Therefore, input was
brought back and opens modal on click. In addition, search link was
removed.
Usage:
```js
@service capabilities;
...
this.capabilities.viewport.sm; // True when viewport is sm or larger
this.capabilities.viewport.md; // True when viewport is md or larger
// etc.
```
These booleans will update live when the browser is resized. Therefore,
they should only be used in an autotracking context, so that Ember will
re-render things appropriately when they change.
We are making this the only option for our login/signup
pages on April 29th, 2025, per
https://meta.discourse.org/t/introducing-our-new-fullscreen-signup-and-login-pages/340401.
This commit removes the `full_page_login` setting and any logic
around it, as well as deleting the old login and signup modals,
and removing leftover problem checks and settings from the database.
This PR makes the following key changes to the load-more component:
* Updating to a Glimmer component
* Changing from an eyeline/scrolling-based mechanism to an
IntersectionObserver to determine when to load
* Keeping track of a single invisible sentinel element to help trigger
the loadMore action instead of having to find and track the last item of
the collection upon every load
* The component can now be used without wrapping around some content to
be yielded - the intent is to use this for cases like
[DiscoveryTopicsList](f0057c7353/app/assets/javascripts/discourse/app/components/discovery/topics.gjs (L222))
where we might want more precise placement of the sentinel element.
* Added utility toggle functions to control observer behaviour in this
class for testing
We will replace the load-more mixin in DiscoveryTopicsList in another
PR.
https://github.com/user-attachments/assets/50d9763f-b5f8-40f6-8630-41bdf107baf7
### Technical Considerations
1. Keeping track of a single sentinel element simplifies the logic
greatly and is also more robust to changes in the collection that's
being loaded. (ref: a [previous
commit](2279519081)
that was following the previous approach of tracking specifically the
last item of the loaded collection); this also sidesteps odd edge cases
like if the tracked element is larger than the entire viewport.
2. Using
[isIntersecting](https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserverEntry/isIntersecting)
instead of calculating manually whether the element is in the viewport
is also less flaky - I ran into issues with the boundingClientRect
inconsistently being calculated as outside the viewport on different
sized screens.
3. We need to properly bind `loadMore` functions with the action
decorator, otherwise the way we pass the loadMore callbacks through to
the observe-intersection modifier results in attempting to call it on
the loadMore component context instead. I've done this for all such
functions except for the one in
[`category-list`](0ed4b09527/app/assets/javascripts/discourse/app/models/category-list.js (L117))
which uses `@bind` that should be equivalent in terms of binding to the
correct `this`.
Instead of having each test go incur the overhead of having to go
through the actual user flow to register a security key, we can generate
the WebAuthn credentials on the server side and adds it to the virtual
authenticator.
This commit applies a similar optimisation as
d0d755ad8c478db45e3298df9de1cdabe59d9592.
Basically, the `full_page_login` site setting is going to be dropped
this week and these extra system tests we are running due to this site
setting is accounting for a significant percentage of the overall
runtime for core system tests.
### Reviewer notes
The PR to remove the `full_page_login` site setting is at
https://github.com/discourse/discourse/pull/32189 and scheduled to be
merged by us on 29th April.