├── .gitignore ├── BACKEND_INSTRUCTIONS.md ├── FRONTEND_INSTRUCTIONS.md ├── MOBILE_INSTRUCTIONS.md ├── blazor-realworld-example-app.sln ├── blazor-realworld-example-app.sln.DotSettings ├── logo.pdn ├── logo.png ├── readme.md ├── src └── BlazorRealworld │ ├── ApiClient.cs │ ├── App.cshtml │ ├── AppState.cs │ ├── BlazorRealworld.csproj │ ├── Model │ ├── ArticleModel.cs │ ├── ErrorsModel.cs │ ├── ProfileModel.cs │ └── UserModel.cs │ ├── NuGet.config │ ├── Pages │ ├── Article.cshtml │ ├── Counter.cshtml │ ├── Editor.cshtml │ ├── FetchData.cshtml │ ├── Index.cshtml │ ├── Profile.cshtml │ ├── Settings.cshtml │ ├── SignIn.cshtml │ ├── SignUp.cshtml │ └── _ViewImports.cshtml │ ├── Program.cs │ ├── Properties │ └── launchSettings.json │ ├── Shared │ ├── ArticleList.cshtml │ ├── ErrorMessages.cshtml │ └── MainLayout.cshtml │ ├── _ViewImports.cshtml │ ├── global.json │ └── wwwroot │ ├── favicon.ico │ ├── index.html │ └── interop.js └── test ├── cypress.json ├── cypress ├── fixtures │ ├── example.json │ ├── profile.json │ └── users.json ├── integration │ └── realworld_spec.js ├── plugins │ └── index.js └── support │ ├── commands.js │ └── index.js ├── package.json └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /bower_components 6 | 7 | # IDEs and editors 8 | /.idea 9 | .project 10 | .classpath 11 | *.launch 12 | .settings/ 13 | .vs 14 | 15 | # System Files 16 | .DS_Store 17 | Thumbs.db 18 | 19 | # Build output 20 | obj/ 21 | bin/ 22 | 23 | # Personal files 24 | **/*.csproj.user 25 | 26 | # Deployment definition 27 | *Web Deploy.pubxml* 28 | 29 | node_modules/ 30 | /test/cypress/screenshots/ 31 | /test/cypress/videos/ 32 | cypress.env.json 33 | /test/*.log 34 | -------------------------------------------------------------------------------- /BACKEND_INSTRUCTIONS.md: -------------------------------------------------------------------------------- 1 | > *Note: Delete this file before publishing your app!* 2 | 3 | # [Backend API spec](https://github.com/gothinkster/realworld/tree/master/api) 4 | 5 | For your convenience, we have a [Postman collection](https://github.com/gothinkster/realworld/blob/master/api/Conduit.postman_collection.json) that you can use to test your API endpoints as you build your app. 6 | -------------------------------------------------------------------------------- /FRONTEND_INSTRUCTIONS.md: -------------------------------------------------------------------------------- 1 | > *Note: Delete this file before publishing your app!* 2 | 3 | ### Using the hosted API 4 | 5 | Simply point your [API requests](https://github.com/gothinkster/realworld/tree/master/api) to `https://conduit.productionready.io/api` and you're good to go! 6 | 7 | ### Routing Guidelines 8 | 9 | - Home page (URL: /#/ ) 10 | - List of tags 11 | - List of articles pulled from either Feed, Global, or by Tag 12 | - Pagination for list of articles 13 | - Sign in/Sign up pages (URL: /#/login, /#/register ) 14 | - Uses JWT (store the token in localStorage) 15 | - Authentication can be easily switched to session/cookie based 16 | - Settings page (URL: /#/settings ) 17 | - Editor page to create/edit articles (URL: /#/editor, /#/editor/article-slug-here ) 18 | - Article page (URL: /#/article/article-slug-here ) 19 | - Delete article button (only shown to article's author) 20 | - Render markdown from server client side 21 | - Comments section at bottom of page 22 | - Delete comment button (only shown to comment's author) 23 | - Profile page (URL: /#/profile/:username, /#/profile/:username/favorites ) 24 | - Show basic user info 25 | - List of articles populated from author's created articles or author's favorited articles 26 | 27 | # Styles 28 | 29 | Instead of having the Bootstrap theme included locally, we recommend loading the precompiled theme from our CDN (our [header template](#header) does this by default): 30 | 31 | ```html 32 | 33 | ``` 34 | 35 | Alternatively, if you want to make modifications to the theme, check out the [theme's repo](https://github.com/gothinkster/conduit-bootstrap-template). 36 | 37 | 38 | # Templates 39 | 40 | - [Layout](#layout) 41 | - [Header](#header) 42 | - [Footer](#footer) 43 | - [Pages](#pages) 44 | - [Home](#home) 45 | - [Login/Register](#loginregister) 46 | - [Profile](#profile) 47 | - [Settings](#settings) 48 | - [Create/Edit Article](#createedit-article) 49 | - [Article](#article) 50 | 51 | 52 | ## Layout 53 | 54 | 55 | ### Header 56 | 57 | ```html 58 | 59 | 60 | 61 | 62 | Conduit 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 95 | 96 | 97 | ``` 98 | 99 | ### Footer 100 | ```html 101 | 109 | 110 | 111 | 112 | ``` 113 | 114 | ## Pages 115 | 116 | ### Home 117 | ```html 118 |
119 | 120 | 126 | 127 |
128 |
129 | 130 |
131 |
132 | 140 |
141 | 142 |
143 | 153 | 154 |

How to build webapps that scale

155 |

This is the description for the post.

156 | Read more... 157 |
158 |
159 | 160 |
161 | 171 | 172 |

The song you won't ever stop singing. No matter how hard you try.

173 |

This is the description for the post.

174 | Read more... 175 |
176 |
177 | 178 |
179 | 180 |
181 | 195 |
196 | 197 |
198 |
199 | 200 |
201 | ``` 202 | 203 | ### Login/Register 204 | 205 | ```html 206 |
207 |
208 |
209 | 210 |
211 |

Sign up

212 |

213 | Have an account? 214 |

215 | 216 |
    217 |
  • That email is already taken
  • 218 |
219 | 220 |
221 |
222 | 223 |
224 |
225 | 226 |
227 |
228 | 229 |
230 | 233 |
234 |
235 | 236 |
237 |
238 |
239 | ``` 240 | 241 | ### Profile 242 | 243 | ```html 244 |
245 | 246 |
247 |
248 |
249 | 250 |
251 | 252 |

Eric Simons

253 |

254 | Cofounder @GoThinkster, lived in Aol's HQ for a few months, kinda looks like Peeta from the Hunger Games 255 |

256 | 261 |
262 | 263 |
264 |
265 |
266 | 267 |
268 |
269 | 270 |
271 |
272 | 280 |
281 | 282 |
283 | 293 | 294 |

How to build webapps that scale

295 |

This is the description for the post.

296 | Read more... 297 |
298 |
299 | 300 |
301 | 311 | 312 |

The song you won't ever stop singing. No matter how hard you try.

313 |

This is the description for the post.

314 | Read more... 315 |
    316 |
  • Music
  • 317 |
  • Song
  • 318 |
319 |
320 |
321 | 322 | 323 |
324 | 325 |
326 |
327 | 328 |
329 | ``` 330 | 331 | ### Settings 332 | 333 | ```html 334 |
335 |
336 |
337 | 338 |
339 |

Your Settings

340 | 341 |
342 |
343 |
344 | 345 |
346 |
347 | 348 |
349 |
350 | 351 |
352 |
353 | 354 |
355 |
356 | 357 |
358 | 361 |
362 |
363 |
364 | 365 |
366 |
367 |
368 | ``` 369 | 370 | ### Create/Edit Article 371 | 372 | ```html 373 |
374 |
375 |
376 | 377 |
378 |
379 |
380 |
381 | 382 |
383 |
384 | 385 |
386 |
387 | 388 |
389 |
390 |
391 |
392 | 395 |
396 |
397 |
398 | 399 |
400 |
401 |
402 | 403 | 404 | ``` 405 | 406 | ### Article 407 | 408 | ```html 409 |
410 | 411 | 437 | 438 |
439 | 440 |
441 |
442 |

443 | Web development technologies have evolved at an incredible clip over the past few years. 444 |

445 |

Introducing RealWorld.

446 |

It's a great solution for learning how other frameworks work.

447 |
448 |
449 | 450 |
451 | 452 |
453 | 472 |
473 | 474 |
475 | 476 |
477 | 478 |
479 |
480 | 481 |
482 | 488 |
489 | 490 |
491 |
492 |

With supporting text below as a natural lead-in to additional content.

493 |
494 | 502 |
503 | 504 |
505 |
506 |

With supporting text below as a natural lead-in to additional content.

