zachallaun/mneme

DateTime structs patterns are generated as `nil`

Closed this issue · 2 comments

Given this code:

def hello do
  started_at =
    ~N[2023-11-04 00:00:00]
    |> DateTime.from_naive!("Etc/UTC")
    |> DateTime.shift_zone!("Pacific/Honolulu")

  [
    %{
      :started_at => started_at,
      :total_seconds => "1800"
    }
  ]
end

And this test:

test "repro" do
  auto_assert(MnemeRepro.hello())
end

The generated pattern (after pressing k once) is: [%{started_at: nil, total_seconds: "1800"}] which doesn't match the input data (so future mix test calls will fail).

I'm not sure what the best way to handle this is, potentially the struct could be inspected and matched with structs: false but that will result in brittle patterns (and isn't respecting the intention of the custom inspect protocol impl).

At the minimum I think that mneme should refuse to create a pattern for a non-inspectible struct like %DateTime{} until it supports a matching pattern. Also I haven't checked but this might affect other types like pids.

Note: the struct values are:

result (structs: true): [
  %{
    started_at: #DateTime<2023-11-03 14:00:00-10:00 HST Pacific/Honolulu>,
    total_seconds: "1800"
  }
]
result (structs: false): [
  %{
    started_at: %{
      microsecond: {0, 0},
      second: 0,
      calendar: Calendar.ISO,
      month: 11,
      __struct__: DateTime,
      day: 3,
      year: 2023,
      minute: 0,
      hour: 14,
      time_zone: "Pacific/Honolulu",
      zone_abbr: "HST",
      utc_offset: -36000,
      std_offset: 0
    },
    total_seconds: "1800"
  }
]

Full reproduction: https://github.com/axelson/mneme_repro

P.S. sorry about filing lots of issues but not being responsive on them once filed!

In case your curious what I ended up doing for this, I decided to not use mneme for this particular test but instead use https://github.com/mtrudel/machete:

defmodule Dash.PomodoroParserTest do
  use ExUnit.Case
  use Machete
  use Mneme

  @case1 """
  started_at,finished_at,rest_started_at,rest_finished_at,total_seconds
  2023-11-04 19:03:06,2023-11-04 19:09:12,,,1800
  2023-11-04 19:10:13,2023-11-04 19:26:16.953404,,,1800
  """
  test "parses case1" do
    today = ~D[2023-11-04]

    expected = [
      %{
        :started_at => datetime(roughly: ~U[2023-11-04 19:03:12Z], time_zone: "Pacific/Honolulu"),
      },
      %{
        :started_at => datetime(roughly: ~U[2023-11-04 19:10:13Z], time_zone: "Pacific/Honolulu"),
      },
    ]

    assert Dash.PomodoroParser.parse(@case1, today: today) ~> expected
  end
end

Theoretically mneme could generate machete "patterns" but due to the flexibility of machete and the specific-ness of each matcher I think it would be a very brittle integration.

@axelson Sorry it took me so long to get to this! On main, Mneme will now generate struct pattern for datetimes/etc. when the sigil shorthand isn't available, as in this case.