Osy#betaRun it on Osyrin: osyrin.com

Reference / Local

Connecting a kit — each seam with the code that connects it

osy kits <kit> --surface [--offline] [--json] · osy kits <kit> --tests-for <seam> [--json]

Prints a kit's composition surface — every event, policy, setting, slot, contract, base, grant, extension member, action and page an app connects — each with the kit's own test app code that connects it and the tests that show it working; `--tests-for` prints those tests whole with the test app code they call.

stablelocalclipackageskits

Summary#

Once you have chosen a kit, osy kits <kit> --surface shows how to connect it — not as a description, but as working code. For each seam an app connects, it prints the kit's own test app declaration that connects it, verbatim — the [On] handler, the policy line, the app.X = new … setting, the contribution to a slot — and the tests that show that seam working. Copy the shape; --tests-for <seam> prints the tests whole.

$ osy kits Osysharp.SatisfactionSurveys --surface
Policies — your app defines these
  policy ManagesFeedback;  — your app defines it
    Who decides whether, when and for how long people are asked — the settings page.
    ── tests/model/app.osy:17 ──
    policy ManagesFeedback => IsOwner;
    shown by tests/ui.test.osy::the_owner_decides_whether_and_when_people_are_asked · …

Events — what happens; hear one with `[On] void H(TheEvent e)`
  [Event("Feedback answered")] FeedbackAnswered { Ask, Change }
    Somebody answered (`FeedbackChange.First`) or changed their answer (`Changed`).
    raised by ApplyFeedbackReply
    ── tests/model/app.osy:48 ──
    /// What the workshop does as customers answer: the answer is noted on the repair.
    [On]
    void RepairAnswered(FeedbackAnswered e) {
      if (e.Ask.About is Repair r) {
        new RepairNote { Repair = r, Says = (e.Change == FeedbackChange.First ? "answered " : "changed to ")
                                            + (e.Ask.Rating == FeedbackRating.Bad ? "bad" : "good") };
      }
    }
    shown by tests/answers.test.osy::a_finished_repair_asks_its_customer_and_one_click_answers · …

Signature#

osy kits <kit> --surface            # every seam, each with its test app code and the tests that show it
osy kits <kit> --tests-for <seam>   # the tests for one seam, whole, with the test app code they call
  --offline                         # a kit not on this machine: do not fetch its examples from its release
  --project <dir>                   # where to look for kits (default: the current directory)
  --json                            # { seams: [{ kind, name, signature, doc, declaredAt, examples, tests, mustBeTested }] }

<kit> is a package name (Osysharp.SatisfactionSurveys), its last segment (feedback) or its directory in this repository. A kit this project does not use yet is fetched from its newest release, so you can read it before writing the use line.

Description#

What the seams are#

kindwhat your app writesthe example shown
settingapp.Feedback = new FeedbackSetup { … }the test app's line; fields with no default are marked
policypolicy ReadsFeedback => …; — a question the kit asks, which your app answers with its own rolesthe test app's definition
basea type of your own derived from the kit's (Customer : Party) — required when the base is abstractthe test app's subtype
grantpartial entity FeedbackAsk { security { allow create when IsStaff; } }the test app's grant
event[On] void H(TheEvent e) { … } to react after the committhe test app's handler; who raises it
slota component : TheSlot drawn where the kit's page draws the slotthe test app's contribution
contracta class implementing the kit's interface, named in its settingthe test app's implementation
extensionnothing — a bridge adds these members to another kit's recordthe tests that read them
actionnothing — an action the kit offers on a recordthe test app code that runs it
appPagea page at the route the kit links to (appPage "/bag";)the test app's page
page · hears · startsnothing — pages the kit serves, events it hears, what it starts by itself—
callthe kit's functions your test app callsthe test app code that calls it

A bridge that completes the kit with another is listed first: it arrives by itself in an app that uses both (Bridges — a package that arrives when an app uses the two it completes).