507 |
508 | 520 |
521 | 522 |
523 | 524 |
525 | 526 |
527 | 528 |
529 | ``` 530 | -------------------------------------------------------------------------------- /MOBILE_INSTRUCTIONS.md: -------------------------------------------------------------------------------- 1 | > *Note: Delete this file before publishing your app!* 2 | 3 | # [Mobile Icons (iOS/Android)](https://github.com/gothinkster/realworld/tree/master/spec/mobile_icons) 4 | 5 | ### Using the hosted API 6 | 7 | Simply point your [API requests](https://github.com/gothinkster/realworld/tree/master/api) to `https://conduit.productionready.io/api` and you're good to go! 8 | 9 | ### Styles/Templates 10 | 11 | Unfortunately, there isn't a common way for us to reuse & share styles/templates for cross-platform mobile apps. 12 | 13 | Instead, we recommend using the Medium.com [iOS](https://itunes.apple.com/us/app/medium/id828256236?mt=8) and [Android](https://play.google.com/store/apps/details?id=com.medium.reader&hl=en) apps as a "north star" regarding general UI functionality/layout, but try not to go too overboard otherwise it will unnecessarily complicate your codebase (in other words, [KISS](https://en.wikipedia.org/wiki/KISS_principle) :) 14 | -------------------------------------------------------------------------------- /blazor-realworld-example-app.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26124.0 5 | MinimumVisualStudioVersion = 15.0.26124.0 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlazorRealworld", "src\BlazorRealworld\BlazorRealworld.csproj", "{16DD9FA4-F02E-43BD-A02D-D4BD3BA19779}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {16DD9FA4-F02E-43BD-A02D-D4BD3BA19779}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {16DD9FA4-F02E-43BD-A02D-D4BD3BA19779}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {16DD9FA4-F02E-43BD-A02D-D4BD3BA19779}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {16DD9FA4-F02E-43BD-A02D-D4BD3BA19779}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {975FD1C9-83E7-44FE-A690-DCC0B547FEAA} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /blazor-realworld-example-app.sln.DotSettings: -------------------------------------------------------------------------------- 1 |  2 | True -------------------------------------------------------------------------------- /logo.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torhovland/blazor-realworld-example-app/68c2d690ab09cb6ab62b7c8532612a21aa7cbef5/logo.pdn -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torhovland/blazor-realworld-example-app/68c2d690ab09cb6ab62b7c8532612a21aa7cbef5/logo.png -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # ![RealWorld Example App](logo.png) 2 | 3 | > ### [Blazor](https://github.com/aspnet/Blazor) codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the [RealWorld](https://github.com/gothinkster/realworld) spec and API. 4 | 5 | 6 | ### [Demo](http://blazor-realworld.azurewebsites.net)    [RealWorld](https://github.com/gothinkster/realworld) 7 | 8 | 9 | This codebase was created to demonstrate a fully fledged fullstack application built with **Blazor** including CRUD operations, authentication, routing, pagination, and more. 10 | 11 | We've gone to great lengths to adhere to the **Blazor** community styleguides & best practices. 12 | 13 | For more information on how to this works with other frontends/backends, head over to the [RealWorld](https://github.com/gothinkster/realworld) repo. 14 | 15 | 16 | # How it works 17 | 18 | > Describe the general architecture of your app here 19 | 20 | # Getting started 21 | 22 | > npm install, npm start, etc. 23 | -------------------------------------------------------------------------------- /src/BlazorRealworld/ApiClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net.Http; 4 | using System.Net.Http.Headers; 5 | using System.Threading.Tasks; 6 | using Microsoft.AspNetCore.Blazor; 7 | using BlazorRealworld.Model; 8 | 9 | namespace BlazorRealworld 10 | { 11 | public class ApiClient 12 | { 13 | const string BaseUrl = "https://conduit.productionready.io/api"; 14 | private readonly HttpClient _httpClient; 15 | 16 | public ApiClient(HttpClient httpClient) 17 | { 18 | _httpClient = httpClient; 19 | } 20 | 21 | public void SetToken(string token) 22 | { 23 | _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Token", token); 24 | } 25 | 26 | public void ClearToken() 27 | { 28 | _httpClient.DefaultRequestHeaders.Authorization = null; 29 | } 30 | 31 | public async Task SignUpAsync(UserModel userForm) 32 | { 33 | return await PostUserFormAsync("/users", userForm); 34 | } 35 | 36 | public async Task SignInAsync(UserModel userForm) 37 | { 38 | return await PostUserFormAsync("/users/login", userForm); 39 | } 40 | 41 | public async Task UpdateUserAsync(UserModel userForm) 42 | { 43 | return await PutUserFormAsync("/user", userForm); 44 | } 45 | 46 | public async Task GetUserAsync() 47 | { 48 | var response = await _httpClient.GetJsonAsync($"{BaseUrl}/user"); 49 | return response.user; 50 | } 51 | 52 | async Task PostUserFormAsync(string urlFragment, UserModel userForm) 53 | { 54 | return await _httpClient.PostJsonAsync($"{BaseUrl}{urlFragment}", 55 | new 56 | { 57 | user = userForm 58 | }); 59 | } 60 | 61 | async Task PutUserFormAsync(string urlFragment, UserModel userForm) 62 | { 63 | return await _httpClient.PutJsonAsync($"{BaseUrl}{urlFragment}", 64 | new 65 | { 66 | user = userForm 67 | }); 68 | } 69 | 70 | public async Task GetProfileAsync(string username) 71 | { 72 | var response = await _httpClient.GetJsonAsync($"{BaseUrl}/profiles/{username}"); 73 | return response.profile; 74 | } 75 | 76 | public async Task> GetArticlesAsync() 77 | { 78 | return await GetArticlesAsync("/articles", null, null); 79 | } 80 | 81 | public async Task> GetArticlesByTagAsync(string tag) 82 | { 83 | return await GetArticlesAsync("/articles", tag, null); 84 | } 85 | 86 | public async Task> GetArticlesByAuthorAsync(string author) 87 | { 88 | return await GetArticlesAsync("/articles", null, author); 89 | } 90 | 91 | public async Task> GetArticleFeedAsync() 92 | { 93 | return await GetArticlesAsync("/articles/feed", null, null); 94 | } 95 | 96 | async Task> GetArticlesAsync(string urlFragment, string tag, string author) 97 | { 98 | var tagFilter = tag == null ? "" : $"tag={tag}&"; 99 | var authorFilter = author == null ? "" : $"author={author}&"; 100 | var query = $"?{tagFilter}{authorFilter}limit=10&offset=0"; 101 | var response = await _httpClient.GetJsonAsync($"{BaseUrl}{urlFragment}{query}"); 102 | return response.articles; 103 | } 104 | 105 | public async Task GetArticleAsync(string slug) 106 | { 107 | var response = await _httpClient.GetJsonAsync($"{BaseUrl}/articles/{slug}"); 108 | return response.article; 109 | } 110 | 111 | public async Task> GetTagsAsync() 112 | { 113 | var response = await _httpClient.GetJsonAsync($"{BaseUrl}/tags"); 114 | return response.tags; 115 | } 116 | 117 | public async Task SaveArticleAsync(ArticleModel article) 118 | { 119 | string url = $"{BaseUrl}/articles"; 120 | object content = new 121 | { 122 | article = article 123 | }; 124 | 125 | if (String.IsNullOrEmpty(article.slug)) 126 | return await _httpClient.PostJsonAsync(url, content); 127 | else 128 | return await _httpClient.PutJsonAsync($"{url}/{article.slug}", content); 129 | } 130 | 131 | public async Task DeleteArticleAsync(string slug) 132 | { 133 | var response = await _httpClient.DeleteAsync($"{BaseUrl}/articles/{slug}"); 134 | return response.IsSuccessStatusCode; 135 | } 136 | } 137 | 138 | public class UserResponse 139 | { 140 | public ErrorsModel errors { get; set; } 141 | public UserModel user { get; set; } 142 | } 143 | 144 | public class ProfileResponse 145 | { 146 | public ProfileModel profile { get; set; } 147 | } 148 | 149 | public class ArticleResponse 150 | { 151 | public ErrorsModel errors { get; set; } 152 | public ArticleModel article { get; set; } 153 | } 154 | 155 | class ArticlesResponse 156 | { 157 | public ArticleModel[] articles { get; set; } 158 | } 159 | 160 | class TagResponse 161 | { 162 | public string[] tags { get; set; } 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/BlazorRealworld/App.cshtml: -------------------------------------------------------------------------------- 1 | @inject ApiClient api 2 | @inject AppState state 3 | 4 | 8 | 9 | 10 | @functions { 11 | protected override async Task OnInitAsync() 12 | { 13 | var token = RegisteredFunction.Invoke("getStoredToken"); 14 | 15 | if (token != null) 16 | { 17 | api.SetToken(token); 18 | var user = await api.GetUserAsync(); 19 | state.UpdateUser(user); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/BlazorRealworld/AppState.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using BlazorRealworld.Model; 3 | 4 | namespace BlazorRealworld 5 | { 6 | public class AppState 7 | { 8 | private readonly ApiClient api; 9 | 10 | public AppState(ApiClient api) 11 | { 12 | this.api = api; 13 | User = new UserModel(); 14 | } 15 | 16 | public event Action OnUserChange; 17 | 18 | private void NotifyUserChanged() => OnUserChange?.Invoke(); 19 | 20 | public ErrorsModel Errors { get; private set; } 21 | public UserModel User { get; private set; } 22 | 23 | public bool IsSignedIn => User?.token != null; 24 | 25 | public void UpdateUser(UserModel user) 26 | { 27 | User = user; 28 | var token = User?.token; 29 | 30 | if (token != null) 31 | api.SetToken(token); 32 | 33 | NotifyUserChanged(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/BlazorRealworld/BlazorRealworld.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | netstandard2.0 5 | dotnet 6 | blazor serve 7 | 7.3 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/BlazorRealworld/Model/ArticleModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace BlazorRealworld.Model 4 | { 5 | public class ArticleModel 6 | { 7 | public ArticleModel() 8 | { 9 | author = new AuthorModel(); 10 | } 11 | 12 | public string title { get; set; } 13 | public string slug { get; set; } 14 | public string body { get; set; } 15 | public DateTime createdAt { get; set; } 16 | public string[] tagList { get; set; } 17 | public string description { get; set; } 18 | public AuthorModel author { get; set; } 19 | public int favoritesCount { get; set; } 20 | } 21 | 22 | public class AuthorModel 23 | { 24 | public string username { get; set; } 25 | public string image { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/BlazorRealworld/Model/ErrorsModel.cs: -------------------------------------------------------------------------------- 1 | namespace BlazorRealworld 2 | { 3 | public class ErrorsModel 4 | { 5 | public string[] username { get; set; } 6 | public string[] email { get; set; } 7 | public string[] password { get; set; } 8 | public string[] title { get; set; } 9 | public string[] body { get; set; } 10 | public string[] description { get; set; } 11 | public string[] emailOrPassword { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/BlazorRealworld/Model/ProfileModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace BlazorRealworld.Model 4 | { 5 | public class ProfileModel 6 | { 7 | public string username { get; set; } 8 | public string bio { get; set; } 9 | public string image { get; set; } 10 | public bool following { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/BlazorRealworld/Model/UserModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace BlazorRealworld.Model 4 | { 5 | public class UserModel 6 | { 7 | public string email { get; set; } 8 | public string username { get; set; } 9 | public string bio { get; set; } 10 | public string image { get; set; } 11 | public string token { get; set; } 12 | public string password { get; set; } 13 | 14 | public UserModel Clone() 15 | { 16 | return new UserModel 17 | { 18 | // Password and token will not be cloned. 19 | 20 | email = email, 21 | username = username, 22 | bio = bio, 23 | image = image 24 | }; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/BlazorRealworld/NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/BlazorRealworld/Pages/Article.cshtml: -------------------------------------------------------------------------------- 1 | @page "/article/{Slug}" 2 | @using BlazorRealworld.Model 3 | @inject ApiClient api 4 | @inject AppState state 5 | @inject IUriHelper uriHelper 6 | 7 | @if (article != null) 8 | { 9 |
10 | 11 | 53 | 54 |
55 | 56 |
57 |
58 |
59 |
60 | 61 |
62 | 63 |
64 | 83 |
84 | 85 |
86 | 87 |
88 | 89 |
90 |
91 | 92 |
93 | 99 |
100 | 101 |
102 |
103 |

With supporting text below as a natural lead-in to additional content.

104 |
105 | 113 |
114 | 115 |
116 |
117 |

With supporting text below as a natural lead-in to additional content.

