Nx After Dark: Implementing the CO2 forecast feature

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello welcome to nx after dark it is just after dark in denmark and uh today we're going to continue on the first feature of the energy insights angular app that's the co2 forecast feature and uh let's get into looking at first some data about the danish electricity grid today it's going to be just below what we're considering uh a green electricity uh producing day or at least the next eight hours and right now we're running on 58 wind and solar electricity in the grid and here's the let's get into the live view i'm going to find the english version and here's the link here we go okay so right now we're producing hello bill welcome glad you like it trying to do something meaningful meaningful and hopefully you'll all learn something from watching me work on this right now we have just above two gigawatts of uh wind uh power being produced and uh we have just short of 900 megawatts of non-green electricity being produced in denmark and for the exchange we're importing from norway from sweden more from sweden to eastern denmark exporting from eastern denmark to germany and exporting to the netherlands exporting to germany from western denmark so let's see we have what's the net exchange oh so we're actually importing 400 megawatts more than we're exporting so we're adding energy to our electricity grid right now in this moment so that's interesting and yeah currently on 61 grams of co2 emitted per kilowatt hour produced okay oh that's interesting okay so the data set we're using you can find it here from the energy data service the decay is co2 emissions and these are the historical data these are the forecast data we're working at uh or we're working with so basically this is what we want to see something like this initially and let's check out or let's see here let's make a filter we want the current date it's the 24th of may and this is an exclusive end range so we have to go to what days two days forward here to get uh tomorrow as well and we're ascended sorted ascending so that the oldest data is first and so that it comes in chronological order instead of the reverse chronological order so when we do this we see that we have 1152 rows because there's two prize areas dk1 which is western denmark and dk2 is eastern denmark and we're working with five minute intervals as we can see here so this should should all add up if you add the numbers of numbers of hours let's just make sure here um that yeah we're getting the final oh yeah okay so there's actually a buck here and or oh no okay my bad we are getting the final five minute interval of tomorrow as well and that is made available after 3 p.m in the afternoon and that now we're at night quarter to 10 so that's why we can see the forecast for tomorrow so yeah this is the data we want so let's let's go back to the first page here it's showing i don't know i don't know how many it's showing at a time but i want to pick up the query here so i'll hit submit again and here we can see the query or the http request they're sending and they're using this can data provider so that they have a sql query string parameter which has a postgres sql selector inside of it so i just want to make sure that we're doing something like this with our code because we had some issue yesterday that we're going to look into and an important thing is how it's being url encoded so we should also be looking at this raw request url where we can see that this is a space it's a percentage 20 and if we go to the console here you can see that e code uri component give it percentage 20 will give us back a space character you can see the next one is percentage 22 that would be the double quotes as you can see here and when the string is in double quotes it will escape this the double quote string but we could do like so or sorry like so uh no apparently not because the browser console is insisting on turning it into a double quoted string and then it has to escape the double quote to display it okay anything else uh another space no another double quote another space are there any other um yeah this one 27 right i wonder what that is let's just check i think i know what it is uh single quote because this is the where the date time string the iso 8601 string starts and this is where it ends then there's another space should also see maybe uh greater than smaller than symbols maybe this one right this would be the yeah i wonder 3c is that greater than or smaller than that smaller than okay so we should see something like this in our own request being sent so let's try start up the app but first let's see what bill is saying here okay i heard that copenhagen does not counter exclusive co2 emissions anything i know about well i don't actually know what cash drop co2 emissions is let's google that yes i can't spell right now you're talking about the airport caster with a k and this is danish google results right here saying that castro the copenhagen airport is co2 neutral well that's exactly the kind of thing we're trying to challenge at my workplace my employer this is what you call green washing when you say that you're co2 neutral but maybe you're buying a certificate that tells you that green energy was produced at some time during a year maybe you're planting some trees on halfway around the earth but that's not really doing anything about your own co2 emissions so that's what we call green washing and the big tech companies the big cloud providers are doing exactly the same thing yeah facebook as well facebook google apple microsoft they're all building green data centers in denmark and i don't know which energy they're using uh when when we're not running on 100 clean energy as we saw here on the front page of energy net energynet dk because we're of course we're not really running on 100 um no energy data service sorry rally running on 100 green or renewable energy uh right now it's night time so we're on 58 wind and solar and there's a few other sources you might consider renewable depending on your your definition of that so you are saying they do not count or excludes cash drop co2 missions okay i'll try to translate i haven't haven't heard about this i tried to translate what they are claiming here on the the castro airport website or there's an english version and now it went away from the co2 page you can find it future no neutral airport but then it switches to danish page there's no english page for this and i can't really hit google translate because i've specifically added ask it not to translate danish i guess um okay it's saying that the copenhagen airport's climate strategy uh what was to become a ceo to neutral airport and we became bad in 2019 work doesn't stop here our ambitions are big wow uh promotion um it takes a continuous big focus on reductio reducing the emissions we have a direct influence on okay so they have been certified by the international airport certification program called the airport carbon accreditation i wonder who's playing for that yeah okay so this is a bunch of bs in my book this is what we call green washing do they have planes not emitting co2 no they're not co2 neutral do they have planes running on electricity i doubt it even if they were our electricity is not green not a hundred percent uh there's this new thing power to x where we're building and especially in denmark we're starting to build some some big facilities for producing hydrogen uh heavy fuel that might be used with planes for example or trucks or boats or ships or whatever um i'm producing it based on almost solely based on on electricity right of course needs some raw material but yeah the the energy source is electricity so when there's a surplus in the electricity grid uh we can turn that into something i guess like storing energy right rather than having to export it or even shut down wind turbines or solar farms which we want to avoid right so yeah my i mean i don't know the details about this but yeah it seems like they have just bought a certificate and now they're claiming to be co2 neutral with which doesn't make sense at all okay let's get back to our app it's still nx after dark uh but we're working on this energy insights app uh so yeah i just want to give you some background and some domain knowledge what i want to do with this this app i want um yeah people have been talking about smart grid for decades at this point and it's not going to happen like denmark is uh sorry for stealing the focus from coding that's all right this is what i'm another thing i'm passionate about um but yeah even though denmark in some areas are trying to innovate like we're not going to have a smart grid it didn't happen it's not going to happen not a national scale uh and certainly not on a global scale and if you then narrow down to local or yeah local scale like national for denmark are you going to have manufacturers produce smart grid appliances for danish people and danish people only no that doesn't make sense what we can do however is we can use this one so we can be smart about our electricity consumption how would we do that so i have a washing machine i have a dryer i have a dishwasher and maybe a few other things like charging phones and laptops and whatnot ipads and all that um what if i time shifted that consumption of electricity until the few hours in the night where the the energy sources are the most green i have to do this uh to run my household um but i can manage like within a few hours when i want to do it most of the yeah most of the appliances like dishwashers washing machine dryers they have a delay uh program so i can delay it a certain amount of hours but how would i know which hours to do it in which are the most green well that's what i want to give insights to here with this web app because the data is out there but like i don't want to go into this this website every time and have a look at this i want it to be well first at first in a web app but i'm probably going or hopefully if i continue with this i'm going to make it into a progressive web app so that you can put it on your phone and always have it handy because you usually have your phone nearby so eventually i would like something like which hours will be the most green uh in the like tonight based on the forecasts so then you can go and be the smart the smart grid yourself on your own uh electricity consumption and say oh so i will delay the dishwasher i'll delay the washer i'll delay the dryer three hours and then i will spend the electricity or consume it in the hours that are the most green the most climate friendly and additionally it will most often be the cheapest hours for me because we're built by the hour there's there's a different price in each hour depending on the energy sources being used in that hour so that's my vision for this project additionally my my father my dad works in a small central heating plant and they produce power as a site effect or byproduct of producing heat so they sell that on the market but they also have an electricity based uh heat pump and in electricity or i don't i don't think he has but some of his colleagues has but he has um on his work uh what's how to say that like a boiler an electric boiler uh so that he can heat up water and store it in his um i don't know if the english term is also an accumulation tank but a huge reservoir of water where they store the heated energy and in the water and they can that can last throughout the night for some hours maybe six seven eight hours or so or so so for him it's a matter of when is the well he looks at mostly at the price i wanted to also look at the climate effect um because they go hand in hand so to him it's a matter of what is the cheapest energy source right now to me is it firing up my by my fossil fuel uh boiler or is it running on the electricity driven one and uh yeah so that's the kind of math he's doing he's doing that several times per day each day seven seven days a week uh so i want him to be able to easily see in which hours are is the electricity going to be cheap and green and then he can plan on um yeah then he can say to the grid i'm going to be able to consume this many megawatts of electricity rather than having to supply fossil fuel electricity um into the system so that's a lot better for the grid for the climate and even for um so in the the centralized heat plants the consumers are actually the owners they all have a share um in the company that's kind of interesting uh but yeah it'll be cheaper for them as well if he he does this so i want to help him out with that and and hopefully it can also like it can be for me and others private persons and for other like him on a small central heat plant that can yeah take good make good decisions for their owners the consumers and both for mo both money wise so the electricity or sorry the heat is cheaper but also for for the climate so yeah many concerns uh to take into account but that's the background for this project and starting out small but we'll get there eventually right okay let's uh start it up i believe i already did um here we were working on this htp client because we hooked up the ui but some things seem to be off so let's open the app it's an angular app using nx12 and angular 12. and i need a drink a sip of water excuse me okay so there is no data here uh so something went wrong go to the console you can see that it's a 400 status code bad request so i wonder what i did wrong right let's refresh if i can hit the button here it is okay so what's wrong let's look at the decoded sql parameter here select i mean maybe my ass syntax is off here i'm not i don't do much um sequel anymore but you know what here's the problem at least one problem so we d we encoded the plus signs manually yesterday but seems like they were already encoded because now they're encoded twice so that's that's not too good so let's start by removing that and see what happens so it's rebuilding i should have added hot module replacement i will enable that some other time okay now let's look at the decoded sql parameter oh yeah oh yeah here is an issue because this is now a space character where it should be plus when it's decoded so let's look at the raw format here yeah plus okay this is a bit annoying because this should be encoded but when i encoded it before it seems like it was encoded too many times right because it didn't become a plus down here and that decoded thingy uh what are you saying bill if you're interested what i was referring to was a documentary i watched on swedish television by greta tunberg you can find a watch it for free here requires swedish vpn i assume what's it called bill tell me the name and i'll be happy to watch it if i can access it from denmark but yeah there like there's many factors going into co2 like as a company for example if you wanted to to make a sorry we're going getting sidetracked again but this is my passion i'm by no means an expert but i do apply whatever knowledge i have um there's many factors like if as a company first of all electricity is not your only energy source you also have heat yeah you have electricity you have heat you have water and you can even go beyond that and say you also have yeah for the fresh water they are consuming electricity to filter that water for you so should you also take that into account right uh greater listener listener means what i'm not sure uh enzapo mai uh means uh well depending on the first word my is me paul is on intel is not third episode she visits denmark uh episode 3 one year of pandemic don't listen to me yeah that's what i thought this night to pomade don't listen to me okay so i'll try to find those i mean people are criticizing kaita i think at the very least she's inspiring other people and you can say what you want about her not being like go and do actual activism rather than tweeting about it i don't know she's inspiring people that's also good it brings attention to an important topic yeah but what i wanted to say was you have several energy sources not only electricity so if you only look at one of them you're missing the big picture and she wants us to listen to the scientist not her yeah well that's uh that's what you get when people start to criticize you for yeah not like speaking about things you know nothing about or whatever um not that i'm saying that about her uh i i admire her for what she's doing but yeah you have you have fresh water supply that spends energy you have central heating or your own heating that's also an energy source and depending on what is like the fuel or the source for that that also emits uh greenhouse gases and whatnot um and you have um the dimension which one did i mention electricity so you have to take all of that into account to see like what's your effect on the climate as a company or as a private person even uh but you can go even further right you can say uh yeah we're running on solar power that's great we're running on wind turbines that's great free green energy right but a lot of energy was spent manufacturing um installing and servicing those energy producers say the wind turbines many of them are growing offshore because that's where you can build the big ones and you have the high volumes of energy and you're not annoying the neighbors by by installing a 200 meter tall windmill with even bigger wings um so they're a lot of fuel a lot of fossil fuel goes into manufacturing and transportation servicing especially on the water right so it's very expensive it takes a lot of energy even to get that first kilowatt hour of electricity produced so in reality we should look at what's the expected lifetime of that windmill and how much energy is spent on installing and servicing and manufacturing it and then we should like have a quota per kilowatt of energy i'm consuming because it might be it might not be my direct emission of greenhouse gases but it took some energy to to get that and to maintain that energy source that should also be taken into account if you want to a truer number of your effect on the climate and yeah that's for wind turbines same for solar they are like their solar cells have let's see i don't yeah i don't remember because i'm i'm also usually i'm looking into solar panels for heat and they're using more of a they're using more glass but that's a special there's also a special kind of glass where you have to use special kinds of sand and they're like digging up entire islands entire islands are being removed from the surface of the planet to dig for sand to melt into glass for solar panels and solar cells so that's not very green either uh all of those machines digging and transporting around the world and all that so that energy is not clean it was dirty before it even was fired up the first time those energy sources so yeah something to keep in mind but it all starts in my opinion with insights insights into what am i doing like what is my consumption and which hours and how can i um is can i can i change that in some way is there a better time to be spending that energy or of course even better don't spend it at all so yeah a bit of background about this this project okay so i have an issue here with the plus sign or plus two hours um i think i'm going to make a quick fix here and um convert it into utc uh plus zero so that would be c uh and i think that's what the same as what we would see here we'd also see them they're using the c or the set which means utc plus zero so we can convert our uh using our we're using the luxon the time library so we should be able to convert it into the ucc offset of zero so this should become instead of midnight it should become 22 hours on the 23rd of may utc time but yeah the date time library should be able to manage that for us what am i doing here i'm trying to find the editor here it is uh so yeah deleting this url and code function we were working on uh yesterday i think and let's have this okay so we're we're doing a query here but is this the place you want to yeah maybe this is the right place to convert into utc because it is because of this query parameter that we have to do it in general it shouldn't matter because they're representing the same moment in time but here there is an issue because of the url encoding so i will i already have it this interval data type is from luxon so i should be able to take this one and say uh yeah like convert or zone something about so yeah set zone that should convert it hopefully oh by default the setter keeps the underlying time the same ah but the new instance will report different local times and consider data settings [Music] to you to see okay there's a 2u to see what we want in this case okay i can't hit the buttons at all today or the right keys okay so now we have a test failing uh because this is not what we're expecting let's let's see in the app here and then we'll correct the test yeah now it works great let's look at what we got out here so now it converted it to the z or set which is the plus zero hours utc offset and the time was also moved to 2200 hours and in both cases and the date was one day earlier because it's utc time instead of danish local time so now we actually have some numbers here let's just have a quick look zoom in a bit and okay the date pipe i should give them some more parameters so i can see the whole thing i'm using the angular date pipe and i also seem to remember that i did a nasty thing i used logic in the template which is something we really want to avoid let's let's get the time as well though in the first place here let's go to our feature library shut this one down uh feature forecast the forecast single file component and here we're using the date pipe so let's look at parameters for the date type so to get give a different format angular yeah i like angular logos but annoying that it's the default one i didn't think i used it that much datepipe here it is let's see the format we can use oh okay so here's also something about the time zone and this is where the date pipe is actually awful uh and yeah i don't want to explain why right now but um well i can it only supports uh us time zone shorthands or you have to do like plus 02 hours of utc or minus one hour or whatever so i can't really tell it what's the use the danish local time because sometimes it's plus one hour sometimes plus two hours so it's it sucks the date pipe in this um yeah at least in this concern okay formats where the other formats um here they are so what do we want to see which format uh oh that's not at all what i'm looking for actually uh oh this one looks good since it has the utc offset as well yeah let's let's use this one so the option is long but we could also customize it in some of these formatting symbols but long we'll use long for now and see how what that looks like so to pass in an an option for an angular pipe we do the colon sign and it's a string and it's a string of long i hit save and printer will put in a space character here for some reason so let's see what that looks like yeah okay good i mean this is not a very good format but yeah i want to put it in a chart anyways and not in a table uh maybe both at some point right now this is just temporary uh to to make it work and then we'll add an and chart to it as well so midnight that is 12 a.m uh we in dk one we had 66 grams of co2 equivalent um per kilowatt hour of electricity produced same in dk2 and yeah this is i think i mentioned this before right now they're not doing it per the western and eastern denmark they're doing an average between them so they will always be the same hopefully that will change at some point and our app will be ready for that so yeah let's look at here some low values be below 80 or at 80 it's good but here at 2am on may 24th that's today wait yeah okay so it was 88 according to the forecast at least there is also historical numbers the actual numbers so they might be different this was the forecast um let's go and look at them tomorrow instead that's the 25th of may scrolling down there's actually a lot here when you have five minute intervals here we go midnight 67 let's look at five o'clock sometimes that's when uh it starts to get bad or non-green uh look at five am yeah this is where it crosses 80 for the first time so now with 81. so let's look at i think seven in the morning is usually when the consumption really starts to go high so let's find that but here it is oh below 80. that's a good forecast let's hope it holds now let's go to eight or nine o'clock eight still below eighty that's good oh but yeah as soon as we get past eight in the morning numbers start to climb and now they're getting relatively bad right um yeah but oh here it's really bad one o'clock uh in the afternoon 160 oh even worse here so maybe it's not as windy or there's not a lot of sun in this place so maybe we should add a weather forecast to to the app at some point so you can kind of correlate these things to to try to make sense of it if you want to then to learn about what like what affects the co2 emissions in our electricity grid good we have the data wow this is a long list this will look a lot nicer as a chart um and then we'll we'll have a look at whether we should keep it at five minute intervals or we should um aggregate it into say quarters or hours or something but yeah at least we we fixed the issue of not loading the data because of that url encoding so now let's look at our tests and i'm using wallaby js a paid product which is here and has a side panel here for vs code works for other browsers as well and i'm not uh being paid to promote them i just like them and pay for it been using it for year years um so here here's a failing test there's two i can control click here to jump to it and here it is and it's because this one expected the iso value of this so you know what let me put in the this actual literal value here um so that will make it a bit easier to see what's going on so we'll convert to the utc plus zero and then we should turn back the date one so on 22nd and it will be 22 hours right this is something still wrong um let's see uh let me i can focus on this test here using wallaby and so now i know the output is only from this test it's also over here in line but i'm at a big zoom level so it's a bit difficult to read for me but i can easily see it down here okay so it's looking for this sub string and this is what it's getting so here okay so it's adding milliseconds so i should have that as well here in my expected string right are you giving me more trouble i don't hope so um let's see oh was this the maybe i took the start date yeah i took the start date instead of the end date of the part of the interval converting it to utc plus zero adding milliseconds going back one day and then to 2200 hours 22. now it's green wallabies tell me it's passing now yes wallaby is free for open source that's right i should remember to mention that um yeah for open source projects it's free fully featured fully free but it will detect which repos you're working on if you're using the free version so don't go and try to cheat because it won't work it will actually look if if the repos you're you're working on have a public repo on github or anything like that and to get a license go to wallabyjs.com and all you have to do is enter your email address if you want to apply for the open source license um i actually don't remember how i mean google for wallaby oss and you should be able to find that license but all you have to do is enter your email address they'll send you a license key and you'll open up the command palette here and say wallaby license and i don't want to show my license because that's a paid one but here you'll be able to enter that which has been emailed to you and that's all you need no credit cards no verification process because all of you will be checking that you're actually using it for open source projects exclusively so that's a good trade-off um and gives you some gives you a chance to try it out uh just create a repo on github and use it for that that now you have open source right a public repo on github is all you need and it's a lovely tool removing this test filter and now we have one more failing test let's jump to that here it is and it's probably the same issue but with the start part of the interval so now let me take the start i'm here and adding the milliseconds turning it into the utc zero hours out offset by winding back time two hours and shifting the date great now my tests are passing again everything is green here in the gutter and if you're sorry i should share my screen again my bad uh yeah i did the same thing here i took this start interval now and put it down here and converted it to the utc offset and now what i'll be showing you over here that it's passing these are green if you have a color deficiency of some sort you can customize the colors so that they're not red and green because that's the most common uh color deficiency so at least they took that into account lots of products dealt including the ones we're building ourselves so so yeah good thing red and green green not good colors for color deficiencies and i believe that on average 25 of all male adults have a color color deficiency and most of them are red green deficiencies good test our passing so let's see what we have done and try to turn it into a commit we have let's see noth anything change here maybe i i deleted a line a blank line i want to keep that so there is no changes here but in this component i changed the date format that can be a separate commit play date and time in co2 forecast here we are um let's see we are convert interval to utc ideally i should leave a comment here explaining why that's actually good not a bad idea let me let me do that but this is a big multi-line string so i can add the comment here so i'll add it as a js doc instead vote to self um converting to utc time zone because of issues with url encoding the plus character there we go and i think the tests are just taking that into account right yeah good here we go here we go pushing this what's our next step what's our next step so we have an app and currently i have a table i seem to remember that i was not very good at making this table so let's go into our feature forecast library look at the presentational component yeah look at me i did manage to do the t-head but i forgot to do the t-body people body and html is forgiving enough that it will do it for you your browser will work too much but at least try to to make it right good okay you know what let's have a look at our layers uh by using the nx dependency graph let's see how it's now connected in our angular app look at this look at this we have our angular app and it's importing our co2 feature the forecast feature in the co2 domain library it has the scope of co2 the type of feature and that is referencing the co2 domain library it's using the co2 data access library which is also referencing that domain library and the data access is then using the util date time utilities here and we have these root level libraries as well and we're going to have to connect them to the app but we'll have to do that manually and that's for another feature now we can start to see the layers here we have the app it's importing a feature feature depending on the data access library and that isn't turned um yeah those are our main layers here well the app is not really a layer it's kind of the main file or the entry point of our application the app project shouldn't be much more than that and it really isn't in our case so our top layer is presentation that's our feature library the feature library has smart components and routed components and page components and a ui library would have presentational components so those two would be our presentation layer and this is our persistence and state management layer right here the data access library and everything else is just implementation details uh except this is actually our domain layer here even though it it just holds an interface at this point so that is really good a good overview uh you could also take for example the feature here focus on it and now it will display only the the libraries or the projects that are connected in the dependency graph to to this project include projects and path didn't do anything i don't remember what that's supposed to do group by folder is nice because now we can see our grouping folders we have this youtube grouping folders with all of these libraries and the root grouping folder for the root level libraries one-off libraries here this is also a nice view can't click on anything here apparently but yeah this is a nice view as well could easily see if something was out of place right so this is our co2 domain or bounded context or sub domain or whatever you want to call it or just grouping folder that's youtube grouping folder holding all these projects that are related good that's the nx dependency graph the tool you can also see the effect that dependency graph to see what your branch or your pull request is affecting which libraries are touched by the code being changed and which libraries or other projects are depending on the code being changed so let's shut down this app don't think we're going to need that right now let's display wallaby again and what's our next move maybe we should start testing this component because i don't believe we added any tests let's just make sure let's look at our wallaby app oh we're down to 98 test coverage look at that very bad so and where's the culprit who's who's um whose fault is it how are the utilities oh what do we have here that's not tested oh update today that's probably because it's never being used is it no it's not not right now so yeah one i guess we could delete that we'll actually do that um danish date store because this is never ever been called right now private method so it's not like it's going to be tested individually it's an implementation detail so rather it is it would be tested covered by test if if it was being used in any other of the public methods or or properties remove the unused updater and let's have another look at that test coverage now we have a hundred percent here and in fact we have a hundred percent test coverage in all of the app something is wrong because there's no feature uh library here so this is only displaying the files that are covered by test or touch by tests so do we actually not they're not listed here either no okay so yeah we don't have any tests in the feature library and yeah maybe that's what we want to do now see not using track buy in ng4 you might explain when one needs that or when it's beneficial that's good for if you have data that's updating a lot or you have a very long list or both and this is a pretty long list but it's only like a thousand elements or so or a thousand rows but yeah um it's just this is a temporary uh solution uh so i'm not adding track uh by but yeah you're right i should have added the track by here to the ng4 uh but then comes the issue of what would identify this data point and we actually don't have that if we go to the sorry not this one if we go to the co2 forecast domain uh our interface here we don't have anything to identify this data point or this forecast so we wouldn't be able to use the track by so yeah we don't have like a serial number um or id or anything like that to represent this data point or the whole forecast the whole time series so we actually wouldn't be able to use track by in this case well one thing we could do to track by we would have to like make a hash of the whole thing or maybe the json representation because that's a kind of a unique string right so that's what we could do but i don't know if that will be better because like calculating json representation of every object in that thousand object that's that's also a heavy computation task kind of so not sure that would be better in our case wouldn't index be better than nothing no because the index would remain the same even if the values were changing the co2 emission values for example when we get updated data price area will stay the same minutes 5 the date time will stay the same but the co2 emission will change maybe but it's not like we can use the co2 emission as the identifier here um so [Music] and we cannot use a combination of the date time and the price area we would have to include all of them actually so that that's a that's not really a a good thing i mean we could add a unique id but we would have to generate it ourselves so it's not something that's coming from the server so it's not really of any use so the only thing that we could use here from my perspective is the json representation of each object or each data structure here but not sure that's going to be better since we would have to make heavy computations on a thousand objects there yeah but i'm going to use the solution is to use a a package that takes all of this into account and that's going to be ag grid so hopefully that will help me out i'm going to use their data table and their chart initially i just want to display a chart actually then i'll think about adding a table view as well so hopefully the ag grid community edition will serve me well and has what i it will have what i need here okay so i actually think the next step here is testing starting to test this but i have to keep in mind here that i'm going to replace this html table with a g grid chart so i don't really want to spend time testing this table it's going to be replaced in this pull request so let's look if there's anything here that makes sense to to test we have an input uh yeah that's basically it that's all of our component model and we have some nasty um logic in the template uh so yeah so the okay so where where should this belong this shouldn't be in the template that's the worst place to put a logic like this so should it be here in the presentational component model no it should if if we wanted it here in this part of the app should be in a presenter service but even better it could be in the container component because that's supposed to do the mapping if our presentational component wants the data in another format but then now is the question do we want it in another format and this is our best data structure right now to represent a data point of a co2 forecast but it's not the data we need we need that date because what we have is the date time from luxon and the date pipe of angular doesn't support that so we would have to create our own date pipe and also probably ag grid doesn't understand luxon either so when we're using ag grid for a chart we're also going to have to convert it into a javascript date so so yeah it seems like we're we're not going to need the um the date time data type here from luxon if we needed to manipulate the date here um other than formatting uh we should keep it as date time because i i don't really want to use the native js date um for any data date time manipulation in this app i want to use the library for that but this class doesn't need to do any manipulation so it it would be good to just pause the date instances instead and if that's the rod we're going to take we should do it in our container component that should be the one doing the mapping here so but now comes the issue that then we need a special interface here for that format the data structure we want in in our co2 forecast so what would that look like yeah we probably need to map it even more to turn it into something that the chart uh understands so i'm actually going to postpone this until we start implementing uh the chart using ag grid because then we can see which properties in which type of array does it accept and then we'll do that mapping in the container component so that the the presentational component is only concerned about presentation formatting and not about mapping a data structure that's a different concern so postponing that for a while keeping it here in the in the template for now even though that's a very very bad practice instead is there anything we can test right now well there is one thing we can test this to test this nullability thing that we're assigning a default of empty we could also test that initially the forecast is empty and empty array but this is kind of like it doesn't really add any value um so the only other thing which could test is the table and i'm going to we're going to replace that very soon so i don't want to add test for that and the title is also just there temporarily so i don't want to add tests for that either so instead let's focus on the the container component starting to add test for that and that is using the co2 forecast store and right now it's exposing a public variable a public observable property rather called forecast dollar the finish rxjs notation with that dollar sign so let's add a test suite for this one same name but then that spec in front of ts let's open them side by side and let's start by importing the subject under test the class we want to test here container there's also a scam single component angular module and to describe the name of that class that's the class the subject under test that will appear in our test reports this name but yeah just on a side note this is good for tests but don't try to use this at runtime because angular goes and minifies the class names so it will be rubbish the name will not be co2 forecast container component in a production build most likely so don't try to use the name in any of your code at runtime only use it in tests or for something during development like something debugging in development mode that's the only places where you should use the name of a class in an angular app okay so what are we going to need this is a container component so it shouldn't depend on its template this is its template but there should be nothing worth testing here since it should only be displaying and binding against some presentational components so we should be focusing our test on the component model which is the class here and there's one more interesting thing here that it provides to co2 forecast store um so one of the slow things about using the test bed is the compilation of templates and their sub templates and so on so we're going to test this not as a component with a ui but as a class but we're going to use the dependency injection system of angular which yeah which is the reason we're using the test bed still even though we're not testing it as a component with a with a template let's look what that let's see what that looks like i'm going to use uh before each hook here and i'm hitting the wrong keys on my keyboard um so this is a function that will be called before each test case let's add a test case page case and a test cage i don't know what that is and when i yeah let's just add a placeholder here it works now we have a test case while i'll be starting to become happy so before this callback this test case is being run the code inside of this one will be executed and also when we do the next one it works this function is called but before each is called again and by the way the order of these test cases is randomized so so that you're not yet to try to prevent that we're making test cases that depend on each other because they shouldn't this is the known as the test setup phase where we're setting up the environment the testing environment for our test case and in our case uh when testing angular it's often about configuring the testing module but yeah and then after that you'll usually do testbed.createcomponent this is what we're not going to do here usually you would do that and pass the component name but this is not what we're avoiding to do here because we don't need the template and this is an expensive operation compiling the template and all the child components and so on so let's not do that instead we will do like so we will have a shared variable called container the type of the class we're testing here then we'll do container is assigned to testbed.inject and then the class here the type of the class this will create an instance of this class but it will ignore the template and the styles and all of this uh yeah only thing now is what about this view providers will that work i actually don't know let's find out see if there's an error here there is null injector error no provider for this component all right when we test a component as a class we think we have to add a provider for it what about the provider for this um co2 forecast store which is an ngrx component store will that be provided will that be picked up by the testbed i don't think so and yeah you can see here the container component depends on the co2 for forecast store it requires that and we can see that in the constructor so angular doesn't know how to instantiate this one because when we're not testing it as a component by calling testbet create component it doesn't take these component options metadata options into account so it's not picking up this view providers so we'll have to add that as well ourselves here now comes the question does the co2 forecast store itself have some dependencies and yeah it has it has http client so now like we're going down the dependency chain here um so now we have to and http client is not a service we can just provide on its own we have to import now a module because it has a lot of dependencies itself so here we will add the http client testing module which um so that it can resolve the hp client and we can control or simulate or emulate or stop out the response in the test the response from the server okay you're asking here bill what's the naming convention or pound design you use as a prefix to some variables only for stores now this is um this is the real private member syntax for ecmascript which is finally fully supported in typescript as a version four two a four three and we're on four two here in the newest version of nx and angular 12. yeah what was remaining was an issue with you can also do them for methods my private method there was an issue with that in typescript and might still be here in 4-2 yeah so it's still an issue in typescript 4-2 i'm going i'm not going to i'm going to make them private instead for methods i think this was solved in textbook 4 3 though so i'll be using that in the future so yeah i prefer ecmascript features rather than made up typescript features so this is a you can consider it the same as if it said private here private if i can spell instead of the hashtag but the hashtag is actually a real private member so it's runtime private which the type of private access modifier is not so in my opinion it's better and i'd like to stick to the ecmascript standards when there's like when you can if there's two standards competing i'll pick ecmascript that's also how we got to imports and exports module system because typescript used to have its own module system which was just global objects now today they call them namespaces and no one uses them anymore but in typescript one that was all there was this module system which has now been renamed to namespace which is just a global object because that's how we did in the dark ages of javascript so always bet on the ecmascript standard if you have two competing standards between ecmascript and typescript so i started to use the private fields from ecmascript rather than the private access modifiers from typescript yes and you will use them like so you will say this dot and then the hashtag signifier so one one tradeoff here is that i cannot do it like so whereas if i would use think private i could say it here and then i wouldn't have to do this this is again another thing that typescript made up it's not an ecmascript syntax or standard so i'm okay with that that's that's an okay um enough for me and in fact this is standard ecmascript this is some this is some syntax sugar and magic from typescript so i'm okay with that trade-off so at runtime if you had a reference to an instance of this component container component you wouldn't be able to access this co2 forecast store property so that's actual runtime privacy so just a personal preference and this became available in typescript 373839 something like that with angular 9 10 or so but there has been some issues uh with the typescript implementation of this for a while and it's only finally fixed in four three of typescript the method part the private method part so i'm using the private fields here for now okay enough about that let's move on with the tests so now we have mentioned or taken care of all the dependencies we have provided the container component which is kind of strange but it's because we want to avoid compiling the compiling it as a component with a template because that's an expensive relatively expensive operation and we shouldn't be if we're testing the component of a container component it's not a container component uh in that case you actually have a mixed proponent despite your best efforts so you should look into that okay so this is our setup for the for every test case and now we should be focusing on testing something and what do we have to test we can't test the private property it's also just the dependency so it's not really worth testing right and yeah looking at it here where are we referencing this only here so actually we don't even need this private property just do like so why not now it's easier like there's no noise of a property that we don't even need because it's only used in the constructor to reference an observable and then it's not ever used since so for now this is actually a better implementation um less to consider less to fit into your brain so better uh yeah so what do we have to test well there's only one property so that's what we could test but what is there to say about this property well it is exactly like the forecast observable from the co2 forecast store so whenever something is emitted from the co2 forecast store same value will be emitted in well how did i do that dragging part of the name of a property okay that's very strange i didn't know vs code could do that um really can i drag and drop this is news to me wow look at that okay interesting what was i saying i was saying that currently everything there is to say about this property is that it will emit the same value as the forecast property on the co2 forecast store that's the only thing that is worth worth noting noting about this class this container component class right now so what do we want to test we want to test deleting this one it will we could let's start already now by adding a group of tests that are focusing on this forecast observable property so that when we add more properties we know that we have to add another group so that it's easier to yeah we can minimize it for example it's easier to to navigate this test suite this whole file so what do we want to test about the forecast dollar observable property it emits um value emitted by the co2 forecast store this is not something you should know as a consumer of this observable because the co2 forecaster is an implementation detail but this is a unit test um so so that's quite all right because this tells us how the data is flowing in the application how could we test this well if only there was a way to control this co2 forecast store let's go look at it so this is implemented by extending a component store from ngrx um is there a way to update this forecast when is this forecast updated so it's based on the forecast internal state that is represented by this interface i did it again um when is this updated let's see do we have an updater we do so now we can see all the sources of updates well there's an initial state here that is initialized in the constructor by using the super by calling the the component store constructor passing in an initial state object and yeah there's a question here i'll get to that in a moment in the chat what's the places it's being updated here two places right next to each other so every time our http client the co2 emission prognosis http client every time we get a response tab response is an rxjs operator from ngrx component store as well it accepts callbacks one for the success case and one for the failure path so if there's an error what happens we we clear the arrays the forecast array if is a good response a successful response we will put that into our internal state so we will update the forecast property and that in turn will emit a value through this forecast dollar observable so unfortunately this one is a private method so we can't call that directly in our test um maybe there is a mirror yeah since it is a component store a component store has a lot of dependencies that i don't recommend your components to depend on or use but they are there since i'm extending the component store not hiding it as a service dependency so maybe we can try to use those for for testing purposes yeah that might actually be a good plan because what i sometimes do is i add a stop store which is a class that has the same public of properties and methods but is used only for tests so that you can control the emissions of the different things and so on but maybe component store has something we can use for the tests our only issue here is it will it will also be running this effect uh because that's that's triggered or set up immediately here in in the constructor which is actually a bit of a code smell um so there's ways around this as well for now let's see if we can actually use this store um somehow in our tests so gpu forecast store [Music] um do we have access to that yes we do so we can also solve that instance the same instance our container component is using here from the test bed we pass it the name of the class that's the dependency injection symbol or token now we will have access to this instance as well so let's see if we can control it okay there's a question here from muzamil thank you for joining thank you for your question is it efficient way to use self component routing and query programs for pagination or what are the other options for packing nation okay uh let me try to get out of the zone of energy insights just a second let me read your question again is it okay is it good practice or is it a good technique to use self-component routing i wonder what okay maybe you could explain what is self-component routing and query params for pagination are there other options for pagination i guess i need to know what what is what is this you call self component routing query params that is a query string parameters right so that would be um i don't know what's what's the normal name for pagination maybe it would be offset and page size or something like that that would be query parameters or query string parameters or query params as it's called in the angular router but i'm i'm not sure what you mean by self component routing so please put that in the chat if you can explain it moving on for now uh okay what are we interested in we're interested in testing this co2 forecast dollar and uh i don't use rxjs marbles um i'm more of a low-level guy when it comes to testing rxjs observables simply because i haven't really used marvel so [Music] i just haven't gotten familiar with them and i don't really have an urgent need to use them because i get by in other ways so okay so for all tests in this group uh we're interested in testing the forecast dollar observable so let's start by creating an observer and we're using just here so this will be at what's called a just mock uh and it will call the forecast of server the type is just mock and then the see it's the return type of this function here return type and then it's an array of the arguments um since this is an observer to an observer shouldn't return anything so the return will be void but then the first argument will be whatever is emitted into that observer so in this case it would be this co2 forecast right so this is what we need so let's construct that we'll use another before each so now we have a layered test setup hooks before each you might remember we had one up here that will be run before this one this one will only be run for the test cases the it function calls here inside of this test group this describe block so everything inside of here before the functions are being called this test hook will be called before each but even before that this one will have been called and we will have access to these shared variables and inside of these test cases they will have access to this shared variable because it's using the function scope of this function body here so let's create this shared variable for these test cases forecast of server is adjust function that's it just need to type to be right and it will be as soon as we here it's it's adjust mark of any to any uh but here we assign it uh here so so inside of the test cases it will have the proper type but also now that we have it we can say we take our container instance and we take the forecast observable property and we subscribe to it and we use the forecast observer to take the emitted values here so this will be set up before this test case is being run but notice now that we're making a manual subscription and even in tests we should clean up we should un unsubscribe from any subscriptions we're making unless the observable is completing so we could do then we could do take one or we could do first because that will force both of them will force it to this observable to complete so it will unsubscribe rxjs will unsubscribe but what if we wanted to listen to multiple values here from this one so this is actually not a good a very robust solution for uh something that's shared between multiple test cases what we could do instead and what i usually do is let's make another shared globally shared for all the test cases a variable called subscription and it will use the rhjs class of subscription let's look at our import statements here that they're all all right they are except subscription oh yeah from arcgis so in our global before each test setup hook we will start by creating a subscription we can actually do a new subscription and what you would use that for is exactly this case down here so we will actually do subscription dot add and we will add the subscription that is returned from calling subscribe on another server it returns as we can see if i can find the type here here it returns a subscription so that subscription is kind of tied together with our original subscription and now we can after do a an after reach and it's a test tear down after each test case is being run this is the only test case we have right now after that has been run this block will be called this block will do subscription.unsubscribe so that will unsubscribe all the subscriptions that are connected to this subscription so all the ones we have added through the add method they will be unsubscribed so after each test case the subscriptions will be shut down if we remember to do subscription.add so now we have cleaned up our ref our resources here our observables as you would also need to do in an application you have to think in the same way in the tests see you bill thank you for hanging in here late at night okay let's look have another look at your question can we read that we can redirect on the same url same component with changed page number as query param is it a best practice or how would i implement pagination on an angular component okay so say we have a component we have one right here we could inject the and now i'll just do private the activated route activated route and from angular router and yeah so this if you wanted to do it programmatically say in yeah i don't know next page we'll do a method that's called next page you could do listed route but well we would also need the router not sharing the screen thank you bill i thought you went to bed yeah sorry back to yeah i'm taking a component here i'm injecting the activated route and actually also the router service this is the programmatic way of routing router now down here in our next page method we can do this that router navigate and we could pass it or rather let's do navigate by url and you're saying here was a mill you're saying we can redirect to the same components that would look like dot slash which means the same route as we're currently on we could also do dot dot that would mean the parent drop and then we can pass it here some navigation extras here extras and apparently they have been renamed to navigation behavior options that's a new thing probably in angular 12 and what do we have state skip location change replace url no no okay so maybe it's to navigate instead this was not what i was looking for navigate an array here and now you should have some more options yeah here they are so these are the navigation extras here we can do like query params and we should do relative to or yeah relative to and then we need to do this route which is the activated route service for the route yeah the route that activated this component so relative to and then something like the query params and say we had already in activated route page in the activated route we might have a program page or what is this this is an observable is there also did they remove the more imperative [Music] api for params or the maybe that's this one no paramap query param map is that also an observable yeah that's an observable of a curve ram map did they remove the imperative api all together yeah they did they did okay so i don't really want to like turn this into an observable and whatnot but let's say we had the page value so we'll do page plus one or something like that so hopefully this is something like what you're asking and the other option is in your template you would have like a say say a url here or an anchor element a link to next page this is the declarative way so we would have a router link and i'm not able to use that because i would need in my scan to import the router module now i'm able to use the router link directive hopefully apparently not right now but yeah good work it's just angular language service not being happy right now um that's actually an issue yeah sometimes when you do a single file component angle language servers get confused so trying to make it work here okay is an unknown property of a well it should be so here you could also do something like slash then there would be some other options on on router outer link let's try to find them okay you're yeah you understand what i'm trying to demonstrate here that's exactly how you use it but is it an effective way or is there another option okay um maybe another option would be if you had uh some ui library that that had a component for pagination for example let's check if there's an insurance screen again then let's check if there's something in angular material there's like a pagination something here paginator here it is um so this of course this is on the ui part so you would still have to yeah how can you add links to the next page but i think you're i think you're exactly right that yeah you would have to to to do the like you would have just to change the route whenever you click this uh i mean well it depends on do you want the ability to share whatever page you're on up in the url it's it's not very big in this stream sorry but i'll i'll um try to change that what can i do i can go to vs code this is the url right so but i want this um size 20 page one or offs it could also be offset 20 um but let's just say it's page one or page two um do you want this to be in the url um you want this in the url if you want people to be able to directly navigate to that place every time and does that make sense maybe for some data that doesn't change very much i mean if you're going to page 2 and you're seeing something different from the last time you visited um every time it might not even make a lot of sense so maybe shouldn't even do this at all if we had some table or something here with a paginator i mean the the the most important thing is that the list disable you would have here is is changing and if it's not important to be able to navigate to that exact page don't put it in the url putting stuff in the url is more work it's a very nice feature of of the web that we can store state in the url so that people can return to an exact state in our apps so but make sure it it's what you need for your app make sure it's it's a requirement that makes sense that it is indeed important for people to to go back to exactly the fifth page here in this result otherwise don't spend your time doing it let's say it is a requirement that makes sense for for your application then absolutely this something like this is the way to go um this is what this was the the programmatic api so something like this um yeah this is a good way to go um like you could probably like maybe you could expand the extract as logic to a service but then you would have to provide that service on the component level so that it can inject the component level activated route because the activator route is specific to each component in the component tree so it's not something you can inject on a global level because there is an instance per component that is currently active so yeah this is uh this is something what like what you would do um and then there's the declarative version where we'd use the router link and let's see if we can find some of the options here you would have similar um other link with hrev you would have similar options to what we had here in the the programmatic interface like query params and re even relative to i think you you do you need that hopefully you don't need that in in the template if you do you would have to provide it also with this um this activated route instance but let's see here if we have uh for example query params we do that means you could do what's the name of this input property let's turn example down here now maybe in this one here yeah okay yeah here it is okay here we see i hope it's big enough but here we see the router link directive we don't see a relative route oh there's an example up here for that if the first segment begins with dot slash or doesn't begin with a slash the router looks in the children of the current activated route but yeah if it's if it's exactly dot slash it means the current route but just with some other query params right so here you could add query params and this is like a query fragment and you have yeah you have similar properties to to what you would have in the programmatic api yeah relative to is also something you can you can add you might need that in some cases um so very similar to i had to add i think i have to add the relative to when i use relative urls um i have to pass in this property relative to distant route which is the activated route so yeah this is how you do it is there a more effective way no this is uh based on what i need or what i know this is a good solution this is a good solution but just make sure that this is a requirement that makes sense for your app that they need to have that page number in the url to be able to return to it otherwise just put them to the first page and let them click the button whatever number of times they need that's that's easier but since you have it already in place good job okay uh reverting some of this back to the code here i think this was it now here we go now we're back you're welcome thank you for the question thank you for joining the stream okay it's getting a little late here it's um 30 minutes to midnight danish time so should be finishing up but yeah let's uh let's finish this test for the container component and then we'll end this stream good so we want to add test this forecast dollar property this observable so we're creating an observer and an observer for for example the next emission is just a function so just can create a function that accepts any input and we can even control the output but since an observer shouldn't return anything it's not needed here so we're we are subscribing the our marked observer here to the property we want to test and subscribing returns a subscription so we're actually connecting that subscription to a global subscription here which is just new subscription the reason for that is we can connect multiple subscriptions and then after each test case we can unsubscribe once from this one and it will unsubscribe all the subscriptions that have been connected to it through the add method so this one will be unsubscribed automatically after the test case because of this after each hook i hope that's starting to make sense so we have our setup done we also still have all the setup up here for for the global before each of this whole file this whole test suite spec file so we will have an instance of the container component and now we'll also have the instance it depends on of this co2 forecast store so we want to test that it it referring to this forecast observable emits the value emitted by the co2 forecast store so let's see if we can control what the forecast store is emitting so let's see if the njr store has some something we can use here i think it's it's um a bit uh how do you say that i think these should be protected um all these public methods and properties coming from inject store i should i think they should only be used by the base classes and not be publicly available but yeah people want some flexibility and there's edge cases and luckily for us this is one of those edge cases in a test we want to control the internal state so here we can do set state and then we have to pass it a full state object for the internal state on this forecast store that's just a forecast property so we could do an empty array here or we could do some forecast objects that would look like so all right but let's put that in in a separate um property or variable we could even and this is pretty pretty pretty stupid and not not that anger components are stupid just that you can do this seems really unintentional and not not very that's that's that you can use it in this way it will be abused so i can create an updater here update forecast and yeah state forecast and return a new equals return a new state with the forecast being the new forecast right or am i doing something wrong oh yeah forecast so yeah so i could even add custom updaters here in the test which is kind of yeah the fact that you can also do that other place in the code is kind of triggering some knee-jerk reactions here that this this this doesn't um look good can be abused and misused a lot um so yeah i think it's unfortunate that um the component store has all these methods marked as public all these this is internal mechanics of the component store that's something that should be publicly available in an ideal world but yeah probably just for flexibility purposes but it brings some unfortunate trade-offs with that decision that design decision for us it turns out well we can now control the internal state of this store in our tests but we will still be competing with the uh if we find the store implementation here we'll be competing with this effect so every minute and even initially it will it will be asking the http client for new data so um ideally we should create a like maybe we should make an option of turning this off off somehow this effect or we should create a stopped store service only for testing purposes but it has the same public api the same public properties and methods let's let's just try this method and see this technique see if we can have success with that so forecast is a co2 forecast which is an array which has some values here 80 grams per kilowatt hour some minutes which is this should be an interval right now and date time sorry from luxon so now we need date time from luxon from iso and we'll just do i've mentioned a few times that working with time series is great for testing because you can always make up some test data i'll just use whatever the time approximately is right now so we're in this five minute interval very i'm in dk1 and like i could take the real value here but it doesn't matter it's a realistic value so let's do one more we don't have to make a full forecast of all in all the minute intervals because it should work the same right shouldn't care how many are passed so here it's 82 but so we will emit this we'll change the internal state of the store to this expected forecast and now what should happen well the forecast property of the container component should also emit the same forecast array so how can we check that remember that we subscribe the forecast observer which is a variable here we have access to which is a function it's it's a just mock function which is kind of a has the same features as just spy that you might also know from jasmine so now we will go and inspect that mock function by saying forecast observer expect forecast observer to have been called with the expected forecast and yeah okay so it didn't work it is saying that um the minus is what we expected the plus is what we received so we received an an empty array and this might be due to either the let's see either the if we go to the store implementation either the initialization of the the state which has an empty forecast or it might be due to this effect that is immediately triggered by this timer but that will go and ask the http client for new data and we haven't told it that there's new data available so that that shouldn't be the case so more likely it's this initial state so how can we get to this one well we need to yeah i don't know maybe we should some time should pass before we could also check how many times has this been called this observer um i can call one time what will that say yeah that's that's okay it's only been called one time it when did we subscribe so we subscribed of course after the store and the container was initialized but we wouldn't be able to subscribe before the container was initialized and the container can only be initialized when the store has been initialized because it's a dependency in its constructor right here so we can't really subscribe at any other time now what if it's a matter of we need some time to pass before we can get this value or maybe this is just not working this set state in the test but now i i'm using the fake async utility from angular core testing so i'll try here to say now it's saying it was actually called two times because of the initial state change or state initialization which is the empty array forecast and now it's been called two times so hopefully the second time is our forecast the state we set right here so let's see okay shouldn't be called two times yes now the expected forecast has been passed to the observer so it was a matter of a tick or the vm turn to move to the next turn before this value was was emitted this this expected forecast okay so let's see if it's actually zero seconds it is good so what else could we do we could ignore the initial emission we could do that up here we could say one in this way we would this is from rxjs of course we would stick the initial emission and now it would only be called once and it will be called with the expected forecast but what if we wanted to test the initial emission uh in on one of the other test cases then we couldn't really share this test setup so we shouldn't um if we want to keep that option open we shouldn't do this skip one what we could do instead is well we don't really care how many times it has been called but what we should care about is to have been last called with the expected forecast so we're only interested in the latest emission on that observable the forecast dollar observable so the last emission was whatever was emitted by the store the co2 forecast store that was also emitted on the container components forecast dollar property here so now this test is a million is describing how those two are interacting together the forecast store has a forecast dollar property which we're not mentioning in this test but we're updating the state which then triggers a value for that observable so they are somehow connected which is demonstrated by this test so yeah this is exactly what i wanted to to exercise in this test whatever state is is emitted by the co2 forecast store will be in the container components forecast dollar observable property will be emitted here and just to make it clear i'm using the aaa pattern here arrange act sorry i usually don't add these comments uh i make it implicit so i don't have to mention it in every test case i make it implicit instead by just making a blank space between these groups like so so when we get to the first blank space we'll know that now it's the act group the end of the s arranged group and finally we're going to getting to the assert group here after the second blank space in this test case we might also have some teardown here so that would be in another blank space right for example if we had some subscription we needed to to unsubscribe in some cases rarely but in some cases you would also have an arranged or sorry an act then an assert then another ad then then another then another assert and so on but usually you should have only one because the test case should be verifying one very specific thing not many things you should add we should add more test cases instead okay everything is passing according to wallaby that's great um so yeah that's actually everything we have to say about this container component right now so let's look at our changes we removed this private property because we don't really need it outside of the constructor this year to forecast store um so that's a refactor remove unused private private field and here cover forecast brother and finally let me run the formatting script the npm format and see if there's any changes because i have one vs code extension that's sometimes rearranging the imports differently from from prettier okay so i had an extra blank line here or something so it's just this the previous commit was to this file so i will do commit amend so let's push this change and let's see is there anything else in this feature library that is worth testing let's have a look we decided that the presentational component is not worth testing right now because we're we have this temporary table but we're going to replace it next with a chart from ag grid hopefully so there's nothing really to test here right now we tested the container component there was only one thing to worth testing we the only thing remaining we have is this forecast module which is actually a scam for the container component or rather it is re-exporting the the scam from the container component so importing this feature angular feature module uh the the importer the importing modules components would be able to to use the forecast container component in its template so that is what we're exposing in this feature library only this module which gives access to this scam which get gives access to this container component yes that's complicated yes modules suck i agree couldn't agree more um there is still on the angular road map years later there's still the intent of making ng modules optional unfortunately it's not fully getting rid of angular modules if when and if we get optional ng modules it will only be for being able to properly lazy load a component without an angular module so it won't be module-free applications you it seems that you will always and forever need angular modules for an angular application which is kind of sad but for lazy loading modules you'll be able to do it without or sorry lazy loading components you'll you might be able to do it without angular modules in the future i know i know not very very great good good good where's the wallaby there it is uh okay is there anything we can test about this module yeah we could we could they want me to show you how i'm speaking to myself because there's no one online watching right now okay it's a quarter to midnight i can probably show you how in within 15 minutes so i will i'll show you how to test in a module this feature module actually seems it's important because it's the only one um exported from for this old feature library so how could we test how could we show in our test what this feature module does okay starting by taking the name of this feature module adding a file that's called spec.ts splitting the screen my mouse is not very good anymore um adding a describe block will have this name name of the test suite here it is we will have some test case showing that it works and now wallaby is in a happy place everything's green we're done just kidding of course how can we test the module okay let's add a test setup here before each we're going to configure the angular testing module through testbed configured a testing module and we're going to import the module we're going to test which is this one the c2 feature forecast module and now we want to demonstrate what does it do this module what do you now have access to after importing it it exports the now we can add the name of this container component exports the co2 forecast container component okay how can we show that well now we need a test component so let's make a testing component component selector test post so this is our test post component and we need at least some template and eslint is unhappy that we're using test so say energy test host then so how can we use this test host component in our test we have to declare it in the testing module and now since we're importing this feature module our testing host component here will have access to whatever declarables are exported by that feature module so now we should actually have access to this container component we should be able to do this basically and here comes the question do we can we do that okay let's add a shared variable here call it host and it'll be the test post component and now we have to do post we is assigned to assign to the host variable testbed create component and then test post component okay so now we're getting all these issues of there's no provider for the htp client what are you doing dummy okay let's add the i think like we have seen this before right let's add this okay fortunately that was everything we needed um i mean we're now actually rendering also the presentational component we're providing the forecast store the forecast stores injected into this um container component where is it here it is um so and this co2 forecast store actually has effect running so we're actually starting up this whole feature of the app inside of this test by putting it in the template of our test host component and this shows exactly what we would do in the app we would list this component and i think that is indeed what we have done if we go to our app component here look at this this is exactly what we have done so now we're exercising or documenting that in our test for for this feature module what's the benefit you get from importing this feature module you can render this forecast this co2 forecast container component and everything it has in its template right so this setup is instantiating this test host component by the way notice that we didn't have to do compile components we also didn't have to make it async and to await so if you've been doing this there's no need it's just ngcli generating this for you for no reason at all if you're using angular cli you don't even i think you don't even have to do compile components um or at least or sorry it at least it doesn't have to be async you might need to do to call compile components if the template or the styles are in other files but i have intentionally created here single file components where the styles and the template is in the same file and even this the component or the scam is in the same file and it's 43 lines of code so because of this i don't have to call compile component because that's um or i don't have to order it's not async and maybe you don't even need to call compile components if you're using angular cli let me know would be nice to know for sure so i think it's mostly there for historical reasons because back in the day there were many ways of many setups for angular not only using angular cli there's still some custom webpack solutions out there today some using system jazz i'm using broccoli you name it grunt gulp i mean there are still some out there somewhere okay um yes so it exports the co2 forecast container component how can we show this oh by the way i messed up here because this is what we get here is a component fixture i wonder why typescript didn't complain about that um so this instead should be the host host fixture we'll have a variable called host fixture which is a component fixture of the test host component so then we probably don't even need the host um instance um reference we need this fixture what can we do from here well now that it has been created instantiated compiled and everything and rendered we should be able to reference or query for this component our container component and how could we do that we can do that through the host fixture let's say host fixture um debug element query i directive now we need to find that by and auto import doesn't work so let's see if i can remember so where is by it's in platform browser testing no then it's platform browser dynamic testing oh and i have no idea i have to go look in the documentation hi oh yeah it's not here oh you know what it's probably not even in the testing sub package probably here or here i for some reason maybe because you can use it in at runtime using the debugging api at least when you're in development mode and not in a production mode build um maybe that's why it's not in a testing package because you can actually use it at runtime for debugging purposes i don't know only use it for test i only use it for tests so yeah query by directive and we all know that a component is also a directive right it's just that sometimes we forget so here uh container youtube forecast container is this but in fact or this is rather the debug element of that but if we couldn't find this it i think it would return null so what should we do here we should expect that the co2 forecast container not to be null it seems to work we could also do a component instance to be up to the instance of and then this class okay that definitely seems to be right yeah it seems to be right but it's always good to first see the test failing so that we know when it's passing it's for the right reason so we can remove this export now it should fail and it does why does it fail well already in in the template some here somewhere and here cannot read debug element of undefined the whole host fixture is actually doesn't work this great component doesn't work because it's trying to use this um an element of this name and there is no component to match to that element or tag name so when we add back the x part here is passing so we're good what is this complaining about defined but never used that's not true it's used right here uh might be some other sync something here we go okay so now we have a test for um for that feature module we're at we are testing that it exports the co2 forecast container component so that you're able to do this good run the formatter then i will cover co2 forecast feature module very good okay let's try to get an overview of what did we do in this episode we worked in the forecast feature but in fact we also made a small fix here in the data access because in the http service we needed to when the query the sql query parameter is generated we needed to convert it to the utc time zone so that it produced the set suffix here because it for some reason uh c can there there's an issue of when you do plus um it thinks that the plus is a space which is not really a valid um utc offset here like so so instead we're going to convert it to utc so it gets this set uh or z set whatever you want to say um identify that this by the way means plus 0 0 12 or even minus you can do as well it's the same that's one of the changes we made we got stuck in the last episode and had to end uh so now we the data fetching is actually working everything in this uh co2 forecast um sorry that in this day co2 data access library is now working and in our feature we're now able to display where is it there it is we're now able to display data in this table and we saw that maybe we should see it one last time and now data might have been updated since last time let's have a look and what we have right now come on angular run faster this is a pretty potent machine i know it's in danish but has 12 logical cars it's the i7 10 7050 running at 4 gigahertz right now so yeah it should have plenty of cpu power only thing is it only has 16 gigabytes of ram and that's actually not very much when you're using nx and wallaby and angular compiler and all this goodness so but yeah it should be fast so i'll say it's the angular compiler that's slow okay the dev server has started so let's look at our app what do we have now yes they changed so yeah this is a little oh oh awesome it also works since um now we just passed midnight it's three minutes past midnight so now the first values we're getting are from the current date may 25th but now we'll see that uh date for tomorrow may 22nd the 26th is not available yet go to the bottom of this list and everything is from may 25th why because the forecast for the following day is only published after 3 p.m in the afternoon so we can only display whatever is available right so right now we just have this very long list our table and um going next we're going to replace that with um aj grid charts and uh maybe at some point we'll add a table view but i don't really think so i'm more into visuals so only thing is if we're going to turn it into a progressive web app that can be used on mobile how would you be able to get the details um hopefully ag grid has a way of dealing with that or we'll have to figure something out for that or maybe not maybe you're not as interested in what's the exact value as just yeah it's below 80 right that's the important thing below 80 grams of co2 equivalent per kilowatt hour produced let's have a final look here at the next eight hours of co2 emissions by today's electricity grid it will stay below 80 until here four o'clock oh that's bad then mark you're getting dirty already at four am but at six a.m in that hour from six to seven it's averaging to 74 grams per kilowatt hour but then we get to seven o'clock between seven and eight and it's uh 91 and yeah we should probably expect that to to increase we could see that in our own app if we scroll down to later than nine here oh look at that 119. this is dirty the mark oh 205 206 209 it gets worse this is a very dirty day there much must not be much wind and soul uh sun solar power yeah when will it go below 80 okay 6 15 pm um yeah but then people get home from work and they start making dinner so at seven we will give get above 80 again and it will stay that way until here 8 p.m so that hour between seven and eight you can really see the energy consumption increasing which yeah if there's not enough solar power or wind what are you going to do you need to fire up the power plants that are running on fossil fuels so when will it stay on 80 or below maybe from here 8 15 p.m nope it's about 80 again maybe from here 10 05 pm yeah seems so right where was it 1005 here okay so according to the forecast from 1005 it will be clean energy up until midnight and then after 3 p.m today on 25th we'll be able to see the forecast for the 26th and see how that goes so someone like me could use this to say what's a good time to run my like charge my laptop my ipad or maybe more something like when it's a good time to run the dishwasher the washer the dryer and so on or charge my electric car right i don't have one unfortunately but if i had that would also be a significant consumption of electricity right so it would be good to know what's the good time to charge an electric vehicle yes this is the background of what we're trying to do let's also take a look at the the wind just for fun but it's like right now around midnight going to the english version of energynet going to look at the electricity net right now and here it is currently producing 1.8 gigawatts of electricity from wind turbines and we have around 800 megawatts so just just below half of that from fossil fuels dirty energy dirty electricity but right now we're at 61 grams per kilowatt hour produced and the whole of denmark is at almost three um sorry i'm saying yeah oh yeah gigawatts uh almost three um gigawatts of electricity in the whole of denmark right now and we are importing 322 megawatts uh so either we don't have enough energy for ourselves or germany and netherlands are requesting more energy than yeah then we can produce on our own and and still have enough for ourselves so we're importing mostly hopefully mostly clean energy from sweden and from norway because they have a lot of hydrogen energy as well we just don't have the geographical um areas to do that in denmark we're very small country and very flat so we can't really set up those those dams and so on for for hydro water-based energy and we don't have glacier water coming down from the mountains because we don't have any mountains like it's it's a joke we have we have a small hill that we call the mount of heaven or something like that in in denmark but let's see here how big it is it's 147 meters above sea level so yeah like that's the highest point we have in denmark this is it that's the highest point in denmark it's a joke telling you [Laughter] i mean the city of silkenborg is also some above sea level so of course this is not entirely 147 meters but still it's kind of funny right this is all we have in denmark the peak of denmark right we don't have any mountains at all or we barely have any cliffs yes uh yeah that was i guess that was all what's this problem it's not a known element okay get a grip angular language service see if it fixes it okay i'm giving it a good kick yeah okay so now it's good great that was it for nx after dark for today and now it's getting late so i should catch some sleep and we'll get back to this some other day and start working on that chart and see what we can test in our feature library so i hope you find this useful interesting i hope you learned something learned anything that would make me happy and hopefully i don't run out of free streaming minutes on stream yard oh no because it will only be reset in three weeks from now so i hope i don't hit that limit but i actually will very soon so that's going to be an issue working on a solution but it's not going to happen anytime soon so might be a bit of a pause for a few weeks then we'll catch up again and i can work on other content in the meantime so let's see who joined today we had bill thank you for joining bill and we had uh musamil asking about paginators pagination in angular and it seems like you were doing great and the way you were doing it and bill saw for the first time private fields in ecmascript and typescript using the hashtag rather than private which is not actually private only at compile time so yeah that was it and everyone has gone to bed except for me so now it's my turn see you some other time bye
Info
Channel: Lars Gyrup Brink Nielsen
Views: 83
Rating: undefined out of 5
Keywords: nx, angular, ngrx, rxjs
Id: aJ5vFFzdxXM
Channel Id: undefined
Length: 156min 9sec (9369 seconds)
Published: Mon May 24 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.