boutique-inventory
This commit is contained in:
parent
f324155864
commit
ec644472b3
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"authors": [
|
||||||
|
"angelikatyborska"
|
||||||
|
],
|
||||||
|
"contributors": [
|
||||||
|
"neenjaw",
|
||||||
|
"fmmatheus"
|
||||||
|
],
|
||||||
|
"files": {
|
||||||
|
"solution": [
|
||||||
|
"lib/boutique_inventory.ex"
|
||||||
|
],
|
||||||
|
"test": [
|
||||||
|
"test/boutique_inventory_test.exs"
|
||||||
|
],
|
||||||
|
"exemplar": [
|
||||||
|
".meta/exemplar.ex"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"language_versions": ">=1.10",
|
||||||
|
"blurb": "Learn about the Enum module by preparing your fashion boutique for the big annual sale."
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
{"track":"elixir","exercise":"boutique-inventory","id":"cdb368dfafa84deaaad78b0b83747be0","url":"https://exercism.org/tracks/elixir/exercises/boutique-inventory","handle":"negrienko","is_requester":true,"auto_approve":false}
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Used by "mix format"
|
||||||
|
[
|
||||||
|
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||||
|
]
|
|
@ -0,0 +1,24 @@
|
||||||
|
# The directory Mix will write compiled artifacts to.
|
||||||
|
/_build/
|
||||||
|
|
||||||
|
# If you run "mix test --cover", coverage assets end up here.
|
||||||
|
/cover/
|
||||||
|
|
||||||
|
# The directory Mix downloads your dependencies sources to.
|
||||||
|
/deps/
|
||||||
|
|
||||||
|
# Where third-party dependencies like ExDoc output generated docs.
|
||||||
|
/doc/
|
||||||
|
|
||||||
|
# Ignore .fetch files in case you like to edit your project deps locally.
|
||||||
|
/.fetch
|
||||||
|
|
||||||
|
# If the VM crashes, it generates a dump, let's ignore it too.
|
||||||
|
erl_crash.dump
|
||||||
|
|
||||||
|
# Also ignore archive artifacts (built via "mix archive.build").
|
||||||
|
*.ez
|
||||||
|
|
||||||
|
# Ignore package tarball (built via "mix hex.build").
|
||||||
|
nil-*.tar
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
From the terminal, change to the base directory of the exercise then execute the tests with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ mix test
|
||||||
|
```
|
||||||
|
|
||||||
|
This will execute the test file found in the `test` subfolder -- a file ending in `_test.exs`
|
||||||
|
|
||||||
|
Documentation:
|
||||||
|
|
||||||
|
* [`mix test` - Elixir's test execution tool](https://hexdocs.pm/mix/Mix.Tasks.Test.html)
|
||||||
|
* [`ExUnit` - Elixir's unit test library](https://hexdocs.pm/ex_unit/ExUnit.html)
|
||||||
|
|
||||||
|
## Pending tests
|
||||||
|
|
||||||
|
In test suites of practice exercises, all but the first test have been tagged to be skipped.
|
||||||
|
|
||||||
|
Once you get a test passing, you can unskip the next one by commenting out the relevant `@tag :pending` with a `#` symbol.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# @tag :pending
|
||||||
|
test "shouting" do
|
||||||
|
assert Bob.hey("WATCH OUT!") == "Whoa, chill out!"
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
If you wish to run all tests at once, you can include all skipped test by using the `--include` flag on the `mix test` command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ mix test --include pending
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, you can enable all the tests by commenting out the `ExUnit.configure` line in the file `test/test_helper.exs`.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# ExUnit.configure(exclude: :pending, trace: true)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Useful `mix test` options
|
||||||
|
|
||||||
|
* `test/<FILE>.exs:LINENUM` - runs only a single test, the test from `<FILE>.exs` whose definition is on line `LINENUM`
|
||||||
|
* `--failed` - runs only tests that failed the last time they ran
|
||||||
|
* `--max-failures` - the suite stops evaluating tests when this number of test failures
|
||||||
|
is reached
|
||||||
|
* `--seed 0` - disables randomization so the tests in a single file will always be ran
|
||||||
|
in the same order they were defined in
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit lib/boutique_inventory.ex` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Elixir track's documentation](https://exercism.org/docs/tracks/elixir)
|
||||||
|
- The [Elixir track's programming category on the forum](https://forum.exercism.org/c/programming/elixir)
|
||||||
|
- [Exercism's programming category on the forum](https://forum.exercism.org/c/programming/5)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
If you're stuck on something, it may help to look at some of the [available resources](https://exercism.org/docs/tracks/elixir/resources) out there where answers might be found.
|
|
@ -0,0 +1,42 @@
|
||||||
|
# Hints
|
||||||
|
|
||||||
|
## General
|
||||||
|
|
||||||
|
- Read about the `Enum` module in the [official Getting Started guide][getting-started-enum] or on [elixirschool.com][elixir-school-enum].
|
||||||
|
- Take a look in the documentation for the full [list of functions in the `Enum` module][enum-functions].
|
||||||
|
|
||||||
|
## 1. Sort items by price
|
||||||
|
|
||||||
|
- There is a [built-in function][enum-sort-by] for sorting enumerables using a sorter function.
|
||||||
|
|
||||||
|
## 2. Find all items with missing prices
|
||||||
|
|
||||||
|
- There is a [built-in function][enum-filter] for filtering enumerables.
|
||||||
|
|
||||||
|
## 3. Update item names
|
||||||
|
|
||||||
|
- There is a [built-in function][enum-map] for transforming every element in an enumerable.
|
||||||
|
- There is a [built-in function][string-replace] that can replace all instances of one string with a different one.
|
||||||
|
|
||||||
|
## 4. Increment the item's quantity
|
||||||
|
|
||||||
|
- Maps implement the enumerable protocol.
|
||||||
|
- `Enum` functions convert maps to a list of `{key, value}` tuples.
|
||||||
|
- There are two different functions that can transform a list of `{key, value}` tuples back into a map using a transformation function. [One of them always returns a new map][map-new], while [the other lets you choose a collectible][enum-into].
|
||||||
|
|
||||||
|
## 5. Calculate the item's total quantity
|
||||||
|
|
||||||
|
- Maps implement the enumerable protocol.
|
||||||
|
- `Enum` functions convert maps to a list of `{key, value}` tuples.
|
||||||
|
- There is a [built-in function][enum-reduce] for reducing an enumerable to a single value.
|
||||||
|
|
||||||
|
[getting-started-enum]: https://elixir-lang.org/getting-started/enumerables-and-streams.html#enumerables
|
||||||
|
[elixir-school-enum]: https://elixirschool.com/en/lessons/basics/enum/
|
||||||
|
[enum-functions]: https://hexdocs.pm/elixir/Enum.html#functions
|
||||||
|
[enum-sort-by]: https://hexdocs.pm/elixir/Enum.html#sort_by/3
|
||||||
|
[enum-filter]: https://hexdocs.pm/elixir/Enum.html#filter/2
|
||||||
|
[enum-map]: https://hexdocs.pm/elixir/Enum.html#map/2
|
||||||
|
[enum-into]: https://hexdocs.pm/elixir/Enum.html#into/3
|
||||||
|
[enum-reduce]: https://hexdocs.pm/elixir/Enum.html#reduce/3
|
||||||
|
[map-new]: https://hexdocs.pm/elixir/Map.html#new/2
|
||||||
|
[string-replace]: https://hexdocs.pm/elixir/String.html#replace/4
|
|
@ -0,0 +1,175 @@
|
||||||
|
# Boutique Inventory
|
||||||
|
|
||||||
|
Welcome to Boutique Inventory on Exercism's Elixir Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
If you get stuck on the exercise, check out `HINTS.md`, but try and solve it without using those first :)
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
|
||||||
|
## Enum
|
||||||
|
|
||||||
|
`Enum` is a very useful module that provides a set of algorithms for working with enumerables. It offers sorting, filtering, grouping, counting, searching, finding min/max values, and much more.
|
||||||
|
|
||||||
|
In general, an _enumerable_ is any data that can be iterated over, a collection. In Elixir, an enumerable is any data type that implements the `Enumerable` [protocol][exercism-protocols]. The most common of those are [lists][exercism-lists] and [maps][exercism-maps].
|
||||||
|
|
||||||
|
Many `Enum` functions accept a function as an argument.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
Enum.all?([1, 2, 3, 4, 5], fn x -> x > 3 end)
|
||||||
|
# => false
|
||||||
|
```
|
||||||
|
|
||||||
|
The most common `Enum` functions are `map` and `reduce`.
|
||||||
|
|
||||||
|
### `map/2`
|
||||||
|
|
||||||
|
`Enum.map/2` allows you to replace every element in an enumerable with another element. The second argument to `Enum.map/2` is a function that accepts the original element and returns its replacement.
|
||||||
|
|
||||||
|
### `reduce/3`
|
||||||
|
|
||||||
|
`Enum.reduce/3` allows you to _reduce_ the whole enumerable to a single value. To achieve this, a special variable called the _accumulator_ is used. The accumulator carries the intermediate state of the reduction between iterations.
|
||||||
|
|
||||||
|
The second argument to `Enum.reduce/3` is the initial value of the accumulator. The third argument is a function that accepts an element and an accumulator, and returns the new value for the accumulator.
|
||||||
|
|
||||||
|
### Working with maps
|
||||||
|
|
||||||
|
When using maps with `Enum` functions, the map gets automatically converted to a list of 2 `{key, value}` tuples.
|
||||||
|
|
||||||
|
To transform it back to a map, use `Enum.into/2`. `Enum.into/2` is a function that transforms an enumerable into a collectable - any data structure implementing the `Collectable` protocol. It can be thought of as the opposite of `Enum.reduce/3`.
|
||||||
|
|
||||||
|
`Enum` also has `Enum.into/3`. `Enum.into/3` is a variation of `Enum.into/2` that accepts a transformation function to be applied while transforming the enumerable into a collectable.
|
||||||
|
|
||||||
|
#### Mapping maps
|
||||||
|
|
||||||
|
Instead of using `Enum.into/3` or `Enum.map/2` plus `Enum.into/1` to apply a transformation (mapping) to a map, we can also use a dedicated `Map.new/2` function. It works exactly like `Enum.into/3` in that it accepts an enumerable and a transformation function, but it always returns a new map instead of letting us choose a collectible.
|
||||||
|
|
||||||
|
[exercism-protocols]: https://exercism.org/tracks/elixir/concepts/protocols
|
||||||
|
[exercism-lists]: https://exercism.org/tracks/elixir/concepts/lists
|
||||||
|
[exercism-maps]: https://exercism.org/tracks/elixir/concepts/maps
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
You are running an online fashion boutique. Your big annual sale is coming up, so you need to take stock of your inventory to make sure you're ready.
|
||||||
|
|
||||||
|
A single item in the inventory is represented by a map, and the whole inventory is a list of such maps.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
%{
|
||||||
|
name: "White Shirt",
|
||||||
|
price: 40,
|
||||||
|
quantity_by_size: %{s: 3, m: 7, l: 8, xl: 4}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 1. Sort items by price
|
||||||
|
|
||||||
|
Implement the `sort_by_price/1` function. It should take the inventory and return it sorted by item price, ascending.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
BoutiqueInventory.sort_by_price([
|
||||||
|
%{price: 65, name: "Maxi Brown Dress", quantity_by_size: %{}},
|
||||||
|
%{price: 50, name: "Red Short Skirt", quantity_by_size: %{}},
|
||||||
|
%{price: 50, name: "Black Short Skirt", quantity_by_size: %{}},
|
||||||
|
%{price: 20, name: "Bamboo Socks Cats", quantity_by_size: %{}}
|
||||||
|
])
|
||||||
|
# => [
|
||||||
|
# %{price: 20, name: "Bamboo Socks Cats", quantity_by_size: %{}},
|
||||||
|
# %{price: 50, name: "Red Short Skirt", quantity_by_size: %{}},
|
||||||
|
# %{price: 50, name: "Black Short Skirt", quantity_by_size: %{}},
|
||||||
|
# %{price: 65, name: "Maxi Brown Dress", price: 65, quantity_by_size: %{}}
|
||||||
|
# ]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Find all items with missing prices
|
||||||
|
|
||||||
|
After sorting your inventory by price, you noticed that you must have made a mistake when you were taking stock and forgot to fill out prices for a few items.
|
||||||
|
|
||||||
|
Implement the `with_missing_price/1` function. It should take the inventory and return a list of items that do not have prices.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
BoutiqueInventory.with_missing_price([
|
||||||
|
%{price: 40, name: "Black T-shirt", quantity_by_size: %{}},
|
||||||
|
%{price: nil, name: "Denim Pants", quantity_by_size: %{}},
|
||||||
|
%{price: nil, name: "Denim Skirt", quantity_by_size: %{}},
|
||||||
|
%{price: 40, name: "Orange T-shirt", quantity_by_size: %{}}
|
||||||
|
])
|
||||||
|
# => [
|
||||||
|
# %{price: nil, name: "Denim Pants", quantity_by_size: %{}},
|
||||||
|
# %{price: nil, name: "Denim Skirt", quantity_by_size: %{}}
|
||||||
|
# ]
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Update item names
|
||||||
|
|
||||||
|
You noticed that some item names have a word that you don't like to use anymore. Now you need to update all the item names with that word.
|
||||||
|
|
||||||
|
Implement the `update_names/3` function. It should take the inventory, the old word that you want to remove, and a new word that you want to use instead. It should return a list of items with updated names.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
BoutiqueInventory.update_names(
|
||||||
|
[
|
||||||
|
%{price: 40, name: "Black T-shirt", quantity_by_size: %{}},
|
||||||
|
%{price: 70, name: "Denim Pants", quantity_by_size: %{}},
|
||||||
|
%{price: 65, name: "Denim Skirt", quantity_by_size: %{}},
|
||||||
|
%{price: 40, name: "Orange T-shirt", quantity_by_size: %{}}
|
||||||
|
],
|
||||||
|
"T-shirt",
|
||||||
|
"Tee"
|
||||||
|
)
|
||||||
|
# => [
|
||||||
|
# %{price: 40, name: "Black Tee", quantity_by_size: %{}},
|
||||||
|
# %{price: 70, name: "Denim Pants", quantity_by_size: %{}},
|
||||||
|
# %{price: 65, name: "Denim Skirt", quantity_by_size: %{}},
|
||||||
|
# %{price: 40, name: "Orange Tee", quantity_by_size: %{}}
|
||||||
|
# ]
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## 4. Increment the item's quantity
|
||||||
|
|
||||||
|
Some items were selling especially well, so you ordered more, in all sizes.
|
||||||
|
|
||||||
|
Implement the `increase_quantity/2` function. It should take a single item and a number `n`, and return that item with the quantity for each size increased by `n`.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
BoutiqueInventory.increase_quantity(
|
||||||
|
%{
|
||||||
|
name: "Polka Dot Skirt",
|
||||||
|
price: 68,
|
||||||
|
quantity_by_size: %{s: 3, m: 5, l: 3, xl: 4}
|
||||||
|
},
|
||||||
|
6
|
||||||
|
)
|
||||||
|
# => %{
|
||||||
|
# name: "Polka Dot Skirt",
|
||||||
|
# price: 68,
|
||||||
|
# quantity_by_size: %{l: 9, m: 11, s: 9, xl: 10}
|
||||||
|
# }
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
## 5. Calculate the item's total quantity
|
||||||
|
|
||||||
|
To know how much space you need in your storage, you need to know how many of each item you have in total.
|
||||||
|
|
||||||
|
Implement the `total_quantity/1` function. It should take a single item and return how many pieces you have in total, in any size.
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
BoutiqueInventory.total_quantity(%{
|
||||||
|
name: "Red Shirt",
|
||||||
|
price: 62,
|
||||||
|
quantity_by_size: %{s: 3, m: 6, l: 5, xl: 2}
|
||||||
|
})
|
||||||
|
# => 16
|
||||||
|
```
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @angelikatyborska
|
||||||
|
|
||||||
|
### Contributed to by
|
||||||
|
|
||||||
|
- @neenjaw
|
||||||
|
- @fmmatheus
|
|
@ -0,0 +1,41 @@
|
||||||
|
defmodule BoutiqueInventory do
|
||||||
|
def sort_by_price(inventory) do
|
||||||
|
Enum.sort_by(inventory, & &1[:price])
|
||||||
|
end
|
||||||
|
|
||||||
|
def with_missing_price(inventory) do
|
||||||
|
Enum.filter(inventory, &(!&1[:price]))
|
||||||
|
end
|
||||||
|
|
||||||
|
def update_names(inventory, old_word, new_word) do
|
||||||
|
inventory
|
||||||
|
|> Enum.map(fn item ->
|
||||||
|
new_name = String.replace(item.name, old_word, new_word)
|
||||||
|
%{item | name: new_name}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def increase_quantity(item, count) do
|
||||||
|
item
|
||||||
|
|> Map.get_and_update(:quantity_by_size, fn quantities ->
|
||||||
|
{quantities, update_quantities(quantities, count)}
|
||||||
|
end)
|
||||||
|
|> elem(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp update_quantities(quantities, count) do
|
||||||
|
quantities
|
||||||
|
|> Map.to_list()
|
||||||
|
|> Enum.map(&increase_size_quantity(&1, count))
|
||||||
|
|> Enum.into(%{})
|
||||||
|
end
|
||||||
|
|
||||||
|
defp increase_size_quantity({key, value}, count), do: {key, value + count}
|
||||||
|
|
||||||
|
def total_quantity(item) do
|
||||||
|
item.quantity_by_size
|
||||||
|
|> Enum.reduce(0, &sum_total_quantity/2)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp sum_total_quantity({_key, value}, acc), do: acc + value
|
||||||
|
end
|
|
@ -0,0 +1,28 @@
|
||||||
|
defmodule BoutiqueInventory.MixProject do
|
||||||
|
use Mix.Project
|
||||||
|
|
||||||
|
def project do
|
||||||
|
[
|
||||||
|
app: :boutique_inventory,
|
||||||
|
version: "0.1.0",
|
||||||
|
# elixir: "~> 1.10",
|
||||||
|
start_permanent: Mix.env() == :prod,
|
||||||
|
deps: deps()
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Run "mix help compile.app" to learn about applications.
|
||||||
|
def application do
|
||||||
|
[
|
||||||
|
extra_applications: [:logger]
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
# Run "mix help deps" to learn about dependencies.
|
||||||
|
defp deps do
|
||||||
|
[
|
||||||
|
# {:dep_from_hexpm, "~> 0.3.0"},
|
||||||
|
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,150 @@
|
||||||
|
defmodule BoutiqueInventoryTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
describe "sort_by_price/1" do
|
||||||
|
@tag task_id: 1
|
||||||
|
test "works for an empty inventory" do
|
||||||
|
assert BoutiqueInventory.sort_by_price([]) == []
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag task_id: 1
|
||||||
|
test "sorts items by price" do
|
||||||
|
assert BoutiqueInventory.sort_by_price([
|
||||||
|
%{price: 65, name: "Maxi Yellow Summer Dress", quantity_by_size: %{}},
|
||||||
|
%{price: 60, name: "Cream Linen Pants", quantity_by_size: %{}},
|
||||||
|
%{price: 33, name: "Straw Hat", quantity_by_size: %{}}
|
||||||
|
]) == [
|
||||||
|
%{price: 33, name: "Straw Hat", quantity_by_size: %{}},
|
||||||
|
%{price: 60, name: "Cream Linen Pants", quantity_by_size: %{}},
|
||||||
|
%{price: 65, name: "Maxi Yellow Summer Dress", quantity_by_size: %{}}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag task_id: 1
|
||||||
|
test "the order of items of equal price is preserved" do
|
||||||
|
assert BoutiqueInventory.sort_by_price([
|
||||||
|
%{price: 65, name: "Maxi Yellow Summer Dress", quantity_by_size: %{}},
|
||||||
|
%{price: 60, name: "Cream Linen Pants", quantity_by_size: %{}},
|
||||||
|
%{price: 33, name: "Straw Hat", quantity_by_size: %{}},
|
||||||
|
%{price: 60, name: "Brown Linen Pants", quantity_by_size: %{}}
|
||||||
|
]) == [
|
||||||
|
%{price: 33, name: "Straw Hat", quantity_by_size: %{}},
|
||||||
|
%{price: 60, name: "Cream Linen Pants", quantity_by_size: %{}},
|
||||||
|
%{price: 60, name: "Brown Linen Pants", quantity_by_size: %{}},
|
||||||
|
%{price: 65, name: "Maxi Yellow Summer Dress", quantity_by_size: %{}}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with_missing_price/1" do
|
||||||
|
@tag task_id: 2
|
||||||
|
test "works for an empty inventory" do
|
||||||
|
assert BoutiqueInventory.with_missing_price([]) == []
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag task_id: 2
|
||||||
|
test "filters out items that do have a price" do
|
||||||
|
assert BoutiqueInventory.with_missing_price([
|
||||||
|
%{name: "Red Flowery Top", price: 50, quantity_by_size: %{}},
|
||||||
|
%{name: "Purple Flowery Top", price: nil, quantity_by_size: %{}},
|
||||||
|
%{name: "Bamboo Socks Avocado", price: 10, quantity_by_size: %{}},
|
||||||
|
%{name: "Bamboo Socks Palm Trees", price: 10, quantity_by_size: %{}},
|
||||||
|
%{name: "Bamboo Socks Kittens", price: nil, quantity_by_size: %{}}
|
||||||
|
]) == [
|
||||||
|
%{name: "Purple Flowery Top", price: nil, quantity_by_size: %{}},
|
||||||
|
%{name: "Bamboo Socks Kittens", price: nil, quantity_by_size: %{}}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "update_names/3" do
|
||||||
|
@tag task_id: 3
|
||||||
|
test "works for an empty inventory" do
|
||||||
|
assert BoutiqueInventory.update_names([], "T-Shirt", "Tee") == []
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag task_id: 3
|
||||||
|
test "replaces the word in all the names" do
|
||||||
|
assert BoutiqueInventory.update_names(
|
||||||
|
[
|
||||||
|
%{name: "Bambo Socks Avocado", price: 10, quantity_by_size: %{}},
|
||||||
|
%{name: "3x Bambo Socks Palm Trees", price: 26, quantity_by_size: %{}},
|
||||||
|
%{name: "Red Sequin Top", price: 87, quantity_by_size: %{}}
|
||||||
|
],
|
||||||
|
"Bambo",
|
||||||
|
"Bamboo"
|
||||||
|
) == [
|
||||||
|
%{name: "Bamboo Socks Avocado", price: 10, quantity_by_size: %{}},
|
||||||
|
%{name: "3x Bamboo Socks Palm Trees", price: 26, quantity_by_size: %{}},
|
||||||
|
%{name: "Red Sequin Top", price: 87, quantity_by_size: %{}}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag task_id: 3
|
||||||
|
test "replaces all the instances of the word within one name" do
|
||||||
|
assert BoutiqueInventory.update_names(
|
||||||
|
[
|
||||||
|
%{name: "GO! GO! GO! Tee", price: 8, quantity_by_size: %{}}
|
||||||
|
],
|
||||||
|
"GO!",
|
||||||
|
"Go!"
|
||||||
|
) == [
|
||||||
|
%{name: "Go! Go! Go! Tee", price: 8, quantity_by_size: %{}}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "increase_quantity/2" do
|
||||||
|
@tag task_id: 4
|
||||||
|
test "works for an empty quantity map" do
|
||||||
|
assert BoutiqueInventory.increase_quantity(
|
||||||
|
%{
|
||||||
|
name: "Long Black Evening Dress",
|
||||||
|
price: 105,
|
||||||
|
quantity_by_size: %{}
|
||||||
|
},
|
||||||
|
1
|
||||||
|
) == %{
|
||||||
|
name: "Long Black Evening Dress",
|
||||||
|
price: 105,
|
||||||
|
quantity_by_size: %{}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag task_id: 4
|
||||||
|
test "increases quantity of an item" do
|
||||||
|
assert BoutiqueInventory.increase_quantity(
|
||||||
|
%{
|
||||||
|
name: "Green Swimming Shorts",
|
||||||
|
price: 46,
|
||||||
|
quantity_by_size: %{s: 1, m: 2, l: 4, xl: 1}
|
||||||
|
},
|
||||||
|
3
|
||||||
|
) == %{
|
||||||
|
name: "Green Swimming Shorts",
|
||||||
|
price: 46,
|
||||||
|
quantity_by_size: %{s: 4, m: 5, l: 7, xl: 4}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "total_quantity/1" do
|
||||||
|
@tag task_id: 5
|
||||||
|
test "works for an empty quantity map" do
|
||||||
|
assert BoutiqueInventory.total_quantity(%{
|
||||||
|
name: "Red Denim Pants",
|
||||||
|
price: 77,
|
||||||
|
quantity_by_size: %{}
|
||||||
|
}) == 0
|
||||||
|
end
|
||||||
|
|
||||||
|
@tag task_id: 5
|
||||||
|
test "sums up total quantity" do
|
||||||
|
assert BoutiqueInventory.total_quantity(%{
|
||||||
|
name: "Black Denim Skirt",
|
||||||
|
price: 50,
|
||||||
|
quantity_by_size: %{s: 4, m: 11, l: 6, xl: 8}
|
||||||
|
}) == 29
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,2 @@
|
||||||
|
ExUnit.start()
|
||||||
|
ExUnit.configure(exclude: :pending, trace: true, seed: 0)
|
Loading…
Reference in New Issue