118 |
119 | 131 |
132 | 133 |
134 | 135 |
136 | 137 |
138 | 139 |
140 | } 141 | 142 | @functions 143 | { 144 | public string Slug { get; set; } 145 | 146 | ArticleModel article = null; 147 | 148 | protected override async Task OnInitAsync() 149 | { 150 | article = await api.GetArticleAsync(Slug); 151 | StateHasChanged(); 152 | 153 | var articleBody = CommonMark.CommonMarkConverter.Convert(article.body); 154 | 155 | // Until raw HTML is supported in Blazor: 156 | // https://github.com/aspnet/Blazor/issues/167 157 | RegisteredFunction.Invoke("showRawHtml", "article-body", articleBody); 158 | } 159 | 160 | async Task DeleteArticle() 161 | { 162 | await api.DeleteArticleAsync(Slug); 163 | uriHelper.NavigateTo("/"); 164 | } 165 | } -------------------------------------------------------------------------------- /src/BlazorRealworld/Pages/Counter.cshtml: -------------------------------------------------------------------------------- 1 | @page "/counter" 2 |

Counter

3 | 4 |

Current count: @currentCount

5 | 6 | 7 | 8 | @functions { 9 | int currentCount = 0; 10 | 11 | void IncrementCount() 12 | { 13 | currentCount++; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/BlazorRealworld/Pages/Editor.cshtml: -------------------------------------------------------------------------------- 1 | @using BlazorRealworld.Model 2 | @page "/editor" 3 | @page "/editor/{Slug}" 4 | @inject ApiClient api 5 | @inject IUriHelper uriHelper 6 | 7 | @if (articleModel != null) 8 | { 9 |
10 |
11 |
12 | 13 |
14 | 15 |
16 |
17 |
18 | 19 |
20 |
21 | 22 |
23 |
24 | 25 |
26 |
27 |
28 |
29 | 32 |
33 |
34 |
35 | 36 |
37 |
38 |
39 | } 40 | 41 | @functions 42 | { 43 | public string Slug { get; set; } 44 | 45 | ArticleModel articleModel = null; 46 | ArticleResponse response = new ArticleResponse(); 47 | string tagString = ""; 48 | 49 | protected override async Task OnInitAsync() 50 | { 51 | if (Slug == null) 52 | { 53 | articleModel = new ArticleModel(); 54 | } 55 | else 56 | { 57 | articleModel = await api.GetArticleAsync(Slug); 58 | } 59 | } 60 | 61 | async Task Submit() 62 | { 63 | articleModel.tagList = tagString.Split(' '); 64 | response = await api.SaveArticleAsync(articleModel); 65 | var postedArticle = response?.article; 66 | 67 | if (postedArticle != null) 68 | { 69 | uriHelper.NavigateTo($"/article/{postedArticle.slug}"); 70 | } 71 | else 72 | // Show errors 73 | StateHasChanged(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/BlazorRealworld/Pages/FetchData.cshtml: -------------------------------------------------------------------------------- 1 | @page "/fetchdata" 2 | @inject HttpClient Http 3 | 4 |

Weather forecast

5 | 6 |

This component demonstrates fetching data from the server.

7 | 8 | @if (forecasts == null) 9 | { 10 |

Loading...

11 | } 12 | else 13 | { 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | @foreach (var forecast in forecasts) 25 | { 26 | 27 | 28 | 29 | 30 | 31 | 32 | } 33 | 34 |
DateTemp. (C)Temp. (F)Summary
@forecast.Date.ToShortDateString()@forecast.TemperatureC@forecast.TemperatureF@forecast.Summary
35 | } 36 | 37 | @functions { 38 | WeatherForecast[] forecasts; 39 | 40 | protected override async Task OnInitAsync() 41 | { 42 | forecasts = await Http.GetJsonAsync("/sample-data/weather.json"); 43 | } 44 | 45 | class WeatherForecast 46 | { 47 | public DateTime Date { get; set; } 48 | public int TemperatureC { get; set; } 49 | public int TemperatureF { get; set; } 50 | public string Summary { get; set; } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/BlazorRealworld/Pages/Index.cshtml: -------------------------------------------------------------------------------- 1 | @page "/" 2 | @using BlazorRealworld.Model 3 | @inject ApiClient api 4 | @inject AppState state 5 | 6 |
7 | @if (!state.IsSignedIn) 8 | { 9 | 15 | } 16 |
17 |
18 |
19 |
20 | 34 |
35 | 36 |
37 |
38 | 54 |
55 |
56 |
57 |
58 | 59 | @functions { 60 | IEnumerable articles; 61 | IEnumerable tags; 62 | SelectedTab selectedTab; 63 | string selectedTag; 64 | 65 | string FeedState 66 | { 67 | get 68 | { 69 | if (!state.IsSignedIn) return "disabled"; 70 | if (selectedTab == SelectedTab.Feed) return "active"; 71 | return ""; 72 | } 73 | } 74 | 75 | string GlobalState => selectedTab == SelectedTab.Global ? "active" : ""; 76 | 77 | protected override async Task OnInitAsync() 78 | { 79 | await GlobalFeedAsync(); 80 | tags = await api.GetTagsAsync(); 81 | } 82 | 83 | async Task YourFeedAsync() 84 | { 85 | selectedTab = SelectedTab.Feed; 86 | articles = await api.GetArticleFeedAsync(); 87 | StateHasChanged(); 88 | } 89 | 90 | async Task GlobalFeedAsync() 91 | { 92 | selectedTab = SelectedTab.Global; 93 | articles = await api.GetArticlesAsync(); 94 | StateHasChanged(); 95 | } 96 | 97 | async Task SelectTag(string tag) 98 | { 99 | selectedTab = SelectedTab.Tag; 100 | selectedTag = tag; 101 | articles = await api.GetArticlesByTagAsync(tag); 102 | StateHasChanged(); 103 | } 104 | 105 | enum SelectedTab 106 | { 107 | Feed, 108 | Global, 109 | Tag 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/BlazorRealworld/Pages/Profile.cshtml: -------------------------------------------------------------------------------- 1 | @page "/profile/{Username}" 2 | @using BlazorRealworld.Model 3 | @inject ApiClient api 4 | 5 |
6 | 24 |
25 |
26 |
27 |
28 | 36 |
37 | 38 |
39 |
40 |
41 |
42 | 43 | @functions 44 | { 45 | public string Username { get; set; } 46 | 47 | ProfileModel profile = new ProfileModel(); 48 | IEnumerable articles = null; 49 | 50 | protected override async Task OnInitAsync() 51 | { 52 | profile = await api.GetProfileAsync(Username); 53 | articles = await api.GetArticlesByAuthorAsync(Username); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/BlazorRealworld/Pages/Settings.cshtml: -------------------------------------------------------------------------------- 1 | @page "/settings" 2 | @implements IDisposable 3 | @using System 4 | @using BlazorRealworld 5 | @using BlazorRealworld.Model 6 | @inject AppState state 7 | @inject ApiClient api 8 | @inject IUriHelper uriHelper 9 | 10 |
11 |
12 |
13 |
14 |

Your Settings

15 | 16 |
17 |
18 |
19 | 20 |
21 |
22 | 23 |
24 |
25 | 26 |
27 |
28 | 29 |
30 |
31 | 32 |
33 | 36 |
37 |
38 |
39 |
40 |
41 |
42 | 43 | @functions 44 | { 45 | UserModel userModel = new UserModel(); 46 | UserResponse response = new UserResponse(); 47 | 48 | protected override void OnInit() 49 | { 50 | state.OnUserChange += UserHasLoaded; 51 | } 52 | 53 | public void Dispose() 54 | { 55 | state.OnUserChange -= UserHasLoaded; 56 | } 57 | 58 | void UserHasLoaded() 59 | { 60 | userModel = state.User.Clone(); 61 | StateHasChanged(); 62 | } 63 | 64 | async Task Submit() 65 | { 66 | response = await api.UpdateUserAsync(userModel); 67 | 68 | if (response.user != null) 69 | { 70 | state.UpdateUser(response.user); 71 | uriHelper.NavigateTo("/"); 72 | } 73 | else 74 | // Show errors 75 | StateHasChanged(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/BlazorRealworld/Pages/SignIn.cshtml: -------------------------------------------------------------------------------- 1 | @page "/signin" 2 | @using BlazorRealworld.Model 3 | @inject ApiClient api 4 | @inject AppState state 5 | @inject IUriHelper uriHelper 6 | 7 |
8 |
9 |
10 |
11 |

Sign in

12 |

13 | Need an account? 14 |

15 | 16 |
17 |
18 | 19 |
20 |
21 | 22 |
23 | 26 |
27 |
28 |
29 |
30 |
31 | 32 | @functions { 33 | UserModel userModel = new UserModel(); 34 | UserResponse response = new UserResponse(); 35 | 36 | async Task Submit() 37 | { 38 | response = await api.SignInAsync(userModel); 39 | var user = response.user; 40 | 41 | if (user != null) 42 | { 43 | state.UpdateUser(user); 44 | RegisteredFunction.Invoke("saveToken", user.token); 45 | uriHelper.NavigateTo("/"); 46 | } 47 | else 48 | { 49 | // Show errors 50 | response.errors.emailOrPassword = new string[] { "is wrong" }; 51 | StateHasChanged(); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/BlazorRealworld/Pages/SignUp.cshtml: -------------------------------------------------------------------------------- 1 | @page "/signup" 2 | @using BlazorRealworld.Model 3 | @inject ApiClient api 4 | @inject IUriHelper uriHelper 5 | 6 |
7 |
8 |
9 |
10 |

Sign up

11 |

12 | Have an account? 13 |

14 | 15 |
16 |
17 | 18 |
19 |
20 | 21 |
22 |
23 | 24 |
25 | 28 |
29 |
30 |
31 |
32 |
33 | 34 | @functions { 35 | UserModel userModel = new UserModel(); 36 | UserResponse response = new UserResponse(); 37 | 38 | async Task Submit() 39 | { 40 | response = await api.SignUpAsync(userModel); 41 | 42 | if (response.errors == null) 43 | uriHelper.NavigateTo("/"); 44 | else 45 | // Show errors 46 | StateHasChanged(); 47 | } 48 | } -------------------------------------------------------------------------------- /src/BlazorRealworld/Pages/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @layout MainLayout 2 | -------------------------------------------------------------------------------- /src/BlazorRealworld/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Blazor.Browser.Rendering; 2 | using Microsoft.AspNetCore.Blazor.Browser.Services; 3 | using Microsoft.Extensions.DependencyInjection; 4 | using System; 5 | 6 | namespace BlazorRealworld 7 | { 8 | class Program 9 | { 10 | static void Main(string[] args) 11 | { 12 | var serviceProvider = new BrowserServiceProvider(configure => 13 | { 14 | configure.Add(ServiceDescriptor.Singleton()); 15 | configure.Add(ServiceDescriptor.Singleton()); 16 | }); 17 | 18 | new BrowserRenderer(serviceProvider).AddComponent("app"); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/BlazorRealworld/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "BlazorRealworld": { 4 | "commandName": "Project", 5 | "launchBrowser": true, 6 | "environmentVariables": { 7 | "ASPNETCORE_ENVIRONMENT": "Development" 8 | }, 9 | "applicationUrl": "http://localhost:50077/" 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/BlazorRealworld/Shared/ArticleList.cshtml: -------------------------------------------------------------------------------- 1 | @using BlazorRealworld 2 | @using BlazorRealworld.Model 3 | 4 | @if (Articles == null) 5 | { 6 |
7 | Loading articles... 8 |
9 | } 10 | else if (Articles.Count() == 0) 11 | { 12 |
13 | No articles here... yet. 14 |
15 | } 16 | else 17 | { 18 | foreach (var article in Articles) 19 | { 20 | var date = article.createdAt; 21 | 22 |
23 | 33 | 34 |

@article.title

35 |

@article.description

36 | Read more... 37 |
38 |
39 | } 40 | } 41 | 42 | @functions { 43 | [Parameter] 44 | IEnumerable Articles { get; set; } 45 | 46 | static string Ordinal(int number) 47 | { 48 | var work = number.ToString(); 49 | if ((number % 100) == 11 || (number % 100) == 12 || (number % 100) == 13) 50 | return work + "th"; 51 | switch (number % 10) 52 | { 53 | case 1: work += "st"; break; 54 | case 2: work += "nd"; break; 55 | case 3: work += "rd"; break; 56 | default: work += "th"; break; 57 | } 58 | return work; 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/BlazorRealworld/Shared/ErrorMessages.cshtml: -------------------------------------------------------------------------------- 1 | @using BlazorRealworld 2 | 3 |
    4 | @foreach (var error in Errors?.username ?? new string[0]) 5 | { 6 |
  • The username @error.
  • 7 | } 8 | @foreach (var error in Errors?.email ?? new string[0]) 9 | { 10 |
  • The email address @error.
  • 11 | } 12 | @foreach (var error in Errors?.password ?? new string[0]) 13 | { 14 |
  • The password @error.
  • 15 | } 16 | @foreach (var error in Errors?.title ?? new string[0]) 17 | { 18 |
  • The title @error.
  • 19 | } 20 | @foreach (var error in Errors?.description ?? new string[0]) 21 | { 22 |
  • The description @error.
  • 23 | } 24 | @foreach (var error in Errors?.body ?? new string[0]) 25 | { 26 |
  • The article text @error.
  • 27 | } 28 | @foreach (var error in Errors?.emailOrPassword ?? new string[0]) 29 | { 30 |
  • The email or password @error.
  • 31 | } 32 |
33 | 34 | @functions { 35 | [Parameter] 36 | ErrorsModel Errors { get; set; } 37 | } 38 | -------------------------------------------------------------------------------- /src/BlazorRealworld/Shared/MainLayout.cshtml: -------------------------------------------------------------------------------- 1 | @using System 2 | @inherits BlazorLayoutComponent 3 | @inject AppState state 4 | @inject ApiClient api 5 | @inject IUriHelper uriHelper 6 | 7 | 59 | 60 | @Body 61 | 62 |
63 |
64 | conduit 65 | 66 | An interactive learning project from Thinkster. Code & design licensed under MIT. 67 | 68 |
69 |
70 | 71 | @functions { 72 | void SignOut() 73 | { 74 | api.ClearToken(); 75 | state.UpdateUser(null); 76 | RegisteredFunction.Invoke("deleteStoredToken"); 77 | uriHelper.NavigateTo("/"); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/BlazorRealworld/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using Microsoft.AspNetCore.Blazor 3 | @using Microsoft.AspNetCore.Blazor.Browser.Interop 4 | @using Microsoft.AspNetCore.Blazor.Components 5 | @using Microsoft.AspNetCore.Blazor.Layouts 6 | @using Microsoft.AspNetCore.Blazor.Routing 7 | @using Microsoft.AspNetCore.Blazor.Services 8 | @using BlazorRealworld 9 | @using BlazorRealworld.Shared 10 | -------------------------------------------------------------------------------- /src/BlazorRealworld/global.json: -------------------------------------------------------------------------------- 1 | { 2 | "sdk": { 3 | "version": "2.1.300-preview1-008174" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /src/BlazorRealworld/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/torhovland/blazor-realworld-example-app/68c2d690ab09cb6ab62b7c8532612a21aa7cbef5/src/BlazorRealworld/wwwroot/favicon.ico -------------------------------------------------------------------------------- /src/BlazorRealworld/wwwroot/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Conduit 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | Loading... 15 | 16 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/BlazorRealworld/wwwroot/interop.js: -------------------------------------------------------------------------------- 1 | Blazor.registerFunction('saveToken', token => { 2 | window.localStorage.setItem('jwt', token); 3 | console.log("Authentication token has been stored."); 4 | return true; 5 | }); 6 | 7 | Blazor.registerFunction('getStoredToken', () => { 8 | var token = window.localStorage.getItem('jwt'); 9 | console.log(token ? "Autentication token read from storage." : "No authentication token found in storage."); 10 | return token; 11 | }); 12 | 13 | Blazor.registerFunction('deleteStoredToken', () => { 14 | window.localStorage.removeItem('jwt'); 15 | console.log("Authentication token has been deleted."); 16 | return true; 17 | }); 18 | 19 | Blazor.registerFunction('showRawHtml', (elementId, html) => { 20 | var el = document.getElementById(elementId); 21 | el.innerHTML = html; 22 | return true; 23 | }); 24 | -------------------------------------------------------------------------------- /test/cypress.json: -------------------------------------------------------------------------------- 1 | { 2 | "baseUrl": "http://localhost:50077", 3 | "defaultCommandTimeout": 15000, 4 | "env": { 5 | "apiUrl": "https://conduit.productionready.io/api", 6 | "email": "set privately in cypress.env.json", 7 | "password": "set privately in cypress.env.json", 8 | "username": "set privately in cypress.env.json", 9 | "token": "set privately in cypress.env.json" 10 | } 11 | } -------------------------------------------------------------------------------- /test/cypress/fixtures/example.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Using fixtures to represent data", 3 | "email": "hello@cypress.io", 4 | "body": "Fixtures are a great way to mock data for responses to routes" 5 | } -------------------------------------------------------------------------------- /test/cypress/fixtures/profile.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": 8739, 3 | "name": "Jane", 4 | "email": "jane@example.com" 5 | } -------------------------------------------------------------------------------- /test/cypress/fixtures/users.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "id": 1, 4 | "name": "Leanne Graham", 5 | "username": "Bret", 6 | "email": "Sincere@april.biz", 7 | "address": { 8 | "street": "Kulas Light", 9 | "suite": "Apt. 556", 10 | "city": "Gwenborough", 11 | "zipcode": "92998-3874", 12 | "geo": { 13 | "lat": "-37.3159", 14 | "lng": "81.1496" 15 | } 16 | }, 17 | "phone": "1-770-736-8031 x56442", 18 | "website": "hildegard.org", 19 | "company": { 20 | "name": "Romaguera-Crona", 21 | "catchPhrase": "Multi-layered client-server neural-net", 22 | "bs": "harness real-time e-markets" 23 | } 24 | }, 25 | { 26 | "id": 2, 27 | "name": "Ervin Howell", 28 | "username": "Antonette", 29 | "email": "Shanna@melissa.tv", 30 | "address": { 31 | "street": "Victor Plains", 32 | "suite": "Suite 879", 33 | "city": "Wisokyburgh", 34 | "zipcode": "90566-7771", 35 | "geo": { 36 | "lat": "-43.9509", 37 | "lng": "-34.4618" 38 | } 39 | }, 40 | "phone": "010-692-6593 x09125", 41 | "website": "anastasia.net", 42 | "company": { 43 | "name": "Deckow-Crist", 44 | "catchPhrase": "Proactive didactic contingency", 45 | "bs": "synergize scalable supply-chains" 46 | } 47 | }, 48 | { 49 | "id": 3, 50 | "name": "Clementine Bauch", 51 | "username": "Samantha", 52 | "email": "Nathan@yesenia.net", 53 | "address": { 54 | "street": "Douglas Extension", 55 | "suite": "Suite 847", 56 | "city": "McKenziehaven", 57 | "zipcode": "59590-4157", 58 | "geo": { 59 | "lat": "-68.6102", 60 | "lng": "-47.0653" 61 | } 62 | }, 63 | "phone": "1-463-123-4447", 64 | "website": "ramiro.info", 65 | "company": { 66 | "name": "Romaguera-Jacobson", 67 | "catchPhrase": "Face to face bifurcated interface", 68 | "bs": "e-enable strategic applications" 69 | } 70 | }, 71 | { 72 | "id": 4, 73 | "name": "Patricia Lebsack", 74 | "username": "Karianne", 75 | "email": "Julianne.OConner@kory.org", 76 | "address": { 77 | "street": "Hoeger Mall", 78 | "suite": "Apt. 692", 79 | "city": "South Elvis", 80 | "zipcode": "53919-4257", 81 | "geo": { 82 | "lat": "29.4572", 83 | "lng": "-164.2990" 84 | } 85 | }, 86 | "phone": "493-170-9623 x156", 87 | "website": "kale.biz", 88 | "company": { 89 | "name": "Robel-Corkery", 90 | "catchPhrase": "Multi-tiered zero tolerance productivity", 91 | "bs": "transition cutting-edge web services" 92 | } 93 | }, 94 | { 95 | "id": 5, 96 | "name": "Chelsey Dietrich", 97 | "username": "Kamren", 98 | "email": "Lucio_Hettinger@annie.ca", 99 | "address": { 100 | "street": "Skiles Walks", 101 | "suite": "Suite 351", 102 | "city": "Roscoeview", 103 | "zipcode": "33263", 104 | "geo": { 105 | "lat": "-31.8129", 106 | "lng": "62.5342" 107 | } 108 | }, 109 | "phone": "(254)954-1289", 110 | "website": "demarco.info", 111 | "company": { 112 | "name": "Keebler LLC", 113 | "catchPhrase": "User-centric fault-tolerant solution", 114 | "bs": "revolutionize end-to-end systems" 115 | } 116 | }, 117 | { 118 | "id": 6, 119 | "name": "Mrs. Dennis Schulist", 120 | "username": "Leopoldo_Corkery", 121 | "email": "Karley_Dach@jasper.info", 122 | "address": { 123 | "street": "Norberto Crossing", 124 | "suite": "Apt. 950", 125 | "city": "South Christy", 126 | "zipcode": "23505-1337", 127 | "geo": { 128 | "lat": "-71.4197", 129 | "lng": "71.7478" 130 | } 131 | }, 132 | "phone": "1-477-935-8478 x6430", 133 | "website": "ola.org", 134 | "company": { 135 | "name": "Considine-Lockman", 136 | "catchPhrase": "Synchronised bottom-line interface", 137 | "bs": "e-enable innovative applications" 138 | } 139 | }, 140 | { 141 | "id": 7, 142 | "name": "Kurtis Weissnat", 143 | "username": "Elwyn.Skiles", 144 | "email": "Telly.Hoeger@billy.biz", 145 | "address": { 146 | "street": "Rex Trail", 147 | "suite": "Suite 280", 148 | "city": "Howemouth", 149 | "zipcode": "58804-1099", 150 | "geo": { 151 | "lat": "24.8918", 152 | "lng": "21.8984" 153 | } 154 | }, 155 | "phone": "210.067.6132", 156 | "website": "elvis.io", 157 | "company": { 158 | "name": "Johns Group", 159 | "catchPhrase": "Configurable multimedia task-force", 160 | "bs": "generate enterprise e-tailers" 161 | } 162 | }, 163 | { 164 | "id": 8, 165 | "name": "Nicholas Runolfsdottir V", 166 | "username": "Maxime_Nienow", 167 | "email": "Sherwood@rosamond.me", 168 | "address": { 169 | "street": "Ellsworth Summit", 170 | "suite": "Suite 729", 171 | "city": "Aliyaview", 172 | "zipcode": "45169", 173 | "geo": { 174 | "lat": "-14.3990", 175 | "lng": "-120.7677" 176 | } 177 | }, 178 | "phone": "586.493.6943 x140", 179 | "website": "jacynthe.com", 180 | "company": { 181 | "name": "Abernathy Group", 182 | "catchPhrase": "Implemented secondary concept", 183 | "bs": "e-enable extensible e-tailers" 184 | } 185 | }, 186 | { 187 | "id": 9, 188 | "name": "Glenna Reichert", 189 | "username": "Delphine", 190 | "email": "Chaim_McDermott@dana.io", 191 | "address": { 192 | "street": "Dayna Park", 193 | "suite": "Suite 449", 194 | "city": "Bartholomebury", 195 | "zipcode": "76495-3109", 196 | "geo": { 197 | "lat": "24.6463", 198 | "lng": "-168.8889" 199 | } 200 | }, 201 | "phone": "(775)976-6794 x41206", 202 | "website": "conrad.com", 203 | "company": { 204 | "name": "Yost and Sons", 205 | "catchPhrase": "Switchable contextually-based project", 206 | "bs": "aggregate real-time technologies" 207 | } 208 | }, 209 | { 210 | "id": 10, 211 | "name": "Clementina DuBuque", 212 | "username": "Moriah.Stanton", 213 | "email": "Rey.Padberg@karina.biz", 214 | "address": { 215 | "street": "Kattie Turnpike", 216 | "suite": "Suite 198", 217 | "city": "Lebsackbury", 218 | "zipcode": "31428-2261", 219 | "geo": { 220 | "lat": "-38.2386", 221 | "lng": "57.2232" 222 | } 223 | }, 224 | "phone": "024-648-3804", 225 | "website": "ambrose.net", 226 | "company": { 227 | "name": "Hoeger LLC", 228 | "catchPhrase": "Centralized empowering task-force", 229 | "bs": "target end-to-end models" 230 | } 231 | } 232 | ] -------------------------------------------------------------------------------- /test/cypress/integration/realworld_spec.js: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | const apiUrl = Cypress.env('apiUrl') 4 | const email = Cypress.env('email') 5 | const password = Cypress.env('password') 6 | const username = Cypress.env('username') 7 | const token = Cypress.env('token') 8 | 9 | function post(urlFragment, body) { 10 | return cy.request({ 11 | "method": "POST", 12 | "url": `${apiUrl}${urlFragment}`, 13 | "headers": { "Authorization": `Token ${token}` }, 14 | "body": body 15 | }) 16 | } 17 | 18 | describe('Home page', function () { 19 | it("Opens an article", function () { 20 | cy.visit('/') 21 | cy.get('.article-preview h1').first().then(($title) => { 22 | // Find title of first article 23 | const title = $title.text() 24 | 25 | // Click on it 26 | $title.click() 27 | 28 | // Verify that we find the article title on the new page 29 | cy.contains(title) 30 | }) 31 | }) 32 | 33 | it("Selects a tag", function () { 34 | cy.visit('/') 35 | 36 | // Click first tag pill 37 | cy.get('.sidebar .tag-pill').first().click() 38 | 39 | cy.get('.sidebar .tag-pill').first().then(($tagPill) => { 40 | // Find value of first tag pill 41 | const tag = $tagPill.text() 42 | 43 | // Verify that we find the tag hash on the new page 44 | cy.get('.ion-pound').parents().first().contains(tag) 45 | }) 46 | }) 47 | }) 48 | 49 | describe('Sign up', function () { 50 | it("Shows error messages", function () { 51 | cy.visit('/') 52 | cy.contains('Sign up').click() 53 | cy.get('[type=submit]').click() 54 | cy.contains("can't be blank") 55 | }) 56 | }) 57 | 58 | describe('Sign in', function () { 59 | it("Logs in", function () { 60 | cy.visit('/') 61 | cy.contains('Sign in').click() 62 | cy.get('[type=email]').type(email) 63 | cy.get('[type=password]').type(password) 64 | cy.get('[type=submit]').click() 65 | 66 | // Verify we're back on the Home page 67 | cy.contains("Read more") 68 | }) 69 | }) 70 | 71 | describe('Secured operations', function () { 72 | beforeEach(function () { 73 | // Sign in 74 | window.localStorage.setItem('jwt', token); 75 | }) 76 | 77 | describe('Editor', function () { 78 | it.only("Submits an article", function () { 79 | cy.visit('/') 80 | 81 | // Submit article 82 | cy.contains("New Post").click() 83 | cy.get('input').eq(0).type('Blazor Realworld test article') 84 | cy.get('input').eq(1).type('Description') 85 | cy.get('input').eq(2).type('testing blazor') 86 | cy.get('textarea').first().type('# Article body') 87 | cy.contains('Publish Article').click() 88 | cy.contains('Blazor Realworld test article') 89 | cy.url().then((articleUrl) => { 90 | // Edit article 91 | cy.contains("Edit Article").click() 92 | cy.get('input').eq(0).as('titleInput') 93 | cy.get('@titleInput').should('have.value', 'Blazor Realworld test article') 94 | cy.get('@titleInput').clear() 95 | cy.get('@titleInput').type('Blazor Realworld edited article') 96 | cy.contains('Publish Article').click() 97 | 98 | // Wait until article has been updated 99 | cy.contains('Edit Article') 100 | 101 | // Check edited article 102 | cy.visit(articleUrl) 103 | cy.contains('Blazor Realworld edited article') 104 | cy.get('.article-content h1').first().should('contain', 'Article body') 105 | 106 | // Delete article 107 | cy.contains("Delete Article").click() 108 | 109 | // Verify we're back on the Home page 110 | cy.contains("Global Feed") 111 | }) 112 | }) 113 | }) 114 | 115 | describe('Profile', function () { 116 | it("Shows my name and articles", function () { 117 | post('/articles', { 118 | "article": { "title": "Blazor Realworld profile test", "description": "Description", "body": "Body", "tagList": ["blazor", "testing"] } 119 | }) 120 | .then((response) => { 121 | const slug = response.body.article.slug 122 | 123 | cy.visit('/') 124 | 125 | // Wait until logged in 126 | cy.get('.nav-link .user-pic') 127 | 128 | // Go to profile 129 | cy.get('.nav').contains(username).click() 130 | cy.get('.user-info').contains(username) 131 | cy.contains('Blazor Realworld profile test').click({ force: true }) 132 | 133 | // Delete article 134 | cy.contains("Delete Article").click() 135 | }) 136 | }) 137 | }) 138 | }) 139 | -------------------------------------------------------------------------------- /test/cypress/plugins/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example plugins/index.js can be used to load plugins 3 | // 4 | // You can change the location of this file or turn off loading 5 | // the plugins file with the 'pluginsFile' configuration option. 6 | // 7 | // You can read more here: 8 | // https://on.cypress.io/plugins-guide 9 | // *********************************************************** 10 | 11 | // This function is called when a project is opened or re-opened (e.g. due to 12 | // the project's config changing) 13 | 14 | module.exports = (on, config) => { 15 | // `on` is used to hook into various events Cypress emits 16 | // `config` is the resolved Cypress config 17 | } 18 | -------------------------------------------------------------------------------- /test/cypress/support/commands.js: -------------------------------------------------------------------------------- 1 | // *********************************************** 2 | // This example commands.js shows you how to 3 | // create various custom commands and overwrite 4 | // existing commands. 5 | // 6 | // For more comprehensive examples of custom 7 | // commands please read more here: 8 | // https://on.cypress.io/custom-commands 9 | // *********************************************** 10 | // 11 | // 12 | // -- This is a parent command -- 13 | // Cypress.Commands.add("login", (email, password) => { ... }) 14 | // 15 | // 16 | // -- This is a child command -- 17 | // Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... }) 18 | // 19 | // 20 | // -- This is a dual command -- 21 | // Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... }) 22 | // 23 | // 24 | // -- This is will overwrite an existing command -- 25 | // Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... }) 26 | -------------------------------------------------------------------------------- /test/cypress/support/index.js: -------------------------------------------------------------------------------- 1 | // *********************************************************** 2 | // This example support/index.js is processed and 3 | // loaded automatically before your test files. 4 | // 5 | // This is a great place to put global configuration and 6 | // behavior that modifies Cypress. 7 | // 8 | // You can change the location of this file or turn off 9 | // automatically serving support files with the 10 | // 'supportFile' configuration option. 11 | // 12 | // You can read more here: 13 | // https://on.cypress.io/configuration 14 | // *********************************************************** 15 | 16 | // Import commands.js using ES2015 syntax: 17 | import './commands' 18 | 19 | // Alternatively you can use CommonJS syntax: 20 | // require('./commands') 21 | -------------------------------------------------------------------------------- /test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "devDependencies": { 7 | "cross-env": "^5.1.4", 8 | "cypress": "^2.1.0" 9 | }, 10 | "scripts": { 11 | "cypress": "cypress open", 12 | "cypress:react": "cross-env CYPRESS_baseUrl=https://react-redux.realworld.io/# cypress open", 13 | "test": "cypress run", 14 | "test:react": "cross-env CYPRESS_baseUrl=https://react-redux.realworld.io/# cypress run" 15 | } 16 | } -------------------------------------------------------------------------------- /test/yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@cypress/listr-verbose-renderer@0.4.1": 6 | version "0.4.1" 7 | resolved "https://registry.yarnpkg.com/@cypress/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#a77492f4b11dcc7c446a34b3e28721afd33c642a" 8 | dependencies: 9 | chalk "^1.1.3" 10 | cli-cursor "^1.0.2" 11 | date-fns "^1.27.2" 12 | figures "^1.7.0" 13 | 14 | "@cypress/xvfb@1.1.3": 15 | version "1.1.3" 16 | resolved "https://registry.yarnpkg.com/@cypress/xvfb/-/xvfb-1.1.3.tgz#6294a7d1feb751f12302248f2089fc534c4acb7f" 17 | dependencies: 18 | lodash.once "^4.1.1" 19 | 20 | "@types/blob-util@1.3.3": 21 | version "1.3.3" 22 | resolved "https://registry.yarnpkg.com/@types/blob-util/-/blob-util-1.3.3.tgz#adba644ae34f88e1dd9a5864c66ad651caaf628a" 23 | 24 | "@types/bluebird@3.5.18": 25 | version "3.5.18" 26 | resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.18.tgz#6a60435d4663e290f3709898a4f75014f279c4d6" 27 | 28 | "@types/chai-jquery@1.1.35": 29 | version "1.1.35" 30 | resolved "https://registry.yarnpkg.com/@types/chai-jquery/-/chai-jquery-1.1.35.tgz#9a8f0a39ec0851b2768a8f8c764158c2a2568d04" 31 | dependencies: 32 | "@types/chai" "*" 33 | "@types/jquery" "*" 34 | 35 | "@types/chai@*": 36 | version "4.1.2" 37 | resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.1.2.tgz#f1af664769cfb50af805431c407425ed619daa21" 38 | 39 | "@types/chai@4.0.8": 40 | version "4.0.8" 41 | resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.0.8.tgz#d27600e9ba2f371e08695d90a0fe0408d89c7be7" 42 | 43 | "@types/jquery@*": 44 | version "3.3.1" 45 | resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.3.1.tgz#55758d44d422756d6329cbf54e6d41931d7ba28f" 46 | 47 | "@types/jquery@3.2.16": 48 | version "3.2.16" 49 | resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.2.16.tgz#04419c404a3194350e7d3f339a90e72c88db3111" 50 | 51 | "@types/lodash@4.14.87": 52 | version "4.14.87" 53 | resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.87.tgz#55f92183b048c2c64402afe472f8333f4e319a6b" 54 | 55 | "@types/minimatch@3.0.1": 56 | version "3.0.1" 57 | resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.1.tgz#b683eb60be358304ef146f5775db4c0e3696a550" 58 | 59 | "@types/mocha@2.2.44": 60 | version "2.2.44" 61 | resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-2.2.44.tgz#1d4a798e53f35212fd5ad4d04050620171cd5b5e" 62 | 63 | "@types/sinon-chai@2.7.29": 64 | version "2.7.29" 65 | resolved "https://registry.yarnpkg.com/@types/sinon-chai/-/sinon-chai-2.7.29.tgz#4db01497e2dd1908b2bd30d1782f456353f5f723" 66 | dependencies: 67 | "@types/chai" "*" 68 | "@types/sinon" "*" 69 | 70 | "@types/sinon@*": 71 | version "4.3.0" 72 | resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.3.0.tgz#7f53915994a00ccea24f4e0c24709822ed11a3b1" 73 | 74 | "@types/sinon@4.0.0": 75 | version "4.0.0" 76 | resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-4.0.0.tgz#9a93ffa4ee1329e85166278a5ed99f81dc4c8362" 77 | 78 | ajv@^4.9.1: 79 | version "4.11.8" 80 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536" 81 | dependencies: 82 | co "^4.6.0" 83 | json-stable-stringify "^1.0.1" 84 | 85 | ansi-escapes@^1.0.0: 86 | version "1.4.0" 87 | resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-1.4.0.tgz#d3a8a83b319aa67793662b13e761c7911422306e" 88 | 89 | ansi-regex@^2.0.0: 90 | version "2.1.1" 91 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 92 | 93 | ansi-styles@^2.2.1: 94 | version "2.2.1" 95 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 96 | 97 | ansi-styles@^3.1.0: 98 | version "3.2.1" 99 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 100 | dependencies: 101 | color-convert "^1.9.0" 102 | 103 | asn1@~0.2.3: 104 | version "0.2.3" 105 | resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.3.tgz#dac8787713c9966849fc8180777ebe9c1ddf3b86" 106 | 107 | assert-plus@1.0.0, assert-plus@^1.0.0: 108 | version "1.0.0" 109 | resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" 110 | 111 | assert-plus@^0.2.0: 112 | version "0.2.0" 113 | resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234" 114 | 115 | async@2.1.4: 116 | version "2.1.4" 117 | resolved "https://registry.yarnpkg.com/async/-/async-2.1.4.tgz#2d2160c7788032e4dd6cbe2502f1f9a2c8f6cde4" 118 | dependencies: 119 | lodash "^4.14.0" 120 | 121 | asynckit@^0.4.0: 122 | version "0.4.0" 123 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 124 | 125 | aws-sign2@~0.6.0: 126 | version "0.6.0" 127 | resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.6.0.tgz#14342dd38dbcc94d0e5b87d763cd63612c0e794f" 128 | 129 | aws4@^1.2.1: 130 | version "1.6.0" 131 | resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.6.0.tgz#83ef5ca860b2b32e4a0deedee8c771b9db57471e" 132 | 133 | babel-runtime@^6.18.0: 134 | version "6.26.0" 135 | resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" 136 | dependencies: 137 | core-js "^2.4.0" 138 | regenerator-runtime "^0.11.0" 139 | 140 | balanced-match@^1.0.0: 141 | version "1.0.0" 142 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 143 | 144 | bcrypt-pbkdf@^1.0.0: 145 | version "1.0.1" 146 | resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz#63bc5dcb61331b92bc05fd528953c33462a06f8d" 147 | dependencies: 148 | tweetnacl "^0.14.3" 149 | 150 | bluebird@3.5.0: 151 | version "3.5.0" 152 | resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.0.tgz#791420d7f551eea2897453a8a77653f96606d67c" 153 | 154 | boom@2.x.x: 155 | version "2.10.1" 156 | resolved "https://registry.yarnpkg.com/boom/-/boom-2.10.1.tgz#39c8918ceff5799f83f9492a848f625add0c766f" 157 | dependencies: 158 | hoek "2.x.x" 159 | 160 | brace-expansion@^1.1.7: 161 | version "1.1.11" 162 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 163 | dependencies: 164 | balanced-match "^1.0.0" 165 | concat-map "0.0.1" 166 | 167 | buffer-crc32@~0.2.3: 168 | version "0.2.13" 169 | resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" 170 | 171 | caseless@~0.12.0: 172 | version "0.12.0" 173 | resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" 174 | 175 | chalk@2.1.0: 176 | version "2.1.0" 177 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.1.0.tgz#ac5becf14fa21b99c6c92ca7a7d7cfd5b17e743e" 178 | dependencies: 179 | ansi-styles "^3.1.0" 180 | escape-string-regexp "^1.0.5" 181 | supports-color "^4.0.0" 182 | 183 | chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: 184 | version "1.1.3" 185 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 186 | dependencies: 187 | ansi-styles "^2.2.1" 188 | escape-string-regexp "^1.0.2" 189 | has-ansi "^2.0.0" 190 | strip-ansi "^3.0.0" 191 | supports-color "^2.0.0" 192 | 193 | check-more-types@2.24.0: 194 | version "2.24.0" 195 | resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600" 196 | 197 | ci-info@^1.0.0: 198 | version "1.1.3" 199 | resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.1.3.tgz#710193264bb05c77b8c90d02f5aaf22216a667b2" 200 | 201 | cli-cursor@^1.0.2: 202 | version "1.0.2" 203 | resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-1.0.2.tgz#64da3f7d56a54412e59794bd62dc35295e8f2987" 204 | dependencies: 205 | restore-cursor "^1.0.1" 206 | 207 | cli-spinners@^0.1.2: 208 | version "0.1.2" 209 | resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-0.1.2.tgz#bb764d88e185fb9e1e6a2a1f19772318f605e31c" 210 | 211 | cli-truncate@^0.2.1: 212 | version "0.2.1" 213 | resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-0.2.1.tgz#9f15cfbb0705005369216c626ac7d05ab90dd574" 214 | dependencies: 215 | slice-ansi "0.0.4" 216 | string-width "^1.0.1" 217 | 218 | co@^4.6.0: 219 | version "4.6.0" 220 | resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" 221 | 222 | code-point-at@^1.0.0: 223 | version "1.1.0" 224 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 225 | 226 | color-convert@^1.9.0: 227 | version "1.9.1" 228 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" 229 | dependencies: 230 | color-name "^1.1.1" 231 | 232 | color-name@^1.1.1: 233 | version "1.1.3" 234 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 235 | 236 | combined-stream@^1.0.5, combined-stream@~1.0.5: 237 | version "1.0.6" 238 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" 239 | dependencies: 240 | delayed-stream "~1.0.0" 241 | 242 | commander@2.11.0: 243 | version "2.11.0" 244 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" 245 | 246 | common-tags@1.4.0: 247 | version "1.4.0" 248 | resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.4.0.tgz#1187be4f3d4cf0c0427d43f74eef1f73501614c0" 249 | dependencies: 250 | babel-runtime "^6.18.0" 251 | 252 | concat-map@0.0.1: 253 | version "0.0.1" 254 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 255 | 256 | concat-stream@1.6.0: 257 | version "1.6.0" 258 | resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.0.tgz#0aac662fd52be78964d5532f694784e70110acf7" 259 | dependencies: 260 | inherits "^2.0.3" 261 | readable-stream "^2.2.2" 262 | typedarray "^0.0.6" 263 | 264 | core-js@^2.4.0: 265 | version "2.5.4" 266 | resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.4.tgz#f2c8bf181f2a80b92f360121429ce63a2f0aeae0" 267 | 268 | core-util-is@1.0.2, core-util-is@~1.0.0: 269 | version "1.0.2" 270 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 271 | 272 | cross-env@^5.1.4: 273 | version "5.1.4" 274 | resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.1.4.tgz#f61c14291f7cc653bb86457002ea80a04699d022" 275 | dependencies: 276 | cross-spawn "^5.1.0" 277 | is-windows "^1.0.0" 278 | 279 | cross-spawn@^5.1.0: 280 | version "5.1.0" 281 | resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" 282 | dependencies: 283 | lru-cache "^4.0.1" 284 | shebang-command "^1.2.0" 285 | which "^1.2.9" 286 | 287 | cryptiles@2.x.x: 288 | version "2.0.5" 289 | resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8" 290 | dependencies: 291 | boom "2.x.x" 292 | 293 | cypress@^2.1.0: 294 | version "2.1.0" 295 | resolved "https://registry.yarnpkg.com/cypress/-/cypress-2.1.0.tgz#a8bd7d9b89c38a1e380db83b57d9bba0dbb95ba4" 296 | dependencies: 297 | "@cypress/listr-verbose-renderer" "0.4.1" 298 | "@cypress/xvfb" "1.1.3" 299 | "@types/blob-util" "1.3.3" 300 | "@types/bluebird" "3.5.18" 301 | "@types/chai" "4.0.8" 302 | "@types/chai-jquery" "1.1.35" 303 | "@types/jquery" "3.2.16" 304 | "@types/lodash" "4.14.87" 305 | "@types/minimatch" "3.0.1" 306 | "@types/mocha" "2.2.44" 307 | "@types/sinon" "4.0.0" 308 | "@types/sinon-chai" "2.7.29" 309 | bluebird "3.5.0" 310 | chalk "2.1.0" 311 | check-more-types "2.24.0" 312 | commander "2.11.0" 313 | common-tags "1.4.0" 314 | debug "3.1.0" 315 | extract-zip "1.6.6" 316 | fs-extra "4.0.1" 317 | getos "2.8.4" 318 | glob "7.1.2" 319 | is-ci "1.0.10" 320 | is-installed-globally "0.1.0" 321 | lazy-ass "1.6.0" 322 | listr "0.12.0" 323 | lodash "4.17.4" 324 | minimist "1.2.0" 325 | progress "1.1.8" 326 | ramda "0.24.1" 327 | request "2.81.0" 328 | request-progress "0.3.1" 329 | supports-color "5.1.0" 330 | tmp "0.0.31" 331 | url "0.11.0" 332 | yauzl "2.8.0" 333 | 334 | dashdash@^1.12.0: 335 | version "1.14.1" 336 | resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" 337 | dependencies: 338 | assert-plus "^1.0.0" 339 | 340 | date-fns@^1.27.2: 341 | version "1.29.0" 342 | resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" 343 | 344 | debug@2.6.9: 345 | version "2.6.9" 346 | resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" 347 | dependencies: 348 | ms "2.0.0" 349 | 350 | debug@3.1.0: 351 | version "3.1.0" 352 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" 353 | dependencies: 354 | ms "2.0.0" 355 | 356 | delayed-stream@~1.0.0: 357 | version "1.0.0" 358 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 359 | 360 | ecc-jsbn@~0.1.1: 361 | version "0.1.1" 362 | resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz#0fc73a9ed5f0d53c38193398523ef7e543777505" 363 | dependencies: 364 | jsbn "~0.1.0" 365 | 366 | elegant-spinner@^1.0.1: 367 | version "1.0.1" 368 | resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" 369 | 370 | escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: 371 | version "1.0.5" 372 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 373 | 374 | exit-hook@^1.0.0: 375 | version "1.1.1" 376 | resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" 377 | 378 | extend@~3.0.0: 379 | version "3.0.1" 380 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.1.tgz#a755ea7bc1adfcc5a31ce7e762dbaadc5e636444" 381 | 382 | extract-zip@1.6.6: 383 | version "1.6.6" 384 | resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-1.6.6.tgz#1290ede8d20d0872b429fd3f351ca128ec5ef85c" 385 | dependencies: 386 | concat-stream "1.6.0" 387 | debug "2.6.9" 388 | mkdirp "0.5.0" 389 | yauzl "2.4.1" 390 | 391 | extsprintf@1.3.0: 392 | version "1.3.0" 393 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" 394 | 395 | extsprintf@^1.2.0: 396 | version "1.4.0" 397 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" 398 | 399 | fd-slicer@~1.0.1: 400 | version "1.0.1" 401 | resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" 402 | dependencies: 403 | pend "~1.2.0" 404 | 405 | figures@^1.7.0: 406 | version "1.7.0" 407 | resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" 408 | dependencies: 409 | escape-string-regexp "^1.0.5" 410 | object-assign "^4.1.0" 411 | 412 | forever-agent@~0.6.1: 413 | version "0.6.1" 414 | resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" 415 | 416 | form-data@~2.1.1: 417 | version "2.1.4" 418 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.1.4.tgz#33c183acf193276ecaa98143a69e94bfee1750d1" 419 | dependencies: 420 | asynckit "^0.4.0" 421 | combined-stream "^1.0.5" 422 | mime-types "^2.1.12" 423 | 424 | fs-extra@4.0.1: 425 | version "4.0.1" 426 | resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.1.tgz#7fc0c6c8957f983f57f306a24e5b9ddd8d0dd880" 427 | dependencies: 428 | graceful-fs "^4.1.2" 429 | jsonfile "^3.0.0" 430 | universalify "^0.1.0" 431 | 432 | fs.realpath@^1.0.0: 433 | version "1.0.0" 434 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 435 | 436 | getos@2.8.4: 437 | version "2.8.4" 438 | resolved "https://registry.yarnpkg.com/getos/-/getos-2.8.4.tgz#7b8603d3619c28e38cb0fe7a4f63c3acb80d5163" 439 | dependencies: 440 | async "2.1.4" 441 | 442 | getpass@^0.1.1: 443 | version "0.1.7" 444 | resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" 445 | dependencies: 446 | assert-plus "^1.0.0" 447 | 448 | glob@7.1.2: 449 | version "7.1.2" 450 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" 451 | dependencies: 452 | fs.realpath "^1.0.0" 453 | inflight "^1.0.4" 454 | inherits "2" 455 | minimatch "^3.0.4" 456 | once "^1.3.0" 457 | path-is-absolute "^1.0.0" 458 | 459 | global-dirs@^0.1.0: 460 | version "0.1.1" 461 | resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" 462 | dependencies: 463 | ini "^1.3.4" 464 | 465 | graceful-fs@^4.1.2, graceful-fs@^4.1.6: 466 | version "4.1.11" 467 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" 468 | 469 | har-schema@^1.0.5: 470 | version "1.0.5" 471 | resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-1.0.5.tgz#d263135f43307c02c602afc8fe95970c0151369e" 472 | 473 | har-validator@~4.2.1: 474 | version "4.2.1" 475 | resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-4.2.1.tgz#33481d0f1bbff600dd203d75812a6a5fba002e2a" 476 | dependencies: 477 | ajv "^4.9.1" 478 | har-schema "^1.0.5" 479 | 480 | has-ansi@^2.0.0: 481 | version "2.0.0" 482 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 483 | dependencies: 484 | ansi-regex "^2.0.0" 485 | 486 | has-flag@^2.0.0: 487 | version "2.0.0" 488 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" 489 | 490 | hawk@~3.1.3: 491 | version "3.1.3" 492 | resolved "https://registry.yarnpkg.com/hawk/-/hawk-3.1.3.tgz#078444bd7c1640b0fe540d2c9b73d59678e8e1c4" 493 | dependencies: 494 | boom "2.x.x" 495 | cryptiles "2.x.x" 496 | hoek "2.x.x" 497 | sntp "1.x.x" 498 | 499 | hoek@2.x.x: 500 | version "2.16.3" 501 | resolved "https://registry.yarnpkg.com/hoek/-/hoek-2.16.3.tgz#20bb7403d3cea398e91dc4710a8ff1b8274a25ed" 502 | 503 | http-signature@~1.1.0: 504 | version "1.1.1" 505 | resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.1.1.tgz#df72e267066cd0ac67fb76adf8e134a8fbcf91bf" 506 | dependencies: 507 | assert-plus "^0.2.0" 508 | jsprim "^1.2.2" 509 | sshpk "^1.7.0" 510 | 511 | indent-string@^2.1.0: 512 | version "2.1.0" 513 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-2.1.0.tgz#8e2d48348742121b4a8218b7a137e9a52049dc80" 514 | dependencies: 515 | repeating "^2.0.0" 516 | 517 | indent-string@^3.0.0: 518 | version "3.2.0" 519 | resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-3.2.0.tgz#4a5fd6d27cc332f37e5419a504dbb837105c9289" 520 | 521 | inflight@^1.0.4: 522 | version "1.0.6" 523 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 524 | dependencies: 525 | once "^1.3.0" 526 | wrappy "1" 527 | 528 | inherits@2, inherits@^2.0.3, inherits@~2.0.3: 529 | version "2.0.3" 530 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" 531 | 532 | ini@^1.3.4: 533 | version "1.3.5" 534 | resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" 535 | 536 | is-ci@1.0.10: 537 | version "1.0.10" 538 | resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.0.10.tgz#f739336b2632365061a9d48270cd56ae3369318e" 539 | dependencies: 540 | ci-info "^1.0.0" 541 | 542 | is-finite@^1.0.0: 543 | version "1.0.2" 544 | resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" 545 | dependencies: 546 | number-is-nan "^1.0.0" 547 | 548 | is-fullwidth-code-point@^1.0.0: 549 | version "1.0.0" 550 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 551 | dependencies: 552 | number-is-nan "^1.0.0" 553 | 554 | is-installed-globally@0.1.0: 555 | version "0.1.0" 556 | resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" 557 | dependencies: 558 | global-dirs "^0.1.0" 559 | is-path-inside "^1.0.0" 560 | 561 | is-path-inside@^1.0.0: 562 | version "1.0.1" 563 | resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" 564 | dependencies: 565 | path-is-inside "^1.0.1" 566 | 567 | is-promise@^2.1.0: 568 | version "2.1.0" 569 | resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" 570 | 571 | is-stream@^1.1.0: 572 | version "1.1.0" 573 | resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" 574 | 575 | is-typedarray@~1.0.0: 576 | version "1.0.0" 577 | resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 578 | 579 | is-windows@^1.0.0: 580 | version "1.0.2" 581 | resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" 582 | 583 | isarray@~1.0.0: 584 | version "1.0.0" 585 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 586 | 587 | isexe@^2.0.0: 588 | version "2.0.0" 589 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 590 | 591 | isstream@~0.1.2: 592 | version "0.1.2" 593 | resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" 594 | 595 | jsbn@~0.1.0: 596 | version "0.1.1" 597 | resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" 598 | 599 | json-schema@0.2.3: 600 | version "0.2.3" 601 | resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" 602 | 603 | json-stable-stringify@^1.0.1: 604 | version "1.0.1" 605 | resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" 606 | dependencies: 607 | jsonify "~0.0.0" 608 | 609 | json-stringify-safe@~5.0.1: 610 | version "5.0.1" 611 | resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 612 | 613 | jsonfile@^3.0.0: 614 | version "3.0.1" 615 | resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" 616 | optionalDependencies: 617 | graceful-fs "^4.1.6" 618 | 619 | jsonify@~0.0.0: 620 | version "0.0.0" 621 | resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" 622 | 623 | jsprim@^1.2.2: 624 | version "1.4.1" 625 | resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" 626 | dependencies: 627 | assert-plus "1.0.0" 628 | extsprintf "1.3.0" 629 | json-schema "0.2.3" 630 | verror "1.10.0" 631 | 632 | lazy-ass@1.6.0: 633 | version "1.6.0" 634 | resolved "https://registry.yarnpkg.com/lazy-ass/-/lazy-ass-1.6.0.tgz#7999655e8646c17f089fdd187d150d3324d54513" 635 | 636 | listr-silent-renderer@^1.1.1: 637 | version "1.1.1" 638 | resolved "https://registry.yarnpkg.com/listr-silent-renderer/-/listr-silent-renderer-1.1.1.tgz#924b5a3757153770bf1a8e3fbf74b8bbf3f9242e" 639 | 640 | listr-update-renderer@^0.2.0: 641 | version "0.2.0" 642 | resolved "https://registry.yarnpkg.com/listr-update-renderer/-/listr-update-renderer-0.2.0.tgz#ca80e1779b4e70266807e8eed1ad6abe398550f9" 643 | dependencies: 644 | chalk "^1.1.3" 645 | cli-truncate "^0.2.1" 646 | elegant-spinner "^1.0.1" 647 | figures "^1.7.0" 648 | indent-string "^3.0.0" 649 | log-symbols "^1.0.2" 650 | log-update "^1.0.2" 651 | strip-ansi "^3.0.1" 652 | 653 | listr-verbose-renderer@^0.4.0: 654 | version "0.4.1" 655 | resolved "https://registry.yarnpkg.com/listr-verbose-renderer/-/listr-verbose-renderer-0.4.1.tgz#8206f4cf6d52ddc5827e5fd14989e0e965933a35" 656 | dependencies: 657 | chalk "^1.1.3" 658 | cli-cursor "^1.0.2" 659 | date-fns "^1.27.2" 660 | figures "^1.7.0" 661 | 662 | listr@0.12.0: 663 | version "0.12.0" 664 | resolved "https://registry.yarnpkg.com/listr/-/listr-0.12.0.tgz#6bce2c0f5603fa49580ea17cd6a00cc0e5fa451a" 665 | dependencies: 666 | chalk "^1.1.3" 667 | cli-truncate "^0.2.1" 668 | figures "^1.7.0" 669 | indent-string "^2.1.0" 670 | is-promise "^2.1.0" 671 | is-stream "^1.1.0" 672 | listr-silent-renderer "^1.1.1" 673 | listr-update-renderer "^0.2.0" 674 | listr-verbose-renderer "^0.4.0" 675 | log-symbols "^1.0.2" 676 | log-update "^1.0.2" 677 | ora "^0.2.3" 678 | p-map "^1.1.1" 679 | rxjs "^5.0.0-beta.11" 680 | stream-to-observable "^0.1.0" 681 | strip-ansi "^3.0.1" 682 | 683 | lodash.once@^4.1.1: 684 | version "4.1.1" 685 | resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" 686 | 687 | lodash@4.17.4: 688 | version "4.17.4" 689 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" 690 | 691 | lodash@^4.14.0: 692 | version "4.17.5" 693 | resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" 694 | 695 | log-symbols@^1.0.2: 696 | version "1.0.2" 697 | resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-1.0.2.tgz#376ff7b58ea3086a0f09facc74617eca501e1a18" 698 | dependencies: 699 | chalk "^1.0.0" 700 | 701 | log-update@^1.0.2: 702 | version "1.0.2" 703 | resolved "https://registry.yarnpkg.com/log-update/-/log-update-1.0.2.tgz#19929f64c4093d2d2e7075a1dad8af59c296b8d1" 704 | dependencies: 705 | ansi-escapes "^1.0.0" 706 | cli-cursor "^1.0.2" 707 | 708 | lru-cache@^4.0.1: 709 | version "4.1.2" 710 | resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.2.tgz#45234b2e6e2f2b33da125624c4664929a0224c3f" 711 | dependencies: 712 | pseudomap "^1.0.2" 713 | yallist "^2.1.2" 714 | 715 | mime-db@~1.33.0: 716 | version "1.33.0" 717 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" 718 | 719 | mime-types@^2.1.12, mime-types@~2.1.7: 720 | version "2.1.18" 721 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" 722 | dependencies: 723 | mime-db "~1.33.0" 724 | 725 | minimatch@^3.0.4: 726 | version "3.0.4" 727 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 728 | dependencies: 729 | brace-expansion "^1.1.7" 730 | 731 | minimist@0.0.8: 732 | version "0.0.8" 733 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 734 | 735 | minimist@1.2.0: 736 | version "1.2.0" 737 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" 738 | 739 | mkdirp@0.5.0: 740 | version "0.5.0" 741 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.0.tgz#1d73076a6df986cd9344e15e71fcc05a4c9abf12" 742 | dependencies: 743 | minimist "0.0.8" 744 | 745 | ms@2.0.0: 746 | version "2.0.0" 747 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" 748 | 749 | number-is-nan@^1.0.0: 750 | version "1.0.1" 751 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 752 | 753 | oauth-sign@~0.8.1: 754 | version "0.8.2" 755 | resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" 756 | 757 | object-assign@^4.0.1, object-assign@^4.1.0: 758 | version "4.1.1" 759 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 760 | 761 | once@^1.3.0: 762 | version "1.4.0" 763 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 764 | dependencies: 765 | wrappy "1" 766 | 767 | onetime@^1.0.0: 768 | version "1.1.0" 769 | resolved "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz#a1f7838f8314c516f05ecefcbc4ccfe04b4ed789" 770 | 771 | ora@^0.2.3: 772 | version "0.2.3" 773 | resolved "https://registry.yarnpkg.com/ora/-/ora-0.2.3.tgz#37527d220adcd53c39b73571d754156d5db657a4" 774 | dependencies: 775 | chalk "^1.1.1" 776 | cli-cursor "^1.0.2" 777 | cli-spinners "^0.1.2" 778 | object-assign "^4.0.1" 779 | 780 | os-tmpdir@~1.0.1: 781 | version "1.0.2" 782 | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" 783 | 784 | p-map@^1.1.1: 785 | version "1.2.0" 786 | resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" 787 | 788 | path-is-absolute@^1.0.0: 789 | version "1.0.1" 790 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 791 | 792 | path-is-inside@^1.0.1: 793 | version "1.0.2" 794 | resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" 795 | 796 | pend@~1.2.0: 797 | version "1.2.0" 798 | resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" 799 | 800 | performance-now@^0.2.0: 801 | version "0.2.0" 802 | resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" 803 | 804 | process-nextick-args@~2.0.0: 805 | version "2.0.0" 806 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" 807 | 808 | progress@1.1.8: 809 | version "1.1.8" 810 | resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" 811 | 812 | pseudomap@^1.0.2: 813 | version "1.0.2" 814 | resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" 815 | 816 | punycode@1.3.2: 817 | version "1.3.2" 818 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" 819 | 820 | punycode@^1.4.1: 821 | version "1.4.1" 822 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" 823 | 824 | qs@~6.4.0: 825 | version "6.4.0" 826 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" 827 | 828 | querystring@0.2.0: 829 | version "0.2.0" 830 | resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" 831 | 832 | ramda@0.24.1: 833 | version "0.24.1" 834 | resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.24.1.tgz#c3b7755197f35b8dc3502228262c4c91ddb6b857" 835 | 836 | readable-stream@^2.2.2: 837 | version "2.3.5" 838 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.5.tgz#b4f85003a938cbb6ecbce2a124fb1012bd1a838d" 839 | dependencies: 840 | core-util-is "~1.0.0" 841 | inherits "~2.0.3" 842 | isarray "~1.0.0" 843 | process-nextick-args "~2.0.0" 844 | safe-buffer "~5.1.1" 845 | string_decoder "~1.0.3" 846 | util-deprecate "~1.0.1" 847 | 848 | regenerator-runtime@^0.11.0: 849 | version "0.11.1" 850 | resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" 851 | 852 | repeating@^2.0.0: 853 | version "2.0.1" 854 | resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" 855 | dependencies: 856 | is-finite "^1.0.0" 857 | 858 | request-progress@0.3.1: 859 | version "0.3.1" 860 | resolved "https://registry.yarnpkg.com/request-progress/-/request-progress-0.3.1.tgz#0721c105d8a96ac6b2ce8b2c89ae2d5ecfcf6b3a" 861 | dependencies: 862 | throttleit "~0.0.2" 863 | 864 | request@2.81.0: 865 | version "2.81.0" 866 | resolved "https://registry.yarnpkg.com/request/-/request-2.81.0.tgz#c6928946a0e06c5f8d6f8a9333469ffda46298a0" 867 | dependencies: 868 | aws-sign2 "~0.6.0" 869 | aws4 "^1.2.1" 870 | caseless "~0.12.0" 871 | combined-stream "~1.0.5" 872 | extend "~3.0.0" 873 | forever-agent "~0.6.1" 874 | form-data "~2.1.1" 875 | har-validator "~4.2.1" 876 | hawk "~3.1.3" 877 | http-signature "~1.1.0" 878 | is-typedarray "~1.0.0" 879 | isstream "~0.1.2" 880 | json-stringify-safe "~5.0.1" 881 | mime-types "~2.1.7" 882 | oauth-sign "~0.8.1" 883 | performance-now "^0.2.0" 884 | qs "~6.4.0" 885 | safe-buffer "^5.0.1" 886 | stringstream "~0.0.4" 887 | tough-cookie "~2.3.0" 888 | tunnel-agent "^0.6.0" 889 | uuid "^3.0.0" 890 | 891 | restore-cursor@^1.0.1: 892 | version "1.0.1" 893 | resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-1.0.1.tgz#34661f46886327fed2991479152252df92daa541" 894 | dependencies: 895 | exit-hook "^1.0.0" 896 | onetime "^1.0.0" 897 | 898 | rxjs@^5.0.0-beta.11: 899 | version "5.5.8" 900 | resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-5.5.8.tgz#b2b0809a57614ad6254c03d7446dea0d83ca3791" 901 | dependencies: 902 | symbol-observable "1.0.1" 903 | 904 | safe-buffer@^5.0.1, safe-buffer@~5.1.0, safe-buffer@~5.1.1: 905 | version "5.1.1" 906 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.1.tgz#893312af69b2123def71f57889001671eeb2c853" 907 | 908 | shebang-command@^1.2.0: 909 | version "1.2.0" 910 | resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" 911 | dependencies: 912 | shebang-regex "^1.0.0" 913 | 914 | shebang-regex@^1.0.0: 915 | version "1.0.0" 916 | resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" 917 | 918 | slice-ansi@0.0.4: 919 | version "0.0.4" 920 | resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-0.0.4.tgz#edbf8903f66f7ce2f8eafd6ceed65e264c831b35" 921 | 922 | sntp@1.x.x: 923 | version "1.0.9" 924 | resolved "https://registry.yarnpkg.com/sntp/-/sntp-1.0.9.tgz#6541184cc90aeea6c6e7b35e2659082443c66198" 925 | dependencies: 926 | hoek "2.x.x" 927 | 928 | sshpk@^1.7.0: 929 | version "1.14.1" 930 | resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.1.tgz#130f5975eddad963f1d56f92b9ac6c51fa9f83eb" 931 | dependencies: 932 | asn1 "~0.2.3" 933 | assert-plus "^1.0.0" 934 | dashdash "^1.12.0" 935 | getpass "^0.1.1" 936 | optionalDependencies: 937 | bcrypt-pbkdf "^1.0.0" 938 | ecc-jsbn "~0.1.1" 939 | jsbn "~0.1.0" 940 | tweetnacl "~0.14.0" 941 | 942 | stream-to-observable@^0.1.0: 943 | version "0.1.0" 944 | resolved "https://registry.yarnpkg.com/stream-to-observable/-/stream-to-observable-0.1.0.tgz#45bf1d9f2d7dc09bed81f1c307c430e68b84cffe" 945 | 946 | string-width@^1.0.1: 947 | version "1.0.2" 948 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 949 | dependencies: 950 | code-point-at "^1.0.0" 951 | is-fullwidth-code-point "^1.0.0" 952 | strip-ansi "^3.0.0" 953 | 954 | string_decoder@~1.0.3: 955 | version "1.0.3" 956 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" 957 | dependencies: 958 | safe-buffer "~5.1.0" 959 | 960 | stringstream@~0.0.4: 961 | version "0.0.5" 962 | resolved "https://registry.yarnpkg.com/stringstream/-/stringstream-0.0.5.tgz#4e484cd4de5a0bbbee18e46307710a8a81621878" 963 | 964 | strip-ansi@^3.0.0, strip-ansi@^3.0.1: 965 | version "3.0.1" 966 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 967 | dependencies: 968 | ansi-regex "^2.0.0" 969 | 970 | supports-color@5.1.0: 971 | version "5.1.0" 972 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.1.0.tgz#058a021d1b619f7ddf3980d712ea3590ce7de3d5" 973 | dependencies: 974 | has-flag "^2.0.0" 975 | 976 | supports-color@^2.0.0: 977 | version "2.0.0" 978 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 979 | 980 | supports-color@^4.0.0: 981 | version "4.5.0" 982 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" 983 | dependencies: 984 | has-flag "^2.0.0" 985 | 986 | symbol-observable@1.0.1: 987 | version "1.0.1" 988 | resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" 989 | 990 | throttleit@~0.0.2: 991 | version "0.0.2" 992 | resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-0.0.2.tgz#cfedf88e60c00dd9697b61fdd2a8343a9b680eaf" 993 | 994 | tmp@0.0.31: 995 | version "0.0.31" 996 | resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.31.tgz#8f38ab9438e17315e5dbd8b3657e8bfb277ae4a7" 997 | dependencies: 998 | os-tmpdir "~1.0.1" 999 | 1000 | tough-cookie@~2.3.0: 1001 | version "2.3.4" 1002 | resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.3.4.tgz#ec60cee38ac675063ffc97a5c18970578ee83655" 1003 | dependencies: 1004 | punycode "^1.4.1" 1005 | 1006 | tunnel-agent@^0.6.0: 1007 | version "0.6.0" 1008 | resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" 1009 | dependencies: 1010 | safe-buffer "^5.0.1" 1011 | 1012 | tweetnacl@^0.14.3, tweetnacl@~0.14.0: 1013 | version "0.14.5" 1014 | resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" 1015 | 1016 | typedarray@^0.0.6: 1017 | version "0.0.6" 1018 | resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" 1019 | 1020 | universalify@^0.1.0: 1021 | version "0.1.1" 1022 | resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7" 1023 | 1024 | url@0.11.0: 1025 | version "0.11.0" 1026 | resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" 1027 | dependencies: 1028 | punycode "1.3.2" 1029 | querystring "0.2.0" 1030 | 1031 | util-deprecate@~1.0.1: 1032 | version "1.0.2" 1033 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 1034 | 1035 | uuid@^3.0.0: 1036 | version "3.2.1" 1037 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" 1038 | 1039 | verror@1.10.0: 1040 | version "1.10.0" 1041 | resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" 1042 | dependencies: 1043 | assert-plus "^1.0.0" 1044 | core-util-is "1.0.2" 1045 | extsprintf "^1.2.0" 1046 | 1047 | which@^1.2.9: 1048 | version "1.3.0" 1049 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.0.tgz#ff04bdfc010ee547d780bec38e1ac1c2777d253a" 1050 | dependencies: 1051 | isexe "^2.0.0" 1052 | 1053 | wrappy@1: 1054 | version "1.0.2" 1055 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1056 | 1057 | yallist@^2.1.2: 1058 | version "2.1.2" 1059 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" 1060 | 1061 | yauzl@2.4.1: 1062 | version "2.4.1" 1063 | resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.4.1.tgz#9528f442dab1b2284e58b4379bb194e22e0c4005" 1064 | dependencies: 1065 | fd-slicer "~1.0.1" 1066 | 1067 | yauzl@2.8.0: 1068 | version "2.8.0" 1069 | resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.8.0.tgz#79450aff22b2a9c5a41ef54e02db907ccfbf9ee2" 1070 | dependencies: 1071 | buffer-crc32 "~0.2.3" 1072 | fd-slicer "~1.0.1" 1073 | --------------------------------------------------------------------------------