2023-12-01 16:47:54 +01:00
import { click , currentURL , fillIn , visit } from "@ember/test-helpers" ;
import { test } from "qunit" ;
2025-06-04 21:40:29 +08:00
import Category from "discourse/models/category" ;
2024-08-28 13:51:37 +02:00
import { acceptance } from "discourse/tests/helpers/qunit-helpers" ;
2025-06-04 21:40:29 +08:00
import selectKit from "discourse/tests/helpers/select-kit-helper" ;
async function runQuery ( ) {
await click ( "form.query-run button" ) ;
}
2022-12-27 12:10:29 -06:00
acceptance ( "Data Explorer Plugin | Param Input" , function ( needs ) {
needs . user ( ) ;
needs . settings ( { data _explorer _enabled : true } ) ;
needs . pretender ( ( server , helper ) => {
server . get ( "/admin/plugins/explorer/groups.json" , ( ) => {
2025-06-04 21:40:29 +08:00
return helper . response ( [ ] ) ;
2022-12-27 12:10:29 -06:00
} ) ;
server . get ( "/admin/plugins/explorer/schema.json" , ( ) => {
2025-06-04 21:40:29 +08:00
return helper . response ( { } ) ;
2022-12-27 12:10:29 -06:00
} ) ;
server . get ( "/admin/plugins/explorer/queries" , ( ) => {
return helper . response ( {
queries : [
{
id : - 6 ,
name : "Top 100 Likers" ,
description :
"returns the top 100 likers for a given monthly period ordered by like_count. It accepts a ‘ months_ago’ parameter, defaults to 1 to give results for the last calendar month." ,
username : "system" ,
group _ids : [ ] ,
last _run _at : "2021-02-11T08:29:59.337Z" ,
user _id : - 1 ,
} ,
{
id : - 7 ,
name : "Invalid Query" ,
description : "" ,
username : "bianca" ,
group _ids : [ ] ,
last _run _at : "2022-01-14T16:47:34.244Z" ,
user _id : 1 ,
} ,
2024-08-05 15:58:51 +08:00
{
id : 3 ,
name : "Params test" ,
description : "test for params." ,
username : "system" ,
group _ids : [ 41 ] ,
last _run _at : "2021-02-11T08:29:59.337Z" ,
user _id : - 1 ,
} ,
2022-12-27 12:10:29 -06:00
] ,
} ) ;
} ) ;
2025-02-10 14:54:01 +11:00
server . get ( "/admin/plugins/explorer/queries/-6" , ( ) => {
return helper . response ( {
query : {
id : - 6 ,
sql : "-- [params]\n-- int :months_ago = 1\n\nWITH query_period AS (\n SELECT\n date_trunc('month', CURRENT_DATE) - INTERVAL ':months_ago months' as period_start,\n date_trunc('month', CURRENT_DATE) - INTERVAL ':months_ago months' + INTERVAL '1 month' - INTERVAL '1 second' as period_end\n )\n\n SELECT\n ua.user_id,\n count(1) AS like_count\n FROM user_actions ua\n INNER JOIN query_period qp\n ON ua.created_at >= qp.period_start\n AND ua.created_at <= qp.period_end\n WHERE ua.action_type = 1\n GROUP BY ua.user_id\n ORDER BY like_count DESC\n LIMIT 100\n" ,
name : "Top 100 Likers" ,
description :
"returns the top 100 likers for a given monthly period ordered by like_count. It accepts a ‘ months_ago’ parameter, defaults to 1 to give results for the last calendar month." ,
param _info : [
{
identifier : "months_ago" ,
type : "int" ,
default : "1" ,
nullable : false ,
} ,
] ,
created _at : "2021-02-02T12:21:11.449Z" ,
username : "system" ,
group _ids : [ ] ,
last _run _at : "2021-02-11T08:29:59.337Z" ,
hidden : false ,
user _id : - 1 ,
} ,
} ) ;
} ) ;
2022-12-27 12:10:29 -06:00
server . put ( "/admin/plugins/explorer/queries/-6" , ( ) => {
return helper . response ( {
success : true ,
errors : [ ] ,
duration : 27.5 ,
result _count : 2 ,
columns : [ "user_id" , "like_count" ] ,
default _limit : 1000 ,
relations : {
user : [
{
id : - 2 ,
username : "discobot" ,
name : null ,
avatar _template : "/user_avatar/localhost/discobot/{size}/2_2.png" ,
} ,
{
id : 2 ,
username : "andrey1" ,
name : null ,
avatar _template :
"/letter_avatar_proxy/v4/letter/a/c0e974/{size}.png" ,
} ,
] ,
} ,
colrender : {
0 : "user" ,
} ,
rows : [
[ - 2 , 2 ] ,
[ 2 , 2 ] ,
] ,
} ) ;
} ) ;
server . post ( "/admin/plugins/explorer/queries/-6/run" , ( ) => {
return helper . response ( {
success : true ,
errors : [ ] ,
duration : 27.5 ,
result _count : 2 ,
params : { months _ago : "1" } ,
columns : [ "user_id" , "like_count" ] ,
default _limit : 1000 ,
relations : {
user : [
{
id : - 2 ,
username : "discobot" ,
name : null ,
avatar _template : "/user_avatar/localhost/discobot/{size}/2_2.png" ,
} ,
{
id : 2 ,
username : "andrey1" ,
name : null ,
avatar _template :
"/letter_avatar_proxy/v4/letter/a/c0e974/{size}.png" ,
} ,
] ,
} ,
colrender : {
0 : "user" ,
} ,
rows : [
[ - 2 , 2 ] ,
[ 2 , 2 ] ,
] ,
} ) ;
} ) ;
2022-12-28 09:50:55 -06:00
server . get ( "/g/discourse/reports/-8" , ( ) => {
return helper . response ( {
query : {
id : - 8 ,
sql : "-- [params]\n-- int :months_ago = 1\n\nWITH query_period AS (\n SELECT\n date_trunc('month', CURRENT_DATE) - INTERVAL ':months_ago months' as period_start,\n date_trunc('month', CURRENT_DATE) - INTERVAL ':months_ago months' + INTERVAL '1 month' - INTERVAL '1 second' as period_end\n )\n\n SELECT\n ua.user_id,\n count(1) AS like_count\n FROM user_actions ua\n INNER JOIN query_period qp\n ON ua.created_at >= qp.period_start\n AND ua.created_at <= qp.period_end\n WHERE ua.action_type = 1\n GROUP BY ua.user_id\n ORDER BY like_count DESC\n LIMIT 100\n" ,
name : "Top 100 Likers Report" ,
description :
"returns the top 100 likers for a given monthly period ordered by like_count. It accepts a ‘ months_ago’ parameter, defaults to 1 to give results for the last calendar month." ,
param _info : [
{
identifier : "months_ago" ,
type : "int" ,
default : "1" ,
nullable : false ,
} ,
] ,
created _at : "2021-02-02T12:21:11.449Z" ,
username : "system" ,
group _ids : [ 41 ] ,
last _run _at : "2021-02-11T08:29:59.337Z" ,
hidden : false ,
user _id : - 1 ,
} ,
} ) ;
} ) ;
2025-02-10 14:54:01 +11:00
server . get ( "/admin/plugins/explorer/queries/-7" , ( ) => {
return helper . response ( {
query : {
id : - 7 ,
sql : "-- [params]\n-- user_id :user\n\nSELECT :user_id\n\n" ,
name : "Invalid Query" ,
description : "" ,
param _info : [
{
identifier : "user" ,
type : "user_id" ,
default : null ,
nullable : false ,
} ,
] ,
created _at : "2022-01-14T16:40:05.458Z" ,
username : "bianca" ,
group _ids : [ ] ,
last _run _at : "2022-01-14T16:47:34.244Z" ,
hidden : false ,
user _id : 1 ,
} ,
} ) ;
} ) ;
2022-12-27 12:10:29 -06:00
server . post ( "/admin/plugins/explorer/queries/-7/run" , ( ) => {
return helper . response ( {
success : true ,
errors : [ ] ,
duration : 27.5 ,
params : { user _id : "null" } ,
columns : [ "user_id" ] ,
default _limit : 1000 ,
relations : {
user : [
{
id : 2 ,
username : "andrey1" ,
name : null ,
avatar _template :
"/letter_avatar_proxy/v4/letter/a/c0e974/{size}.png" ,
} ,
] ,
} ,
colrender : {
0 : "user" ,
} ,
rows : [ ] ,
} ) ;
} ) ;
2022-12-28 09:50:55 -06:00
server . post ( "/g/discourse/reports/-8/run" , ( ) => {
return helper . response ( {
success : true ,
errors : [ ] ,
duration : 27.5 ,
result _count : 2 ,
params : { months _ago : "1" } ,
columns : [ "user_id" , "like_count" ] ,
default _limit : 1000 ,
relations : {
user : [
{
id : - 2 ,
username : "discobot" ,
name : null ,
avatar _template : "/user_avatar/localhost/discobot/{size}/2_2.png" ,
} ,
{
id : 2 ,
username : "andrey1" ,
name : null ,
avatar _template :
"/letter_avatar_proxy/v4/letter/a/c0e974/{size}.png" ,
} ,
] ,
} ,
colrender : {
0 : "user" ,
} ,
rows : [
[ - 2 , 2 ] ,
[ 2 , 2 ] ,
] ,
} ) ;
} ) ;
2024-08-05 15:58:51 +08:00
server . get ( "/admin/plugins/explorer/queries/3" , ( ) => {
return helper . response ( {
query : {
id : 3 ,
sql : "SELECT 1" ,
name : "Params test" ,
description : "test for params." ,
param _info : [ ] ,
created _at : "2021-02-02T12:21:11.449Z" ,
username : "system" ,
group _ids : [ 41 ] ,
last _run _at : "2021-02-11T08:29:59.337Z" ,
hidden : false ,
user _id : - 1 ,
} ,
} ) ;
} ) ;
2024-08-28 13:51:37 +02:00
2024-08-05 15:58:51 +08:00
server . put ( "/admin/plugins/explorer/queries/3" , ( ) => {
return helper . response ( {
query : {
id : 3 ,
sql : "-- [params]\n-- int :months_ago = 1\n\nSELECT 1" ,
name : "Params test" ,
description : "test for params." ,
param _info : [
{
identifier : "months_ago" ,
type : "int" ,
default : "1" ,
nullable : false ,
} ,
] ,
created _at : "2021-02-02T12:21:11.449Z" ,
username : "system" ,
group _ids : [ 41 ] ,
last _run _at : "2021-02-11T08:29:59.337Z" ,
hidden : false ,
user _id : - 1 ,
} ,
} ) ;
} ) ;
2025-06-04 21:40:29 +08:00
server . get ( "/admin/plugins/explorer/queries/4" , ( ) => {
return helper . response ( {
query : {
id : 4 ,
sql : "-- [params]\n-- null category_id :category\n\nSELECT 1" ,
name : "Params test - category_id chooser" ,
description : "Test for category_id param." ,
param _info : [
{
identifier : "category" ,
type : "category_id" ,
default : null ,
nullable : true ,
} ,
] ,
created _at : "2025-06-03T09:05:59.337Z" ,
username : "system" ,
group _ids : [ ] ,
last _run _at : "2025-06-03T09:05:59.337Z" ,
hidden : false ,
category _id : null ,
} ,
} ) ;
} ) ;
server . post ( "/admin/plugins/explorer/queries/4/run" , ( ) => {
return helper . response ( { } ) ;
} ) ;
2022-12-27 12:10:29 -06:00
} ) ;
2025-06-04 21:40:29 +08:00
function getSearchParam ( param ) {
const searchParams = new URLSearchParams ( currentURL ( ) . split ( "?" ) [ 1 ] ) ;
return JSON . parse ( searchParams . get ( "params" ) ) [ param ] ;
}
2024-08-28 13:51:37 +02:00
test ( "puts params for the query into the url" , async function ( assert ) {
2025-02-10 14:54:01 +11:00
await visit ( "/admin/plugins/explorer/queries/-6" ) ;
2022-12-27 12:10:29 -06:00
const monthsAgoValue = "2" ;
await fillIn ( ".query-params input" , monthsAgoValue ) ;
2025-06-04 21:40:29 +08:00
await runQuery ( ) ;
2022-12-27 12:10:29 -06:00
2025-06-04 21:40:29 +08:00
assert . strictEqual ( getSearchParam ( "months_ago" ) , monthsAgoValue ) ;
2024-07-05 17:49:18 +08:00
} ) ;
2024-08-28 13:51:37 +02:00
test ( "puts params for the query into the url for group reports" , async function ( assert ) {
2024-07-05 17:49:18 +08:00
await visit ( "/g/discourse/reports/-8" ) ;
const monthsAgoValue = "2" ;
await fillIn ( ".query-params input" , monthsAgoValue ) ;
2025-06-04 21:40:29 +08:00
await runQuery ( ) ;
2024-07-05 17:49:18 +08:00
2025-06-04 21:40:29 +08:00
assert . strictEqual ( getSearchParam ( "months_ago" ) , monthsAgoValue ) ;
2022-12-27 12:10:29 -06:00
} ) ;
2024-08-28 13:51:37 +02:00
test ( "loads the page if one of the parameter is null" , async function ( assert ) {
2025-02-10 14:54:01 +11:00
await visit ( '/admin/plugins/explorer/queries/-7?params={"user":null}' ) ;
2024-08-28 13:51:37 +02:00
assert . dom ( ".query-params .user-chooser" ) . exists ( ) ;
assert . dom ( ".query-run .btn.btn-primary" ) . exists ( ) ;
2022-12-27 12:10:29 -06:00
} ) ;
2022-12-28 09:50:55 -06:00
2024-08-28 13:51:37 +02:00
test ( "loads the page if one of the parameter is null for group reports" , async function ( assert ) {
2024-07-05 17:49:18 +08:00
await visit ( '/g/discourse/reports/-8?params={"months_ago":null}' ) ;
2024-08-28 13:51:37 +02:00
assert . dom ( ".query-params input" ) . exists ( ) ;
assert . dom ( ".query-run .btn.btn-primary" ) . exists ( ) ;
2024-07-05 17:49:18 +08:00
} ) ;
2024-08-28 13:51:37 +02:00
test ( "applies params when running a report" , async function ( assert ) {
2022-12-28 09:50:55 -06:00
await visit ( "/g/discourse/reports/-8" ) ;
const monthsAgoValue = "2" ;
await fillIn ( ".query-params input" , monthsAgoValue ) ;
2025-06-04 21:40:29 +08:00
await runQuery ( ) ;
2024-08-28 13:51:37 +02:00
assert . dom ( ".query-params input" ) . hasValue ( monthsAgoValue ) ;
2022-12-28 09:50:55 -06:00
} ) ;
2024-08-05 15:58:51 +08:00
2024-08-28 13:51:37 +02:00
test ( "creates input boxes if has parameters when save" , async function ( assert ) {
2025-02-10 14:54:01 +11:00
await visit ( "/admin/plugins/explorer/queries/3" ) ;
2024-08-28 13:51:37 +02:00
assert . dom ( ".query-params input" ) . doesNotExist ( ) ;
2024-08-05 15:58:51 +08:00
await click ( ".query-edit .btn-edit-query" ) ;
await fillIn (
".query-editor .ace_text-input" ,
"-- [params]\n-- int :months_ago = 1\n\nSELECT 1"
) ;
2025-06-04 21:40:29 +08:00
await click ( ".query-editor .ace_text-input" ) ; // enables `Save Changes` button
2024-08-05 15:58:51 +08:00
await click ( ".query-edit .btn-save-query" ) ;
2024-08-28 13:51:37 +02:00
assert . dom ( ".query-params input" ) . exists ( ) ;
2024-08-05 15:58:51 +08:00
} ) ;
2025-06-04 21:40:29 +08:00
test ( "nullable category_id param" , async function ( assert ) {
await visit ( "/admin/plugins/explorer/queries/4" ) ;
const catChooser = selectKit ( ".category-chooser" ) ;
assert . strictEqual ( catChooser . header ( ) . value ( ) , null ) ;
await runQuery ( ) ;
assert . strictEqual ( getSearchParam ( "category" ) , "" ) ;
const category = Category . findById ( 6 ) ;
await catChooser . expand ( ) ;
await catChooser . selectRowByValue ( category . id ) ;
assert . strictEqual ( catChooser . header ( ) . label ( ) , category . name ) ;
await runQuery ( ) ;
assert . strictEqual (
getSearchParam ( "category" ) ,
category . id . toString ( ) ,
"it updates the URL with the selected category id"
) ;
await catChooser . expand ( ) ;
await catChooser . selectRowByIndex ( 0 ) ;
await runQuery ( ) ;
assert . strictEqual (
getSearchParam ( "category" ) ,
undefined ,
"it removes the category id from the URL when selecting the first row (null value)"
) ;
} ) ;
2022-12-27 12:10:29 -06:00
} ) ;