Which test shows a seam#

The mapping is derived, never written by hand. Each test's names are followed through the test app's declarations and the kit's — a test calls the test app's FinishRepair, which calls the kit's AskForFeedback, … which raises FeedbackAnswered — and a test that reaches the seam in at most four steps shows it. The nearest come first; a test that also reaches what the test app's code LEAVES BEHIND (the record a handler creates, the contribution a slot draws) comes before one that only touches the seam.

Two things a test does without naming them count too. A test that opens a page by its address — Ui.Visit("/orders/" + id) for [Route("/orders/{id}")] — reaches that page and everything it draws. And a setting is shown by a test that asserts a value the test app gave it: the test app's AppName = "Studio", read back in Assert.Equal("1 thing waiting for you in Studio", …), because a setting is usually read by work the kit delivers after the commit, which no test calls by name.

An abstract base the kit completes itself — the shared half of two connectors it ships — is the kit's own plumbing, not a seam: an app declares a connector and never derives the base, so it is listed only where the test app does.

A seam no test shows is said to be one — no test shows it — and osy kits check reports it as KIT_SEAM_UNTESTED, which osy publish refuses (Checking a kit composes — osy kits check).

The tests for one seam#

--tests-for <seam> prints the seam, the test app code that connects it, then up to three tests whole — the one that shows the outcome first — and the test app's own declarations those tests call, so the arrange step is visible:

$ osy kits Osysharp.SatisfactionSurveys --tests-for FeedbackAnswered
[Event("Feedback answered")] FeedbackAnswered { Ask, Change } (event of Osysharp.SatisfactionSurveys)

── tests/model/app.osy:48 — the test app fills it ──
[On]
void RepairAnswered(FeedbackAnswered e) { … }

── tests/answers.test.osy:9 — the test ──
[Test(Workshop)]
void a_finished_repair_asks_its_customer_and_one_click_answers() {
  Finish("city bike");
  …
  Assert.Equal(["answered good"], NotesOn("city bike"));
  …
}

── tests/workshop.test.osy:… — the test app's NotesOn, which the test calls ──
…

Where the examples come from#

In a repository that holds the kit, from its directory: the test app named by tests "…"; in its package.osy. For a kit fetched from GitHub, from examples.zip, the second file of every release — osy publish uploads the test app and its tests beside package.zip. They are not inside the package on purpose: a package's address is the hash of what an app compiles, and a test is not compiled into anyone's app. The examples are cached beside the package, so a kit is fetched once. A release published before kits shipped their tests says so, naming the file it did not find.

See also#

Related

Finding a kit, and learning one from its tests

Lists the kits (packages) this project can build on — each one's contracts, the kits that implement them, and what this…

Composing kits — what they give together, and what is left for you

Before any code, shows what a set of kits gives together — the bridges that arrive by themselves, every event with its…

Checking a kit composes — osy kits check

Checks that a kit composes with the kits around it: it uses no other product kit it does not complete…

[Event] — what happens to a record, declared once

An event is a class marked `[Event]`: something that happens to a record, declared once by the code that owns the…

[On] — hear an event, after the commit that raised it

`[On]` on a function makes it a HANDLER of the event its one parameter is. Every handler of an event — in the app and…

Slot (child content)

A `Slot` marks where a component renders the content block its caller wrapped around it. Writing `Card { Text("hi"); }`…

[Slot] and contributions — a place on a page that other kits, and the app, add to

A slot is a place on a page others add to. A kit marks one (`[Slot] public abstract component QuotePanel(Quote…

settings a package asks its app for (app settings)

A package — or an app — declares a setting by marking a class `[AppSetting("Name")]`. The app that uses it fills it in…

Extension members

A `partial entity X { … }` in a bridge package or in the app adds OPTIONAL members to an entity another package…

Bridges — a package that arrives when an app uses the two it completes

A bridge is a package whose manifest says `completes A@0, B@0;`. An app that uses every package it completes gets it…