Initial commit
This commit is contained in:
commit
04a2595a88
17 changed files with 4784 additions and 0 deletions
4
.formatter.exs
Normal file
4
.formatter.exs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# Used by "mix format"
|
||||||
|
[
|
||||||
|
inputs: ["{mix,.formatter}.exs", "{config,lib,test}/**/*.{ex,exs}"]
|
||||||
|
]
|
26
.gitignore
vendored
Normal file
26
.gitignore
vendored
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# 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").
|
||||||
|
language_colours-*.tar
|
||||||
|
|
||||||
|
# Temporary files, for example, from tests.
|
||||||
|
/tmp/
|
2
.tool-versions
Normal file
2
.tool-versions
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
elixir 1.12.1-otp-24
|
||||||
|
erlang 24.0.3
|
19
README.md
Normal file
19
README.md
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
# LanguageColours
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
If [available in Hex](https://hex.pm/docs/publish), the package can be installed
|
||||||
|
by adding `language_colours` to your list of dependencies in `mix.exs`:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
def deps do
|
||||||
|
[
|
||||||
|
{:language_colours, "~> 1.0.0"}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc)
|
||||||
|
and published on [HexDocs](https://hexdocs.pm). Once published, the docs can
|
||||||
|
be found at [https://hexdocs.pm/language_colours](https://hexdocs.pm/language_colours).
|
||||||
|
|
7
config/config.exs
Normal file
7
config/config.exs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import Config
|
||||||
|
|
||||||
|
config :language_colours, json_parser: Jason
|
||||||
|
|
||||||
|
if Config.config_env() == "test" do
|
||||||
|
import_config("test.exs")
|
||||||
|
end
|
12
config/test.exs
Normal file
12
config/test.exs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import Config
|
||||||
|
|
||||||
|
config :language_colours,
|
||||||
|
databases: %{
|
||||||
|
test_db: %{
|
||||||
|
db: LanguageColours.ETSDatabase,
|
||||||
|
ets_table: :lc_ets_test,
|
||||||
|
file: "test/colours.json",
|
||||||
|
server_name: TestETSDatabase,
|
||||||
|
fallback: true
|
||||||
|
}
|
||||||
|
}
|
6
lib/colour.ex
Normal file
6
lib/colour.ex
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
defmodule LanguageColours.Colour do
|
||||||
|
@typedoc """
|
||||||
|
A colour returned by the API, a hex colour of six characters with a hash prepended.
|
||||||
|
"""
|
||||||
|
@type t :: String.t()
|
||||||
|
end
|
20
lib/database.ex
Normal file
20
lib/database.ex
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
defmodule LanguageColours.Database do
|
||||||
|
@moduledoc """
|
||||||
|
Behaviour that must be implemented by a database.
|
||||||
|
|
||||||
|
Each function gets a database configuration as argument. This configuration should be used to
|
||||||
|
talk to the correct database instance.
|
||||||
|
|
||||||
|
It is not necessary to deal with the fallback as the main module handles that.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Get a colour for the given language, or `nil`.
|
||||||
|
"""
|
||||||
|
@callback get(language :: String.t(), db_config :: map()) :: LanguageColours.Colour.t() | nil
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Update the language dataset using the configuration.
|
||||||
|
"""
|
||||||
|
@callback update(db_config :: map()) :: :ok
|
||||||
|
end
|
143
lib/ets_database.ex
Normal file
143
lib/ets_database.ex
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
defmodule LanguageColours.ETSDatabase do
|
||||||
|
@moduledoc """
|
||||||
|
Database that stores the language colours in an ETS table. Get operations will directly read
|
||||||
|
from the database, update operations will be serialized through the database process.
|
||||||
|
|
||||||
|
Please see [the main module documentation](LanguageColours.html#module-configuration) for the
|
||||||
|
available configuration options and how to set up the database.
|
||||||
|
"""
|
||||||
|
|
||||||
|
use GenServer
|
||||||
|
|
||||||
|
require Logger
|
||||||
|
|
||||||
|
@behaviour LanguageColours.Database
|
||||||
|
|
||||||
|
@table :language_colours_etsdatabase
|
||||||
|
|
||||||
|
defmodule Options do
|
||||||
|
@enforce_keys [:file]
|
||||||
|
defstruct [:file, server_opts: [], ets_table: :language_colours_etsdatabase]
|
||||||
|
|
||||||
|
@typedoc """
|
||||||
|
Options to give to the `LanguageColours.ETSDatabase.start_link/1` function.
|
||||||
|
|
||||||
|
* `:server_opts`: Any options to give to `GenServer.start_link/3`.
|
||||||
|
* `:file`: The file to read JSON data from.
|
||||||
|
* `:ets_table`: Name of the ETS table to store the data in.
|
||||||
|
"""
|
||||||
|
@type t :: %__MODULE__{
|
||||||
|
server_opts: GenServer.options(),
|
||||||
|
file: Path.t(),
|
||||||
|
ets_table: atom()
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defmodule State do
|
||||||
|
@moduledoc false
|
||||||
|
|
||||||
|
@enforce_keys [:ets_table, :init_file]
|
||||||
|
defstruct [:ets_table, :init_file]
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{
|
||||||
|
ets_table: :ets.tid() | atom(),
|
||||||
|
init_file: Path.t()
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec start_link(Options.t()) :: GenServer.on_start()
|
||||||
|
def start_link(%Options{} = opts) do
|
||||||
|
opts = update_in(opts.server_opts[:name], &(&1 || __MODULE__))
|
||||||
|
|
||||||
|
GenServer.start_link(__MODULE__, opts, opts.server_opts)
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
@spec init(Options.t()) :: {:ok, State.t()}
|
||||||
|
def init(%Options{} = opts) do
|
||||||
|
tid =
|
||||||
|
:ets.new(opts.ets_table, [
|
||||||
|
:named_table,
|
||||||
|
:set,
|
||||||
|
:protected,
|
||||||
|
read_concurrency: true
|
||||||
|
])
|
||||||
|
|
||||||
|
load_file(tid, opts.file)
|
||||||
|
|
||||||
|
{:ok, %State{ets_table: tid, init_file: opts.file}}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def handle_call(msg, from, state)
|
||||||
|
|
||||||
|
def handle_call({:update, file}, _from, %State{} = state) do
|
||||||
|
file = file || state.init_file
|
||||||
|
|
||||||
|
load_file(state.ets_table, file)
|
||||||
|
{:reply, :ok, state}
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def get(language, db_config) do
|
||||||
|
table = Map.get(db_config, :ets_table, @table)
|
||||||
|
|
||||||
|
case :ets.lookup(table, String.downcase(language)) do
|
||||||
|
[] -> nil
|
||||||
|
[{_, colour}] -> colour
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@impl true
|
||||||
|
def update(db_config) do
|
||||||
|
server = Map.get(db_config, :server_name, __MODULE__)
|
||||||
|
file = Map.get(db_config, :file)
|
||||||
|
|
||||||
|
GenServer.call(server, {:update, file})
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Get an `t:LanguageColours.ETSDatabase.Options.t/0` struct corresponding to the given database
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
This is a helper for forming the options struct for starting the database in a supervisor.
|
||||||
|
|
||||||
|
NOTE: When using this function, the `:file` option is required.
|
||||||
|
"""
|
||||||
|
@spec startup_options(map()) :: Options.t()
|
||||||
|
def startup_options(db_config) do
|
||||||
|
%Options{
|
||||||
|
file: Map.fetch!(db_config, :file),
|
||||||
|
ets_table: Map.get(db_config, :ets_table, @table),
|
||||||
|
server_opts: [name: Map.get(db_config, :server_name)]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec load_file(:ets.tid() | atom(), Path.t()) :: :ok
|
||||||
|
defp load_file(tid, file) do
|
||||||
|
json_parser = Application.get_env(:language_colours, :json_parser, Jason)
|
||||||
|
|
||||||
|
with {:read, {:ok, data}} <- {:read, File.read(file)},
|
||||||
|
{:json, {:ok, parsed}} <- {:json, json_parser.decode(data)} do
|
||||||
|
data =
|
||||||
|
Enum.map(parsed, fn {key, value} ->
|
||||||
|
{String.downcase(key), Map.get(value, "color")}
|
||||||
|
end)
|
||||||
|
|
||||||
|
:ets.insert(tid, data)
|
||||||
|
|
||||||
|
# Delete any languages that were not in updated data
|
||||||
|
new_languages = parsed |> Map.keys() |> MapSet.new(&String.downcase/1)
|
||||||
|
all_languages = tid |> :ets.tab2list() |> Enum.map(&elem(&1, 0)) |> MapSet.new()
|
||||||
|
old_languages = MapSet.difference(all_languages, new_languages)
|
||||||
|
Enum.each(old_languages, &:ets.delete(tid, &1))
|
||||||
|
|
||||||
|
Logger.debug(
|
||||||
|
"Read #{Enum.count(data)} languages from JSON and deleted #{Enum.count(old_languages)} stale."
|
||||||
|
)
|
||||||
|
else
|
||||||
|
{:read, _} -> raise "Could not read file #{file}"
|
||||||
|
{:json, err} -> raise "Could not parse file #{file}: #{inspect(err)}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
177
lib/language_colours.ex
Normal file
177
lib/language_colours.ex
Normal file
|
@ -0,0 +1,177 @@
|
||||||
|
defmodule LanguageColours do
|
||||||
|
@moduledoc """
|
||||||
|
LanguageColours offers an API for retrieving colours for programming languages based on GitHub
|
||||||
|
colour data (or some other dataset).
|
||||||
|
|
||||||
|
```iex
|
||||||
|
iex> LanguageColours.get("Ada", :my_db)
|
||||||
|
"#02f88c"
|
||||||
|
```
|
||||||
|
|
||||||
|
To install, add LanguageColours as a dependency of your Mix project:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
defp deps do
|
||||||
|
[
|
||||||
|
{:language_colours, "~> 1.0.0"},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
## Databases
|
||||||
|
|
||||||
|
LanguageColours can be served by different databases. Databases must conform to the
|
||||||
|
`LanguageColours.Database` behaviour. There is one database included, the
|
||||||
|
`LanguageColours.ETSDatabase`, that uses ETS to store the language colour data. As a source, it
|
||||||
|
uses a JSON file in the format found in the https://github.com/ozh/github-colors/ repo. This
|
||||||
|
file can be downloaded in a development environment with `mix language.colours.dl.data`.
|
||||||
|
|
||||||
|
## Fallback colours
|
||||||
|
|
||||||
|
If a language is not found in the database, `nil` will be returned by default. Optionally, the
|
||||||
|
[Rainbow](https://hex.pm/packages/rainbow) package can be used to generate a random colour based
|
||||||
|
on the language name as fallback. To use the fallback, set the database configuration option
|
||||||
|
`:fallback` to `true`, and install Rainbow as a dependency:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
defp deps do
|
||||||
|
[
|
||||||
|
{:rainbow, "~> 0.1.0"},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
To configure a database, you can give the configuration directly in the function call:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config = %{...}
|
||||||
|
LanguageColours.get("C++", config)
|
||||||
|
```
|
||||||
|
|
||||||
|
Or you can configure database aliases in your favourite config file (`runtime.exs` is
|
||||||
|
recommended so you don't need to recompile the app on config changes):
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
# Config file
|
||||||
|
config :language_colours,
|
||||||
|
databases: %{
|
||||||
|
foo_db: %{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you can use this name in the function call:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
LanguageColours.get("COBOL", :foo_db)
|
||||||
|
```
|
||||||
|
|
||||||
|
The supported configuration options are:
|
||||||
|
|
||||||
|
* `:json_parser`: Module name of the JSON parser to use. Default is
|
||||||
|
[Jason](https://hex.pm/packages/jason).
|
||||||
|
* `:databases`: An atom-keyed map of database specific configurations, which can be maps
|
||||||
|
themselves or keyword lists.
|
||||||
|
|
||||||
|
The database specific configuration options are:
|
||||||
|
|
||||||
|
* `:db`: The database module to use. This option is required.
|
||||||
|
* `:fallback`: Boolean specifying whether to get a fallback colour from Rainbow or not, if
|
||||||
|
language was not found in database. Default `false`.
|
||||||
|
|
||||||
|
Additionally, the ETSDatabase has its own database specific options:
|
||||||
|
|
||||||
|
* `:file`: Path to the file to read the JSON data from.
|
||||||
|
* `:server_name`: The name to use for the database process. Must conform to
|
||||||
|
`t:GenServer.name/0`. By default the module name is used.
|
||||||
|
* `:ets_table`: Name of the ETS table to use.
|
||||||
|
|
||||||
|
## Setting up using ETSDatabase
|
||||||
|
|
||||||
|
First configure your database. Then start the database in your supervisor using the
|
||||||
|
`LanguageColours.ETSDatabase.startup_options/1` function like this:
|
||||||
|
|
||||||
|
```elixir
|
||||||
|
config = LanguageColours.config!(:foo_db)
|
||||||
|
children = [
|
||||||
|
...,
|
||||||
|
{LanguageColours.ETSDatabase, LanguageColours.ETSDatabase.startup_options(config)},
|
||||||
|
...
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively you can directly give the `t:LanguageColours.ETSDatabase.Options.t/0` struct as
|
||||||
|
the argument.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Get the colour corresponding to the given language.
|
||||||
|
|
||||||
|
The database specified in the second argument (as configuration or preconfigured database name)
|
||||||
|
is used to fetch the language. If the language is not found and fallback is not configured,
|
||||||
|
`nil` is returned.
|
||||||
|
"""
|
||||||
|
@spec get(String.t(), atom() | keyword() | map()) :: LanguageColours.Colour.t() | nil
|
||||||
|
def get(language, db_or_config)
|
||||||
|
|
||||||
|
def get(language, db) when is_atom(db) do
|
||||||
|
config = config!(db)
|
||||||
|
|
||||||
|
get(language, config)
|
||||||
|
end
|
||||||
|
|
||||||
|
def get(language, config) when is_list(config) do
|
||||||
|
get(language, Map.new(config))
|
||||||
|
end
|
||||||
|
|
||||||
|
def get(language, config) when is_map(config) do
|
||||||
|
colour = config.db.get(language, config)
|
||||||
|
|
||||||
|
if is_nil(colour) && Map.get(config, :fallback) do
|
||||||
|
Rainbow.colorize(language, format: "hexcolor")
|
||||||
|
else
|
||||||
|
colour
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Update the database specified in the argument.
|
||||||
|
|
||||||
|
The argument may be a preconfigured database name or a configuration map/kwlist.
|
||||||
|
"""
|
||||||
|
@spec update(atom() | keyword() | map()) :: :ok
|
||||||
|
def update(db_or_config)
|
||||||
|
|
||||||
|
def update(db) when is_atom(db) do
|
||||||
|
config = config!(db)
|
||||||
|
|
||||||
|
update(config)
|
||||||
|
end
|
||||||
|
|
||||||
|
def update(config) when is_list(config) do
|
||||||
|
update(Map.new(config))
|
||||||
|
end
|
||||||
|
|
||||||
|
def update(config) when is_map(config) do
|
||||||
|
config.db.update(config)
|
||||||
|
end
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Retrieve the configuration for the given database name.
|
||||||
|
|
||||||
|
If the database is not configured, an error will be raised.
|
||||||
|
"""
|
||||||
|
@spec config!(atom()) :: map()
|
||||||
|
def config!(db) do
|
||||||
|
conf =
|
||||||
|
Application.get_env(:language_colours, :databases) ||
|
||||||
|
raise "LanguageColours databases not configured!"
|
||||||
|
|
||||||
|
Map.get(conf, db) || raise "Configuration for #{inspect(db)} colour database not found!"
|
||||||
|
end
|
||||||
|
end
|
36
lib/mix/tasks/language.colours.dl.data.ex
Normal file
36
lib/mix/tasks/language.colours.dl.data.ex
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
defmodule Mix.Tasks.Language.Colours.Dl.Data do
|
||||||
|
use Mix.Task
|
||||||
|
|
||||||
|
@moduledoc """
|
||||||
|
Download the GitHub colours JSON dataset (or any other specified dataset).
|
||||||
|
|
||||||
|
**NOTE**: This function does not check the HTTPS certificate! Check the file after downloading
|
||||||
|
and only use this task as a helper during development.
|
||||||
|
|
||||||
|
You can specify the download URL and file path to put the download to with flags:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mix language.colours.dl.data --url 'https://raw.githubusercontent.com/ozh/github-colors/master/colors.json' --path 'priv/language_colours/data.json'
|
||||||
|
```
|
||||||
|
|
||||||
|
The directories leading to the output file will be created if necessary.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@default_url "https://raw.githubusercontent.com/ozh/github-colors/master/colors.json"
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
@impl true
|
||||||
|
def run(argv) do
|
||||||
|
{opts, _, _} = OptionParser.parse(argv, strict: [url: :string, path: :string])
|
||||||
|
|
||||||
|
url = opts |> Keyword.get(:url, @default_url) |> String.to_charlist()
|
||||||
|
path = Keyword.get(opts, :path, Path.join(File.cwd!(), "colours.json"))
|
||||||
|
|
||||||
|
Application.ensure_all_started(:inets)
|
||||||
|
Application.ensure_all_started(:ssl)
|
||||||
|
|
||||||
|
{:ok, {_, _, data}} = :httpc.request(:get, {url, []}, [], [])
|
||||||
|
path |> Path.dirname() |> File.mkdir_p!()
|
||||||
|
File.write!(path, data)
|
||||||
|
end
|
||||||
|
end
|
38
mix.exs
Normal file
38
mix.exs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
defmodule LanguageColours.MixProject do
|
||||||
|
use Mix.Project
|
||||||
|
|
||||||
|
def project do
|
||||||
|
[
|
||||||
|
app: :language_colours,
|
||||||
|
version: "1.0.0",
|
||||||
|
elixir: "~> 1.12",
|
||||||
|
start_permanent: Mix.env() == :prod,
|
||||||
|
deps: deps(),
|
||||||
|
|
||||||
|
# Docs
|
||||||
|
name: "LanguageColours",
|
||||||
|
source_url: "https://gitlab.com/Nicd/language_colours",
|
||||||
|
homepage_url: "https://gitlab.com/Nicd/language_colours",
|
||||||
|
docs: [
|
||||||
|
# The main page in the docs
|
||||||
|
main: "LanguageColours"
|
||||||
|
]
|
||||||
|
]
|
||||||
|
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
|
||||||
|
[
|
||||||
|
{:ex_doc, "~> 0.24", only: :dev, runtime: false},
|
||||||
|
{:rainbow, "~> 0.1.0", optional: true},
|
||||||
|
{:jason, "~> 1.2.2", optional: true}
|
||||||
|
]
|
||||||
|
end
|
||||||
|
end
|
10
mix.lock
Normal file
10
mix.lock
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
%{
|
||||||
|
"earmark_parser": {:hex, :earmark_parser, "1.4.15", "b29e8e729f4aa4a00436580dcc2c9c5c51890613457c193cc8525c388ccb2f06", [:mix], [], "hexpm", "044523d6438ea19c1b8ec877ec221b008661d3c27e3b848f4c879f500421ca5c"},
|
||||||
|
"ex_doc": {:hex, :ex_doc, "0.25.2", "4f1cae793c4d132e06674b282f1d9ea3bf409bcca027ddb2fe177c4eed6a253f", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "5b0c172e87ac27f14dfd152d52a145238ec71a95efbf29849550278c58a393d6"},
|
||||||
|
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
|
||||||
|
"makeup": {:hex, :makeup, "1.0.5", "d5a830bc42c9800ce07dd97fa94669dfb93d3bf5fcf6ea7a0c67b2e0e4a7f26c", [:mix], [{:nimble_parsec, "~> 0.5 or ~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "cfa158c02d3f5c0c665d0af11512fed3fba0144cf1aadee0f2ce17747fba2ca9"},
|
||||||
|
"makeup_elixir": {:hex, :makeup_elixir, "0.15.1", "b5888c880d17d1cc3e598f05cdb5b5a91b7b17ac4eaf5f297cb697663a1094dd", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.1", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "db68c173234b07ab2a07f645a5acdc117b9f99d69ebf521821d89690ae6c6ec8"},
|
||||||
|
"makeup_erlang": {:hex, :makeup_erlang, "0.1.1", "3fcb7f09eb9d98dc4d208f49cc955a34218fc41ff6b84df7c75b3e6e533cc65f", [:mix], [{:makeup, "~> 1.0", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm", "174d0809e98a4ef0b3309256cbf97101c6ec01c4ab0b23e926a9e17df2077cbb"},
|
||||||
|
"nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"},
|
||||||
|
"rainbow": {:hex, :rainbow, "0.1.0", "8d7da09f978997bd45c99315cc01319704516edd40d3c20d11cf4abd0e4f3d80", [:mix], [], "hexpm", "301a771cbbd2898bebddfddbfa5ae2bef27fe1edb8cd9574e6452239eb8eb80b"},
|
||||||
|
}
|
2106
test/colours-without-ada.json
Normal file
2106
test/colours-without-ada.json
Normal file
File diff suppressed because it is too large
Load diff
2110
test/colours.json
Normal file
2110
test/colours.json
Normal file
File diff suppressed because it is too large
Load diff
67
test/language_colours_test.exs
Normal file
67
test/language_colours_test.exs
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
defmodule LanguageColoursTest do
|
||||||
|
use ExUnit.Case
|
||||||
|
|
||||||
|
setup_all do
|
||||||
|
start_supervised!(
|
||||||
|
{LanguageColours.ETSDatabase,
|
||||||
|
LanguageColours.ETSDatabase.startup_options(
|
||||||
|
Application.get_env(:language_colours, :databases).test_db
|
||||||
|
)}
|
||||||
|
)
|
||||||
|
|
||||||
|
:ok
|
||||||
|
end
|
||||||
|
|
||||||
|
test "gets the correct colour" do
|
||||||
|
assert LanguageColours.get("Ada", :test_db) == "#02f88c"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "gets fallback if colour doesn't exist" do
|
||||||
|
assert "#" <> <<_rest::binary-size(6)>> = LanguageColours.get("Aaaaaaadaaaaaaa", :test_db)
|
||||||
|
end
|
||||||
|
|
||||||
|
test "is case insensitive" do
|
||||||
|
assert LanguageColours.get("AdA", :test_db) == "#02f88c"
|
||||||
|
end
|
||||||
|
|
||||||
|
test "returns nil if there is no fallback and language wasn't found" do
|
||||||
|
config =
|
||||||
|
Application.get_env(:language_colours, :databases).test_db
|
||||||
|
|> Map.put(:fallback, false)
|
||||||
|
|> Map.put(:server_name, :test_db_2)
|
||||||
|
|> Map.put(:ets_table, :best_table)
|
||||||
|
|
||||||
|
start_supervised!(
|
||||||
|
{LanguageColours.ETSDatabase, LanguageColours.ETSDatabase.startup_options(config)}
|
||||||
|
)
|
||||||
|
|
||||||
|
assert is_nil(LanguageColours.get("Aaaaaaadaaaaaaa", config))
|
||||||
|
end
|
||||||
|
|
||||||
|
test "language is deleted if no longer in updated dataset" do
|
||||||
|
config =
|
||||||
|
Application.get_env(:language_colours, :databases).test_db
|
||||||
|
|> Map.put(:file, "test/colours-without-ada.json")
|
||||||
|
|
||||||
|
assert LanguageColours.update(config) == :ok
|
||||||
|
assert LanguageColours.get("Ada", config) != "#02f88c"
|
||||||
|
|
||||||
|
# Teardown
|
||||||
|
config = Application.get_env(:language_colours, :databases).test_db
|
||||||
|
assert LanguageColours.update(config) == :ok
|
||||||
|
end
|
||||||
|
|
||||||
|
test "languages are updated correctly" do
|
||||||
|
config =
|
||||||
|
Application.get_env(:language_colours, :databases).test_db
|
||||||
|
|> Map.put(:file, "test/colours-without-ada.json")
|
||||||
|
|
||||||
|
assert LanguageColours.get("1C Enterprise", config) == "#814CCC"
|
||||||
|
assert LanguageColours.update(config) == :ok
|
||||||
|
assert LanguageColours.get("Ada", config) != "#ABCDEF"
|
||||||
|
|
||||||
|
# Teardown
|
||||||
|
config = Application.get_env(:language_colours, :databases).test_db
|
||||||
|
assert LanguageColours.update(config) == :ok
|
||||||
|
end
|
||||||
|
end
|
1
test/test_helper.exs
Normal file
1
test/test_helper.exs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
ExUnit.start()
|
Loading…
Reference in a new issue