mirror of
https://github.com/GothenburgBitFactory/timewarrior.git
synced 2025-06-26 10:54:28 +02:00
Handle case of empty interval, fix tests
Signed-off-by: Thomas Lauf <thomas.lauf@tngtech.com>
This commit is contained in:
parent
da27fdcdf0
commit
bf87509329
4 changed files with 67 additions and 65 deletions
|
@ -31,7 +31,7 @@
|
|||
#include <Lexer.h>
|
||||
#include <sstream>
|
||||
#include <JSON.h>
|
||||
#include "Interval.h"
|
||||
#include <Interval.h>
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -39,7 +39,8 @@ bool Interval::empty () const
|
|||
{
|
||||
return start.toEpoch () == 0 &&
|
||||
end.toEpoch () == 0 &&
|
||||
_tags.empty ();
|
||||
_tags.empty () &&
|
||||
annotation.empty ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -99,48 +100,46 @@ std::string Interval::serialize () const
|
|||
std::string Interval::json () const
|
||||
{
|
||||
std::stringstream out;
|
||||
out << "{\"id\":" << id;
|
||||
out << "{";
|
||||
|
||||
if (is_started ()) {
|
||||
out << ",\"start\":\"" << start.toISO () << "\"";
|
||||
}
|
||||
|
||||
if (is_ended ()) {
|
||||
out << ",\"end\":\"" << end.toISO () << "\"";
|
||||
}
|
||||
|
||||
if (! _tags.empty ())
|
||||
if (!empty ())
|
||||
{
|
||||
std::string tags;
|
||||
for (auto& tag : _tags)
|
||||
{
|
||||
if (tags[0])
|
||||
tags += ',';
|
||||
out << "\"id\":" << id;
|
||||
|
||||
tags += "\"" + escape (tag, '"') + "\"";
|
||||
if (is_started ())
|
||||
{
|
||||
out << ",\"start\":\"" << start.toISO () << "\"";
|
||||
}
|
||||
|
||||
if (start.toEpoch () ||
|
||||
end.toEpoch ())
|
||||
out << ',';
|
||||
|
||||
out << "\"tags\":["
|
||||
<< tags
|
||||
<< ']';
|
||||
}
|
||||
|
||||
if (!annotation.empty ())
|
||||
{
|
||||
if (start.toEpoch () || end.toEpoch () || !_tags.empty ())
|
||||
if (is_ended ())
|
||||
{
|
||||
out << ',';
|
||||
out << ",\"end\":\"" << end.toISO () << "\"";
|
||||
}
|
||||
|
||||
out << "\"annotation\":\"" << escape (annotation, '"') << "\"";
|
||||
}
|
||||
if (!_tags.empty ())
|
||||
{
|
||||
std::string tags;
|
||||
for (auto &tag : _tags)
|
||||
{
|
||||
if (tags[0])
|
||||
tags += ',';
|
||||
|
||||
tags += "\"" + escape (tag, '"') + "\"";
|
||||
}
|
||||
|
||||
out << ",\"tags\":["
|
||||
<< tags
|
||||
<< ']';
|
||||
}
|
||||
|
||||
if (!annotation.empty ())
|
||||
{
|
||||
out << ",\"annotation\":\"" << escape (annotation, '"') << "\"";
|
||||
}
|
||||
}
|
||||
out << "}";
|
||||
return out.str ();
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -128,6 +128,9 @@ Interval IntervalFactory::fromJson (const std::string& jsonString)
|
|||
interval.start = (start != nullptr) ? Datetime(start->_data) : 0;
|
||||
json::string* end = (json::string*) json->_data["end"];
|
||||
interval.end = (end != nullptr) ? Datetime(end->_data) : 0;
|
||||
|
||||
json::number* id = (json::number*) json->_data["id"];
|
||||
interval.id = (id != nullptr) ? id->_dvalue : 0;
|
||||
}
|
||||
|
||||
return interval;
|
||||
|
|
|
@ -144,7 +144,7 @@ class TestDOM(TestCase):
|
|||
"""Test dom.active.json with an active interval"""
|
||||
self.t("start foo")
|
||||
code, out, err = self.t("get dom.active.json")
|
||||
self.assertRegex(out, r'{"start":"\d{8}T\d{6}Z","tags":\["foo"\]}')
|
||||
self.assertRegex(out, r'{"id":1,"start":"\d{8}T\d{6}Z","tags":\["foo"\]}')
|
||||
|
||||
def test_dom_tracked_count_none(self):
|
||||
"""Test dom.active without an active interval"""
|
||||
|
@ -226,12 +226,12 @@ class TestDOMTracked(TestCase):
|
|||
def test_dom_tracked_N_json_inactive(self):
|
||||
"""Test dom.tracked.N.json of closed track"""
|
||||
code, out, err = self.t("get dom.tracked.2.json")
|
||||
self.assertRegex(out, r'{"start":"\d{8}T\d{6}Z","end":"\d{8}T\d{6}Z","tags":\["one","two"\]}')
|
||||
self.assertRegex(out, r'{"id":2,"start":"\d{8}T\d{6}Z","end":"\d{8}T\d{6}Z","tags":\["one","two"\]}')
|
||||
|
||||
def test_dom_tracked_N_json_active(self):
|
||||
"""Test dom.tracked.N.json of open track"""
|
||||
code, out, err = self.t("get dom.tracked.1.json")
|
||||
self.assertRegex(out, r'{"start":"\d{8}T\d{6}Z"}')
|
||||
self.assertRegex(out, r'{"id":1,"start":"\d{8}T\d{6}Z"}')
|
||||
|
||||
|
||||
class TestDOMRC(TestCase):
|
||||
|
|
|
@ -144,104 +144,104 @@ int main (int, char**)
|
|||
|
||||
Interval i12a;
|
||||
i12a = IntervalFactory::fromSerialization ("inc # # \"this is an annotation\"");
|
||||
t.is (i12a.json (), "{\"annotation\":\"this is an annotation\"}",
|
||||
"JSON '{\"annotation\":\"this is an annotation\"}'");
|
||||
t.is (i12a.json (), "{\"id\":0,\"annotation\":\"this is an annotation\"}",
|
||||
"JSON '{\"id\":0,\"annotation\":\"this is an annotation\"}'");
|
||||
t.is (IntervalFactory::fromJson (i12a.json ()).serialize (),
|
||||
"inc # # \"this is an annotation\"",
|
||||
"Round-trip 'inc # # \"this is an annotation\"'");
|
||||
|
||||
Interval i13;
|
||||
i13 = IntervalFactory::fromSerialization ("inc # foo");
|
||||
t.is (i13.json (), "{\"tags\":[\"foo\"]}",
|
||||
"JSON '{\"tags\":[\"foo\"]}'");
|
||||
t.is (i13.json (), "{\"id\":0,\"tags\":[\"foo\"]}",
|
||||
"JSON '{\"id\":0,\"tags\":[\"foo\"]}'");
|
||||
t.is (IntervalFactory::fromJson (i13.json ()).serialize (),
|
||||
"inc # foo",
|
||||
"Round-trip 'inc # foo'");
|
||||
|
||||
Interval i13a;
|
||||
i13a = IntervalFactory::fromSerialization ("inc # foo # \"this is an annotation\"");
|
||||
t.is (i13a.json (), "{\"tags\":[\"foo\"],\"annotation\":\"this is an annotation\"}",
|
||||
"JSON '{\"tags\":[\"foo\"],\"annotation\":\"this is an annotation\"}'");
|
||||
t.is (i13a.json (), "{\"id\":0,\"tags\":[\"foo\"],\"annotation\":\"this is an annotation\"}",
|
||||
"JSON '{\"id\":0,\"tags\":[\"foo\"],\"annotation\":\"this is an annotation\"}'");
|
||||
t.is (IntervalFactory::fromJson (i13a.json ()).serialize (),
|
||||
"inc # foo # \"this is an annotation\"",
|
||||
"Round-trip 'inc # foo # \"this is an annotation\"'");
|
||||
|
||||
Interval i14;
|
||||
i14 = IntervalFactory::fromSerialization ("inc # bar foo");
|
||||
t.is (i14.json (), "{\"tags\":[\"bar\",\"foo\"]}",
|
||||
"JSON '{\"tags\":[\"bar\",\"foo\"]}'");
|
||||
t.is (i14.json (), "{\"id\":0,\"tags\":[\"bar\",\"foo\"]}",
|
||||
"JSON '{\"id\":0,\"tags\":[\"bar\",\"foo\"]}'");
|
||||
t.is (IntervalFactory::fromJson (i14.json ()).serialize (),
|
||||
"inc # bar foo",
|
||||
"Round-trip 'inc # bar foo'");
|
||||
|
||||
Interval i14a;
|
||||
i14a = IntervalFactory::fromSerialization ("inc # bar foo # \"this is an annotation\"");
|
||||
t.is (i14a.json (), "{\"tags\":[\"bar\",\"foo\"],\"annotation\":\"this is an annotation\"}",
|
||||
"JSON '{\"tags\":[\"bar\",\"foo\"],\"annotation\":\"this is an annotation\"}'");
|
||||
t.is (i14a.json (), "{\"id\":0,\"tags\":[\"bar\",\"foo\"],\"annotation\":\"this is an annotation\"}",
|
||||
"JSON '{\"id\":0,\"tags\":[\"bar\",\"foo\"],\"annotation\":\"this is an annotation\"}'");
|
||||
t.is (IntervalFactory::fromJson (i14a.json ()).serialize (),
|
||||
"inc # bar foo # \"this is an annotation\"",
|
||||
"Round-trip 'inc # bar foo # \"this is an annotation\"'");
|
||||
|
||||
Interval i15;
|
||||
i15 = IntervalFactory::fromSerialization ("inc 19700101T000001Z");
|
||||
t.is (i15.json (), "{\"start\":\"19700101T000001Z\"}",
|
||||
"JSON '{\"start\":\"19700101T000001Z\"}'");
|
||||
t.is (i15.json (), "{\"id\":0,\"start\":\"19700101T000001Z\"}",
|
||||
"JSON '{\"id\":0,\"start\":\"19700101T000001Z\"}'");
|
||||
t.is (IntervalFactory::fromJson (i15.json ()).serialize (),
|
||||
"inc 19700101T000001Z",
|
||||
"Round-trip 'inc 19700101T000001Z'");
|
||||
|
||||
Interval i15a;
|
||||
i15a = IntervalFactory::fromSerialization ("inc 19700101T000001Z # # \"this is an annotation\"");
|
||||
t.is (i15a.json (), "{\"start\":\"19700101T000001Z\",\"annotation\":\"this is an annotation\"}",
|
||||
"JSON '{\"start\":\"19700101T000001Z\",\"annotation\":\"this is an annotation\"}'");
|
||||
t.is (i15a.json (), "{\"id\":0,\"start\":\"19700101T000001Z\",\"annotation\":\"this is an annotation\"}",
|
||||
"JSON '{\"id\":0,\"start\":\"19700101T000001Z\",\"annotation\":\"this is an annotation\"}'");
|
||||
t.is (IntervalFactory::fromJson (i15a.json ()).serialize (),
|
||||
"inc 19700101T000001Z # # \"this is an annotation\"",
|
||||
"Round-trip 'inc 19700101T000001Z # # \"this is an annotation\"'");
|
||||
|
||||
Interval i16;
|
||||
i16 = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z");
|
||||
t.is (i16.json (), "{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\"}",
|
||||
"JSON '{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\"}'");
|
||||
t.is (i16.json (), "{\"id\":0,\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\"}",
|
||||
"JSON '{\"id\":0,\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\"}'");
|
||||
t.is (IntervalFactory::fromJson (i16.json ()).serialize (),
|
||||
"inc 19700101T000001Z - 19700101T000002Z",
|
||||
"Round-trip 'inc 19700101T000001Z - 19700101T000002Z'");
|
||||
|
||||
Interval i16a;
|
||||
i16a = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z # # \"this is an annotation\"");
|
||||
t.is (i16a.json (), "{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"annotation\":\"this is an annotation\"}",
|
||||
"JSON '{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"annotation\":\"this is an annotation\"}'");
|
||||
t.is (i16a.json (), "{\"id\":0,\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"annotation\":\"this is an annotation\"}",
|
||||
"JSON '{\"id\":0,\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"annotation\":\"this is an annotation\"}'");
|
||||
t.is (IntervalFactory::fromJson (i16a.json ()).serialize (),
|
||||
"inc 19700101T000001Z - 19700101T000002Z # # \"this is an annotation\"",
|
||||
"Round-trip 'inc 19700101T000001Z - 19700101T000002Z # # \"this is an annotation\"'");
|
||||
|
||||
Interval i17;
|
||||
i17 = IntervalFactory::fromSerialization ("inc 19700101T000001Z # bar foo");
|
||||
t.is (i17.json (), "{\"start\":\"19700101T000001Z\",\"tags\":[\"bar\",\"foo\"]}",
|
||||
"JSON '{\"start\":\"19700101T000001Z\",\"tags\":[\"bar\",\"foo\"]}'");
|
||||
t.is (i17.json (), "{\"id\":0,\"start\":\"19700101T000001Z\",\"tags\":[\"bar\",\"foo\"]}",
|
||||
"JSON '{\"id\":0,\"start\":\"19700101T000001Z\",\"tags\":[\"bar\",\"foo\"]}'");
|
||||
t.is (IntervalFactory::fromJson (i17.json ()).serialize (),
|
||||
"inc 19700101T000001Z # bar foo",
|
||||
"Round-trip 'inc 19700101T000001Z # bar foo'");
|
||||
|
||||
Interval i18;
|
||||
i18 = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z # bar foo");
|
||||
t.is (i18.json (), "{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"bar\",\"foo\"]}",
|
||||
"JSON '{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"bar\",\"foo\"]}'");
|
||||
t.is (i18.json (), "{\"id\":0,\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"bar\",\"foo\"]}",
|
||||
"JSON '{\"id\":0,\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"bar\",\"foo\"]}'");
|
||||
t.is (IntervalFactory::fromJson (i18.json ()).serialize (),
|
||||
"inc 19700101T000001Z - 19700101T000002Z # bar foo",
|
||||
"Round-trip 'inc 19700101T000001Z - 19700101T000002Z # bar foo'");
|
||||
|
||||
Interval i18a;
|
||||
i18a = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z # bar foo # \"this is an annotation\"");
|
||||
t.is (i18a.json (), "{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"bar\",\"foo\"],\"annotation\":\"this is an annotation\"}",
|
||||
"JSON '{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"bar\",\"foo\"],\"annotation\":\"this is an annotation\"}'");
|
||||
t.is (i18a.json (), "{\"id\":0,\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"bar\",\"foo\"],\"annotation\":\"this is an annotation\"}",
|
||||
"JSON '{\"id\":0,\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"bar\",\"foo\"],\"annotation\":\"this is an annotation\"}'");
|
||||
t.is (IntervalFactory::fromJson (i18a.json ()).serialize (),
|
||||
"inc 19700101T000001Z - 19700101T000002Z # bar foo # \"this is an annotation\"",
|
||||
"Round-trip 'inc 19700101T000001Z - 19700101T000002Z # bar foo # \"this is an annotation\"'");
|
||||
|
||||
Interval i19;
|
||||
i19 = IntervalFactory::fromSerialization ("inc 19700101T000001Z - 19700101T000002Z # \"Trans-Europe Express\" bar foo");
|
||||
t.is (i19.json (), "{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"Trans-Europe Express\",\"bar\",\"foo\"]}",
|
||||
"JSON '{\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"Trans-Europe Express\",\"bar\",\"foo\"]}'");
|
||||
t.is (i19.json (), "{\"id\":0,\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"Trans-Europe Express\",\"bar\",\"foo\"]}",
|
||||
"JSON '{\"id\":0,\"start\":\"19700101T000001Z\",\"end\":\"19700101T000002Z\",\"tags\":[\"Trans-Europe Express\",\"bar\",\"foo\"]}'");
|
||||
t.is (IntervalFactory::fromJson (i19.json ()).serialize (),
|
||||
"inc 19700101T000001Z - 19700101T000002Z # \"Trans-Europe Express\" bar foo",
|
||||
"Round-trip 'inc 19700101T000001Z - 19700101T000002Z # \"Trans-Europe Express\" bar foo");
|
||||
|
@ -254,8 +254,8 @@ int main (int, char**)
|
|||
Interval i21;
|
||||
i21.tag ("one-two");
|
||||
i21.tag ("three");
|
||||
t.is (i21.json (), "{\"tags\":[\"one-two\",\"three\"]}",
|
||||
"JSON '{\"tags\":[\"one-two\",\"three\"]}'");
|
||||
t.is (i21.json (), "{\"id\":0,\"tags\":[\"one-two\",\"three\"]}",
|
||||
"JSON '{\"id\":0,\"tags\":[\"one-two\",\"three\"]}'");
|
||||
|
||||
// make sure that underscores are escaped
|
||||
Interval i22;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue