--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" width="27" height="27"><g fill="none" fill-rule="evenodd" transform="rotate(-90 13.5 18.5)"><path fill="#236A97" fill-rule="nonzero" d="M23.755102 18.5408163L19.7526885 14.5v3.0306122H12v2.0204082h7.7526885v3.0306123z"/><path d="M0 0h36v36H0z"/><circle cx="18.5" cy="18.5" r="12" stroke="#236A97" stroke-width="3"/></g></svg>
\ No newline at end of file
--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" width="56" height="76"><path fill="#236A97" fill-rule="nonzero" d="M17.0487743 26.4874701c-.2633309-.4728576-1.091713.3613828-1.79162.7607377-2.0687996.6851018-3.9790932-1.532657-4.4992041-4.0925528-.3969505-1.9537243.6064908-3.6941751 1.7771685-4.1474922 2.1227488-.8219843 3.5884107-.2877 4.1680091 2.8376465 1.1349544.0049922 1.9983633-.1127172 2.3897069-.6850429-.0684018-1.529288-.7478783-2.8505691-.7226231-4.0184879.0659164-3.0482709 1.46717-5.1785694.4644218-8.35489055.0664461-.87419458 2.0685712-3.12052482 4.7722246-4.86588792 1.9747258-1.27479955 3.7726433-2.2680363 6.5660309-2.29279903 2.423728-.02148573 4.703752.44235801 8.5545414 2.25344223.9477408.4457359 2.8432176 2.82299404 4.1298563 4.4905583.0345611.08007787.014399.0857984-.192986.05719856-1.8308574-.32752321-2.8607584.55403556-2.7853569 1.76171361.9885263-.77163072 2.8770115-.60270742 4.1852372.7550201 3.0931417 2.8159886 1.0480218 16.8814333-1.4373276 20.0309168-2.0538241 3.9080016-4.3234108 5.2699709-8.6354801 6.2460792-1.8609157.2797775-3.8362101-.0940405-5.7140137-1.1865931-2.1407315-1.2455341-4.4144694-3.503981-6.0553618-6.1948739.0187808 2.0723495 3.7764384 6.0576603 5.9342381 7.2376698-.9367737.0237142-2.4691968-.3932156-3.1200741.7386627-5.9998256-.1512471-6.5604195-1.8928926-8.2563742-5.9540435-.3390647-.8119272-.7232751-1.9810477-.756441-2.6943729-.4627059-1.3040079 1.3941192-1.5492592 1.0254278-2.6826088zm1.4114021-18.4179207c-.7504505.44015027-1.1164727-.15117563-2.4875059.28615942-1.4904753.47543417-1.7618711.51125029-1.7438222.42310144 1.1400862-3.0500199 7.9781043-6.31313247 8.6498836-5.70269013h.0028816c.2534771.20019524.0555727.54255567-.3888558.69496208-.269705.09248869-1.768848 1.30622226-2.1944501 1.75372426-.4601907.48386846-.9379839 1.74136047-1.8381312 2.54474293zm-6.552946 9.7466289c-.2453848-3.0207694-.3236691-5.386481 1.5237371-6.8752622 1.8657474-1.5035618 4.4617843-2.02415494 4.5452929-1.6015585h-.0028736c.7186455 2.3687677-.3154615 4.9265824-.2585473 7.8946002.0184245.960804.6820579 2.3650825.4947415 3.0188752-.1190424.2205283-.3172893.2902448-.6567364.3431914-.1298428-2.3835495-2.5874789-4.2332759-5.6456142-2.7798461zm32.4737865 34.630842c1.0554108-3.1369598 4.2353252-11.7545206 4.0642596-13.2528985.040128-1.658918-2.5599197-2.6618238-5.334522-5.7627521-.2239439-.3911208.1247224-1.0979212.5605312-1.8527667 1.9562556-3.0924062 2.7360681-8.5637912 3.0284629-13.0388633 9.9973171 10.8607839 7.8274932 25.1614774 3.1482943 32.2027661-3.3426731.4176008-5.4734514 2.0281428-5.467026 1.7045145zm-3.9864971-16.3044329c.0779954-.1555206 1.260896-1.1362674 1.4862967-1.3212856.4301278.2716838 1.38033 1.2429404 2.383406 2.1319682 1.1109469.9846328 2.2727537 1.9048948 2.5593899 2.4582061.1526616.3031561.1526616.3088738.1238546.8408196-.836367 4.9767902-3.0647228 10.5983295-4.0252504 12.2770078-.2847638.4976759-1.1681317.5097189-2.4528022.5583352-1.1838459.0486209-1.5813443.1058206-1.9413954.2859939-.2246724.1143994-.2880451.1201171-.2880451.0200188 0-.1000938 4.6173036-7.6760398 4.8074125-8.0478265.2808776-.2329702-.8649593-1.0602052-.8785271-1.5129012.5691258-1.4867022.7019038-3.7086756.1826514-5.4432341-.6463905-2.1592441-1.4993073-1.6584963-1.9569909-2.2471022zM7.42243884 42.1312658c2.96225546-2.586478 6.14876306-4.4512718 9.48232206-5.8428294.5016567.0859968 1.2529385 1.2522493 2.1113377 2.1363665.9583995.987113 3.0928106 2.0244973 5.5447976 3.1401973 1.0727713 4.0182114 1.3969963 6.8164438 3.2692673 6.0230073.1814641-.0657785.3600511-.1201171.3888559-.1201171.4755212.2040689-1.4584967 1.587195-.8468409 2.5596351.927405.9815222 3.901969 2.1249765 6.2677861 3.2202814-4.3627853.216851-9.7240752.8353422-12.6450164 1.0381506-.3479927-.3262174-.5738478-1.5709715-.1526594-6.5864073 0-1.1983142-.5789648-1.1897309-.8007555.0142966-.3498102.8189554.7433036 5.0602025-.2010874 6.2322951-.7221824-.1516801-1.6541154-1.166919-1.9736252-.9986391-.1152167.1773168-.0057598.4747507.308206.8379585.4796679.6176388.3551967 1.0049462-.4579872 1.1296701-.6279317.1344181-.9015687.3317491-.9015687.6663639-.1395094.3793679 1.7505102-.2829514 3.5342674.2173543.2443345 2.3134203.7231506 6.0003224 1.2126529 9.7494889-.9334102.1562189-2.6924146-.144593-5.3689015-1.2736192-1.3569528-.5724096-2.9659282-1.5385969-4.7903192-2.4042461-.200343-6.1900766-1.0420005-13.0804379-3.98073156-19.7392074zm33.34942636-4.1568963c1.0761987.6798942 1.2887029 4.6628109.5588004 5.5525415-1.6636188-.111969-3.5862152-.3158021-4.634591-.6463406l.0144058-1.5100401c.2330021-.2415718.7888386-.3189489 1.4641343-.335567.1722553-.0263259.0618314-.1123771-.7209905-.256435-.3190395-.0503213-.3024234-.0644636-.5357543-.0228799-.296683.0571997-.3686937.0085833-.4464653-.2659706-.2473759-.6561483-.3081684-.5911451-.0748878-.6806605 1.7038609-1.0030418 3.0355483-2.2834828 4.3753484-1.8346478zm-5.570723 1.5515014c-2.185086.1358646-2.8748468-.4421992-3.5372803-.9069699-.1847635-.1519839-.0382396-.2665147.2881729-.1941026 1.500481.5652363 3.0031449-.2086077 5.104091-.5147882.1092616.0026072.1216968.0972554-.0086357.1887613l-1.8463479 1.4270994zm-10.7900283.366069c-.0288047.2345164-.0432083.2516741-.1584226.2516741-2.0120338-.3476962-3.7995849-1.358682-3.5745951-1.9418921.0921728-.2950715.0477019-.2362622.6610565.0114399 1.2486549.4270956 3.4091261.2227999 3.2937519.5605479l-.2217907 1.1182302zm1.5928594-1.3184178c.528331-.508549 1.3135619-.2434308 3.3405929.4603 2.1563543.7486335 2.3527608 1.4729544 3.6588196 1.62458.0561572.2824799.1364588.3496232-.1526616.5033482-.6745057.2826975-.9914879.3036775-1.4488495.4375697-.2534725.0714962-.3110842.1916133-.0662497.1429924.2794002-.0571997 1.6764011.3346103 1.8204201.5090659.0483778.1974263.0158878.6200102-.0057632 1.0124142-1.0173949.6903864-1.5958346 1.4047092-2.4893247 1.9470792-1.6727499 1.0154068-3.4106559 1.5628416-3.8879125 1.1702382-1.2952561-2.9770501-1.932367-5.7144963-.7690714-7.8075878zm8.583643 4.0925506c-.3825812 0-.5086758.0036728-.592898-.1884484l-.3086707-1.4931862c-.0375089-.2543493.0086426-.3002905.1353811-.3632124.8101859-.491804 1.505968-.2981457 1.7599291.2945727.3145116.7340378.0616898 1.7664571-.9937415 1.7502743zm2.6931749 9.5121068c-1.4713976-2.4595278-2.2944343-5.4311004-4.0585054-7.8190368l.4925506-.6492017c1.0905427.2081633 1.2475496-.429535 2.1902373-.3751193.5379942.0310551 1.0523054.9250978 2.2427228 1.0128856-.1457864 3.9609981-.3897989 6.9955018-.8670053 7.8304722zm1.6090782-7.7096341c1.3227297-.7345955 2.8101361.0347732 3.3798098 1.1032127-1.610471 2.9352215-3.4830136 5.9623388-4.3829794 6.8766044.5539163-2.3396918.9406874-5.2615781 1.0031696-7.9798171zm-10.4749847 4.7267303c.558451-2.0553211 2.0712576-2.9049145 3.9116025-4.0982773 1.4246776 1.5691577 2.6177963 4.4670215 3.8050284 7.3986337-.2971831.24412-5.4596849-1.8637622-7.7166309-3.3003564zm23.1182041 12.895413c-1.3330231.5543042-4.0072895.5021466-4.1852372.1315615.0739037-.3542844 3.1411702-.7231918 3.1396495-.8608383-.6133912-.3748428-2.7728487-.3046524-5.4785479-.077223-.270648-2.6463211-.537597-5.3210721-.9793426-6.6521858.7334235-.8522005 3.4006662-1.4868246 4.5191437-1.9646812.815803-.3485441 2.1127077-1.3390668 3.4019951.8207101.9678298 2.8423689 2.7158877 6.8163441-.4176606 8.6026567zm-9.3987815-.1401404c-.1433729-1.4407521-.5979511-4.2829396-.9707023-7.1269364.0110378-.0756541-.1462499-.1899945 1.5642693-.1007512.9756754 1.6290689 1.2601698 4.0207551 1.2412544 6.7472193-.8914739.3505799-1.4238694.4422762-1.8348214.4804683zM24.6559484 73.4016815c-1.8657839-5.9032529-3.0647183-11.7852764-3.5861148-17.6457396 4.4640711-.8617996 10.0507435-1.5304034 15.1941792-.643475.7175837 8.3497085.7617578 15.8041862 1.3480363 18.5580554-3.4600635.9393037-7.5809416 1.0867443-12.9561007-.2688408zm12.9647364-9.9096299c-.2218158-2.9470242-.3887851-5.8165669-.3226039-8.3567048.6615704-.1614876 1.3503996-.2862705 2.2747495-.1747186.5406201 2.071853.6619904 5.487357.888204 7.8893586.0043704.0464353.0030917.1411424-.0233041.1901941-1.1417039.2140125-2.6601893.5458614-2.8170455.4518707zm2.7940109 6.8009004c-.8881082.3303344-1.7105329.5320546-2.4109114.4947649-.1643206-2.1891635-.2022245-4.4026532-.2534748-5.9429278 1.1125659-.0275274 1.9020826-.6572183 1.8549904.0600654.2541758 1.6986744.8236669 3.3178768.8093958 5.3880975zm.8612375-52.6483682c-.1872274.0486197-.2073895.0657774-.2073895.1944744 0 .4575884.3312441.8751371.7949877 1.0124141.7517909.2144932 2.0422154-.1773156 2.7219934-.8179397.4176606-.4003899.4118974-.37179.0720084-.9323357-.2765209-.4518684-.8324396-1.5557987-1.4142792-2.8084481-.1296224-.2859928-.2506-.514787-.2678805-.514787-.0230438 0-.0360042.1673074-.0360042.3675006 0 .6463429.1598679 1.2855387.5861688 2.3437103.1296179.3231715.2304333.632043.2189114.6892427-.047622.3048632-1.7124007.2862909-2.4685163.4661684zm-8.8054178-.674945c-.6048834-.6291842-.7345035-.8379596-1.2068942-1.9418898-.1785871-.4146899-.5357612-1.1697088-.5357612-1.1697088-.3586149 1.3439377 1.1471681 3.4797556 1.3221155 4.0782541-.1473871.3515298-.8972714.4688277-1.686263.3515298-1.1793841-.1753364-1.6776272-.344411-1.750074-.0969969-.1583062.3134421-.1793109.5622358.0695743.8514627.5033395.584924 2.0079877.7810739 3.0671136.5706162.5009488-.0995429.7407462-.3381674 1.0283939-.5784016.4119202-.3440245.5241525-.9569113.2809826-1.3840749-.1231057-.2162525-.3522101-.4109649-.5891875-.6807908zm2.4483473 10.2070751c3.5064365.196941 5.3796962-1.1430348 7.4055398-2.3394175.0751549-.4534056.3155985-1.0462102.4608666-1.5929808.0950567-.4575862.0576094-.5290869-.7517864-1.3184268-2.0854214-2.0276848-4.3580678-5.1621667-4.6288254-6.3947939-.1719059-.8159288-.6864408-.820938-.599127-.2087743-.0130198 2.2932077 2.1214256 4.9591893 4.0786677 7.0954765.5821227.5774902.8298593 1.3924554.146903 2.2450436-1.2912055.6016759-2.579438 1.2011618-3.3412803 1.4128052-2.725544.4427795-2.5725262.0994839-3.0445949-1.5701032 0-.0085788-.0172852-.0200187-.0489669-.0200187-.2396513.1542918-.8132822 1.5595995.3226038 2.6911899zm-18.9272026-3.7121806c.5120563-3.2591491-3.2341125-4.7353352-3.8154246-2.0384129.0684612.2191362.3203958-.6146734 1.1193578-.3667876-.4047299 1.4989357-.30906 2.6578608.2144074 3.5278289.1771645.219805.0729697-1.9784269.2378166-2.4439163.2146791-.578057.6621457-.8122356 1.0242599-.5554809.3348872.2374501.7232739 1.3000631 1.2195829 1.8767688zM37.977868 29.985162c.0058957-.6745097-.0058591-1.3032075-.1008131-1.7159567-2.5228263-.0387385-5.4137344-.0493554-7.1319052-.8579772-.0777716-.0343199-.0720107-.0042895.0489646.2216437.6669865 1.320313 3.4760563 2.5471818 7.1837537 2.3522902zm-8.3186418-.5205058c.605251.5591037 1.2321735 1.5441173 1.797381 2.2164415 1.5968598 1.9539169 5.8118059 1.4710364 7.0598944.6377641.1497801-.1229782.4925506-.6005854.4925506-.6806627-4.1099886-.0213768-7.289903.2138719-8.6412433-2.3079588-.1630898-.3833694-.2429941-.3504598-.5720645-.2768302-.3105339.0694807-.2772858.2201542-.1365182.4112461zm19.8505261 24.8374977c-.7082744-.0782477-2.9402106.3236555-3.846942 1.6425538 1.1316115.177081 2.5202484-1.1793474 3.846942-1.6425538zm.879815 2.3975761c.1807562-.0576803-1.3810242-.4067458-2.5775565-.3445675-.6858425.0356393-1.3818187.3913883-1.2303536.5447597.7647057.0825235 2.1757607-.0261355 3.8079101-.2001922zm.37445 2.0334071c-1.2844649-.396648-3.5702567-.7666799-4.297579-.0858018.204348.1373155 4.7274557.2154227 4.297579.0858018zM10.00905 17.2442234c.4131133-.5564388.4900949.7719747.3360872 1.1800536-2.26958619 2.8168025-.64580712 9.8906178 4.1429491 10.7114866-.0527059 2.1839014 1.7782406 4.0514339 1.7922055 5.0245428.0131558.9233499-2.643008 1.7219601-8.20474079 5.4054705-1.01301658.6709164-2.16982393.9905273-2.26615024 2.0049455-.14060831 1.7961928 3.26377063 7.4421808 3.76758284 14.0451018-7.74279379-6.602921-13.29829129-25.1133417.43206639-38.3716008zm11.3344206 49.95143c.7744808 2.7034618 1.5656256 5.539773 2.540527 7.8562177 4.1938386 1.2252114 8.3597722 1.0468518 12.3713795.6577851 1.7400089-.2462784 2.3531033-.8003196 2.67046-1.6274548.0736981-.1920849-.1473962-.978711-.1212927-1.8530705 1.3465269-.278195 2.5070002-.3087876 2.9177925-1.6649395.3717465-1.2272791-1.1306023-4.8176195-.5932976-6.1483841.7907772-.1828803 1.3238805-.563613 1.2385829-1.3870664.8995479-.5029854 2.2333473-.6780895 3.8107871-.6692205.1209867.2266949.2695702.4509186.4522262.6720862.1785871.2059143.1872274.2087754.679778.2945727 1.5064589.2573964 2.3908406.2226684 4.2313293.0142965 2.9667936-.3240363 3.6401873-5.0599803 2.8055191-7.278503-.4205377-1.4499839-.9678207-2.9257087-1.376841-3.7121852-.6888338-1.1635772-1.1668804-1.1161126-1.3509111-1.3699042 6.1624679-10.1759497 5.1983554-25.3322172-5.0119272-34.8939595-.1491178-6.56000758-2.9313374-10.88118462-8.5286046-14.55627608-3.0926211-2.03057428-12.370489-2.17915292-16.7556673.40250145-3.8552272 2.07365627-7.4997837 3.46897675-8.5519475 7.22703241-2.0096215 1.14435482-2.545466 3.32852382-2.6701461 5.80279012-13.67288175 11.6898471-13.14913114 31.9336859-.34277054 43.1705844.19339699 2.1792606-.08949447 4.8812579.69418034 5.3966763 1.3862439.792693 2.8089087 1.2135222 3.9831199 1.8179844 1.9821925 1.020399 3.7363561 1.9764568 6.9077238 1.8484365zm7.9065686-56.6769982c.2992861-.1857233.3606471-1.38743884-1.4839585-1.54769376-.5022504-.04363432-1.4704433.40739137-2.2695867 1.07719506-.9602103.8048006-1.3603391 1.5809877-1.5712519 2.2658242-.0901726.2927942-.1088871.5476445-.0862246.748247.0238726.2113237.2608089.4837171.3231587.4775267.457599-.0454344.9477407-3.6401765 5.087863-3.0210992zm9.4623346 17.6904915c-.043206.0714985-.0518462 1.2183285-.0086449 1.4757226.0288071.1773168.0374473.1801733.2304333.1801733 2.3590241-.1859341 3.7712802-1.9131607 4.6201829-3.6149456-4.1535211 2.3084802-4.3352318 1.6143485-4.8419713 1.9590497zm-1.955767 17.3298377c0-.4171746-.4541626-.6793274-.8155312-.4707378-.3613687.2085896-.3613664.7328906 0 .9414802.3613686.2085895.8155312-.0535633.8155312-.4707424zm.5558502 2.590917c0-.4113662-.4514727-.6698689-.8107019-.4641858-.3592291.2056831-.3592291.722684 0 .9283671.3592292.2056831.8107019-.0528151.8107019-.4641813z"/></svg>
\ No newline at end of file
--- /dev/null
+<svg xmlns="http://www.w3.org/2000/svg" width="28" height="28"><g fill="none" fill-rule="evenodd" transform="translate(-4 -4)"><path d="M0 0h36v36H0z"/><path fill="#236A97" fill-rule="nonzero" d="M31.3333333 15.2148148H21.28821l4.0595336-4.1777778c-4.0447178-3.99999996-10.5933086-4.14814811-14.6380264-.1481481-4.04471779 4.0148148-4.04471779 10.4888889 0 14.5037037 4.0447178 4.0148148 10.5933086 4.0148148 14.6380264 0 2.014951-1.9851852 3.0224265-4.3111111 3.0224265-7.2444445h2.9631632c0 2.9333334-1.3037918 6.7407408-3.9113754 9.3185186-5.2003515 5.1555555-13.6453667 5.1555555-18.84571821 0-5.18553566-5.1407408-5.2299831-13.4962963-.02963163-18.63703707 5.20035144-5.14074074 13.54165594-5.14074074 18.74200744 0l4.0447178-4.16296296V15.2148148zm-12.5934437-3.1407407v6.2962963l5.1855356 3.0814815-1.0667387 1.7925925-6.3411693-3.7629629v-7.4074074h2.2223724z"/></g></svg>
\ No newline at end of file
} from '../types/alm-settings';
export function getAlmDefinitions(): Promise<AlmSettingsBindingDefinitions> {
- return getJSON('/api/alm_settings/list_definitions').catch(throwGlobalError);
+ return getAlmDefinitionsNoCatch().catch(throwGlobalError);
+}
+
+export function getAlmDefinitionsNoCatch(): Promise<AlmSettingsBindingDefinitions> {
+ return getJSON('/api/alm_settings/list_definitions');
}
export function getAlmSettings(project?: string): Promise<AlmSettingsInstance[]> {
import { connect } from 'react-redux';
import { Alert } from 'sonar-ui-common/components/ui/Alert';
import { translate } from 'sonar-ui-common/helpers/l10n';
-import AnalyzeTutorial from '../../../components/tutorials/manual/AnalyzeTutorial';
+import TutorialSelection from '../../../components/tutorials/TutorialSelection';
import { getBranchLikeDisplayName, isBranch, isMainBranch } from '../../../helpers/branch-like';
import { isLoggedIn } from '../../../helpers/users';
import { getCurrentUser, Store } from '../../../store/rootReducer';
{isLoggedIn(currentUser) ? (
<>
{showWarning && <Alert variant="warning">{warning}</Alert>}
- {showTutorial && <AnalyzeTutorial component={component} currentUser={currentUser} />}
+ {showTutorial && <TutorialSelection component={component} currentUser={currentUser} />}
</>
) : (
<Alert variant="warning">{warning}</Alert>
<div
className="page page-limited"
>
- <AnalyzeTutorial
+ <withRouter(TutorialSelection)
component={
Object {
"breadcrumbs": Array [],
font-size: 11px;
font-weight: normal;
user-select: none;
+ background: var(--gray40);
}
.code-snippet > button:hover,
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { WithRouterProps } from 'react-router';
+import { getAlmDefinitionsNoCatch, getProjectAlmBinding } from '../../api/alm-settings';
+import { AlmBindingDefinition, AlmKeys, ProjectAlmBindingResponse } from '../../types/alm-settings';
+import { withRouter } from '../hoc/withRouter';
+import './styles.css';
+import TutorialSelectionRenderer from './TutorialSelectionRenderer';
+import { TutorialModes } from './types';
+
+interface Props extends Pick<WithRouterProps, 'router' | 'location'> {
+ component: T.Component;
+ currentUser: T.LoggedInUser;
+}
+
+interface State {
+ almBinding?: AlmBindingDefinition;
+ forceManual: boolean;
+ loading: boolean;
+ projectBinding?: ProjectAlmBindingResponse;
+}
+
+export class TutorialSelection extends React.PureComponent<Props, State> {
+ mounted = false;
+ state: State = {
+ forceManual: true,
+ loading: true
+ };
+
+ componentDidMount() {
+ this.mounted = true;
+ this.fetchAlmBindings();
+ }
+
+ fetchAlmBindings = async () => {
+ const { component } = this.props;
+
+ const [almDefinitions, projectBinding] = await Promise.all([
+ getAlmDefinitionsNoCatch().catch(() => undefined),
+ getProjectAlmBinding(component.key).catch(() => undefined)
+ ]);
+
+ if (this.mounted) {
+ // We only support Bitbucket for now.
+ if (projectBinding === undefined || projectBinding.alm !== AlmKeys.Bitbucket) {
+ this.setState({ loading: false, forceManual: true });
+ } else {
+ let almBinding;
+ if (almDefinitions !== undefined) {
+ almBinding = almDefinitions[projectBinding.alm].find(d => d.key === projectBinding.key);
+ }
+ this.setState({ almBinding, forceManual: false, projectBinding, loading: false });
+ }
+ }
+ };
+
+ handleSelectTutorial = (selectedTutorial: TutorialModes) => {
+ const {
+ router,
+ location: { pathname, query }
+ } = this.props;
+
+ router.push({
+ pathname,
+ query: { ...query, selectedTutorial }
+ });
+ };
+
+ render() {
+ const { component, currentUser, location } = this.props;
+ const { almBinding, forceManual, loading, projectBinding } = this.state;
+
+ const selectedTutorial: TutorialModes | undefined = forceManual
+ ? TutorialModes.Manual
+ : location.query?.selectedTutorial;
+
+ return (
+ <TutorialSelectionRenderer
+ almBinding={almBinding}
+ component={component}
+ currentUser={currentUser}
+ loading={loading}
+ onSelectTutorial={this.handleSelectTutorial}
+ projectBinding={projectBinding}
+ selectedTutorial={selectedTutorial}
+ />
+ );
+ }
+}
+
+export default withRouter(TutorialSelection);
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import * as React from 'react';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
+import { AlmBindingDefinition, ProjectAlmBindingResponse } from '../../types/alm-settings';
+import JenkinsTutorial from './jenkins/JenkinsTutorial';
+import ManualTutorial from './manual/ManualTutorial';
+import { TutorialModes } from './types';
+
+export interface TutorialSelectionRendererProps {
+ almBinding?: AlmBindingDefinition;
+ component: T.Component;
+ currentUser: T.LoggedInUser;
+ loading: boolean;
+ onSelectTutorial: (mode: TutorialModes) => void;
+ projectBinding?: ProjectAlmBindingResponse;
+ selectedTutorial?: TutorialModes;
+}
+
+export default function TutorialSelectionRenderer(props: TutorialSelectionRendererProps) {
+ const { almBinding, component, currentUser, loading, projectBinding, selectedTutorial } = props;
+
+ if (loading) {
+ return <i className="spinner" />;
+ }
+
+ return (
+ <>
+ {selectedTutorial === undefined && (
+ <div className="tutorial-selection">
+ <header className="spacer-top spacer-bottom padded">
+ <h1 className="text-center big-spacer-bottom">
+ {translate('onboarding.tutorial.choose_method')}
+ </h1>
+ </header>
+
+ <div className="display-flex-space-around">
+ <button
+ className="button button-huge display-flex-column tutorial-mode-jenkins"
+ onClick={() => props.onSelectTutorial(TutorialModes.Jenkins)}
+ type="button">
+ <img
+ alt="" // Should be ignored by screen readers
+ height={80}
+ src={`${getBaseUrl()}/images/tutorials/jenkins.svg`}
+ />
+ <div className="medium big-spacer-top">
+ {translate('onboarding.tutorial.choose_method.jenkins')}
+ </div>
+ </button>
+
+ <button
+ className="button button-huge display-flex-column tutorial-mode-manual"
+ onClick={() => props.onSelectTutorial(TutorialModes.Manual)}
+ type="button">
+ <img
+ alt="" // Should be ignored by screen readers
+ height={80}
+ src={`${getBaseUrl()}/images/sonarcloud/analysis/manual.svg`}
+ />
+ <div className="medium big-spacer-top">
+ {translate('onboarding.tutorial.choose_method.manual')}
+ </div>
+ </button>
+ </div>
+ </div>
+ )}
+
+ {selectedTutorial === TutorialModes.Manual && (
+ <ManualTutorial component={component} currentUser={currentUser} />
+ )}
+
+ {selectedTutorial === TutorialModes.Jenkins && projectBinding !== undefined && (
+ <JenkinsTutorial
+ almBinding={almBinding}
+ component={component}
+ projectBinding={projectBinding}
+ />
+ )}
+ </>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import { waitAndUpdate } from 'sonar-ui-common/helpers/testUtils';
+import { getAlmDefinitionsNoCatch, getProjectAlmBinding } from '../../../api/alm-settings';
+import { mockBitbucketBindingDefinition } from '../../../helpers/mocks/alm-settings';
+import {
+ mockComponent,
+ mockLocation,
+ mockLoggedInUser,
+ mockRouter
+} from '../../../helpers/testMocks';
+import { AlmKeys } from '../../../types/alm-settings';
+import { TutorialSelection } from '../TutorialSelection';
+import { TutorialModes } from '../types';
+
+jest.mock('../../../api/alm-settings', () => ({
+ getProjectAlmBinding: jest.fn().mockRejectedValue(null),
+ getAlmDefinitionsNoCatch: jest.fn().mockRejectedValue(null)
+}));
+
+beforeEach(jest.clearAllMocks);
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+it('should select manual if project is not bound', async () => {
+ const wrapper = shallowRender();
+ await waitAndUpdate(wrapper);
+ expect(wrapper.state().forceManual).toBe(true);
+});
+
+it('should not select anything if project is bound to Bitbucket', async () => {
+ (getProjectAlmBinding as jest.Mock).mockResolvedValueOnce({ alm: AlmKeys.Bitbucket });
+ const wrapper = shallowRender();
+ await waitAndUpdate(wrapper);
+ expect(wrapper.state().forceManual).toBe(false);
+});
+
+it('should select manual if project is bound to any other ALM', async () => {
+ (getProjectAlmBinding as jest.Mock).mockResolvedValueOnce({ alm: AlmKeys.GitLab });
+ const wrapper = shallowRender();
+ await waitAndUpdate(wrapper);
+ expect(wrapper.state().forceManual).toBe(true);
+});
+
+it('should correctly find the global ALM binding definition', async () => {
+ const key = 'foo';
+ const almBinding = mockBitbucketBindingDefinition({ key });
+ (getProjectAlmBinding as jest.Mock).mockResolvedValueOnce({ alm: AlmKeys.Bitbucket, key });
+ (getAlmDefinitionsNoCatch as jest.Mock).mockResolvedValueOnce({
+ [AlmKeys.Bitbucket]: [almBinding]
+ });
+ const wrapper = shallowRender();
+ await waitAndUpdate(wrapper);
+ expect(wrapper.state().almBinding).toBe(almBinding);
+});
+
+it('should handle selection', () => {
+ const push = jest.fn();
+ const wrapper = shallowRender({ router: mockRouter({ push }) });
+ const instance = wrapper.instance();
+
+ instance.handleSelectTutorial(TutorialModes.Manual);
+ expect(push).toHaveBeenLastCalledWith(
+ expect.objectContaining({
+ query: { selectedTutorial: TutorialModes.Manual }
+ })
+ );
+
+ instance.handleSelectTutorial(TutorialModes.Jenkins);
+ expect(push).toHaveBeenLastCalledWith(
+ expect.objectContaining({
+ query: { selectedTutorial: TutorialModes.Jenkins }
+ })
+ );
+});
+
+function shallowRender(props: Partial<TutorialSelection['props']> = {}) {
+ return shallow<TutorialSelection>(
+ <TutorialSelection
+ component={mockComponent()}
+ currentUser={mockLoggedInUser()}
+ location={mockLocation()}
+ router={mockRouter()}
+ {...props}
+ />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import { click } from 'sonar-ui-common/helpers/testUtils';
+import {
+ mockBitbucketBindingDefinition,
+ mockProjectBitbucketBindingGet
+} from '../../../helpers/mocks/alm-settings';
+import { mockComponent, mockLoggedInUser } from '../../../helpers/testMocks';
+import TutorialSelectionRenderer, {
+ TutorialSelectionRendererProps
+} from '../TutorialSelectionRenderer';
+import { TutorialModes } from '../types';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot('selection');
+ expect(shallowRender({ loading: true })).toMatchSnapshot('loading');
+ expect(shallowRender({ selectedTutorial: TutorialModes.Manual })).toMatchSnapshot(
+ 'manual tutorial'
+ );
+ expect(
+ shallowRender({
+ selectedTutorial: TutorialModes.Jenkins,
+ projectBinding: mockProjectBitbucketBindingGet()
+ })
+ ).toMatchSnapshot('jenkins tutorial');
+});
+
+it('should allow mode selection', () => {
+ const onSelectTutorial = jest.fn();
+ const wrapper = shallowRender({ onSelectTutorial });
+
+ click(wrapper.find('button.tutorial-mode-jenkins'));
+ expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Jenkins);
+
+ click(wrapper.find('button.tutorial-mode-manual'));
+ expect(onSelectTutorial).toHaveBeenLastCalledWith(TutorialModes.Manual);
+});
+
+function shallowRender(props: Partial<TutorialSelectionRendererProps> = {}) {
+ return shallow<TutorialSelectionRendererProps>(
+ <TutorialSelectionRenderer
+ almBinding={mockBitbucketBindingDefinition()}
+ component={mockComponent()}
+ currentUser={mockLoggedInUser()}
+ loading={false}
+ onSelectTutorial={jest.fn()}
+ {...props}
+ />
+ );
+}
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<TutorialSelectionRenderer
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ currentUser={
+ Object {
+ "groups": Array [],
+ "isLoggedIn": true,
+ "login": "luke",
+ "name": "Skywalker",
+ "scmAccounts": Array [],
+ }
+ }
+ loading={true}
+ onSelectTutorial={[Function]}
+ selectedTutorial="manual"
+/>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly: jenkins tutorial 1`] = `
+<Fragment>
+ <JenkinsTutorial
+ almBinding={
+ Object {
+ "key": "key",
+ "personalAccessToken": "asdf1234",
+ "url": "http://bbs.enterprise.com",
+ }
+ }
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ projectBinding={
+ Object {
+ "alm": "bitbucket",
+ "key": "foo",
+ "repository": "PROJECT_KEY",
+ "slug": "repo-slug",
+ }
+ }
+ />
+</Fragment>
+`;
+
+exports[`should render correctly: loading 1`] = `
+<i
+ className="spinner"
+/>
+`;
+
+exports[`should render correctly: manual tutorial 1`] = `
+<Fragment>
+ <ManualTutorial
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ currentUser={
+ Object {
+ "groups": Array [],
+ "isLoggedIn": true,
+ "login": "luke",
+ "name": "Skywalker",
+ "scmAccounts": Array [],
+ }
+ }
+ />
+</Fragment>
+`;
+
+exports[`should render correctly: selection 1`] = `
+<Fragment>
+ <div
+ className="tutorial-selection"
+ >
+ <header
+ className="spacer-top spacer-bottom padded"
+ >
+ <h1
+ className="text-center big-spacer-bottom"
+ >
+ onboarding.tutorial.choose_method
+ </h1>
+ </header>
+ <div
+ className="display-flex-space-around"
+ >
+ <button
+ className="button button-huge display-flex-column tutorial-mode-jenkins"
+ onClick={[Function]}
+ type="button"
+ >
+ <img
+ alt=""
+ height={80}
+ src="/images/tutorials/jenkins.svg"
+ />
+ <div
+ className="medium big-spacer-top"
+ >
+ onboarding.tutorial.choose_method.jenkins
+ </div>
+ </button>
+ <button
+ className="button button-huge display-flex-column tutorial-mode-manual"
+ onClick={[Function]}
+ type="button"
+ >
+ <img
+ alt=""
+ height={80}
+ src="/images/sonarcloud/analysis/manual.svg"
+ />
+ <div
+ className="medium big-spacer-top"
+ >
+ onboarding.tutorial.choose_method.manual
+ </div>
+ </button>
+ </div>
+ </div>
+</Fragment>
+`;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+
+export interface LabelActionPairProps {
+ translationKey: string;
+}
+
+export default function LabelActionPair({ translationKey }: LabelActionPairProps) {
+ return (
+ <>
+ <strong>{translate(translationKey, 'label')}:</strong> {translate(translationKey, 'action')}
+ </>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { ClipboardIconButton } from 'sonar-ui-common/components/controls/clipboard';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+
+export interface LabelValuePairProps {
+ translationKey: string;
+ value: string;
+}
+
+export default function LabelValuePair({ translationKey, value }: LabelValuePairProps) {
+ return (
+ <div className="display-flex-center">
+ <strong className="little-spacer-right">{translate(translationKey, 'label')}:</strong> {value}
+ <ClipboardIconButton className="little-spacer-left" copyValue={value} />
+ </div>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+
+export interface SentenceWithFilenameProps {
+ filename: string;
+ translationKey: string;
+}
+
+export default function SentenceWithFilename({
+ filename,
+ translationKey
+}: SentenceWithFilenameProps) {
+ return (
+ <span className="markdown">
+ <FormattedMessage
+ defaultMessage={translate(translationKey, 'sentence')}
+ id={`${translationKey}.sentence`}
+ values={{
+ file: <code>{filename}</code>
+ }}
+ />
+ </span>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+
+export interface SentenceWithHighlightsProps {
+ highlightKeys: string[];
+ translationKey: string;
+}
+
+export default function SentenceWithHighlights({
+ highlightKeys,
+ translationKey
+}: SentenceWithHighlightsProps) {
+ const values: T.Dict<JSX.Element> = {};
+ highlightKeys.forEach(key => {
+ values[key] = <strong>{translate(translationKey, 'sentence', key)}</strong>;
+ });
+ return (
+ <FormattedMessage
+ defaultMessage={translate(translationKey, 'sentence')}
+ id={`${translationKey}.sentence`}
+ values={values}
+ />
+ );
+}
.onboarding-step {
position: relative;
padding-left: 34px;
+ margin-bottom: var(--gridSize);
+}
+
+.onboarding-step.no-step-number {
+ padding-left: 0;
}
.onboarding-step:not(.is-open):not(.is-finished) {
cursor: pointer;
outline: none;
}
+
+.onboarding-step ol.list-styled {
+ list-style: none;
+ padding-left: 0;
+ counter-reset: step-counter;
+}
+
+.onboarding-step .markdown {
+ line-height: inherit;
+}
+
+.onboarding-step ul.list-styled li {
+ margin-top: var(--gridSize);
+ margin-bottom: var(--gridSize);
+}
+
+.onboarding-step ol.list-styled > li {
+ position: relative;
+ counter-increment: step-counter;
+ margin-bottom: calc(2 * var(--gridSize));
+ padding-left: calc(4 * var(--gridSize));
+}
+
+.onboarding-step ol.list-styled > li::before {
+ content: counter(step-counter);
+ color: white;
+ background-color: var(--blue);
+ display: inline-flex;
+ border-radius: 50%;
+ width: 16px;
+ position: absolute;
+ left: 0;
+ font-size: 10px;
+ height: 16px;
+ justify-content: center;
+ align-items: center;
+}
interface Props {
finished?: boolean;
- onOpen: VoidFunction;
+ onOpen?: VoidFunction;
open: boolean;
renderForm: () => React.ReactNode;
- renderResult: () => React.ReactNode;
- stepNumber: number;
+ renderResult?: () => React.ReactNode;
+ stepNumber?: number;
stepTitle: React.ReactNode;
}
export default function Step(props: Props) {
+ const { finished, open, stepNumber, stepTitle } = props;
const className = classNames('boxed-group', 'onboarding-step', {
- 'is-open': props.open,
- 'is-finished': props.finished
+ 'is-open': open,
+ 'is-finished': finished,
+ 'no-step-number': stepNumber === undefined
});
- const clickable = !props.open && props.finished;
+ const clickable = !open && finished && props.onOpen !== undefined;
const handleClick = (event: React.MouseEvent<HTMLDivElement>) => {
event.preventDefault();
- props.onOpen();
+ if (props.onOpen !== undefined) {
+ props.onOpen();
+ }
};
return (
onClick={clickable ? handleClick : undefined}
role={clickable ? 'button' : undefined}
tabIndex={clickable ? 0 : undefined}>
- <div className="onboarding-step-number">{props.stepNumber}</div>
- {!props.open && props.renderResult()}
+ {stepNumber !== undefined && <div className="onboarding-step-number">{stepNumber}</div>}
+ {!open && props.renderResult && props.renderResult()}
<div className="boxed-group-header">
- <h2>{props.stepTitle}</h2>
+ <h2>{stepTitle}</h2>
</div>
- {!props.open && <div className="boxed-group-inner" />}
- <div className={classNames({ hidden: !props.open })}>{props.renderForm()}</div>
+ {!open && <div className="boxed-group-inner" />}
+ <div className={classNames({ hidden: !open })}>{props.renderForm()}</div>
</div>
);
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import LabelActionPair, { LabelActionPairProps } from '../LabelActionPair';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<LabelActionPairProps> = {}) {
+ return shallow<LabelActionPairProps>(<LabelActionPair translationKey="foo" {...props} />);
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import LabelValuePair, { LabelValuePairProps } from '../LabelValuePair';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<LabelValuePairProps> = {}) {
+ return shallow<LabelValuePairProps>(
+ <LabelValuePair translationKey="foo" value="bar" {...props} />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import SentenceWithFilename, { SentenceWithFilenameProps } from '../SentenceWithFilename';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<SentenceWithFilenameProps> = {}) {
+ return shallow<SentenceWithFilenameProps>(
+ <SentenceWithFilename filename="foo.txt" translationKey="bar" {...props} />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import SentenceWithHighlights, { SentenceWithHighlightsProps } from '../SentenceWithHighlights';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<SentenceWithHighlightsProps> = {}) {
+ return shallow<SentenceWithHighlightsProps>(
+ <SentenceWithHighlights highlightKeys={['hello', 'world']} translationKey="foo" {...props} />
+ );
+}
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Fragment>
+ <strong>
+ foo.label
+ :
+ </strong>
+
+ foo.action
+</Fragment>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<div
+ className="display-flex-center"
+>
+ <strong
+ className="little-spacer-right"
+ >
+ foo.label
+ :
+ </strong>
+
+ bar
+ <ClipboardIconButton
+ className="little-spacer-left"
+ copyValue="bar"
+ />
+</div>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<span
+ className="markdown"
+>
+ <FormattedMessage
+ defaultMessage="bar.sentence"
+ id="bar.sentence"
+ values={
+ Object {
+ "file": <code>
+ foo.txt
+ </code>,
+ }
+ }
+ />
+</span>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<FormattedMessage
+ defaultMessage="foo.sentence"
+ id="foo.sentence"
+ values={
+ Object {
+ "hello": <strong>
+ foo.sentence.hello
+ </strong>,
+ "world": <strong>
+ foo.sentence.world
+ </strong>,
+ }
+ }
+/>
+`;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { Button, ButtonLink } from 'sonar-ui-common/components/controls/buttons';
+import { Alert } from 'sonar-ui-common/components/ui/Alert';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import {
+ BitbucketBindingDefinition,
+ ProjectBitbucketBindingResponse
+} from '../../../types/alm-settings';
+import CodeSnippet from '../../common/CodeSnippet';
+import LabelActionPair from '../components/LabelActionPair';
+import SentenceWithHighlights from '../components/SentenceWithHighlights';
+import Step from '../components/Step';
+
+export interface BitbucketWebhookStepProps {
+ almBinding?: BitbucketBindingDefinition;
+ finished: boolean;
+ onDone: () => void;
+ onOpen: () => void;
+ open: boolean;
+ projectBinding: ProjectBitbucketBindingResponse;
+}
+
+export default function BitbucketWebhookStep(props: BitbucketWebhookStepProps) {
+ const { almBinding, finished, open, projectBinding } = props;
+ return (
+ <Step
+ finished={finished}
+ onOpen={props.onOpen}
+ open={open}
+ renderForm={() => (
+ <div className="boxed-group-inner">
+ <p className="big-spacer-bottom">
+ <FormattedMessage
+ defaultMessage={translate(
+ 'onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.sentence'
+ )}
+ id="onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.sentence"
+ values={{
+ link: (
+ <ButtonLink onClick={props.onDone}>
+ {translate('onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.link')}
+ </ButtonLink>
+ )
+ }}
+ />
+ </p>
+ <ol className="list-styled">
+ <li>
+ <FormattedMessage
+ defaultMessage={translate(
+ 'onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.sentence'
+ )}
+ id="onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.sentence"
+ values={{
+ link:
+ almBinding !== undefined ? (
+ <a
+ href={`${almBinding.url.replace(
+ /\/$/,
+ ''
+ )}/plugins/servlet/webhooks/projects/${projectBinding.repository}/repos/${
+ projectBinding.slug
+ }/create`}
+ rel="noopener noreferrer"
+ target="_blank">
+ {translate('onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.link')}
+ </a>
+ ) : (
+ translate('onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.link')
+ )
+ }}
+ />
+ <ul className="list-styled">
+ <li>
+ <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.name" />
+ </li>
+ <li className="abs-width-600">
+ <p>
+ <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.url" />
+ </p>
+ <CodeSnippet
+ isOneLine={true}
+ snippet={`***JENKINS_URL***/bitbucket-scmsource-hook/notify?server_url=${
+ almBinding !== undefined ? almBinding.url : '***BITBUCKET_URL***'
+ }`}
+ />
+ <Alert variant="info">
+ {translate(
+ 'onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.url.warning'
+ )}
+ </Alert>
+ </li>
+ </ul>
+ </li>
+ <li>
+ <SentenceWithHighlights
+ highlightKeys={['events']}
+ translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step2"
+ />
+ <ul className="list-styled">
+ <li>
+ <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.repo" />
+ </li>
+ <li>
+ <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.pr" />
+ </li>
+ </ul>
+ </li>
+ <li>
+ <SentenceWithHighlights
+ highlightKeys={['create']}
+ translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step3"
+ />
+ </li>
+ </ol>
+ <Button onClick={props.onDone}>{translate('continue')}</Button>
+ </div>
+ )}
+ stepNumber={2}
+ stepTitle={translate('onboarding.tutorial.with.jenkins.bitbucket_webhook.title')}
+ />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { Alert } from 'sonar-ui-common/components/ui/Alert';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import {
+ isBitbucketBindingDefinition,
+ isProjectBitbucketBindingResponse
+} from '../../../helpers/alm-settings';
+import { AlmBindingDefinition, ProjectAlmBindingResponse } from '../../../types/alm-settings';
+import BitbucketWebhookStep from './BitbucketWebhookStep';
+import JenkinsfileStep from './JenkinsfileStep';
+import MultiBranchPipelineStep from './MultiBranchPipelineStep';
+import PreRequisitesStep from './PreRequisitesStep';
+
+export interface JenkinsTutorialProps {
+ almBinding?: AlmBindingDefinition;
+ component: T.Component;
+ projectBinding: ProjectAlmBindingResponse;
+}
+
+enum Steps {
+ PreRequisites = 0,
+ MultiBranchPipeline = 1,
+ BitbucketWebhook = 2,
+ Jenkinsfile = 3
+}
+
+export default function JenkinsTutorial(props: JenkinsTutorialProps) {
+ const { almBinding, component, projectBinding } = props;
+ const [step, setStep] = React.useState(Steps.PreRequisites);
+
+ // Failsafe; should never happen.
+ if (!isProjectBitbucketBindingResponse(projectBinding)) {
+ return (
+ <Alert variant="error">{translate('onboarding.tutorial.with.jenkins.only_bitbucket')}</Alert>
+ );
+ }
+
+ return (
+ <>
+ <div className="page-header big-spacer-bottom">
+ <h1 className="page-title">{translate('onboarding.tutorial.with.jenkins.title')}</h1>
+ </div>
+
+ <PreRequisitesStep
+ onDone={() => setStep(Steps.MultiBranchPipeline)}
+ onOpen={() => setStep(Steps.PreRequisites)}
+ open={step === Steps.PreRequisites}
+ />
+
+ <MultiBranchPipelineStep
+ finished={step > Steps.MultiBranchPipeline}
+ onDone={() => setStep(Steps.BitbucketWebhook)}
+ onOpen={() => setStep(Steps.MultiBranchPipeline)}
+ open={step === Steps.MultiBranchPipeline}
+ projectBinding={projectBinding}
+ />
+
+ <BitbucketWebhookStep
+ almBinding={almBinding && isBitbucketBindingDefinition(almBinding) ? almBinding : undefined}
+ finished={step > Steps.BitbucketWebhook}
+ onDone={() => setStep(Steps.Jenkinsfile)}
+ onOpen={() => setStep(Steps.BitbucketWebhook)}
+ open={step === Steps.BitbucketWebhook}
+ projectBinding={projectBinding}
+ />
+
+ <JenkinsfileStep component={component} open={step === Steps.Jenkinsfile} />
+ </>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import { getBaseUrl } from 'sonar-ui-common/helpers/urls';
+import RenderOptions from '../components/RenderOptions';
+import SentenceWithHighlights from '../components/SentenceWithHighlights';
+import Step from '../components/Step';
+import Gradle from './buildtool-steps/Gradle';
+import Maven from './buildtool-steps/Maven';
+import MSBuild from './buildtool-steps/MSBuild';
+import Other from './buildtool-steps/Other';
+
+export interface JenkinsfileStepProps {
+ component: T.Component;
+ open: boolean;
+}
+
+export enum BuildTools {
+ Maven = 'maven',
+ Gradle = 'gradle',
+ MSBuild = 'msbuild',
+ Other = 'other'
+}
+
+const BUILDTOOL_COMPONENT_MAP: {
+ [x in BuildTools]: React.ComponentType<{ component: T.Component }>;
+} = {
+ [BuildTools.Maven]: Maven,
+ [BuildTools.Gradle]: Gradle,
+ [BuildTools.MSBuild]: MSBuild,
+ [BuildTools.Other]: Other
+};
+
+export default function JenkinsfileStep(props: JenkinsfileStepProps) {
+ const { component, open } = props;
+ const [buildTool, setBuildTool] = React.useState<BuildTools | undefined>(undefined);
+ return (
+ <Step
+ finished={false}
+ open={open}
+ renderForm={() => (
+ <div className="boxed-group-inner">
+ <ol className="list-styled">
+ <li>
+ {translate('onboarding.build')}
+ <RenderOptions
+ checked={buildTool}
+ name="buildtool"
+ onCheck={value => setBuildTool(value as BuildTools)}
+ optionLabelKey="onboarding.build"
+ options={Object.values(BuildTools)}
+ />
+ </li>
+ {buildTool !== undefined &&
+ React.createElement(BUILDTOOL_COMPONENT_MAP[buildTool], { component })}
+ </ol>
+ {buildTool !== undefined && (
+ <>
+ <hr className="huge-spacer-top huge-spacer-bottom" />
+ <div className="abs-width-600">
+ <p className="big-spacer-bottom">
+ <SentenceWithHighlights
+ highlightKeys={['all_set']}
+ translationKey="onboarding.tutorial.with.jenkins.all_set"
+ />
+ </p>
+ <div className="display-flex-row big-spacer-bottom">
+ <div>
+ <img
+ alt="" // Should be ignored by screen readers
+ className="big-spacer-right"
+ width={30}
+ src={`${getBaseUrl()}/images/tutorials/commit.svg`}
+ />
+ </div>
+ <div>
+ <p className="little-spacer-bottom">
+ <strong>{translate('onboarding.tutorial.with.jenkins.commit')}</strong>
+ </p>
+ <p>{translate('onboarding.tutorial.with.jenkins.commit.why')}</p>
+ </div>
+ </div>
+ <div className="display-flex-row huge-spacer-bottom">
+ <div>
+ <img
+ alt="" // Should be ignored by screen readers
+ className="big-spacer-right"
+ width={30}
+ src={`${getBaseUrl()}/images/tutorials/refresh.svg`}
+ />
+ </div>
+ <div>
+ <p className="little-spacer-bottom">
+ <strong>{translate('onboarding.tutorial.with.jenkins.refresh')}</strong>
+ </p>
+ <p>{translate('onboarding.tutorial.with.jenkins.refresh.why')}</p>
+ </div>
+ </div>
+ </div>
+ </>
+ )}
+ </div>
+ )}
+ stepNumber={3}
+ stepTitle={translate('onboarding.tutorial.with.jenkins.jenkinsfile.title')}
+ />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { Button } from 'sonar-ui-common/components/controls/buttons';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import { ProjectBitbucketBindingResponse } from '../../../types/alm-settings';
+import LabelActionPair from '../components/LabelActionPair';
+import LabelValuePair from '../components/LabelValuePair';
+import SentenceWithHighlights from '../components/SentenceWithHighlights';
+import Step from '../components/Step';
+
+export interface MultiBranchPipelineStepProps {
+ finished: boolean;
+ onDone: () => void;
+ onOpen: () => void;
+ open: boolean;
+ projectBinding: ProjectBitbucketBindingResponse;
+}
+
+export default function MultiBranchPipelineStep(props: MultiBranchPipelineStepProps) {
+ const { finished, open, projectBinding } = props;
+ return (
+ <Step
+ finished={finished}
+ onOpen={props.onOpen}
+ open={open}
+ renderForm={() => (
+ <div className="boxed-group-inner">
+ <p className="big-spacer-bottom">
+ {translate('onboarding.tutorial.with.jenkins.multi_branch_pipeline.intro')}
+ </p>
+ <ol className="list-styled">
+ <li>
+ <SentenceWithHighlights
+ highlightKeys={['new_item', 'type']}
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step1"
+ />
+ </li>
+ <li>
+ <SentenceWithHighlights
+ highlightKeys={['tab']}
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2"
+ />
+ <ul className="list-styled">
+ <li>
+ <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.server" />
+ </li>
+ <li>
+ <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.creds" />
+ </li>
+ <li>
+ <LabelValuePair
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.owner"
+ value={projectBinding.repository}
+ />
+ </li>
+ <li>
+ <LabelValuePair
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.repo"
+ value={projectBinding.slug}
+ />
+ </li>
+ <li>
+ <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.behaviour" />
+ </li>
+ </ul>
+ </li>
+ <li>
+ <SentenceWithHighlights
+ highlightKeys={['tab']}
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3"
+ />
+ <ul className="list-styled">
+ <li>
+ <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.mode" />
+ </li>
+ <li>
+ <LabelActionPair translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.script_path" />
+ </li>
+ </ul>
+ </li>
+ <li>
+ <SentenceWithHighlights
+ highlightKeys={['save']}
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step4"
+ />
+ </li>
+ </ol>
+ <Button onClick={props.onDone}>{translate('continue')}</Button>
+ </div>
+ )}
+ stepNumber={1}
+ stepTitle={translate('onboarding.tutorial.with.jenkins.multi_branch_pipeline.title')}
+ />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import { FormattedMessage } from 'react-intl';
+import { Link } from 'react-router';
+import { Button } from 'sonar-ui-common/components/controls/buttons';
+import { translate } from 'sonar-ui-common/helpers/l10n';
+import SentenceWithHighlights from '../components/SentenceWithHighlights';
+import Step from '../components/Step';
+
+export interface PreRequisitesStepProps {
+ onDone: () => void;
+ onOpen: () => void;
+ open: boolean;
+}
+
+export default function PreRequisitesStep(props: PreRequisitesStepProps) {
+ const { open } = props;
+ return (
+ <Step
+ finished={!open}
+ onOpen={props.onOpen}
+ open={open}
+ renderForm={() => (
+ <div className="boxed-group-inner">
+ <p className="big-spacer-bottom">
+ <SentenceWithHighlights
+ highlightKeys={['must_have']}
+ translationKey="onboarding.tutorial.with.jenkins.prereqs.intro"
+ />
+ </p>
+ <ul className="list-styled big-spacer-bottom">
+ <li>{translate('onboarding.tutorial.with.jenkins.prereqs.plugins.branch_source')}</li>
+ <li>{translate('onboarding.tutorial.with.jenkins.prereqs.plugins.sonar_scanner')}</li>
+ </ul>
+ <p className="big-spacer-bottom">
+ <FormattedMessage
+ defaultMessage={translate(
+ 'onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide'
+ )}
+ id="onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide"
+ values={{
+ link: (
+ <Link target="_blank" to="/documentation/analysis/jenkins/">
+ {translate('onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide.link')}
+ </Link>
+ )
+ }}
+ />
+ </p>
+ <p className="big-spacer-bottom">
+ {translate('onboarding.tutorial.with.jenkins.prereqs.following_are_recommendations')}
+ </p>
+ <Button onClick={props.onDone}>
+ {translate('onboarding.tutorial.with.jenkins.prereqs.done')}
+ </Button>
+ </div>
+ )}
+ stepTitle={translate('onboarding.tutorial.with.jenkins.prereqs.title')}
+ />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import {
+ mockBitbucketBindingDefinition,
+ mockProjectBitbucketBindingGet
+} from '../../../../helpers/mocks/alm-settings';
+import BitbucketWebhookStep, { BitbucketWebhookStepProps } from '../BitbucketWebhookStep';
+import { renderStepContent } from '../test-utils';
+
+it('should render correctly', () => {
+ const wrapper = shallowRender();
+ expect(wrapper).toMatchSnapshot('Step wrapper');
+ expect(renderStepContent(wrapper)).toMatchSnapshot('content');
+ expect(renderStepContent(wrapper.setProps({ almBinding: undefined }))).toMatchSnapshot(
+ 'no alm binding'
+ );
+});
+
+function shallowRender(props: Partial<BitbucketWebhookStepProps> = {}) {
+ return shallow<BitbucketWebhookStepProps>(
+ <BitbucketWebhookStep
+ almBinding={mockBitbucketBindingDefinition()}
+ finished={false}
+ onDone={jest.fn()}
+ onOpen={jest.fn()}
+ open={true}
+ projectBinding={mockProjectBitbucketBindingGet()}
+ {...props}
+ />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import {
+ mockProjectAlmBindingResponse,
+ mockProjectBitbucketBindingGet
+} from '../../../../helpers/mocks/alm-settings';
+import { mockComponent } from '../../../../helpers/testMocks';
+import BitbucketWebhookStep from '../BitbucketWebhookStep';
+import JenkinsfileStep from '../JenkinsfileStep';
+import JenkinsTutorial, { JenkinsTutorialProps } from '../JenkinsTutorial';
+import MultiBranchPipelineStep from '../MultiBranchPipelineStep';
+import PreRequisitesStep from '../PreRequisitesStep';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot('default');
+ expect(shallowRender({ projectBinding: mockProjectAlmBindingResponse() })).toMatchSnapshot(
+ 'not Bitbucket binding'
+ );
+});
+
+it('should correctly navigate between steps', () => {
+ const wrapper = shallowRender();
+
+ expect(wrapper.find(PreRequisitesStep).prop('open')).toBe(true);
+ expect(wrapper.find(MultiBranchPipelineStep).prop('open')).toBe(false);
+ expect(wrapper.find(BitbucketWebhookStep).prop('open')).toBe(false);
+ expect(wrapper.find(JenkinsfileStep).prop('open')).toBe(false);
+
+ // Pre-reqs done.
+ wrapper.find(PreRequisitesStep).prop('onDone')();
+ expect(wrapper.find(PreRequisitesStep).prop('open')).toBe(false);
+ expect(wrapper.find(MultiBranchPipelineStep).prop('open')).toBe(true);
+ expect(wrapper.find(BitbucketWebhookStep).prop('open')).toBe(false);
+ expect(wrapper.find(JenkinsfileStep).prop('open')).toBe(false);
+
+ // Multibranch done.
+ wrapper.find(MultiBranchPipelineStep).prop('onDone')();
+ expect(wrapper.find(PreRequisitesStep).prop('open')).toBe(false);
+ expect(wrapper.find(MultiBranchPipelineStep).prop('open')).toBe(false);
+ expect(wrapper.find(BitbucketWebhookStep).prop('open')).toBe(true);
+ expect(wrapper.find(JenkinsfileStep).prop('open')).toBe(false);
+
+ // Webhook done.
+ wrapper.find(BitbucketWebhookStep).prop('onDone')();
+ expect(wrapper.find(PreRequisitesStep).prop('open')).toBe(false);
+ expect(wrapper.find(MultiBranchPipelineStep).prop('open')).toBe(false);
+ expect(wrapper.find(BitbucketWebhookStep).prop('open')).toBe(false);
+ expect(wrapper.find(JenkinsfileStep).prop('open')).toBe(true);
+
+ // Open Pre-reqs.
+ wrapper.find(PreRequisitesStep).prop('onOpen')();
+ expect(wrapper.find(PreRequisitesStep).prop('open')).toBe(true);
+
+ // Open Multibranch.
+ wrapper.find(MultiBranchPipelineStep).prop('onOpen')();
+ expect(wrapper.find(MultiBranchPipelineStep).prop('open')).toBe(true);
+
+ // Open Webhook.
+ wrapper.find(BitbucketWebhookStep).prop('onOpen')();
+ expect(wrapper.find(BitbucketWebhookStep).prop('open')).toBe(true);
+});
+
+function shallowRender(props: Partial<JenkinsTutorialProps> = {}) {
+ return shallow<JenkinsTutorialProps>(
+ <JenkinsTutorial
+ component={mockComponent()}
+ projectBinding={mockProjectBitbucketBindingGet()}
+ {...props}
+ />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow, ShallowWrapper } from 'enzyme';
+import * as React from 'react';
+import { mockComponent } from '../../../../helpers/testMocks';
+import RenderOptions from '../../components/RenderOptions';
+import Step from '../../components/Step';
+import JenkinsfileStep, { BuildTools, JenkinsfileStepProps } from '../JenkinsfileStep';
+import { renderStepContent } from '../test-utils';
+
+it('should render correctly', () => {
+ const wrapper = shallowRender();
+ expect(wrapper).toMatchSnapshot('Step wrapper');
+ expect(renderStepContent(wrapper)).toMatchSnapshot('initial content');
+});
+
+it('should render correctly for Maven', () => {
+ const wrapper = shallowRender();
+ selectBuildTool(wrapper, BuildTools.Maven);
+ expect(
+ wrapper
+ .find(Step)
+ .props()
+ .renderForm()
+ ).toMatchSnapshot();
+});
+
+it('should render correctly for Gradle', () => {
+ const wrapper = shallowRender();
+ selectBuildTool(wrapper, BuildTools.Gradle);
+ expect(renderStepContent(wrapper)).toMatchSnapshot();
+});
+
+it('should render correctly for MSBuild', () => {
+ const wrapper = shallowRender();
+ selectBuildTool(wrapper, BuildTools.MSBuild);
+ expect(renderStepContent(wrapper)).toMatchSnapshot();
+});
+
+it('should render correctly for Other', () => {
+ const wrapper = shallowRender();
+ selectBuildTool(wrapper, BuildTools.Other);
+ expect(renderStepContent(wrapper)).toMatchSnapshot();
+});
+
+function selectBuildTool(wrapper: ShallowWrapper<JenkinsfileStepProps>, tool: BuildTools) {
+ const content = new ShallowWrapper(renderStepContent(wrapper) as JSX.Element);
+ content.find(RenderOptions).prop('onCheck')(tool);
+}
+
+function shallowRender(props: Partial<JenkinsfileStepProps> = {}) {
+ return shallow<JenkinsfileStepProps>(
+ <JenkinsfileStep component={mockComponent()} open={true} {...props} />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import { mockProjectBitbucketBindingGet } from '../../../../helpers/mocks/alm-settings';
+import MultiBranchPipelineStep, { MultiBranchPipelineStepProps } from '../MultiBranchPipelineStep';
+import { renderStepContent } from '../test-utils';
+
+it('should render correctly', () => {
+ const wrapper = shallowRender();
+ expect(wrapper).toMatchSnapshot('Step wrapper');
+ expect(renderStepContent(wrapper)).toMatchSnapshot('content');
+});
+
+function shallowRender(props: Partial<MultiBranchPipelineStepProps> = {}) {
+ return shallow<MultiBranchPipelineStepProps>(
+ <MultiBranchPipelineStep
+ finished={false}
+ onDone={jest.fn()}
+ onOpen={jest.fn()}
+ open={true}
+ projectBinding={mockProjectBitbucketBindingGet()}
+ {...props}
+ />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import PreRequisitesStep, { PreRequisitesStepProps } from '../PreRequisitesStep';
+import { renderStepContent } from '../test-utils';
+
+it('should render correctly', () => {
+ const wrapper = shallowRender();
+ expect(wrapper).toMatchSnapshot('Step wrapper');
+ expect(renderStepContent(wrapper)).toMatchSnapshot('content');
+});
+
+function shallowRender(props: Partial<PreRequisitesStepProps> = {}) {
+ return shallow<PreRequisitesStepProps>(
+ <PreRequisitesStep onDone={jest.fn()} onOpen={jest.fn()} open={false} {...props} />
+ );
+}
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly: Step wrapper 1`] = `
+<Step
+ finished={false}
+ onOpen={[MockFunction]}
+ open={true}
+ renderForm={[Function]}
+ stepNumber={2}
+ stepTitle="onboarding.tutorial.with.jenkins.bitbucket_webhook.title"
+/>
+`;
+
+exports[`should render correctly: content 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <p
+ className="big-spacer-bottom"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.sentence"
+ id="onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.sentence"
+ values={
+ Object {
+ "link": <ButtonLink
+ onClick={[MockFunction]}
+ >
+ onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.link
+ </ButtonLink>,
+ }
+ }
+ />
+ </p>
+ <ol
+ className="list-styled"
+ >
+ <li>
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.sentence"
+ id="onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.sentence"
+ values={
+ Object {
+ "link": <a
+ href="http://bbs.enterprise.com/plugins/servlet/webhooks/projects/PROJECT_KEY/repos/repo-slug/create"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+ onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.link
+ </a>,
+ }
+ }
+ />
+ <ul
+ className="list-styled"
+ >
+ <li>
+ <LabelActionPair
+ translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.name"
+ />
+ </li>
+ <li
+ className="abs-width-600"
+ >
+ <p>
+ <LabelActionPair
+ translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.url"
+ />
+ </p>
+ <CodeSnippet
+ isOneLine={true}
+ snippet="***JENKINS_URL***/bitbucket-scmsource-hook/notify?server_url=http://bbs.enterprise.com"
+ />
+ <Alert
+ variant="info"
+ >
+ onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.url.warning
+ </Alert>
+ </li>
+ </ul>
+ </li>
+ <li>
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "events",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step2"
+ />
+ <ul
+ className="list-styled"
+ >
+ <li>
+ <LabelActionPair
+ translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.repo"
+ />
+ </li>
+ <li>
+ <LabelActionPair
+ translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.pr"
+ />
+ </li>
+ </ul>
+ </li>
+ <li>
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "create",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step3"
+ />
+ </li>
+ </ol>
+ <Button
+ onClick={[MockFunction]}
+ >
+ continue
+ </Button>
+</div>
+`;
+
+exports[`should render correctly: no alm binding 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <p
+ className="big-spacer-bottom"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.sentence"
+ id="onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.sentence"
+ values={
+ Object {
+ "link": <ButtonLink
+ onClick={[MockFunction]}
+ >
+ onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.link
+ </ButtonLink>,
+ }
+ }
+ />
+ </p>
+ <ol
+ className="list-styled"
+ >
+ <li>
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.sentence"
+ id="onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.sentence"
+ values={
+ Object {
+ "link": "onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.link",
+ }
+ }
+ />
+ <ul
+ className="list-styled"
+ >
+ <li>
+ <LabelActionPair
+ translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.name"
+ />
+ </li>
+ <li
+ className="abs-width-600"
+ >
+ <p>
+ <LabelActionPair
+ translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.url"
+ />
+ </p>
+ <CodeSnippet
+ isOneLine={true}
+ snippet="***JENKINS_URL***/bitbucket-scmsource-hook/notify?server_url=***BITBUCKET_URL***"
+ />
+ <Alert
+ variant="info"
+ >
+ onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.url.warning
+ </Alert>
+ </li>
+ </ul>
+ </li>
+ <li>
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "events",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step2"
+ />
+ <ul
+ className="list-styled"
+ >
+ <li>
+ <LabelActionPair
+ translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.repo"
+ />
+ </li>
+ <li>
+ <LabelActionPair
+ translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.pr"
+ />
+ </li>
+ </ul>
+ </li>
+ <li>
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "create",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.bitbucket_webhook.step3"
+ />
+ </li>
+ </ol>
+ <Button
+ onClick={[MockFunction]}
+ >
+ continue
+ </Button>
+</div>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly: default 1`] = `
+<Fragment>
+ <div
+ className="page-header big-spacer-bottom"
+ >
+ <h1
+ className="page-title"
+ >
+ onboarding.tutorial.with.jenkins.title
+ </h1>
+ </div>
+ <PreRequisitesStep
+ onDone={[Function]}
+ onOpen={[Function]}
+ open={true}
+ />
+ <MultiBranchPipelineStep
+ finished={false}
+ onDone={[Function]}
+ onOpen={[Function]}
+ open={false}
+ projectBinding={
+ Object {
+ "alm": "bitbucket",
+ "key": "foo",
+ "repository": "PROJECT_KEY",
+ "slug": "repo-slug",
+ }
+ }
+ />
+ <BitbucketWebhookStep
+ finished={false}
+ onDone={[Function]}
+ onOpen={[Function]}
+ open={false}
+ projectBinding={
+ Object {
+ "alm": "bitbucket",
+ "key": "foo",
+ "repository": "PROJECT_KEY",
+ "slug": "repo-slug",
+ }
+ }
+ />
+ <JenkinsfileStep
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ open={false}
+ />
+</Fragment>
+`;
+
+exports[`should render correctly: not Bitbucket binding 1`] = `
+<Alert
+ variant="error"
+>
+ onboarding.tutorial.with.jenkins.only_bitbucket
+</Alert>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly for Gradle 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <ol
+ className="list-styled"
+ >
+ <li>
+ onboarding.build
+ <RenderOptions
+ checked="gradle"
+ name="buildtool"
+ onCheck={[Function]}
+ optionLabelKey="onboarding.build"
+ options={
+ Array [
+ "maven",
+ "gradle",
+ "msbuild",
+ "other",
+ ]
+ }
+ />
+ </li>
+ <Gradle
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ />
+ </ol>
+ <React.Fragment>
+ <hr
+ className="huge-spacer-top huge-spacer-bottom"
+ />
+ <div
+ className="abs-width-600"
+ >
+ <p
+ className="big-spacer-bottom"
+ >
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "all_set",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.all_set"
+ />
+ </p>
+ <div
+ className="display-flex-row big-spacer-bottom"
+ >
+ <div>
+ <img
+ alt=""
+ className="big-spacer-right"
+ src="/images/tutorials/commit.svg"
+ width={30}
+ />
+ </div>
+ <div>
+ <p
+ className="little-spacer-bottom"
+ >
+ <strong>
+ onboarding.tutorial.with.jenkins.commit
+ </strong>
+ </p>
+ <p>
+ onboarding.tutorial.with.jenkins.commit.why
+ </p>
+ </div>
+ </div>
+ <div
+ className="display-flex-row huge-spacer-bottom"
+ >
+ <div>
+ <img
+ alt=""
+ className="big-spacer-right"
+ src="/images/tutorials/refresh.svg"
+ width={30}
+ />
+ </div>
+ <div>
+ <p
+ className="little-spacer-bottom"
+ >
+ <strong>
+ onboarding.tutorial.with.jenkins.refresh
+ </strong>
+ </p>
+ <p>
+ onboarding.tutorial.with.jenkins.refresh.why
+ </p>
+ </div>
+ </div>
+ </div>
+ </React.Fragment>
+</div>
+`;
+
+exports[`should render correctly for MSBuild 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <ol
+ className="list-styled"
+ >
+ <li>
+ onboarding.build
+ <RenderOptions
+ checked="msbuild"
+ name="buildtool"
+ onCheck={[Function]}
+ optionLabelKey="onboarding.build"
+ options={
+ Array [
+ "maven",
+ "gradle",
+ "msbuild",
+ "other",
+ ]
+ }
+ />
+ </li>
+ <MSBuild
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ />
+ </ol>
+ <React.Fragment>
+ <hr
+ className="huge-spacer-top huge-spacer-bottom"
+ />
+ <div
+ className="abs-width-600"
+ >
+ <p
+ className="big-spacer-bottom"
+ >
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "all_set",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.all_set"
+ />
+ </p>
+ <div
+ className="display-flex-row big-spacer-bottom"
+ >
+ <div>
+ <img
+ alt=""
+ className="big-spacer-right"
+ src="/images/tutorials/commit.svg"
+ width={30}
+ />
+ </div>
+ <div>
+ <p
+ className="little-spacer-bottom"
+ >
+ <strong>
+ onboarding.tutorial.with.jenkins.commit
+ </strong>
+ </p>
+ <p>
+ onboarding.tutorial.with.jenkins.commit.why
+ </p>
+ </div>
+ </div>
+ <div
+ className="display-flex-row huge-spacer-bottom"
+ >
+ <div>
+ <img
+ alt=""
+ className="big-spacer-right"
+ src="/images/tutorials/refresh.svg"
+ width={30}
+ />
+ </div>
+ <div>
+ <p
+ className="little-spacer-bottom"
+ >
+ <strong>
+ onboarding.tutorial.with.jenkins.refresh
+ </strong>
+ </p>
+ <p>
+ onboarding.tutorial.with.jenkins.refresh.why
+ </p>
+ </div>
+ </div>
+ </div>
+ </React.Fragment>
+</div>
+`;
+
+exports[`should render correctly for Maven 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <ol
+ className="list-styled"
+ >
+ <li>
+ onboarding.build
+ <RenderOptions
+ checked="maven"
+ name="buildtool"
+ onCheck={[Function]}
+ optionLabelKey="onboarding.build"
+ options={
+ Array [
+ "maven",
+ "gradle",
+ "msbuild",
+ "other",
+ ]
+ }
+ />
+ </li>
+ <Maven
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ />
+ </ol>
+ <React.Fragment>
+ <hr
+ className="huge-spacer-top huge-spacer-bottom"
+ />
+ <div
+ className="abs-width-600"
+ >
+ <p
+ className="big-spacer-bottom"
+ >
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "all_set",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.all_set"
+ />
+ </p>
+ <div
+ className="display-flex-row big-spacer-bottom"
+ >
+ <div>
+ <img
+ alt=""
+ className="big-spacer-right"
+ src="/images/tutorials/commit.svg"
+ width={30}
+ />
+ </div>
+ <div>
+ <p
+ className="little-spacer-bottom"
+ >
+ <strong>
+ onboarding.tutorial.with.jenkins.commit
+ </strong>
+ </p>
+ <p>
+ onboarding.tutorial.with.jenkins.commit.why
+ </p>
+ </div>
+ </div>
+ <div
+ className="display-flex-row huge-spacer-bottom"
+ >
+ <div>
+ <img
+ alt=""
+ className="big-spacer-right"
+ src="/images/tutorials/refresh.svg"
+ width={30}
+ />
+ </div>
+ <div>
+ <p
+ className="little-spacer-bottom"
+ >
+ <strong>
+ onboarding.tutorial.with.jenkins.refresh
+ </strong>
+ </p>
+ <p>
+ onboarding.tutorial.with.jenkins.refresh.why
+ </p>
+ </div>
+ </div>
+ </div>
+ </React.Fragment>
+</div>
+`;
+
+exports[`should render correctly for Other 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <ol
+ className="list-styled"
+ >
+ <li>
+ onboarding.build
+ <RenderOptions
+ checked="other"
+ name="buildtool"
+ onCheck={[Function]}
+ optionLabelKey="onboarding.build"
+ options={
+ Array [
+ "maven",
+ "gradle",
+ "msbuild",
+ "other",
+ ]
+ }
+ />
+ </li>
+ <Other
+ component={
+ Object {
+ "breadcrumbs": Array [],
+ "key": "my-project",
+ "name": "MyProject",
+ "organization": "foo",
+ "qualifier": "TRK",
+ "qualityGate": Object {
+ "isDefault": true,
+ "key": "30",
+ "name": "Sonar way",
+ },
+ "qualityProfiles": Array [
+ Object {
+ "deleted": false,
+ "key": "my-qp",
+ "language": "ts",
+ "name": "Sonar way",
+ },
+ ],
+ "tags": Array [],
+ }
+ }
+ />
+ </ol>
+ <React.Fragment>
+ <hr
+ className="huge-spacer-top huge-spacer-bottom"
+ />
+ <div
+ className="abs-width-600"
+ >
+ <p
+ className="big-spacer-bottom"
+ >
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "all_set",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.all_set"
+ />
+ </p>
+ <div
+ className="display-flex-row big-spacer-bottom"
+ >
+ <div>
+ <img
+ alt=""
+ className="big-spacer-right"
+ src="/images/tutorials/commit.svg"
+ width={30}
+ />
+ </div>
+ <div>
+ <p
+ className="little-spacer-bottom"
+ >
+ <strong>
+ onboarding.tutorial.with.jenkins.commit
+ </strong>
+ </p>
+ <p>
+ onboarding.tutorial.with.jenkins.commit.why
+ </p>
+ </div>
+ </div>
+ <div
+ className="display-flex-row huge-spacer-bottom"
+ >
+ <div>
+ <img
+ alt=""
+ className="big-spacer-right"
+ src="/images/tutorials/refresh.svg"
+ width={30}
+ />
+ </div>
+ <div>
+ <p
+ className="little-spacer-bottom"
+ >
+ <strong>
+ onboarding.tutorial.with.jenkins.refresh
+ </strong>
+ </p>
+ <p>
+ onboarding.tutorial.with.jenkins.refresh.why
+ </p>
+ </div>
+ </div>
+ </div>
+ </React.Fragment>
+</div>
+`;
+
+exports[`should render correctly: Step wrapper 1`] = `
+<Step
+ finished={false}
+ open={true}
+ renderForm={[Function]}
+ stepNumber={3}
+ stepTitle="onboarding.tutorial.with.jenkins.jenkinsfile.title"
+/>
+`;
+
+exports[`should render correctly: initial content 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <ol
+ className="list-styled"
+ >
+ <li>
+ onboarding.build
+ <RenderOptions
+ name="buildtool"
+ onCheck={[Function]}
+ optionLabelKey="onboarding.build"
+ options={
+ Array [
+ "maven",
+ "gradle",
+ "msbuild",
+ "other",
+ ]
+ }
+ />
+ </li>
+ </ol>
+</div>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly: Step wrapper 1`] = `
+<Step
+ finished={false}
+ onOpen={[MockFunction]}
+ open={true}
+ renderForm={[Function]}
+ stepNumber={1}
+ stepTitle="onboarding.tutorial.with.jenkins.multi_branch_pipeline.title"
+/>
+`;
+
+exports[`should render correctly: content 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <p
+ className="big-spacer-bottom"
+ >
+ onboarding.tutorial.with.jenkins.multi_branch_pipeline.intro
+ </p>
+ <ol
+ className="list-styled"
+ >
+ <li>
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "new_item",
+ "type",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step1"
+ />
+ </li>
+ <li>
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "tab",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2"
+ />
+ <ul
+ className="list-styled"
+ >
+ <li>
+ <LabelActionPair
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.server"
+ />
+ </li>
+ <li>
+ <LabelActionPair
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.creds"
+ />
+ </li>
+ <li>
+ <LabelValuePair
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.owner"
+ value="PROJECT_KEY"
+ />
+ </li>
+ <li>
+ <LabelValuePair
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.repo"
+ value="repo-slug"
+ />
+ </li>
+ <li>
+ <LabelActionPair
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.behaviour"
+ />
+ </li>
+ </ul>
+ </li>
+ <li>
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "tab",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3"
+ />
+ <ul
+ className="list-styled"
+ >
+ <li>
+ <LabelActionPair
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.mode"
+ />
+ </li>
+ <li>
+ <LabelActionPair
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.script_path"
+ />
+ </li>
+ </ul>
+ </li>
+ <li>
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "save",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.multi_branch_pipeline.step4"
+ />
+ </li>
+ </ol>
+ <Button
+ onClick={[MockFunction]}
+ >
+ continue
+ </Button>
+</div>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly: Step wrapper 1`] = `
+<Step
+ finished={true}
+ onOpen={[MockFunction]}
+ open={false}
+ renderForm={[Function]}
+ stepTitle="onboarding.tutorial.with.jenkins.prereqs.title"
+/>
+`;
+
+exports[`should render correctly: content 1`] = `
+<div
+ className="boxed-group-inner"
+>
+ <p
+ className="big-spacer-bottom"
+ >
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "must_have",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.prereqs.intro"
+ />
+ </p>
+ <ul
+ className="list-styled big-spacer-bottom"
+ >
+ <li>
+ onboarding.tutorial.with.jenkins.prereqs.plugins.branch_source
+ </li>
+ <li>
+ onboarding.tutorial.with.jenkins.prereqs.plugins.sonar_scanner
+ </li>
+ </ul>
+ <p
+ className="big-spacer-bottom"
+ >
+ <FormattedMessage
+ defaultMessage="onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide"
+ id="onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide"
+ values={
+ Object {
+ "link": <Link
+ onlyActiveOnIndex={false}
+ style={Object {}}
+ target="_blank"
+ to="/documentation/analysis/jenkins/"
+ >
+ onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide.link
+ </Link>,
+ }
+ }
+ />
+ </p>
+ <p
+ className="big-spacer-bottom"
+ >
+ onboarding.tutorial.with.jenkins.prereqs.following_are_recommendations
+ </p>
+ <Button
+ onClick={[MockFunction]}
+ >
+ onboarding.tutorial.with.jenkins.prereqs.done
+ </Button>
+</div>
+`;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import HelpTooltip from 'sonar-ui-common/components/controls/HelpTooltip';
+import { Alert } from 'sonar-ui-common/components/ui/Alert';
+import CodeSnippet from '../../../common/CodeSnippet';
+import SentenceWithFilename from '../../components/SentenceWithFilename';
+import SentenceWithHighlights from '../../components/SentenceWithHighlights';
+
+export interface CreateJenkinsfileBulletPointProps {
+ snippet: string;
+ alertTranslationKeyPart?: string;
+}
+
+export default function CreateJenkinsfileBulletPoint(props: CreateJenkinsfileBulletPointProps) {
+ const { snippet, alertTranslationKeyPart } = props;
+
+ return (
+ <li className="abs-width-600">
+ <SentenceWithFilename
+ filename="Jenkinsfile"
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.jenkinsfile_step"
+ />
+ {alertTranslationKeyPart !== undefined && (
+ <Alert className="spacer-top" variant="info">
+ <p className="text-middle">
+ <SentenceWithHighlights
+ highlightKeys={['default', 'in_jenkins']}
+ translationKey={`${alertTranslationKeyPart}.replace`}
+ />
+ <HelpTooltip
+ className="little-spacer-left"
+ overlay={
+ <>
+ <p className="spacer-bottom">
+ <SentenceWithHighlights
+ highlightKeys={['path']}
+ translationKey={`${alertTranslationKeyPart}.help1`}
+ />
+ </p>
+ <p>
+ <SentenceWithHighlights
+ highlightKeys={['path', 'name']}
+ translationKey={`${alertTranslationKeyPart}.help2`}
+ />
+ </p>
+ </>
+ }
+ />
+ </p>
+ </Alert>
+ )}
+ <CodeSnippet snippet={snippet} />
+ </li>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import * as React from 'react';
+import CodeSnippet from '../../../common/CodeSnippet';
+import SentenceWithFilename from '../../components/SentenceWithFilename';
+import CreateJenkinsfileBulletPoint from './CreateJenkinsfileBulletPoint';
+
+export interface GradleProps {
+ component: T.Component;
+}
+
+const buildGradleSnippet = (key: string) => `plugins {
+ id "org.sonarqube" version "2.7"
+}
+
+sonarqube {
+ properties {
+ property "sonar.projectKey", "${key}"
+ }
+}`;
+
+const JENKINSFILE_SNIPPET = `node {
+ stage('SCM') {
+ checkout scm
+ }
+ stage('SonarQube Analysis') {
+ withSonarQubeEnv() {
+ sh "./gradlew sonarqube"
+ }
+ }
+}`;
+
+export default function Gradle({ component }: GradleProps) {
+ return (
+ <>
+ <li className="abs-width-600">
+ <SentenceWithFilename
+ filename="build.gradle"
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.gradle.step2"
+ />
+ <CodeSnippet snippet={buildGradleSnippet(component.key)} />
+ </li>
+ <CreateJenkinsfileBulletPoint snippet={JENKINSFILE_SNIPPET} />
+ </>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import * as React from 'react';
+import HelpTooltip from 'sonar-ui-common/components/controls/HelpTooltip';
+import { Alert } from 'sonar-ui-common/components/ui/Alert';
+import CodeSnippet from '../../../common/CodeSnippet';
+import SentenceWithFilename from '../../components/SentenceWithFilename';
+import SentenceWithHighlights from '../../components/SentenceWithHighlights';
+
+export interface MSBuildProps {
+ component: T.Component;
+}
+
+const jenkinsfileSnippet = (key: string) => `node {
+ stage('SCM') {
+ checkout scm
+ }
+ stage('SonarQube Analysis') {
+ def msbuildHome = tool 'Default MSBuild'
+ def scannerHome = tool 'SonarScanner for MSBuild'
+ withSonarQubeEnv() {
+ bat "\\"\${scannerHome}\\\\SonarScanner.MSBuild.exe\\" begin /k:\\"${key}\\""
+ bat "\\"\${msbuildHome}\\\\MSBuild.exe\\" /t:Rebuild"
+ bat "\\"\${scannerHome}\\\\SonarScanner.MSBuild.exe\\" end"
+ }
+ }
+}
+`;
+
+export default function MSBuild({ component }: MSBuildProps) {
+ return (
+ <li className="abs-width-600">
+ <SentenceWithFilename
+ filename="Jenkinsfile"
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.jenkinsfile_step"
+ />
+ <Alert className="spacer-top" variant="info">
+ <p className="text-middle">
+ <SentenceWithHighlights
+ highlightKeys={['default_msbuild', 'default_scanner', 'in_jenkins']}
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.replace"
+ />
+ <HelpTooltip
+ className="little-spacer-left"
+ overlay={
+ <>
+ <p className="spacer-bottom">
+ <SentenceWithHighlights
+ highlightKeys={['path']}
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help1"
+ />
+ </p>
+ <p className="spacer-bottom">
+ <SentenceWithHighlights
+ highlightKeys={['path', 'name']}
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help2"
+ />
+ </p>
+ <p>
+ <SentenceWithHighlights
+ highlightKeys={['path', 'name']}
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help3"
+ />
+ </p>
+ </>
+ }
+ />
+ </p>
+ </Alert>
+ <CodeSnippet snippet={jenkinsfileSnippet(component.key)} />
+ </li>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import * as React from 'react';
+import CodeSnippet from '../../../common/CodeSnippet';
+import SentenceWithFilename from '../../components/SentenceWithFilename';
+import CreateJenkinsfileBulletPoint from './CreateJenkinsfileBulletPoint';
+
+export interface MavenProps {
+ component: T.Component;
+}
+
+const pomSnippet = (key: string) => `<properties>
+ <sonar.projectKey>${key}</sonar.projectKey>
+</properties>`;
+
+const JENKINSFILE_SNIPPET = `node {
+ stage('SCM') {
+ checkout scm
+ }
+ stage('SonarQube Analysis') {
+ def mvn = tool 'Default Maven';
+ withSonarQubeEnv() {
+ sh "\${mvn}/bin/mvn sonar:sonar"
+ }
+ }
+}`;
+
+export default function Maven({ component }: MavenProps) {
+ return (
+ <>
+ <li className="abs-width-600">
+ <SentenceWithFilename
+ filename="pom.xml"
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.maven.step2"
+ />
+ <CodeSnippet snippet={pomSnippet(component.key)} />
+ </li>
+ <CreateJenkinsfileBulletPoint
+ alertTranslationKeyPart="onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3"
+ snippet={JENKINSFILE_SNIPPET}
+ />
+ </>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import * as React from 'react';
+import CodeSnippet from '../../../common/CodeSnippet';
+import SentenceWithFilename from '../../components/SentenceWithFilename';
+import CreateJenkinsfileBulletPoint from './CreateJenkinsfileBulletPoint';
+
+export interface OtherProps {
+ component: T.Component;
+}
+
+const sonarProjectSnippet = (key: string) => `sonar.projectKey=${key}`;
+
+const JENKINSFILE_SNIPPET = `node {
+ stage('SCM') {
+ checkout scm
+ }
+ stage('SonarQube Analysis') {
+ def scannerHome = tool 'SonarScanner';
+ withSonarQubeEnv() {
+ sh "\${scannerHome}/bin/sonar-scanner"
+ }
+ }
+}`;
+
+export default function Other({ component }: OtherProps) {
+ return (
+ <>
+ <li className="abs-width-600">
+ <SentenceWithFilename
+ filename="sonar-project.properties"
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.other.step2"
+ />
+ <CodeSnippet snippet={sonarProjectSnippet(component.key)} />
+ </li>
+ <CreateJenkinsfileBulletPoint
+ alertTranslationKeyPart="onboarding.tutorial.with.jenkins.jenkinsfile.other.step3"
+ snippet={JENKINSFILE_SNIPPET}
+ />
+ </>
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import CreateJenkinsfileBulletPoint, {
+ CreateJenkinsfileBulletPointProps
+} from '../CreateJenkinsfileBulletPoint';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot('default');
+ expect(shallowRender({ alertTranslationKeyPart: 'baz' })).toMatchSnapshot('with alert');
+});
+
+function shallowRender(props: Partial<CreateJenkinsfileBulletPointProps> = {}) {
+ return shallow<CreateJenkinsfileBulletPointProps>(
+ <CreateJenkinsfileBulletPoint snippet="foo { bar() }" {...props} />
+ );
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import { mockComponent } from '../../../../../helpers/testMocks';
+import Gradle, { GradleProps } from '../Gradle';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<GradleProps> = {}) {
+ return shallow<GradleProps>(<Gradle component={mockComponent()} {...props} />);
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import { mockComponent } from '../../../../../helpers/testMocks';
+import MSBuild, { MSBuildProps } from '../MSBuild';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<MSBuildProps> = {}) {
+ return shallow<MSBuildProps>(<MSBuild component={mockComponent()} {...props} />);
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import { mockComponent } from '../../../../../helpers/testMocks';
+import Maven, { MavenProps } from '../Maven';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<MavenProps> = {}) {
+ return shallow<MavenProps>(<Maven component={mockComponent()} {...props} />);
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { shallow } from 'enzyme';
+import * as React from 'react';
+import { mockComponent } from '../../../../../helpers/testMocks';
+import Other, { OtherProps } from '../Other';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+});
+
+function shallowRender(props: Partial<OtherProps> = {}) {
+ return shallow<OtherProps>(<Other component={mockComponent()} {...props} />);
+}
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly: default 1`] = `
+<li
+ className="abs-width-600"
+>
+ <SentenceWithFilename
+ filename="Jenkinsfile"
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.jenkinsfile_step"
+ />
+ <CodeSnippet
+ snippet="foo { bar() }"
+ />
+</li>
+`;
+
+exports[`should render correctly: with alert 1`] = `
+<li
+ className="abs-width-600"
+>
+ <SentenceWithFilename
+ filename="Jenkinsfile"
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.jenkinsfile_step"
+ />
+ <Alert
+ className="spacer-top"
+ variant="info"
+ >
+ <p
+ className="text-middle"
+ >
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "default",
+ "in_jenkins",
+ ]
+ }
+ translationKey="baz.replace"
+ />
+ <HelpTooltip
+ className="little-spacer-left"
+ overlay={
+ <React.Fragment>
+ <p
+ className="spacer-bottom"
+ >
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "path",
+ ]
+ }
+ translationKey="baz.help1"
+ />
+ </p>
+ <p>
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "path",
+ "name",
+ ]
+ }
+ translationKey="baz.help2"
+ />
+ </p>
+ </React.Fragment>
+ }
+ />
+ </p>
+ </Alert>
+ <CodeSnippet
+ snippet="foo { bar() }"
+ />
+</li>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Fragment>
+ <li
+ className="abs-width-600"
+ >
+ <SentenceWithFilename
+ filename="build.gradle"
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.gradle.step2"
+ />
+ <CodeSnippet
+ snippet="plugins {
+ id \\"org.sonarqube\\" version \\"2.7\\"
+}
+
+sonarqube {
+ properties {
+ property \\"sonar.projectKey\\", \\"my-project\\"
+ }
+}"
+ />
+ </li>
+ <CreateJenkinsfileBulletPoint
+ snippet="node {
+ stage('SCM') {
+ checkout scm
+ }
+ stage('SonarQube Analysis') {
+ withSonarQubeEnv() {
+ sh \\"./gradlew sonarqube\\"
+ }
+ }
+}"
+ />
+</Fragment>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<li
+ className="abs-width-600"
+>
+ <SentenceWithFilename
+ filename="Jenkinsfile"
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.jenkinsfile_step"
+ />
+ <Alert
+ className="spacer-top"
+ variant="info"
+ >
+ <p
+ className="text-middle"
+ >
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "default_msbuild",
+ "default_scanner",
+ "in_jenkins",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.replace"
+ />
+ <HelpTooltip
+ className="little-spacer-left"
+ overlay={
+ <React.Fragment>
+ <p
+ className="spacer-bottom"
+ >
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "path",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help1"
+ />
+ </p>
+ <p
+ className="spacer-bottom"
+ >
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "path",
+ "name",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help2"
+ />
+ </p>
+ <p>
+ <SentenceWithHighlights
+ highlightKeys={
+ Array [
+ "path",
+ "name",
+ ]
+ }
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help3"
+ />
+ </p>
+ </React.Fragment>
+ }
+ />
+ </p>
+ </Alert>
+ <CodeSnippet
+ snippet="node {
+ stage('SCM') {
+ checkout scm
+ }
+ stage('SonarQube Analysis') {
+ def msbuildHome = tool 'Default MSBuild'
+ def scannerHome = tool 'SonarScanner for MSBuild'
+ withSonarQubeEnv() {
+ bat \\"\\\\\\"\${scannerHome}\\\\\\\\SonarScanner.MSBuild.exe\\\\\\" begin /k:\\\\\\"my-project\\\\\\"\\"
+ bat \\"\\\\\\"\${msbuildHome}\\\\\\\\MSBuild.exe\\\\\\" /t:Rebuild\\"
+ bat \\"\\\\\\"\${scannerHome}\\\\\\\\SonarScanner.MSBuild.exe\\\\\\" end\\"
+ }
+ }
+}
+"
+ />
+</li>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Fragment>
+ <li
+ className="abs-width-600"
+ >
+ <SentenceWithFilename
+ filename="pom.xml"
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.maven.step2"
+ />
+ <CodeSnippet
+ snippet="<properties>
+ <sonar.projectKey>my-project</sonar.projectKey>
+</properties>"
+ />
+ </li>
+ <CreateJenkinsfileBulletPoint
+ alertTranslationKeyPart="onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3"
+ snippet="node {
+ stage('SCM') {
+ checkout scm
+ }
+ stage('SonarQube Analysis') {
+ def mvn = tool 'Default Maven';
+ withSonarQubeEnv() {
+ sh \\"\${mvn}/bin/mvn sonar:sonar\\"
+ }
+ }
+}"
+ />
+</Fragment>
+`;
--- /dev/null
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<Fragment>
+ <li
+ className="abs-width-600"
+ >
+ <SentenceWithFilename
+ filename="sonar-project.properties"
+ translationKey="onboarding.tutorial.with.jenkins.jenkinsfile.other.step2"
+ />
+ <CodeSnippet
+ snippet="sonar.projectKey=my-project"
+ />
+ </li>
+ <CreateJenkinsfileBulletPoint
+ alertTranslationKeyPart="onboarding.tutorial.with.jenkins.jenkinsfile.other.step3"
+ snippet="node {
+ stage('SCM') {
+ checkout scm
+ }
+ stage('SonarQube Analysis') {
+ def scannerHome = tool 'SonarScanner';
+ withSonarQubeEnv() {
+ sh \\"\${scannerHome}/bin/sonar-scanner\\"
+ }
+ }
+}"
+ />
+</Fragment>
+`;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import { ShallowWrapper } from 'enzyme';
+import Step from '../components/Step';
+
+export function renderStepContent(wrapper: ShallowWrapper<React.ReactNode>) {
+ return wrapper
+ .find(Step)
+ .props()
+ .renderForm();
+}
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import Tooltip from 'sonar-ui-common/components/controls/Tooltip';
-import BackIcon from 'sonar-ui-common/components/icons/BackIcon';
import { translate } from 'sonar-ui-common/helpers/l10n';
import { isVSTS } from '../../../helpers/almIntegrations';
import InstanceMessage from '../../common/InstanceMessage';
interface Props {
component: T.Component;
currentUser: T.LoggedInUser;
- onBack?: () => void;
}
interface State {
return (
<>
<div className="page-header big-spacer-bottom">
- <h1 className="page-title">
- {this.props.onBack !== undefined && (
- <Tooltip overlay={translate('onboarding.tutorial.return_to_list')}>
- <a
- aria-label={translate('onboarding.tutorial.return_to_list')}
- className="link-no-underline big-spacer-right"
- onClick={this.props.onBack}>
- <BackIcon />
- </a>
- </Tooltip>
- )}
- {translate('onboarding.project_analysis.header')}
- </h1>
+ <h1 className="page-title">{translate('onboarding.project_analysis.header')}</h1>
<p className="page-description">
<InstanceMessage message={translate('onboarding.project_analysis.description')} />
</p>
it('renders correctly', () => {
expect(shallowRender()).toMatchSnapshot('default');
- expect(shallowRender({ onBack: jest.fn() })).toMatchSnapshot('with back button');
});
it('allows to navigate between steps', () => {
/>
</Fragment>
`;
-
-exports[`renders correctly: with back button 1`] = `
-<Fragment>
- <div
- className="page-header big-spacer-bottom"
- >
- <h1
- className="page-title"
- >
- <Tooltip
- overlay="onboarding.tutorial.return_to_list"
- >
- <a
- aria-label="onboarding.tutorial.return_to_list"
- className="link-no-underline big-spacer-right"
- onClick={[MockFunction]}
- >
- <BackIcon />
- </a>
- </Tooltip>
- onboarding.project_analysis.header
- </h1>
- <p
- className="page-description"
- >
- <InstanceMessage
- message="onboarding.project_analysis.description"
- />
- </p>
- </div>
- <TokenStep
- currentUser={
- Object {
- "groups": Array [],
- "isLoggedIn": true,
- "login": "luke",
- "name": "Skywalker",
- "scmAccounts": Array [],
- }
- }
- finished={false}
- initialTokenName="Analyze \\"MyProject\\""
- onContinue={[Function]}
- onOpen={[Function]}
- open={true}
- stepNumber={1}
- />
- <ProjectAnalysisStep
- component={
- Object {
- "breadcrumbs": Array [],
- "key": "my-project",
- "name": "MyProject",
- "organization": "foo",
- "qualifier": "TRK",
- "qualityGate": Object {
- "isDefault": true,
- "key": "30",
- "name": "Sonar way",
- },
- "qualityProfiles": Array [
- Object {
- "deleted": false,
- "key": "my-qp",
- "language": "ts",
- "name": "Sonar way",
- },
- ],
- "tags": Array [],
- }
- }
- displayRowLayout={true}
- open={false}
- stepNumber={2}
- />
-</Fragment>
-`;
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+.tutorial-selection {
+ margin: 0 auto;
+ max-width: 500px;
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+export enum TutorialModes {
+ Manual = 'manual',
+ Jenkins = 'jenkins'
+}
+
+export interface LanguageConfig {
+ language?: string;
+ javaBuild?: string;
+ cFamilyCompiler?: string;
+ os?: string;
+ projectKey?: string;
+}
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-export interface LanguageConfig {
- language?: string;
- javaBuild?: string;
- cFamilyCompiler?: string;
- os?: string;
- projectKey?: string;
-}
+import { LanguageConfig } from './types';
export function isLanguageConfigured(config?: LanguageConfig) {
if (!config) {
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+import { isBitbucketBindingDefinition, isProjectBitbucketBindingResponse } from '../alm-settings';
+import {
+ mockBitbucketBindingDefinition,
+ mockGithubBindingDefinition,
+ mockProjectAlmBindingResponse,
+ mockProjectBitbucketBindingGet
+} from '../mocks/alm-settings';
+
+describe('isProjectBitbucketBindingResponse', () => {
+ it('works as expected', () => {
+ expect(isProjectBitbucketBindingResponse(mockProjectAlmBindingResponse())).toBe(false);
+ expect(isProjectBitbucketBindingResponse(mockProjectBitbucketBindingGet())).toBe(true);
+ });
+});
+
+describe('isBitbucketBindingDefinition', () => {
+ it('works as expected', () => {
+ expect(isBitbucketBindingDefinition(mockGithubBindingDefinition())).toBe(false);
+ expect(isBitbucketBindingDefinition(mockBitbucketBindingDefinition())).toBe(true);
+ });
+});
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+import {
+ AlmBindingDefinition,
+ AlmKeys,
+ BitbucketBindingDefinition,
+ ProjectAlmBindingResponse,
+ ProjectBitbucketBindingResponse
+} from '../types/alm-settings';
+
+export function isProjectBitbucketBindingResponse(
+ binding: ProjectAlmBindingResponse
+): binding is ProjectBitbucketBindingResponse {
+ return binding.alm === AlmKeys.Bitbucket;
+}
+
+export function isBitbucketBindingDefinition(
+ binding: AlmBindingDefinition & { url?: string; personalAccessToken?: string }
+): binding is BitbucketBindingDefinition {
+ return binding.url !== undefined && binding.personalAccessToken !== undefined;
+}
AzureBindingDefinition,
BitbucketBindingDefinition,
GithubBindingDefinition,
- GitlabBindingDefinition
+ GitlabBindingDefinition,
+ ProjectAlmBindingResponse,
+ ProjectBitbucketBindingResponse
} from '../../types/alm-settings';
export function mockAlmSettingsInstance(
...overrides
};
}
+
+export function mockProjectAlmBindingResponse(
+ overrides: Partial<ProjectAlmBindingResponse> = {}
+): ProjectAlmBindingResponse {
+ return {
+ alm: AlmKeys.GitHub,
+ key: 'foo',
+ ...overrides
+ };
+}
+
+export function mockProjectBitbucketBindingGet(
+ overrides: Partial<ProjectBitbucketBindingResponse> = {}
+): ProjectBitbucketBindingResponse {
+ return {
+ alm: AlmKeys.Bitbucket,
+ key: 'foo',
+ repository: 'PROJECT_KEY',
+ slug: 'repo-slug',
+ ...overrides
+ };
+}
summaryCommentEnabled?: boolean;
}
+export interface ProjectBitbucketBindingResponse extends ProjectAlmBindingResponse {
+ alm: AlmKeys.Bitbucket;
+ repository: string;
+ slug: string;
+}
+
export interface ProjectAlmBindingParams {
almSetting: string;
project: string;
onboarding.build.maven=Maven
onboarding.build.gradle=Gradle
onboarding.build.make=Make
+onboarding.build.msbuild=MSBuild
onboarding.build.other=Other (for JS, TS, Go, Python, PHP, ...)
onboarding.language=What is your project's main language?
onboarding.tutorial.return_to_list=Choose another option
+onboarding.tutorial.choose_method=How do you want to analyze your repository?
+onboarding.tutorial.choose_method.manual=Manually
+onboarding.tutorial.choose_method.jenkins=With Jenkins
+
+onboarding.tutorial.with.jenkins.title=Analyze your project with Jenkins
+onboarding.tutorial.with.jenkins.only_bitbucket=This tutorial is only available for projects bound to Bitbucket Server.
+onboarding.tutorial.with.jenkins.prereqs.title=Prerequisites
+onboarding.tutorial.with.jenkins.prereqs.intro.sentence=To run your project analyses with Jenkins, the following plugins {must_have}
+onboarding.tutorial.with.jenkins.prereqs.intro.sentence.must_have=must be installed and configured:
+onboarding.tutorial.with.jenkins.prereqs.plugins.branch_source=Bitbucket Branch Source plugin for Jenkins - version 2.7 or later
+onboarding.tutorial.with.jenkins.prereqs.plugins.sonar_scanner=SonarQube Scanner plugin for Jenkins - version 2.11 or later
+onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide=For a step by step guide on installing and configuring those plugins in Jenkins, visit the {link} documentation page.
+onboarding.tutorial.with.jenkins.prereqs.step_by_step_guide.link=Analysis Prerequisites
+onboarding.tutorial.with.jenkins.prereqs.following_are_recommendations=We recommend using the configuration in the following steps for the best results, but you can customize it as needed.
+onboarding.tutorial.with.jenkins.prereqs.done=Configure Analysis
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.title=Create a Multibranch Pipeline Job
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.intro=Create a Multibranch Pipeline in order to automatically analyze all your branches and pull requests.
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step1.sentence=From Jenkins' dashboard, click {new_item} and create a {type}.
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step1.sentence.new_item=New Item
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step1.sentence.type=Multibranch Pipeline Job
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.sentence=Under {tab}, add a Bitbucket source and enter the following information:
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.sentence.tab=Branch Sources
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.server.label=Server
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.server.action=select the instance hosting the repository you want to analyze.
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.creds.label=Credentials
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.creds.action=select the Bitbucket Server credentials.
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.owner.label=Owner
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.owner.action=enter your project key.
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.repo.label=Repository
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.repo.action=select the repository you want to analyze.
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.behaviour.label=Behavior
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step2.behaviour.action=select Exclude branches that are also filed as PRs.
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.sentence=Jump to the {tab} section and set the following parameters:
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.sentence.tab=Build Configuration
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.mode.label=Mode
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.mode.action=by Jenkinsfile
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.script_path.label=Script Path
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step3.script_path.action=Jenkinsfile
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step4.sentence=Click {save}.
+onboarding.tutorial.with.jenkins.multi_branch_pipeline.step4.sentence.save=Save
+onboarding.tutorial.with.jenkins.bitbucket_webhook.title=Create a Bitbucket Server Webhook
+onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.sentence=Create a Webhook in your repository to trigger the Jenkins job on push. Already have a Webhook configured? {link}
+onboarding.tutorial.with.jenkins.bitbucket_webhook.intro.link=Skip this step.
+onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.sentence=Go to the {link} and enter the following information:
+onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.link=Bitbucket Server Webhook creation page for your repository
+onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.name.label=Name
+onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.name.action=give a unique name.
+onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.url.label=URL
+onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.url.action=Enter the following URL, replacing the tokens as needed:
+onboarding.tutorial.with.jenkins.bitbucket_webhook.step1.url.warning=The Bitbucket Server URL must be identical to the one in your Jenkins configuration. Watch out for any missing or extra "/" at the end.
+onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.sentence=Under {events}, make sure the following options are checked:
+onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.sentence.events=Events
+onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.repo.label=Repository
+onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.repo.action=Push
+onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.pr.label=Pull Request
+onboarding.tutorial.with.jenkins.bitbucket_webhook.step2.pr.action=Opened
+onboarding.tutorial.with.jenkins.bitbucket_webhook.step3.sentence=Click {create}.
+onboarding.tutorial.with.jenkins.bitbucket_webhook.step3.sentence.create=Create
+onboarding.tutorial.with.jenkins.jenkinsfile.title=Create a Jenkinsfile
+onboarding.tutorial.with.jenkins.jenkinsfile.jenkinsfile_step.sentence=Create a {file} file in your repository and paste the following code:
+onboarding.tutorial.with.jenkins.jenkinsfile.maven.step2.sentence=Add the following to your {file} file:
+onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.replace.sentence=Make sure to replace {default} with the name you gave to your Maven tool {in_jenkins}.
+onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.replace.sentence.default=Default Maven
+onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.replace.sentence.in_jenkins=in Jenkins
+onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.help1.sentence=To get the name of your Maven tool in Jenkins, navigate to {path}.
+onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.help1.sentence.path=Manage Jenkins > Global Tool Configuration
+onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.help2.sentence=The name is located under the {path} section, in the {name} field.
+onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.help2.sentence.path=Maven > Maven installations
+onboarding.tutorial.with.jenkins.jenkinsfile.maven.step3.help2.sentence.name=Name
+onboarding.tutorial.with.jenkins.jenkinsfile.gradle.step2.sentence=Add the following to your {file} file:
+onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.replace.sentence=Make sure to replace {default_msbuild} and {default_scanner} with the names you gave to your MSBuild and SonarScanner for MSBuild tools {in_jenkins}.
+onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.replace.sentence.default_msbuild=Default MSBuild
+onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.replace.sentence.default_scanner=SonarScanner for MSBuild
+onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.replace.sentence.in_jenkins=in Jenkins
+onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help1.sentence=To get the name of these tools in Jenkins, navigate to {path}.
+onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help1.sentence.path=Manage Jenkins > Global Tool Configuration
+onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help2.sentence=For your MSBuild tool, the name is located under the {path} section, in the {name} field.
+onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help2.sentence.path=MSBuild > MSBuild installations
+onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help2.sentence.name=Name
+onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help3.sentence=For your SonarScanner for MSBuild tool, the name is located under the {path} section, in the {name} field.
+onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help3.sentence.path=SonarScanner for MSBuild > SonarScanner for MSBuild installations
+onboarding.tutorial.with.jenkins.jenkinsfile.msbuild.step2.help3.sentence.name=Name
+onboarding.tutorial.with.jenkins.jenkinsfile.other.step2.sentence=Create a {file} file in your repository and paste the following code:
+onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.replace.sentence=Make sure to replace {default} with the name you gave to your SonarQube Scanner tool {in_jenkins}.
+onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.replace.sentence.default=SonarScanner
+onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.replace.sentence.in_jenkins=in Jenkins
+onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help1.sentence=To get the name of your SonarQube Scanner tool in Jenkins, navigate to {path}.
+onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help1.sentence.path=Manage Jenkins > Global Tool Configuration
+onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help2.sentence=The name is located under the {path} section, in the {name} field.
+onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help2.sentence.path=SonarQube Scanner > SonarQube Scanner installations
+onboarding.tutorial.with.jenkins.jenkinsfile.other.step3.help2.sentence.name=Name
+onboarding.tutorial.with.jenkins.all_set.sentence={all_set} and ready to improve the quality and security of your code!
+onboarding.tutorial.with.jenkins.all_set.sentence.all_set=You're all set
+onboarding.tutorial.with.jenkins.commit=Commit and push your code to start the analysis.
+onboarding.tutorial.with.jenkins.commit.why=Each new push you make on your branches or pull requests will trigger a new analysis in SonarQube.
+onboarding.tutorial.with.jenkins.refresh=This page will then refresh with your analysis results.
+onboarding.tutorial.with.jenkins.refresh.why=If the page doesn't refresh after a while, please double-check the analysis configuration.
+
#------------------------------------------------------------------------------
#
# BRANCHES