chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
Row ID,Order ID,Order Date,Ship Date,Ship Mode,Customer ID,Segment,Country,City,State,Postal Code,Region,Product ID,Category,Sub-Category,Sales,Quantity,Discount,Profit
|
||||
1,CA-2013-152156,11/9/2013,11/12/2013,Second Class,CG-12520,Consumer,United States,Henderson,Kentucky,42420,South,FUR-BO-10001798,Furniture,Bookcases,261.96,2,0.0,41.9136
|
||||
2,CA-2013-152156,11/9/2013,11/12/2013,Second Class,CG-12520,Consumer,United States,Henderson,Kentucky,42420,South,FUR-CH-10000454,Furniture,Chairs,731.94,3,0.0,219.582
|
||||
3,CA-2013-138688,6/13/2013,6/17/2013,Second Class,DV-13045,Corporate,United States,Los Angeles,California,90036,West,OFF-LA-10000240,Office Supplies,Labels,14.62,2,0.0,6.8714
|
||||
4,US-2012-108966,10/11/2012,10/18/2012,Standard Class,SO-20335,Consumer,United States,Fort Lauderdale,Florida,33311,South,FUR-TA-10000577,Furniture,Tables,957.5775,5,0.45,-383.031
|
||||
5,US-2012-108966,10/11/2012,10/18/2012,Standard Class,SO-20335,Consumer,United States,Fort Lauderdale,Florida,33311,South,OFF-ST-10000760,Office Supplies,Storage,22.368,2,0.2,2.5164
|
||||
6,CA-2011-115812,6/9/2011,6/14/2011,Standard Class,BH-11710,Consumer,United States,Los Angeles,California,90032,West,FUR-FU-10001487,Furniture,Furnishings,48.86,7,0.0,14.1694
|
||||
7,CA-2011-115812,6/9/2011,6/14/2011,Standard Class,BH-11710,Consumer,United States,Los Angeles,California,90032,West,OFF-AR-10002833,Office Supplies,Art,7.28,4,0.0,1.9656
|
||||
8,CA-2011-115812,6/9/2011,6/14/2011,Standard Class,BH-11710,Consumer,United States,Los Angeles,California,90032,West,TEC-PH-10002275,Technology,Phones,907.152,6,0.2,90.7152
|
||||
9,CA-2011-115812,6/9/2011,6/14/2011,Standard Class,BH-11710,Consumer,United States,Los Angeles,California,90032,West,OFF-BI-10003910,Office Supplies,Binders,18.504,3,0.2,5.7825
|
||||
10,CA-2011-115812,6/9/2011,6/14/2011,Standard Class,BH-11710,Consumer,United States,Los Angeles,California,90032,West,OFF-AP-10002892,Office Supplies,Appliances,114.9,5,0.0,34.47
|
||||
11,CA-2011-115812,6/9/2011,6/14/2011,Standard Class,BH-11710,Consumer,United States,Los Angeles,California,90032,West,FUR-TA-10001539,Furniture,Tables,1706.184,9,0.2,85.3092
|
||||
12,CA-2011-115812,6/9/2011,6/14/2011,Standard Class,BH-11710,Consumer,United States,Los Angeles,California,90032,West,TEC-PH-10002033,Technology,Phones,911.424,4,0.2,68.3568
|
||||
13,CA-2014-114412,4/16/2014,4/21/2014,Standard Class,AA-10480,Consumer,United States,Concord,North Carolina,28027,South,OFF-PA-10002365,Office Supplies,Paper,15.552,3,0.2,5.4432
|
||||
14,CA-2013-161389,12/6/2013,12/11/2013,Standard Class,IM-15070,Consumer,United States,Seattle,Washington,98103,West,OFF-BI-10003656,Office Supplies,Binders,407.976,3,0.2,132.5922
|
||||
15,US-2012-118983,11/22/2012,11/26/2012,Standard Class,HP-14815,Home Office,United States,Fort Worth,Texas,76106,Central,OFF-AP-10002311,Office Supplies,Appliances,68.81,5,0.8,-123.858
|
||||
16,US-2012-118983,11/22/2012,11/26/2012,Standard Class,HP-14815,Home Office,United States,Fort Worth,Texas,76106,Central,OFF-BI-10000756,Office Supplies,Binders,2.544,3,0.8,-3.816
|
||||
17,CA-2011-105893,11/11/2011,11/18/2011,Standard Class,PK-19075,Consumer,United States,Madison,Wisconsin,53711,Central,OFF-ST-10004186,Office Supplies,Storage,665.88,6,0.0,13.3176
|
||||
18,CA-2011-167164,5/13/2011,5/15/2011,Second Class,AG-10270,Consumer,United States,West Jordan,Utah,84084,West,OFF-ST-10000107,Office Supplies,Storage,55.5,2,0.0,9.99
|
||||
19,CA-2011-143336,8/27/2011,9/1/2011,Second Class,ZD-21925,Consumer,United States,San Francisco,California,94109,West,OFF-AR-10003056,Office Supplies,Art,8.56,2,0.0,2.4824
|
||||
20,CA-2011-143336,8/27/2011,9/1/2011,Second Class,ZD-21925,Consumer,United States,San Francisco,California,94109,West,TEC-PH-10001949,Technology,Phones,213.48,3,0.2,16.011
|
||||
21,CA-2011-143336,8/27/2011,9/1/2011,Second Class,ZD-21925,Consumer,United States,San Francisco,California,94109,West,OFF-BI-10002215,Office Supplies,Binders,22.72,4,0.2,7.384
|
||||
22,CA-2013-137330,12/10/2013,12/14/2013,Standard Class,KB-16585,Corporate,United States,Fremont,Nebraska,68025,Central,OFF-AR-10000246,Office Supplies,Art,19.46,7,0.0,5.0596
|
||||
23,CA-2013-137330,12/10/2013,12/14/2013,Standard Class,KB-16585,Corporate,United States,Fremont,Nebraska,68025,Central,OFF-AP-10001492,Office Supplies,Appliances,60.34,7,0.0,15.6884
|
||||
24,US-2014-156909,7/17/2014,7/19/2014,Second Class,SF-20065,Consumer,United States,Philadelphia,Pennsylvania,19140,East,FUR-CH-10002774,Furniture,Chairs,71.372,2,0.3,-1.0196
|
||||
25,CA-2012-106320,9/25/2012,9/30/2012,Standard Class,EB-13870,Consumer,United States,Orem,Utah,84057,West,FUR-TA-10000577,Furniture,Tables,1044.63,3,0.0,240.2649
|
||||
26,CA-2013-121755,1/16/2013,1/20/2013,Second Class,EH-13945,Consumer,United States,Los Angeles,California,90049,West,OFF-BI-10001634,Office Supplies,Binders,11.648,2,0.2,4.2224
|
||||
27,CA-2013-121755,1/16/2013,1/20/2013,Second Class,EH-13945,Consumer,United States,Los Angeles,California,90049,West,TEC-AC-10003027,Technology,Accessories,90.57,3,0.0,11.7741
|
||||
28,US-2012-150630,9/17/2012,9/21/2012,Standard Class,TB-21520,Consumer,United States,Philadelphia,Pennsylvania,19140,East,FUR-BO-10004834,Furniture,Bookcases,3083.43,7,0.5,-1665.0522
|
||||
29,US-2012-150630,9/17/2012,9/21/2012,Standard Class,TB-21520,Consumer,United States,Philadelphia,Pennsylvania,19140,East,OFF-BI-10000474,Office Supplies,Binders,9.618,2,0.7,-7.0532
|
||||
30,US-2012-150630,9/17/2012,9/21/2012,Standard Class,TB-21520,Consumer,United States,Philadelphia,Pennsylvania,19140,East,FUR-FU-10004848,Furniture,Furnishings,124.2,3,0.2,15.525
|
||||
31,US-2012-150630,9/17/2012,9/21/2012,Standard Class,TB-21520,Consumer,United States,Philadelphia,Pennsylvania,19140,East,OFF-EN-10001509,Office Supplies,Envelopes,3.264,2,0.2,1.1016
|
||||
32,US-2012-150630,9/17/2012,9/21/2012,Standard Class,TB-21520,Consumer,United States,Philadelphia,Pennsylvania,19140,East,OFF-AR-10004042,Office Supplies,Art,86.304,6,0.2,9.7092
|
||||
33,US-2012-150630,9/17/2012,9/21/2012,Standard Class,TB-21520,Consumer,United States,Philadelphia,Pennsylvania,19140,East,OFF-BI-10001525,Office Supplies,Binders,6.858,6,0.7,-5.715
|
||||
34,US-2012-150630,9/17/2012,9/21/2012,Standard Class,TB-21520,Consumer,United States,Philadelphia,Pennsylvania,19140,East,OFF-AR-10001683,Office Supplies,Art,15.76,2,0.2,3.546
|
||||
35,CA-2014-107727,10/20/2014,10/24/2014,Second Class,MA-17560,Home Office,United States,Houston,Texas,77095,Central,OFF-PA-10000249,Office Supplies,Paper,29.472,3,0.2,9.9468
|
||||
36,CA-2013-117590,12/9/2013,12/11/2013,First Class,GH-14485,Corporate,United States,Richardson,Texas,75080,Central,TEC-PH-10004977,Technology,Phones,1097.544,7,0.2,123.4737
|
||||
37,CA-2013-117590,12/9/2013,12/11/2013,First Class,GH-14485,Corporate,United States,Richardson,Texas,75080,Central,FUR-FU-10003664,Furniture,Furnishings,190.92,5,0.6,-147.963
|
||||
38,CA-2012-117415,12/27/2012,12/31/2012,Standard Class,SN-20710,Home Office,United States,Houston,Texas,77041,Central,OFF-EN-10002986,Office Supplies,Envelopes,113.328,9,0.2,35.415
|
||||
39,CA-2012-117415,12/27/2012,12/31/2012,Standard Class,SN-20710,Home Office,United States,Houston,Texas,77041,Central,FUR-BO-10002545,Furniture,Bookcases,532.3992,3,0.32,-46.9764
|
||||
40,CA-2012-117415,12/27/2012,12/31/2012,Standard Class,SN-20710,Home Office,United States,Houston,Texas,77041,Central,FUR-CH-10004218,Furniture,Chairs,212.058,3,0.3,-15.147
|
||||
41,CA-2012-117415,12/27/2012,12/31/2012,Standard Class,SN-20710,Home Office,United States,Houston,Texas,77041,Central,TEC-PH-10000486,Technology,Phones,371.168,4,0.2,41.7564
|
||||
42,CA-2014-120999,9/11/2014,9/16/2014,Standard Class,LC-16930,Corporate,United States,Naperville,Illinois,60540,Central,TEC-PH-10004093,Technology,Phones,147.168,4,0.2,16.5564
|
||||
43,CA-2013-101343,7/18/2013,7/23/2013,Standard Class,RA-19885,Corporate,United States,Los Angeles,California,90049,West,OFF-ST-10003479,Office Supplies,Storage,77.88,2,0.0,3.894
|
||||
44,CA-2014-139619,9/20/2014,9/24/2014,Standard Class,ES-14080,Corporate,United States,Melbourne,Florida,32935,South,OFF-ST-10003282,Office Supplies,Storage,95.616,2,0.2,9.5616
|
||||
45,CA-2013-118255,3/12/2013,3/14/2013,First Class,ON-18715,Corporate,United States,Eagan,Minnesota,55122,Central,TEC-AC-10000171,Technology,Accessories,45.98,2,0.0,19.7714
|
||||
46,CA-2013-118255,3/12/2013,3/14/2013,First Class,ON-18715,Corporate,United States,Eagan,Minnesota,55122,Central,OFF-BI-10003291,Office Supplies,Binders,17.46,2,0.0,8.2062
|
||||
47,CA-2011-146703,10/20/2011,10/25/2011,Second Class,PO-18865,Consumer,United States,Westland,Michigan,48185,Central,OFF-ST-10001713,Office Supplies,Storage,211.96,4,0.0,8.4784
|
||||
48,CA-2013-169194,6/21/2013,6/26/2013,Standard Class,LH-16900,Consumer,United States,Dover,Delaware,19901,East,TEC-AC-10002167,Technology,Accessories,45.0,3,0.0,4.95
|
||||
49,CA-2013-169194,6/21/2013,6/26/2013,Standard Class,LH-16900,Consumer,United States,Dover,Delaware,19901,East,TEC-PH-10003988,Technology,Phones,21.8,2,0.0,6.104
|
||||
50,CA-2012-115742,4/18/2012,4/22/2012,Standard Class,DP-13000,Consumer,United States,New Albany,Indiana,47150,Central,OFF-BI-10004410,Office Supplies,Binders,38.22,6,0.0,17.9634
|
||||
51,CA-2012-115742,4/18/2012,4/22/2012,Standard Class,DP-13000,Consumer,United States,New Albany,Indiana,47150,Central,OFF-LA-10002762,Office Supplies,Labels,75.18,6,0.0,35.3346
|
||||
52,CA-2012-115742,4/18/2012,4/22/2012,Standard Class,DP-13000,Consumer,United States,New Albany,Indiana,47150,Central,FUR-FU-10001706,Furniture,Furnishings,6.16,2,0.0,2.9568
|
||||
53,CA-2012-115742,4/18/2012,4/22/2012,Standard Class,DP-13000,Consumer,United States,New Albany,Indiana,47150,Central,FUR-CH-10003061,Furniture,Chairs,89.99,1,0.0,17.0981
|
||||
54,CA-2013-105816,12/12/2013,12/18/2013,Standard Class,JM-15265,Corporate,United States,New York City,New York,10024,East,OFF-FA-10000304,Office Supplies,Fasteners,15.26,7,0.0,6.2566
|
||||
55,CA-2013-105816,12/12/2013,12/18/2013,Standard Class,JM-15265,Corporate,United States,New York City,New York,10024,East,TEC-PH-10002447,Technology,Phones,1029.95,5,0.0,298.6855
|
||||
56,CA-2013-111682,6/18/2013,6/19/2013,First Class,TB-21055,Consumer,United States,Troy,New York,12180,East,OFF-ST-10000604,Office Supplies,Storage,208.56,6,0.0,52.14
|
||||
57,CA-2013-111682,6/18/2013,6/19/2013,First Class,TB-21055,Consumer,United States,Troy,New York,12180,East,OFF-PA-10001569,Office Supplies,Paper,32.4,5,0.0,15.552
|
||||
58,CA-2013-111682,6/18/2013,6/19/2013,First Class,TB-21055,Consumer,United States,Troy,New York,12180,East,FUR-CH-10003968,Furniture,Chairs,319.41,5,0.1,7.098
|
||||
59,CA-2013-111682,6/18/2013,6/19/2013,First Class,TB-21055,Consumer,United States,Troy,New York,12180,East,OFF-PA-10000587,Office Supplies,Paper,14.56,2,0.0,6.9888
|
||||
60,CA-2013-111682,6/18/2013,6/19/2013,First Class,TB-21055,Consumer,United States,Troy,New York,12180,East,TEC-AC-10002167,Technology,Accessories,30.0,2,0.0,3.3
|
||||
61,CA-2013-111682,6/18/2013,6/19/2013,First Class,TB-21055,Consumer,United States,Troy,New York,12180,East,OFF-BI-10001460,Office Supplies,Binders,48.48,4,0.2,16.362
|
||||
62,CA-2013-111682,6/18/2013,6/19/2013,First Class,TB-21055,Consumer,United States,Troy,New York,12180,East,OFF-AR-10001868,Office Supplies,Art,1.68,1,0.0,0.84
|
||||
63,CA-2012-135545,11/24/2012,11/30/2012,Standard Class,KM-16720,Consumer,United States,Los Angeles,California,90004,West,TEC-AC-10004633,Technology,Accessories,13.98,2,0.0,6.1512
|
||||
64,CA-2012-135545,11/24/2012,11/30/2012,Standard Class,KM-16720,Consumer,United States,Los Angeles,California,90004,West,OFF-BI-10001078,Office Supplies,Binders,25.824,6,0.2,9.3612
|
||||
65,CA-2012-135545,11/24/2012,11/30/2012,Standard Class,KM-16720,Consumer,United States,Los Angeles,California,90004,West,OFF-PA-10003892,Office Supplies,Paper,146.73,3,0.0,68.9631
|
||||
66,CA-2012-135545,11/24/2012,11/30/2012,Standard Class,KM-16720,Consumer,United States,Los Angeles,California,90004,West,FUR-FU-10000397,Furniture,Furnishings,79.76,4,0.0,22.3328
|
||||
67,US-2012-164175,4/30/2012,5/5/2012,Standard Class,PS-18970,Home Office,United States,Chicago,Illinois,60610,Central,FUR-CH-10001146,Furniture,Chairs,213.115,5,0.3,-15.2225
|
||||
68,CA-2011-106376,12/5/2011,12/10/2011,Standard Class,BS-11590,Corporate,United States,Gilbert,Arizona,85234,West,OFF-AR-10002671,Office Supplies,Art,1113.024,8,0.2,111.3024
|
||||
69,CA-2011-106376,12/5/2011,12/10/2011,Standard Class,BS-11590,Corporate,United States,Gilbert,Arizona,85234,West,TEC-PH-10002726,Technology,Phones,167.968,4,0.2,62.988
|
||||
70,CA-2013-119823,6/5/2013,6/7/2013,First Class,KD-16270,Consumer,United States,Springfield,Virginia,22153,South,OFF-PA-10000482,Office Supplies,Paper,75.88,2,0.0,35.6636
|
||||
71,CA-2013-106075,9/19/2013,9/24/2013,Standard Class,HM-14980,Consumer,United States,New York City,New York,10009,East,OFF-BI-10004654,Office Supplies,Binders,4.616,1,0.2,1.731
|
||||
72,CA-2014-114440,9/15/2014,9/18/2014,Second Class,TB-21520,Consumer,United States,Jackson,Michigan,49201,Central,OFF-PA-10004675,Office Supplies,Paper,19.05,3,0.0,8.763
|
||||
73,US-2012-134026,4/26/2012,5/2/2012,Standard Class,JE-15745,Consumer,United States,Memphis,Tennessee,38109,South,FUR-CH-10000513,Furniture,Chairs,831.936,8,0.2,-114.3912
|
||||
74,US-2012-134026,4/26/2012,5/2/2012,Standard Class,JE-15745,Consumer,United States,Memphis,Tennessee,38109,South,FUR-FU-10003708,Furniture,Furnishings,97.04,2,0.2,1.213
|
||||
75,US-2012-134026,4/26/2012,5/2/2012,Standard Class,JE-15745,Consumer,United States,Memphis,Tennessee,38109,South,OFF-ST-10004123,Office Supplies,Storage,72.784,1,0.2,-18.196
|
||||
76,US-2014-118038,12/10/2014,12/12/2014,First Class,KB-16600,Corporate,United States,Houston,Texas,77041,Central,OFF-BI-10004182,Office Supplies,Binders,1.248,3,0.8,-1.9344
|
||||
77,US-2014-118038,12/10/2014,12/12/2014,First Class,KB-16600,Corporate,United States,Houston,Texas,77041,Central,FUR-FU-10000260,Furniture,Furnishings,9.708,3,0.6,-5.8248
|
||||
78,US-2014-118038,12/10/2014,12/12/2014,First Class,KB-16600,Corporate,United States,Houston,Texas,77041,Central,OFF-ST-10000615,Office Supplies,Storage,27.24,3,0.2,2.724
|
||||
79,US-2011-147606,11/26/2011,12/1/2011,Second Class,JE-15745,Consumer,United States,Houston,Texas,77070,Central,FUR-FU-10003194,Furniture,Furnishings,19.3,5,0.6,-14.475
|
||||
80,CA-2013-127208,6/13/2013,6/16/2013,First Class,SC-20770,Corporate,United States,Decatur,Alabama,35601,South,OFF-AP-10002118,Office Supplies,Appliances,208.16,1,0.0,56.2032
|
||||
81,CA-2013-127208,6/13/2013,6/16/2013,First Class,SC-20770,Corporate,United States,Decatur,Alabama,35601,South,OFF-BI-10002309,Office Supplies,Binders,16.74,3,0.0,8.0352
|
||||
82,CA-2011-139451,10/12/2011,10/16/2011,Standard Class,DN-13690,Consumer,United States,San Francisco,California,94122,West,OFF-AR-10002053,Office Supplies,Art,14.9,5,0.0,4.172
|
||||
83,CA-2011-139451,10/12/2011,10/16/2011,Standard Class,DN-13690,Consumer,United States,San Francisco,California,94122,West,OFF-ST-10002370,Office Supplies,Storage,21.39,1,0.0,6.2031
|
||||
84,CA-2012-149734,9/3/2012,9/8/2012,Standard Class,JC-16105,Corporate,United States,Durham,North Carolina,27707,South,OFF-EN-10000927,Office Supplies,Envelopes,200.984,7,0.2,62.8075
|
||||
85,US-2014-119662,11/14/2014,11/17/2014,First Class,CS-12400,Home Office,United States,Chicago,Illinois,60623,Central,OFF-ST-10003656,Office Supplies,Storage,230.376,3,0.2,-48.9549
|
||||
86,CA-2014-140088,5/29/2014,5/31/2014,Second Class,PO-18865,Consumer,United States,Columbia,South Carolina,29203,South,FUR-CH-10000863,Furniture,Chairs,301.96,2,0.0,33.2156
|
||||
87,CA-2014-155558,10/27/2014,11/3/2014,Standard Class,PG-18895,Consumer,United States,Rochester,Minnesota,55901,Central,TEC-AC-10001998,Technology,Accessories,19.99,1,0.0,6.7966
|
||||
88,CA-2014-155558,10/27/2014,11/3/2014,Standard Class,PG-18895,Consumer,United States,Rochester,Minnesota,55901,Central,OFF-LA-10000134,Office Supplies,Labels,6.16,2,0.0,2.9568
|
||||
89,CA-2013-159695,4/6/2013,4/11/2013,Second Class,GM-14455,Home Office,United States,Houston,Texas,77095,Central,OFF-ST-10003442,Office Supplies,Storage,158.368,7,0.2,13.8572
|
||||
90,CA-2013-109806,9/18/2013,9/23/2013,Standard Class,JS-15685,Corporate,United States,Los Angeles,California,90036,West,OFF-AR-10004930,Office Supplies,Art,20.1,3,0.0,6.633
|
||||
91,CA-2013-109806,9/18/2013,9/23/2013,Standard Class,JS-15685,Corporate,United States,Los Angeles,California,90036,West,TEC-PH-10004093,Technology,Phones,73.584,2,0.2,8.2782
|
||||
92,CA-2013-109806,9/18/2013,9/23/2013,Standard Class,JS-15685,Corporate,United States,Los Angeles,California,90036,West,OFF-PA-10000304,Office Supplies,Paper,6.48,1,0.0,3.1104
|
||||
93,CA-2012-149587,1/31/2012,2/5/2012,Second Class,KB-16315,Consumer,United States,Minneapolis,Minnesota,55407,Central,OFF-PA-10003177,Office Supplies,Paper,12.96,2,0.0,6.2208
|
||||
94,CA-2012-149587,1/31/2012,2/5/2012,Second Class,KB-16315,Consumer,United States,Minneapolis,Minnesota,55407,Central,FUR-FU-10003799,Furniture,Furnishings,53.34,3,0.0,16.5354
|
||||
95,CA-2012-149587,1/31/2012,2/5/2012,Second Class,KB-16315,Consumer,United States,Minneapolis,Minnesota,55407,Central,OFF-BI-10002852,Office Supplies,Binders,32.96,2,0.0,16.1504
|
||||
96,US-2014-109484,11/7/2014,11/13/2014,Standard Class,RB-19705,Home Office,United States,Portland,Oregon,97206,West,OFF-BI-10004738,Office Supplies,Binders,5.682,1,0.7,-3.788
|
||||
97,CA-2014-161018,11/10/2014,11/12/2014,Second Class,PN-18775,Home Office,United States,New York City,New York,10009,East,FUR-FU-10000629,Furniture,Furnishings,96.53,7,0.0,40.5426
|
||||
98,CA-2014-157833,6/18/2014,6/21/2014,First Class,KD-16345,Consumer,United States,San Francisco,California,94122,West,OFF-BI-10001721,Office Supplies,Binders,51.312,3,0.2,17.9592
|
||||
99,CA-2013-149223,9/7/2013,9/12/2013,Standard Class,ER-13855,Corporate,United States,Saint Paul,Minnesota,55106,Central,OFF-AP-10000358,Office Supplies,Appliances,77.88,6,0.0,22.5852
|
||||
|
@@ -0,0 +1,136 @@
|
||||
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
||||
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
||||
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
||||
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
||||
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
||||
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
||||
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
||||
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
||||
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
||||
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
||||
|
||||
import { test, expect } from "@perspective-dev/test";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto("/tools/test/src/html/workspace-test.html");
|
||||
await page.evaluate(async () => {
|
||||
while (!window["__TEST_PERSPECTIVE_READY__"]) {
|
||||
await new Promise((x) => setTimeout(x, 10));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Context menu", () => {
|
||||
test("shows tables in the New Table submenu", async ({ page }) => {
|
||||
await page.evaluate(async () => {
|
||||
await window.__WORKER__.table("x\n1\n2\n", {
|
||||
name: "test_table_1",
|
||||
});
|
||||
|
||||
await window.__WORKER__.table("y\n3\n4\n", {
|
||||
name: "test_table_2",
|
||||
});
|
||||
});
|
||||
|
||||
// Right-click on the workspace to open context menu
|
||||
const workspace = page.locator("perspective-workspace");
|
||||
await workspace.click({
|
||||
button: "right",
|
||||
position: { x: 100, y: 100 },
|
||||
});
|
||||
|
||||
// Wait for the context menu to appear in the shadow DOM
|
||||
const shadowHost = page.locator("perspective-workspace");
|
||||
const menu = shadowHost.locator(".lm-Menu").first();
|
||||
await expect(menu).toBeVisible();
|
||||
|
||||
// Click on "New Table" to open the submenu
|
||||
const newTableItem = menu.locator(
|
||||
".lm-Menu-item:has(.lm-Menu-itemLabel:text('New Table'))",
|
||||
);
|
||||
await newTableItem.hover();
|
||||
|
||||
// Wait for submenu to appear
|
||||
const submenu = shadowHost.locator(".lm-Menu").nth(1);
|
||||
await expect(submenu).toBeVisible();
|
||||
|
||||
// Get the submenu content with table entries
|
||||
const submenuContent = submenu.locator(".lm-Menu-content");
|
||||
|
||||
// Wait for the table items to be populated (they are added asynchronously)
|
||||
// We expect at least our two test tables plus the default "superstore" table
|
||||
await expect(submenuContent.locator("> .lm-Menu-item")).toHaveCount(3, {
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
const menuItems = submenuContent.locator("> .lm-Menu-item");
|
||||
const itemCount = await menuItems.count();
|
||||
|
||||
// Get the labels of the first items (the tables)
|
||||
const labels = [];
|
||||
for (let i = 0; i < itemCount; i++) {
|
||||
const label = await menuItems
|
||||
.nth(i)
|
||||
.locator(".lm-Menu-itemLabel")
|
||||
.textContent();
|
||||
labels.push(label);
|
||||
}
|
||||
|
||||
// Verify our test tables appear in the menu
|
||||
expect(labels).toContain("test_table_1");
|
||||
expect(labels).toContain("test_table_2");
|
||||
expect(labels).toContain("superstore");
|
||||
});
|
||||
|
||||
test("context menu table entries have correct structure", async ({
|
||||
page,
|
||||
}) => {
|
||||
// Create two tables and load the workspace
|
||||
await page.evaluate(async () => {
|
||||
await window.__WORKER__.table("a\n1\n", { name: "alpha" });
|
||||
await window.__WORKER__.table("b\n2\n", { name: "beta" });
|
||||
});
|
||||
|
||||
// Right-click on the workspace
|
||||
const workspace = page.locator("perspective-workspace");
|
||||
await workspace.click({
|
||||
button: "right",
|
||||
position: { x: 100, y: 100 },
|
||||
});
|
||||
|
||||
// Open the "New Table" submenu
|
||||
const shadowHost = page.locator("perspective-workspace");
|
||||
const menu = shadowHost.locator(".lm-Menu").first();
|
||||
await expect(menu).toBeVisible();
|
||||
|
||||
const newTableItem = menu.locator(
|
||||
".lm-Menu-item:has(.lm-Menu-itemLabel:text('New Table'))",
|
||||
);
|
||||
await newTableItem.hover();
|
||||
|
||||
const submenu = shadowHost.locator(".lm-Menu").nth(1);
|
||||
await expect(submenu).toBeVisible();
|
||||
|
||||
// Verify the DOM structure of table entries
|
||||
const submenuContent = submenu.locator(".lm-Menu-content");
|
||||
|
||||
// Wait for table items to be populated
|
||||
await expect(submenuContent.locator("> .lm-Menu-item")).toHaveCount(3, {
|
||||
timeout: 5000,
|
||||
});
|
||||
|
||||
const firstItem = submenuContent.locator("> .lm-Menu-item").first();
|
||||
|
||||
// Check that the menu item has the expected Lumino classes
|
||||
await expect(firstItem).toHaveClass(/lm-Menu-item/);
|
||||
|
||||
// Check that it contains a label element
|
||||
const labelElement = firstItem.locator(".lm-Menu-itemLabel");
|
||||
await expect(labelElement).toBeVisible();
|
||||
|
||||
// Verify the label contains one of our table names
|
||||
const labelText = await labelElement.textContent();
|
||||
expect(["alpha", "beta", "superstore"]).toContain(labelText);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
||||
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
||||
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
||||
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
||||
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
||||
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
||||
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
||||
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
||||
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
||||
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
||||
|
||||
import { test } from "@perspective-dev/test";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto("/tools/test/src/html/workspace-test.html");
|
||||
await page.evaluate(async () => {
|
||||
while (!window["__TEST_PERSPECTIVE_READY__"]) {
|
||||
await new Promise((x) => setTimeout(x, 10));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Workspace table functions", () => {
|
||||
test("flush() waits until delete is resolved", async ({ page }) => {
|
||||
const config = {
|
||||
viewers: {
|
||||
One: { table: "superstore", name: "One" },
|
||||
},
|
||||
detail: {
|
||||
main: {
|
||||
currentIndex: 0,
|
||||
type: "tab-area",
|
||||
widgets: ["One"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
await page.evaluate(async (config) => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
const table = await window.__WORKER__.open_table("superstore");
|
||||
await workspace.restore(config);
|
||||
const viewer_removed =
|
||||
workspace.querySelector("perspective-viewer");
|
||||
|
||||
workspace.removeChild(viewer_removed);
|
||||
await viewer_removed.flush();
|
||||
await table.delete();
|
||||
}, config);
|
||||
});
|
||||
|
||||
test("flush() waits until restore is applied and delete is resolved", async ({
|
||||
page,
|
||||
}) => {
|
||||
const config = {
|
||||
viewers: {
|
||||
One: { table: "superstore", name: "One" },
|
||||
},
|
||||
detail: {
|
||||
main: {
|
||||
currentIndex: 0,
|
||||
type: "tab-area",
|
||||
widgets: ["One"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
await page.evaluate(async (config) => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
const table = await window.__WORKER__.open_table("superstore");
|
||||
workspace.restore(config); // no await
|
||||
await workspace.flush();
|
||||
const viewer_removed =
|
||||
workspace.querySelector("perspective-viewer");
|
||||
|
||||
workspace.removeChild(viewer_removed);
|
||||
await viewer_removed.flush();
|
||||
await table.delete();
|
||||
}, config);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,78 @@
|
||||
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
||||
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
||||
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
||||
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
||||
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
||||
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
||||
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
||||
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
||||
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
||||
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
||||
|
||||
import { test } from "@perspective-dev/test";
|
||||
import {
|
||||
compareLightDOMContents,
|
||||
compareShadowDOMContents,
|
||||
} from "@perspective-dev/test";
|
||||
|
||||
async function setupTestWorkspace(page) {
|
||||
await page.goto("/tools/test/src/html/workspace-test.html");
|
||||
await page.evaluate(async () => {
|
||||
while (!window["__TEST_PERSPECTIVE_READY__"]) {
|
||||
await new Promise((x) => setTimeout(x, 10));
|
||||
}
|
||||
});
|
||||
|
||||
await page.evaluate(async () => {
|
||||
const viewer = document.createElement("perspective-viewer");
|
||||
viewer.setAttribute("table", "superstore");
|
||||
viewer.setAttribute("name", "one");
|
||||
viewer.setAttribute("slot", "one");
|
||||
const viewer2 = document.createElement("perspective-viewer");
|
||||
viewer2.setAttribute("table", "superstore");
|
||||
viewer2.setAttribute("name", "two");
|
||||
viewer2.setAttribute("slot", "two");
|
||||
const workspace = document.getElementById("workspace");
|
||||
workspace.appendChild(viewer);
|
||||
workspace.appendChild(viewer2);
|
||||
await workspace.flush();
|
||||
});
|
||||
|
||||
await page.evaluate(async () => {
|
||||
const viewer = document.body.querySelector(
|
||||
'perspective-viewer[name="one"]',
|
||||
);
|
||||
const workspace = document.getElementById("workspace");
|
||||
workspace.removeChild(viewer);
|
||||
await workspace.flush();
|
||||
});
|
||||
}
|
||||
|
||||
test.describe("Workspace DOM", () => {
|
||||
test.describe("Light DOM", () => {
|
||||
test.describe("removeChild", () => {
|
||||
test("Remove One", async ({ page }) => {
|
||||
await setupTestWorkspace(page);
|
||||
|
||||
await compareLightDOMContents(
|
||||
page,
|
||||
"workspace-light-remove-one-child.txt",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Shadow DOM", () => {
|
||||
test.describe("removeChild", () => {
|
||||
test("Remove One", async ({ page }) => {
|
||||
await setupTestWorkspace(page);
|
||||
|
||||
await compareShadowDOMContents(
|
||||
page,
|
||||
"workspace-dark-remove-one-child.txt",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,472 @@
|
||||
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
||||
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
||||
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
||||
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
||||
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
||||
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
||||
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
||||
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
||||
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
||||
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
||||
|
||||
import { test, expect } from "@playwright/test";
|
||||
import {
|
||||
compareLightDOMContents,
|
||||
compareShadowDOMContents,
|
||||
} from "@perspective-dev/test";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto("/tools/test/src/html/workspace-test.html");
|
||||
await page.evaluate(async () => {
|
||||
while (!window["__TEST_PERSPECTIVE_READY__"]) {
|
||||
await new Promise((x) => setTimeout(x, 10));
|
||||
}
|
||||
});
|
||||
await page.evaluate(async () => {
|
||||
const { PerspectiveSelectDetail } = await import(
|
||||
"/node_modules/@perspective-dev/viewer/dist/cdn/perspective-viewer.js"
|
||||
);
|
||||
window.PerspectiveSelectDetail = PerspectiveSelectDetail;
|
||||
});
|
||||
});
|
||||
|
||||
function tests(context, compare) {
|
||||
// TODO: Implement this correctly
|
||||
test.skip("treemap filters work", async ({ page }) => {
|
||||
const config = {
|
||||
viewers: {
|
||||
One: {
|
||||
table: "superstore",
|
||||
name: "Test",
|
||||
group_by: ["State"],
|
||||
columns: ["Sales"],
|
||||
plugin: "Treemap",
|
||||
},
|
||||
Two: { table: "superstore", name: "One" },
|
||||
},
|
||||
master: {
|
||||
widgets: ["One"],
|
||||
},
|
||||
detail: {
|
||||
main: {
|
||||
currentIndex: 0,
|
||||
type: "tab-area",
|
||||
widgets: ["Two"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const cfg = await page.evaluate(async (config) => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
await workspace.restore(config);
|
||||
await workspace.flush();
|
||||
const timer = Promise.withResolvers();
|
||||
workspace.addEventListener("workspace-layout-update", (x) => {
|
||||
timer.resolve();
|
||||
});
|
||||
|
||||
document
|
||||
.querySelector("perspective-viewer-charts-treemap")
|
||||
.shadowRoot.querySelector("g.treemap > g")
|
||||
.dispatchEvent(new Event("click"));
|
||||
|
||||
await timer.promise;
|
||||
return await workspace.save();
|
||||
}, config);
|
||||
|
||||
expect(cfg.viewers.Two.filter).toEqual([["State", "==", "Alabama"]]);
|
||||
return compare(page, `${context}-treemap-filters-work.txt`);
|
||||
});
|
||||
|
||||
test("Datagrid filters work", async ({ page }) => {
|
||||
const config = {
|
||||
viewers: {
|
||||
One: {
|
||||
table: "superstore",
|
||||
name: "Test",
|
||||
group_by: ["State"],
|
||||
columns: ["Sales"],
|
||||
plugin: "Datagrid",
|
||||
},
|
||||
Two: { table: "superstore", name: "One" },
|
||||
},
|
||||
master: {
|
||||
widgets: ["One"],
|
||||
},
|
||||
detail: {
|
||||
main: {
|
||||
currentIndex: 0,
|
||||
type: "tab-area",
|
||||
widgets: ["Two"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async function awaitConfigChange() {
|
||||
return await page.evaluate(async () => {
|
||||
let resolve;
|
||||
const timer = new Promise((x) => {
|
||||
resolve = x;
|
||||
});
|
||||
|
||||
workspace.addEventListener("workspace-layout-update", resolve);
|
||||
await timer;
|
||||
workspace.removeEventListener(
|
||||
"workspace-layout-update",
|
||||
resolve,
|
||||
);
|
||||
|
||||
return await workspace.save();
|
||||
});
|
||||
}
|
||||
|
||||
await page.evaluate(async (config) => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
await workspace.restore(config);
|
||||
await workspace.flush();
|
||||
}, config);
|
||||
|
||||
let cfgPromise = awaitConfigChange();
|
||||
await page
|
||||
.locator(".workspace-master-widget perspective-viewer-datagrid")
|
||||
.locator("tbody tr:nth-child(6) th:last-of-type")
|
||||
.click();
|
||||
|
||||
let cfg = await cfgPromise;
|
||||
expect(cfg.viewers.Two.filter).toEqual([["State", "==", "Colorado"]]);
|
||||
|
||||
cfgPromise = awaitConfigChange();
|
||||
await page
|
||||
.locator(".workspace-master-widget perspective-viewer-datagrid")
|
||||
.locator("tbody tr:nth-child(6) th:last-of-type")
|
||||
.click();
|
||||
|
||||
cfg = await cfgPromise;
|
||||
expect(cfg.viewers.Two.filter).toEqual([]);
|
||||
|
||||
return compare(page, `${context}-datagrid-filters-work.txt`);
|
||||
});
|
||||
|
||||
test("removeConfigs removes a programmatically applied filter from slave viewers", async ({
|
||||
page,
|
||||
}) => {
|
||||
const config = {
|
||||
viewers: {
|
||||
One: {
|
||||
table: "superstore",
|
||||
name: "Test",
|
||||
group_by: ["State"],
|
||||
columns: ["Sales"],
|
||||
plugin: "Datagrid",
|
||||
},
|
||||
Two: { table: "superstore", name: "One" },
|
||||
},
|
||||
master: {
|
||||
widgets: ["One"],
|
||||
},
|
||||
detail: {
|
||||
main: {
|
||||
currentIndex: 0,
|
||||
type: "tab-area",
|
||||
widgets: ["Two"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async function awaitConfigChange() {
|
||||
return await page.evaluate(async () => {
|
||||
let resolve;
|
||||
const timer = new Promise((x) => {
|
||||
resolve = x;
|
||||
});
|
||||
|
||||
workspace.addEventListener("workspace-layout-update", resolve);
|
||||
await timer;
|
||||
workspace.removeEventListener(
|
||||
"workspace-layout-update",
|
||||
resolve,
|
||||
);
|
||||
|
||||
return await workspace.save();
|
||||
});
|
||||
}
|
||||
|
||||
await page.evaluate(async (config) => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
await workspace.restore(config);
|
||||
await workspace.flush();
|
||||
}, config);
|
||||
|
||||
// Apply a filter for "Category" via programmatic dispatch.
|
||||
// "Category" is not in the master's group_by/split_by/filter, so it
|
||||
// would not be cleared by the candidates mechanism on deselect.
|
||||
let cfgPromise = awaitConfigChange();
|
||||
await page.evaluate(async () => {
|
||||
const masterViewer = document.querySelector(
|
||||
".workspace-master-widget",
|
||||
);
|
||||
masterViewer.dispatchEvent(
|
||||
new CustomEvent("perspective-global-filter", {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
detail: new PerspectiveSelectDetail(
|
||||
true,
|
||||
{},
|
||||
["Category"],
|
||||
[],
|
||||
[{ filter: [["Category", "==", "Furniture"]] }],
|
||||
),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
let cfg = await cfgPromise;
|
||||
expect(cfg.viewers.Two.filter).toEqual([
|
||||
["Category", "==", "Furniture"],
|
||||
]);
|
||||
|
||||
// Use removeConfigs to explicitly clear the Category filter from
|
||||
// slave viewers.
|
||||
cfgPromise = awaitConfigChange();
|
||||
await page.evaluate(async () => {
|
||||
const masterViewer = document.querySelector(
|
||||
".workspace-master-widget",
|
||||
);
|
||||
masterViewer.dispatchEvent(
|
||||
new CustomEvent("perspective-global-filter", {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
detail: new PerspectiveSelectDetail(
|
||||
true,
|
||||
{},
|
||||
[],
|
||||
[{ filter: [["Category", "==", "Furniture"]] }],
|
||||
[],
|
||||
),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
cfg = await cfgPromise;
|
||||
expect(cfg.viewers.Two.filter).toEqual([]);
|
||||
});
|
||||
|
||||
test("removeConfigs preserves other slave filters while clearing targeted column", async ({
|
||||
page,
|
||||
}) => {
|
||||
const config = {
|
||||
viewers: {
|
||||
One: {
|
||||
table: "superstore",
|
||||
name: "Test",
|
||||
group_by: ["State"],
|
||||
columns: ["Sales"],
|
||||
plugin: "Datagrid",
|
||||
},
|
||||
Two: { table: "superstore", name: "One" },
|
||||
},
|
||||
master: {
|
||||
widgets: ["One"],
|
||||
},
|
||||
detail: {
|
||||
main: {
|
||||
currentIndex: 0,
|
||||
type: "tab-area",
|
||||
widgets: ["Two"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
async function awaitConfigChange() {
|
||||
return await page.evaluate(async () => {
|
||||
let resolve;
|
||||
const timer = new Promise((x) => {
|
||||
resolve = x;
|
||||
});
|
||||
|
||||
workspace.addEventListener("workspace-layout-update", resolve);
|
||||
await timer;
|
||||
workspace.removeEventListener(
|
||||
"workspace-layout-update",
|
||||
resolve,
|
||||
);
|
||||
|
||||
return await workspace.save();
|
||||
});
|
||||
}
|
||||
|
||||
await page.evaluate(async (config) => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
await workspace.restore(config);
|
||||
await workspace.flush();
|
||||
}, config);
|
||||
|
||||
// Apply filters for both "Category" and "Segment" via programmatic
|
||||
// dispatch.
|
||||
let cfgPromise = awaitConfigChange();
|
||||
await page.evaluate(async () => {
|
||||
const masterViewer = document.querySelector(
|
||||
".workspace-master-widget",
|
||||
);
|
||||
masterViewer.dispatchEvent(
|
||||
new CustomEvent("perspective-global-filter", {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
detail: new PerspectiveSelectDetail(
|
||||
true,
|
||||
{},
|
||||
["Category", "Segment"],
|
||||
[],
|
||||
[
|
||||
{
|
||||
filter: [
|
||||
["Category", "==", "Furniture"],
|
||||
["Segment", "==", "Consumer"],
|
||||
],
|
||||
},
|
||||
],
|
||||
),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
let cfg = await cfgPromise;
|
||||
expect(cfg.viewers.Two.filter).toEqual([
|
||||
["Category", "==", "Furniture"],
|
||||
["Segment", "==", "Consumer"],
|
||||
]);
|
||||
|
||||
// Remove only "Category"; "Segment" filter should be preserved.
|
||||
cfgPromise = awaitConfigChange();
|
||||
await page.evaluate(async () => {
|
||||
const masterViewer = document.querySelector(
|
||||
".workspace-master-widget",
|
||||
);
|
||||
masterViewer.dispatchEvent(
|
||||
new CustomEvent("perspective-global-filter", {
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
detail: new PerspectiveSelectDetail(
|
||||
true,
|
||||
{},
|
||||
[],
|
||||
[{ filter: [["Category", "==", "Furniture"]] }],
|
||||
[],
|
||||
),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
cfg = await cfgPromise;
|
||||
// Category is cleared, Segment is preserved.
|
||||
expect(cfg.viewers.Two.filter).toEqual([["Segment", "==", "Consumer"]]);
|
||||
});
|
||||
|
||||
test("Child classes of datagrid behave the same way", async ({ page }) => {
|
||||
const config = {
|
||||
viewers: {
|
||||
One: {
|
||||
table: "superstore",
|
||||
name: "Test",
|
||||
group_by: ["State"],
|
||||
columns: ["Sales"],
|
||||
plugin: "My Datagrid",
|
||||
},
|
||||
Two: { table: "superstore", name: "One" },
|
||||
},
|
||||
master: {
|
||||
widgets: ["One"],
|
||||
},
|
||||
detail: {
|
||||
main: {
|
||||
currentIndex: 0,
|
||||
type: "tab-area",
|
||||
widgets: ["Two"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
await page.evaluate(async () => {
|
||||
class MyGrid extends customElements.get(
|
||||
"perspective-viewer-datagrid",
|
||||
) {
|
||||
get_static_config() {
|
||||
return {
|
||||
...super.get_static_config(),
|
||||
name: "My Datagrid",
|
||||
};
|
||||
}
|
||||
}
|
||||
customElements.define("my-grid", MyGrid);
|
||||
customElements.get("perspective-viewer").registerPlugin("my-grid");
|
||||
});
|
||||
|
||||
async function awaitConfigChange() {
|
||||
return await page.evaluate(async () => {
|
||||
let resolve;
|
||||
const timer = new Promise((x) => {
|
||||
resolve = x;
|
||||
});
|
||||
|
||||
workspace.addEventListener("workspace-layout-update", resolve);
|
||||
await timer;
|
||||
workspace.removeEventListener(
|
||||
"workspace-layout-update",
|
||||
resolve,
|
||||
);
|
||||
|
||||
return await workspace.save();
|
||||
});
|
||||
}
|
||||
|
||||
await page.evaluate(async (config) => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
await workspace.restore(config);
|
||||
await workspace.flush();
|
||||
}, config);
|
||||
|
||||
let cfgPromise = awaitConfigChange();
|
||||
await page
|
||||
.locator(".workspace-master-widget my-grid")
|
||||
.locator("tbody tr:nth-child(6) th:last-of-type")
|
||||
|
||||
.click();
|
||||
let cfg = await cfgPromise;
|
||||
|
||||
expect(cfg.viewers.Two.filter).toEqual([["State", "==", "Colorado"]]);
|
||||
|
||||
cfgPromise = awaitConfigChange();
|
||||
await page
|
||||
.locator(".workspace-master-widget my-grid")
|
||||
.locator("tbody tr:nth-child(6) th:last-of-type")
|
||||
.click({
|
||||
delay: 10,
|
||||
});
|
||||
cfg = await cfgPromise;
|
||||
|
||||
// console.log("OLD", cfg.viewers.Two.filter);
|
||||
// await page.evaluate(async () => {
|
||||
// await new Promise((r) => setTimeout(r, 5000));
|
||||
// });
|
||||
// cfg = await page.evaluate(async () => {
|
||||
// const cfg = await workspace.save();
|
||||
// console.log("NEW", JSON.stringify(cfg.viewers.Two.filter));
|
||||
// return cfg;
|
||||
// });
|
||||
|
||||
expect(cfg.viewers.Two.filter).toEqual([]);
|
||||
|
||||
return compare(page, `${context}-my-datagrid-filters-work.txt`);
|
||||
});
|
||||
}
|
||||
|
||||
test.describe("Workspace global filters", () => {
|
||||
test.describe("Light DOM", () => {
|
||||
tests("light-dom", compareLightDOMContents);
|
||||
});
|
||||
|
||||
test.describe("Shadow DOM", () => {
|
||||
tests("shadow-dom", compareShadowDOMContents);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,117 @@
|
||||
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
||||
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
||||
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
||||
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
||||
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
||||
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
||||
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
||||
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
||||
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
||||
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
||||
|
||||
import { test } from "@perspective-dev/test";
|
||||
import {
|
||||
compareLightDOMContents,
|
||||
compareShadowDOMContents,
|
||||
} from "@perspective-dev/test";
|
||||
|
||||
async function createOneWorkspace(page) {
|
||||
// await new Promise((x) => setTimeout(x, 2000));
|
||||
await page.evaluate(async () => {
|
||||
document.querySelector("perspective-workspace").innerHTML = `
|
||||
<perspective-viewer table="superstore"></perspective-viewer>
|
||||
`;
|
||||
|
||||
const workspace = document.body.querySelector("perspective-workspace");
|
||||
await workspace.load(window.__WORKER__);
|
||||
await workspace.flush();
|
||||
});
|
||||
}
|
||||
|
||||
async function createMultipleViewers(page) {
|
||||
await page.evaluate(async () => {
|
||||
document.querySelector("perspective-workspace").innerHTML = `
|
||||
<perspective-viewer table="superstore"></perspective-viewer>
|
||||
<perspective-viewer table="superstore"></perspective-viewer>
|
||||
`;
|
||||
|
||||
const workspace = document.body.querySelector("perspective-workspace");
|
||||
await workspace.flush();
|
||||
});
|
||||
}
|
||||
|
||||
async function createMultipleViewersWithNames(page) {
|
||||
await page.evaluate(async () => {
|
||||
document.querySelector("perspective-workspace").innerHTML = `
|
||||
<perspective-viewer name="Table 1" table="superstore"></perspective-viewer>
|
||||
<perspective-viewer name="Table 2" table="superstore"></perspective-viewer>
|
||||
`;
|
||||
|
||||
const workspace = document.body.querySelector("perspective-workspace");
|
||||
await workspace.flush();
|
||||
});
|
||||
}
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto("/tools/test/src/html/workspace-test.html");
|
||||
await page.evaluate(async () => {
|
||||
while (!window["__TEST_PERSPECTIVE_READY__"]) {
|
||||
await new Promise((x) => setTimeout(x, 10));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Workspace HTML", () => {
|
||||
test.describe("Light DOM", () => {
|
||||
test("Create One", async ({ page }) => {
|
||||
await createOneWorkspace(page);
|
||||
await compareLightDOMContents(
|
||||
page,
|
||||
"workspace-html-light-create-one.txt",
|
||||
);
|
||||
});
|
||||
|
||||
test("Create Multiple", async ({ page }) => {
|
||||
await createMultipleViewers(page);
|
||||
await compareLightDOMContents(
|
||||
page,
|
||||
"workspace-html-light-create-multiple.txt",
|
||||
);
|
||||
});
|
||||
|
||||
test("Create Multiple with names", async ({ page }) => {
|
||||
await createMultipleViewersWithNames(page);
|
||||
await compareLightDOMContents(
|
||||
page,
|
||||
"workspace-html-light-create-multiple-with-names.txt",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Shadow DOM", () => {
|
||||
test("Create One", async ({ page }) => {
|
||||
await createOneWorkspace(page);
|
||||
await compareShadowDOMContents(
|
||||
page,
|
||||
"workspace-html-shadow-create-one.txt",
|
||||
);
|
||||
});
|
||||
|
||||
test("Create Multiple", async ({ page }) => {
|
||||
await createMultipleViewers(page);
|
||||
await compareShadowDOMContents(
|
||||
page,
|
||||
"workspace-html-shadow-create-multiple.txt",
|
||||
);
|
||||
});
|
||||
|
||||
test("Create Multiple with names", async ({ page }) => {
|
||||
await createMultipleViewersWithNames(page);
|
||||
await compareShadowDOMContents(
|
||||
page,
|
||||
"workspace-html-shadow-create-multiple-with-names.txt",
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,260 @@
|
||||
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
||||
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
||||
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
||||
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
||||
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
||||
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
||||
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
||||
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
||||
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
||||
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
||||
|
||||
import { test, expect } from "@perspective-dev/test";
|
||||
import {
|
||||
compareLightDOMContents,
|
||||
compareShadowDOMContents,
|
||||
} from "@perspective-dev/test";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto("/tools/test/src/html/workspace-test.html");
|
||||
await page.evaluate(async () => {
|
||||
while (!window["__TEST_PERSPECTIVE_READY__"]) {
|
||||
await new Promise((x) => setTimeout(x, 10));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function tests(context, compare) {
|
||||
test("restore workspace with detail only", async ({ page }) => {
|
||||
const config = {
|
||||
viewers: {
|
||||
One: { table: "superstore", name: "One" },
|
||||
},
|
||||
detail: {
|
||||
main: {
|
||||
currentIndex: 0,
|
||||
type: "tab-area",
|
||||
widgets: ["One"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
await page.evaluate(async (config) => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
await workspace.restore(config);
|
||||
}, config);
|
||||
|
||||
await page.evaluate(async () => {
|
||||
await workspace.flush();
|
||||
});
|
||||
|
||||
return compare(
|
||||
page,
|
||||
`${context}-restore-workspace-with-detail-only.txt`,
|
||||
);
|
||||
});
|
||||
|
||||
test("restore workspace with master and detail", async ({ page }) => {
|
||||
const config = {
|
||||
viewers: {
|
||||
One: {
|
||||
table: "superstore",
|
||||
name: "Test",
|
||||
group_by: ["State"],
|
||||
columns: ["Sales", "Profit"],
|
||||
},
|
||||
Two: { table: "superstore", name: "One" },
|
||||
},
|
||||
master: {
|
||||
widgets: ["One"],
|
||||
},
|
||||
detail: {
|
||||
main: {
|
||||
currentIndex: 0,
|
||||
type: "tab-area",
|
||||
widgets: ["Two"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
await page.evaluate(async (config) => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
await workspace.restore(config);
|
||||
}, config);
|
||||
|
||||
await page.evaluate(async () => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
await workspace.flush();
|
||||
});
|
||||
|
||||
return compare(
|
||||
page,
|
||||
`${context}-restore-workspace-with-master-and-detail.txt`,
|
||||
);
|
||||
});
|
||||
|
||||
test("restore workspace is symmetric with addViewer", async ({ page }) => {
|
||||
const initial = await page.evaluate(async (config) => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
await workspace.addViewer({ table: "superstore" });
|
||||
await workspace.flush();
|
||||
const result = await workspace.save();
|
||||
return result;
|
||||
});
|
||||
|
||||
const second = await page.evaluate(async (initial) => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
await workspace.restore(initial);
|
||||
await workspace.flush();
|
||||
return await workspace.save();
|
||||
}, initial);
|
||||
|
||||
expect(initial).toEqual(second);
|
||||
|
||||
return compare(
|
||||
page,
|
||||
`${context}-restore-workspace-is-symmetric-with-addviewer.txt`,
|
||||
);
|
||||
});
|
||||
|
||||
test.describe("Toggle master/detail", () => {
|
||||
test("restore a blank view removes master panel", async ({ page }) => {
|
||||
const config = {
|
||||
detail: {
|
||||
main: {
|
||||
type: "tab-area",
|
||||
widgets: ["PERSPECTIVE_GENERATED_ID_1"],
|
||||
currentIndex: 0,
|
||||
},
|
||||
},
|
||||
master: { widgets: ["PERSPECTIVE_GENERATED_ID_0"], sizes: [1] },
|
||||
viewers: {
|
||||
PERSPECTIVE_GENERATED_ID_0: {
|
||||
table: "superstore",
|
||||
},
|
||||
PERSPECTIVE_GENERATED_ID_1: {
|
||||
table: "superstore",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const empty_config = {
|
||||
detail: {},
|
||||
viewers: {},
|
||||
};
|
||||
|
||||
// const x = await page.evaluate(async (config) => {
|
||||
// const workspace = document.getElementById("workspace");
|
||||
// await workspace.restore(config);
|
||||
// await workspace.flush();
|
||||
// return workspace.outerHTML;
|
||||
// }, config);
|
||||
|
||||
// test.expect(x).toEqual(
|
||||
// `<perspective-workspace id=\"workspace\"><perspective-viewer slot=\"PERSPECTIVE_GENERATED_ID_1\" table=\"superstore\" theme=\"Pro Light\" class=\"lm-DockPanel-widget\"><perspective-viewer-datagrid data-edit-mode=\"READ_ONLY\" style=\"position: absolute; inset: 0px; opacity: 1;\" class=\"edit-mode-allowed\"></perspective-viewer-datagrid><perspective-viewer-datagrid-toolbar slot=\"statusbar-extra\"></perspective-viewer-datagrid-toolbar></perspective-viewer><perspective-viewer slot=\"PERSPECTIVE_GENERATED_ID_0\" table=\"superstore\" theme=\"Pro Light\" class=\"workspace-master-widget lm-SplitPanel-child\" selectable=\"\"><perspective-viewer-datagrid data-edit-mode=\"READ_ONLY\" style=\"position: absolute; inset: 0px; opacity: 1;\"></perspective-viewer-datagrid><perspective-viewer-datagrid-toolbar slot=\"statusbar-extra\"></perspective-viewer-datagrid-toolbar></perspective-viewer></perspective-workspace>`,
|
||||
// );
|
||||
|
||||
await page.evaluate(async (config) => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
await workspace.restore(config);
|
||||
await workspace.flush();
|
||||
}, empty_config);
|
||||
|
||||
return compare(
|
||||
page,
|
||||
`${context}-restore-a-blank-view-removes-master-panel.txt`,
|
||||
);
|
||||
});
|
||||
|
||||
test("restore a view which reuses a master viewer, removes master panel", async ({
|
||||
page,
|
||||
}) => {
|
||||
const config = {
|
||||
detail: {
|
||||
main: {
|
||||
type: "tab-area",
|
||||
widgets: ["PERSPECTIVE_GENERATED_ID_1"],
|
||||
currentIndex: 0,
|
||||
},
|
||||
},
|
||||
master: { widgets: ["PERSPECTIVE_GENERATED_ID_0"], sizes: [1] },
|
||||
viewers: {
|
||||
PERSPECTIVE_GENERATED_ID_0: {
|
||||
table: "superstore",
|
||||
title: "One",
|
||||
},
|
||||
PERSPECTIVE_GENERATED_ID_1: {
|
||||
table: "superstore",
|
||||
title: "Two",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const config2 = {
|
||||
detail: {
|
||||
main: {
|
||||
type: "split-area",
|
||||
orientation: "horizontal",
|
||||
children: [
|
||||
{
|
||||
type: "tab-area",
|
||||
widgets: ["PERSPECTIVE_GENERATED_ID_0"],
|
||||
currentIndex: 0,
|
||||
},
|
||||
{
|
||||
type: "tab-area",
|
||||
widgets: ["PERSPECTIVE_GENERATED_ID_1"],
|
||||
currentIndex: 0,
|
||||
},
|
||||
],
|
||||
sizes: [0.5, 0.5],
|
||||
},
|
||||
},
|
||||
master: { widgets: [], sizes: [] },
|
||||
viewers: {
|
||||
PERSPECTIVE_GENERATED_ID_0: {
|
||||
table: "superstore",
|
||||
title: "One",
|
||||
},
|
||||
PERSPECTIVE_GENERATED_ID_1: {
|
||||
table: "superstore",
|
||||
title: "Two",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// const x = await page.evaluate(async (config) => {
|
||||
// const workspace = document.getElementById("workspace");
|
||||
// await workspace.restore(config);
|
||||
// await workspace.flush();
|
||||
// return workspace.outerHTML;
|
||||
// }, config);
|
||||
|
||||
// test.expect(x).toEqual(
|
||||
// `<perspective-workspace id="workspace"><perspective-viewer slot="PERSPECTIVE_GENERATED_ID_1" table="superstore" theme="Pro Light" class="lm-DockPanel-widget"><perspective-viewer-datagrid data-edit-mode="READ_ONLY" style="position: absolute; inset: 0px; opacity: 1;" class="edit-mode-allowed"></perspective-viewer-datagrid><perspective-viewer-datagrid-toolbar slot="statusbar-extra"></perspective-viewer-datagrid-toolbar></perspective-viewer><perspective-viewer slot="PERSPECTIVE_GENERATED_ID_0" table="superstore" theme="Pro Light" class="workspace-master-widget lm-SplitPanel-child" selectable=""><perspective-viewer-datagrid data-edit-mode="READ_ONLY" style="position: absolute; inset: 0px; opacity: 1;"></perspective-viewer-datagrid><perspective-viewer-datagrid-toolbar slot="statusbar-extra"></perspective-viewer-datagrid-toolbar></perspective-viewer></perspective-workspace>`,
|
||||
// );
|
||||
|
||||
await page.evaluate(async (config) => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
await workspace.restore(config);
|
||||
await workspace.flush();
|
||||
}, config2);
|
||||
|
||||
return compare(
|
||||
page,
|
||||
`${context}-restore-which-reseats-master-viewer.txt`,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
test.describe("Workspace restore", () => {
|
||||
test.describe("Light DOM", () => {
|
||||
tests("light-dom", compareLightDOMContents);
|
||||
});
|
||||
|
||||
test.describe("Shadow DOM", () => {
|
||||
tests("shadow-dom", compareShadowDOMContents);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,164 @@
|
||||
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
||||
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
||||
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
||||
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
||||
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
||||
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
||||
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
||||
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
||||
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
||||
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
||||
|
||||
import { test, expect } from "@perspective-dev/test";
|
||||
import {
|
||||
compareLightDOMContents,
|
||||
compareShadowDOMContents,
|
||||
} from "@perspective-dev/test";
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto("/tools/test/src/html/workspace-test.html");
|
||||
await page.evaluate(async () => {
|
||||
while (!window["__TEST_PERSPECTIVE_READY__"]) {
|
||||
await new Promise((x) => setTimeout(x, 10));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function tests(context, compare) {
|
||||
// TODO: 3.x `Client` has no exact `replaceTable`
|
||||
test.skip("replaceTable() frees the `Table` before resolution", async ({
|
||||
page,
|
||||
}) => {
|
||||
const config = {
|
||||
viewers: {
|
||||
One: { table: "superstore", name: "One" },
|
||||
},
|
||||
detail: {
|
||||
main: {
|
||||
currentIndex: 0,
|
||||
type: "tab-area",
|
||||
widgets: ["One"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
await page.evaluate(async (config) => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
await workspace.restore(config);
|
||||
await workspace.replaceTable(
|
||||
"superstore",
|
||||
window.__WORKER__.table("x\n1"),
|
||||
);
|
||||
await window.__TABLE__.delete();
|
||||
}, config);
|
||||
|
||||
await page.evaluate(async () => {
|
||||
await workspace.flush();
|
||||
});
|
||||
|
||||
return compare(page, `${context}-replace-table-frees-table.txt`);
|
||||
});
|
||||
|
||||
test.skip("replaceTable() works when previous table errored", async ({
|
||||
page,
|
||||
}) => {
|
||||
const config = {
|
||||
viewers: {
|
||||
One: { table: "errored", name: "One" },
|
||||
},
|
||||
detail: {
|
||||
main: {
|
||||
currentIndex: 0,
|
||||
type: "tab-area",
|
||||
widgets: ["One"],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const result = await page.evaluate(async (config) => {
|
||||
const workspace = document.getElementById("workspace");
|
||||
await workspace.addTable(
|
||||
"errored",
|
||||
new Promise((_, reject) => setTimeout(reject, 50)),
|
||||
);
|
||||
|
||||
try {
|
||||
await workspace.restore(config);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return e.toString();
|
||||
}
|
||||
}, config);
|
||||
|
||||
// NOTE This is the error message we expect when `restore()` is called
|
||||
// without a `Table`, subject to change.
|
||||
expect(result).toEqual(
|
||||
"Error: Failed to construct table from JsValue(undefined)",
|
||||
);
|
||||
await page.evaluate(async () => {
|
||||
await workspace.replaceTable(
|
||||
"errored",
|
||||
window.__WORKER__.table("x\n1"),
|
||||
);
|
||||
});
|
||||
|
||||
await page.evaluate(async () => {
|
||||
await workspace.flush();
|
||||
});
|
||||
|
||||
return compare(
|
||||
page,
|
||||
`${context}-replace-table-works-with-errored-table.txt`,
|
||||
);
|
||||
});
|
||||
|
||||
test("removeTable() smoke test", async ({ page }) => {
|
||||
await page.evaluate(async () => {
|
||||
await window.__WORKER__.table("x\n1\n", { name: "temptable" });
|
||||
const workspace = document.getElementById("workspace");
|
||||
await workspace.load(window.__WORKER__);
|
||||
await workspace.restore({
|
||||
viewers: {
|
||||
One: { table: "temptable", name: "One" },
|
||||
},
|
||||
detail: {
|
||||
main: {
|
||||
currentIndex: 0,
|
||||
type: "tab-area",
|
||||
widgets: ["One"],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await workspace.flush();
|
||||
});
|
||||
|
||||
await page.evaluate(async () => {
|
||||
await workspace.restore({
|
||||
viewers: {},
|
||||
detail: {
|
||||
main: {
|
||||
currentIndex: 0,
|
||||
type: "tab-area",
|
||||
widgets: [],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await workspace.flush();
|
||||
});
|
||||
|
||||
return compare(page, `${context}-table-delete-works.txt`);
|
||||
});
|
||||
}
|
||||
|
||||
test.describe("Workspace table functions", () => {
|
||||
test.describe("Light DOM", () => {
|
||||
tests("light-dom", compareLightDOMContents);
|
||||
});
|
||||
|
||||
test.describe("Shadow DOM", () => {
|
||||
tests("shadow-dom", compareShadowDOMContents);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,113 @@
|
||||
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
|
||||
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
|
||||
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
|
||||
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
|
||||
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
|
||||
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
|
||||
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
|
||||
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
|
||||
// ┃ This file is part of the Perspective library, distributed under the terms ┃
|
||||
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
|
||||
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
|
||||
|
||||
import { test } from "@perspective-dev/test";
|
||||
import {
|
||||
compareLightDOMContents,
|
||||
compareShadowDOMContents,
|
||||
} from "@perspective-dev/test";
|
||||
|
||||
const BAD_LAYOUT = {
|
||||
sizes: [1],
|
||||
detail: {
|
||||
main: {
|
||||
type: "tab-area",
|
||||
widgets: [
|
||||
"PERSPECTIVE_GENERATED_ID_0",
|
||||
"PERSPECTIVE_GENERATED_ID_1",
|
||||
],
|
||||
currentIndex: 1,
|
||||
},
|
||||
},
|
||||
mode: "globalFilters",
|
||||
viewers: {
|
||||
PERSPECTIVE_GENERATED_ID_0: {
|
||||
plugin: "Sunburst",
|
||||
plugin_config: {},
|
||||
settings: false,
|
||||
theme: null,
|
||||
group_by: ["State"],
|
||||
split_by: [],
|
||||
columns: ["Quantity", null, null],
|
||||
filter: [],
|
||||
sort: [],
|
||||
expressions: {},
|
||||
aggregates: {},
|
||||
master: false,
|
||||
name: "one",
|
||||
table: "superstore",
|
||||
linked: false,
|
||||
},
|
||||
PERSPECTIVE_GENERATED_ID_1: {
|
||||
plugin: "Sunburst",
|
||||
plugin_config: {},
|
||||
settings: false,
|
||||
theme: null,
|
||||
group_by: ["State"],
|
||||
split_by: [],
|
||||
columns: ["Sales", null, null],
|
||||
filter: [],
|
||||
sort: [],
|
||||
expressions: {},
|
||||
aggregates: {},
|
||||
master: false,
|
||||
name: "two",
|
||||
table: "superstore",
|
||||
linked: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function tests(context, compare) {
|
||||
test.describe("visibility", () => {
|
||||
test("Sunburst charts do not loop forever when disconnected from DOM", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.evaluate(async (layout) => {
|
||||
await window.workspace.restore(layout);
|
||||
}, BAD_LAYOUT);
|
||||
|
||||
await page.evaluate(async () => {
|
||||
const viewer = document.body.querySelector(
|
||||
"perspective-viewer[slot=PERSPECTIVE_GENERATED_ID_0]",
|
||||
);
|
||||
const workspace = document.getElementById("workspace");
|
||||
workspace.removeChild(viewer);
|
||||
await workspace.flush();
|
||||
});
|
||||
|
||||
return compare(
|
||||
page,
|
||||
`sunburst-charts-does-not-loop-${context}.txt`,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto("/tools/test/src/html/workspace-test.html");
|
||||
await page.evaluate(async () => {
|
||||
while (!window["__TEST_PERSPECTIVE_READY__"]) {
|
||||
await new Promise((x) => setTimeout(x, 10));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test.describe("Workspace Visibility", () => {
|
||||
test.describe("Light DOM", () => {
|
||||
tests("light-dom", compareLightDOMContents);
|
||||
});
|
||||
|
||||
test.describe("Shadow DOM", () => {
|
||||
tests("shadow-dom", compareShadowDOMContents);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user