public async Task CanApproveNewFeatures() { var client = new LeanwareTestClient(_factory); var feature = (await client.Create <Feature>()).Received; var stories = new List <Story>(); for (int i = 0; i < 5; i++) { var story = (await client.Create <Story>(new { FeatureId = feature.Id })).Received; stories.Add(story); } var response = await client.Post(path : $"api/features/{feature.Id}/approve"); response.EnsureSuccessStatusCode(); feature = await client.Get <Feature>(feature.ReadPath); feature.Status.Should().Be("Approved"); foreach (var s in stories) { var story = await client.Get <Story>(s.ReadPath); story.Status.Should().Be("Approved"); } // Only New feature can be approved, otherwise HTTP 400 BadRequest should be returned response = await client.Post(path : $"api/features/{feature.Id}/approve"); response.StatusCode.Should().Be(HttpStatusCode.BadRequest); }
public async Task CanFilterFeaturesByTags() { var client = new LeanwareTestClient(_factory); var testTag = $"{Guid.NewGuid().ToString().Split('-')[1]}{Guid.NewGuid().ToString().Split('-')[1]}"; var features = new List <Feature>(); var taggedFeatures = new List <Feature>(); for (int i = 0; i < 10; i++) { features.Add((await client.Create <Feature>()).Received); } for (int i = 0; i < 5; i++) { var tag = features[i].Tags.First(); taggedFeatures.Add(features[i]); await client.Update <Feature>(features[i].UpdatePath, new { Tags = new List <string> { testTag } }); } var filteredFeatures = await client.Get <List <Feature> >($"api/features?tag={testTag}"); filteredFeatures.Select(ff => ff.Id).Should().BeEquivalentTo(taggedFeatures.Select(tf => tf.Id)); }
public async Task CanCollectLogs() { var client = new LeanwareTestClient(_factory); var feature = (await client.Create <Feature>()).Received; var story = (await client.Create <Story>(new { FeatureId = feature.Id })).Received; await client.Post(path : $"api/features/{feature.Id}/approve"); await client.Post(path : $"api/stories/{story.Id}/start"); await client.Post(path : $"api/stories/{story.Id}/finish"); var storyUpdate = new { Title = RandomTitle("S") }; await client.Update <Story>(story.UpdatePath, storyUpdate); var logs = await client.Get <List <string> >(path : $"api/logs"); var assertedLogs = new[] { $"Feature #{feature.Id} has been created", $"Story #{story.Id} has been added to feature #{feature.Id}", $"Feature #{feature.Id} has been approved", $"Story #{story.Id} has been started", $"Story #{story.Id} has been finished", $"Feature #{feature.Id} has been finished", $"Story #{story.Id} has been updated" }; foreach (var al in assertedLogs) { logs.Should().Contain(al); } }
public async Task CanEnforceWipLimit() { const int wipLimit = 2; var client = new LeanwareTestClient(_factory); var stories = new List <Story>(); for (int i = 0; i < wipLimit + 1; i++) { var feature = (await client.Create <Feature>()).Received; var story = (await client.Create <Story>(new { FeatureId = feature.Id })).Received; stories.Add(story); await client.Post(path : $"api/features/{feature.Id}/approve"); } for (int i = 0; i < wipLimit; i++) { await client.Post(path : $"api/stories/{stories[i].Id}/start"); var story = await client.Get <Story>(stories[0].ReadPath); story.Status.Should().Be("Implementing"); } var response = await client.Post(path : $"api/stories/{stories[wipLimit].Id}/start"); response.StatusCode.Should().Be(HttpStatusCode.BadRequest, $"only {wipLimit} features can be in progress at the same time"); }
public async Task CanDeleteTags() { var client = new LeanwareTestClient(_factory); var feature = (await client.Create <Feature>()).Received; var tag = feature.Tags.First(); await client.Delete($"api/tags/{tag}"); feature = await client.Get <Feature>(feature.ReadPath); feature.Tags.Should().NotContain(tag); }
public async Task CannotChangeFeatureStatus() { var client = new LeanwareTestClient(_factory); var feature = (await client.Create <Feature>()).Received; var directUpdate = new { Status = "Approved" }; var updateResponse = await client.Patch(feature.UpdatePath, directUpdate); feature = await client.Get <Feature>(feature.ReadPath); feature.Status.Should().Be("New"); }
public async Task CanRenameTags() { var client = new LeanwareTestClient(_factory); var feature = (await client.Create <Feature>()).Received; var tag = feature.Tags.First(); var newTag = string.Join("", tag.Reverse()); await client.Post(path : $"api/tags/{tag}/renameTo/{newTag}"); feature = await client.Get <Feature>(feature.ReadPath); feature.Tags.Should().Contain(newTag); }
public async Task CanImplementStories() { var client = new LeanwareTestClient(_factory); var feature = (await client.Create <Feature>()).Received; var stories = new List <Story>(); for (int i = 0; i < 5; i++) { var s = (await client.Create <Story>(new { FeatureId = feature.Id })).Received; stories.Add(s); } var response = await client.Post(path : $"api/stories/{stories[0].Id}/start"); response.StatusCode.Should().Be(HttpStatusCode.BadRequest, "only approved stories can be implemented"); await client.Post(path : $"api/features/{feature.Id}/approve"); response = await client.Post(path : $"api/stories/{stories[0].Id}/finish"); response.StatusCode.Should().Be(HttpStatusCode.BadRequest, "story cannot be finished without being started first"); response = await client.Post(path : $"api/stories/{stories[0].Id}/start"); response.EnsureSuccessStatusCode(); feature = await client.Get <Feature>(feature.ReadPath); feature.Status.Should().Be("Implementing"); var story = await client.Get <Story>(stories[0].ReadPath); story.Status.Should().Be("Implementing"); response = await client.Post(path : $"api/stories/{story.Id}/finish"); response.EnsureSuccessStatusCode(); feature = await client.Get <Feature>(feature.ReadPath); feature.Status.Should().Be("Implementing"); story = await client.Get <Story>(story.ReadPath); story.Status.Should().Be("Implemented"); for (int i = 1; i < stories.Count; i++) { await client.Post(path : $"api/stories/{stories[i].Id}/start"); await client.Post(path : $"api/stories/{stories[i].Id}/finish"); } feature = await client.Get <Feature>(feature.ReadPath); feature.Status.Should().Be("Implemented", "when all stories are implemented, feature is automatically set to implemented too"); var additionalStory = (await client.Create <Story>(new { FeatureId = feature.Id })).Received; additionalStory.Status.Should().Be("Approved", "when new story is added to implemented feature, it is considered approved by default"); feature = await client.Get <Feature>(feature.ReadPath); feature.Status.Should().Be("ChangeRequested"); }
public async Task CanCrudStoriesAndFeatures() { // Given CRUD client var client = new LeanwareTestClient(_factory); // When I create new feature var createFeatureResult = await client.Create <Feature>(); // Then created feature should have valid ID and title var createdFeature = createFeatureResult.Received; createdFeature.Id.Should().BeGreaterThan(0); createdFeature.Status.Should().Be("New"); createdFeature.Title.Should().Be(createFeatureResult.Sent.Title); // When I update feature var featureUpdate = new { Tags = RandomTags }; // Then updated feature should have new title var featureUpdateResult = await client.Update <Feature>(createdFeature.UpdatePath, featureUpdate); featureUpdateResult.Received.Title.Should().Be(createdFeature.Title); featureUpdateResult.Received.Tags.Should().Contain(featureUpdate.Tags); // When I create story var createStoryResult = await client.Create <Story>(new { FeatureId = createdFeature.Id }); // Then I created story should have valid ID and title var createdStory = createStoryResult.Received; createdStory.Id.Should().BeGreaterThan(0); createdStory.Title.Should().Be(createStoryResult.Sent.Title); createdStory.Status.Should().Be("New"); createdStory.FeatureId.Should().Be(createdFeature.Id); // When I update story var storyUpdate = new { Title = RandomTitle("S") }; // Then updated story should have new title var storyUpdateResult = await client.Update <Story>(createdStory.UpdatePath, storyUpdate); storyUpdateResult.Received.Title.Should().Be(storyUpdate.Title); // When I delete story await client.Delete(createdStory.DeletePath); // Then getting story should return 404 var deletedStory = await client.Get(createdStory.ReadPath); deletedStory.StatusCode.Should().Be(HttpStatusCode.NotFound); // When I delete feature await client.Delete(createdFeature.DeletePath); // Then getting feature should return 404 var deletedFeature = await client.Get(createdFeature.ReadPath); deletedFeature.StatusCode.Should().Be(HttpStatusCode.NotFound); }
public async Task CanCrudStoriesAndFeatures() { var client = new LeanwareTestClient(_factory); var featureTitle = RandomFeatureTitle; var feature = new { Id = 0, Title = featureTitle, Tags = RandomFeatureTags }; feature = await client.PostSelf("api/features", feature); feature.Id.Should().BeGreaterThan(0); feature.Title.Should().Be(featureTitle); var featurePath = $"api/features/{feature.Id}"; var updatedFeature = new { Title = $"{featureTitle} and {featureTitle}" }; await client.Patch(featurePath, updatedFeature); feature = await client.Get(featurePath, feature); feature.Title.Should().Be($"{featureTitle} and {featureTitle}"); var storyTitle = RandomStoryTitle; var story = new { Id = 0, Title = storyTitle, Description = nameof(CanCrudStoriesAndFeatures), Tags = RandomStoryTags, FeatureId = feature.Id }; story = await client.PostSelf("api/stories", story); story.Id.Should().BeGreaterThan(0); var storyPath = $"api/stories/{story.Id}"; story.Title.Should().Be(storyTitle); var updatedStory = new { Title = $"{storyTitle} and {storyTitle}" }; await client.Patch(storyPath, updatedStory); story = await client.Get(storyPath, story); story.Title.Should().Be($"{storyTitle} and {storyTitle}"); await client.Delete(storyPath); var deletedStory = await client.Get(storyPath); deletedStory.StatusCode.Should().Be(HttpStatusCode.NotFound); await client.Delete(featurePath); var deletedFeature = await client.Get(featurePath); deletedFeature.StatusCode.Should().Be(HttpStatusCode.NotFound); }