···11+---
22+name: calibrate
33+description: Terms Of Service
44+compatibility: opencode
55+---
66+ - Scan the existing codebase and reuse existing functions, style and structure wherever possible.
77+ - Write descriptive variable names at all times.
88+ - Keep labels consistent across the entire project.
99+ - Python variable names must be `snake_case` sequence of descriptive words <=5 letters long.
1010+ - Write tests to determine the outcome of an anticipated feature.
1111+ - Only write enough code to pass the test.
1212+ - Write short Sphinx docstrings as a single line description, a single line for each parameter.
1313+ - On first line of docstrings use `\n`.
1414+ - Keep all imports within functions unless they must be mocked in a test.
1515+ - If an import is small, performative, and significantly reduces needs for new code, use the library.
1616+ - Try/except blocks must be written to catch specific, expected exception types.
1717+ - Generally code should stay under 100 lines in a single file. Code over 250 lines in a single file must be refactored.
1818+ - In commit messages use `+` for code adds, `-` for code subtractions, `~` for refactors/fixes.
1919+ - Use build, lint and typecheck after every change.
2020+ - No inline comments.
2121+ - No comments between docstring and next function.
2222+ - No empty lines or linebreaks in docstrings.
2323+ - No abbreviated function names or variables.
2424+ - No emoji.
2525+ - No global variables.
2626+ - No semantic commit messages.
2727+ - Never allow over 250 lines in a single file.
2828+ - Tests must not be modified once complete.
2929+ - No bare or generic exception catching.
3030+ - Do not mark ignore on type errors.
3131+ - Complete task without providing build and lint output.
3232+ - Thoughts can be long, but code, documentation, and stdout to user must be succinct and concise.
3333+ - When encountering ambiguity, ask the user.
+331
skills/gdsl/SKILL.md
···11+---
22+name: gdsl
33+description: Gherkin Domain Specific Language.
44+compatibility: opencode
55+metadata:
66+ type: language
77+---
88+99+**File extension** : `.feature.md`
1010+1111+# Gherkin Syntax
1212+1313+Like YAML or Python, Gherkin is a line-oriented language that uses indentation to define structure. Line endings terminate statements (called steps) and either spaces or tabs may be used for indentation. (We suggest you use spaces for portability.) Finally, most lines in Gherkin start with a special keyword:
1414+1515+Feature: Some terse yet descriptive text of what is desired
1616+ In order to realize a named business value
1717+ As an explicit system actor
1818+ I want to gain some beneficial outcome which furthers the goal
1919+2020+ Scenario: Some determinable business situation
2121+ Given some precondition
2222+ And some other precondition
2323+ When some action by the actor
2424+ And some other action
2525+ And yet another action
2626+ Then some testable outcome is achieved
2727+ And something else we can check happens too
2828+2929+ Scenario: A different situation
3030+ ...
3131+3232+The parser divides the input into features, scenarios and steps. Let’s walk through the above example:
3333+3434+ Feature: Some terse yet descriptive text of what is desired starts the feature and gives it a title. Learn more about features in the “Features” section.
3535+ Behat does not parse the next 3 lines of text. (In order to... As an... I want to...). These lines simply provide context to the people reading your feature, and describe the business value derived from the inclusion of the feature in your software.
3636+ Scenario: Some determinable business situation starts the scenario, and contains a description of the scenario. Learn more about scenarios in the “Scenarios” section.
3737+ The next 7 lines are the scenario steps, each of which is matched to a regular expression defined elsewhere. Learn more about steps in the “Steps” section.
3838+ Scenario: A different situation starts the next scenario, and so on.
3939+4040+Every *.feature file conventionally consists of a single feature. Lines starting with the keyword Feature: (or its localized equivalent) followed by three indented lines starts a feature. A feature usually contains a list of scenarios. You can write whatever you want up until the first scenario, which starts with Scenario: (or localized equivalent) on a new line. You can use tags to group features and scenarios together, independent of your file and directory structure.
4141+4242+Every scenario consists of a list of steps, which must start with one of the keywords Given, When, Then, But or And (or localized one). Here is an example:
4343+4444+Feature: Serve coffee
4545+ In order to earn money
4646+ Customers should be able to
4747+ buy coffee at all times
4848+4949+ Scenario: Buy last coffee
5050+ Given there are 1 coffees left in the machine
5151+ And I have deposited 1 dollar
5252+ When I press the coffee button
5353+ Then I should be served a coffee
5454+5555+In addition to basic scenarios, feature may contain scenario outlines and backgrounds.
5656+5757+## Scenarios
5858+5959+Scenario is one of the core Gherkin structures. Every scenario starts with the Scenario: keyword (or localized one), followed by an optional scenario title. Each feature can have one or more scenarios, and every scenario consists of one or more steps.
6060+6161+The following scenarios each have 3 steps:
6262+6363+Scenario: Wilson posts to his own blog
6464+ Given I am logged in as Wilson
6565+ When I try to post to "Expensive Therapy"
6666+ Then I should see "Your article was published."
6767+6868+Scenario: Wilson fails to post to somebody else's blog
6969+ Given I am logged in as Wilson
7070+ When I try to post to "Greg's anti-tax rants"
7171+ Then I should see "Hey! That's not your blog!"
7272+7373+Scenario: Greg posts to a client's blog
7474+ Given I am logged in as Greg
7575+ When I try to post to "Expensive Therapy"
7676+ Then I should see "Your article was published."
7777+7878+## Scenario Outlines
7979+8080+Copying and pasting scenarios to use different values can quickly become tedious and repetitive:
8181+8282+Scenario: Eat 5 out of 12
8383+ Given there are 12 cucumbers
8484+ When I eat 5 cucumbers
8585+ Then I should have 7 cucumbers
8686+8787+Scenario: Eat 5 out of 20
8888+ Given there are 20 cucumbers
8989+ When I eat 5 cucumbers
9090+ Then I should have 15 cucumbers
9191+9292+Scenario Outlines allow us to more concisely express these examples through the use of a template with placeholders:
9393+9494+Scenario Outline: Eating
9595+ Given there are <start> cucumbers
9696+ When I eat <eat> cucumbers
9797+ Then I should have <left> cucumbers
9898+9999+ Examples:
100100+ | start | eat | left |
101101+ | 12 | 5 | 7 |
102102+ | 20 | 5 | 15 |
103103+104104+The Scenario outline steps provide a template which is never directly run. A Scenario Outline is run once for each row in the Examples section beneath it (not counting the first row of column headers).
105105+106106+The Scenario Outline uses placeholders, which are contained within < > in the Scenario Outline’s steps. For example:
107107+108108+Given <I'm a placeholder and I'm ok>
109109+110110+Think of a placeholder like a variable. It is replaced with a real value from the Examples: table row, where the text between the placeholder angle brackets matches that of the table column header. The value substituted for the placeholder changes with each subsequent run of the Scenario Outline, until the end of the Examples table is reached.
111111+112112+You can also use placeholders in Multiline Arguments.
113113+114114+Your step definitions will never have to match the placeholder text itself, but rather the values replacing the placeholder.
115115+116116+So when running the first row of our example:
117117+118118+Scenario Outline: controlling order
119119+ Given there are <start> cucumbers
120120+ When I eat <eat> cucumbers
121121+ Then I should have <left> cucumbers
122122+123123+ Examples:
124124+ | start | eat | left |
125125+ | 12 | 5 | 7 |
126126+127127+The scenario that is actually run is:
128128+129129+Scenario Outline: controlling order
130130+ - <start> replaced with 12:
131131+ Given there are 12 cucumbers
132132+ - <eat> replaced with 5:
133133+ When I eat 5 cucumbers
134134+ - <left> replaced with 7:
135135+ Then I should have 7 cucumbers
136136+137137+## Backgrounds
138138+139139+Backgrounds allows you to add some context to all scenarios in a single feature. A Background is like an untitled scenario, containing a number of steps. The difference is when it is run: the background is run before each of your scenarios, but after your BeforeScenario hooks (Hooking into the Test Process - Hooks).
140140+141141+Feature: Multiple site support
142142+143143+ Background:
144144+ Given a global administrator named "Greg"
145145+ And a blog named "Greg's anti-tax rants"
146146+ And a customer named "Wilson"
147147+ And a blog named "Expensive Therapy" owned by "Wilson"
148148+149149+ Scenario: Wilson posts to his own blog
150150+ Given I am logged in as Wilson
151151+ When I try to post to "Expensive Therapy"
152152+ Then I should see "Your article was published."
153153+154154+ Scenario: Greg posts to a client's blog
155155+ Given I am logged in as Greg
156156+ When I try to post to "Expensive Therapy"
157157+ Then I should see "Your article was published."
158158+159159+## Steps
160160+161161+Features consist of steps, also known as Givens, Whens and Thens. These words have been carefully selected for their purpose, and you should know what the purpose is to get into the BDD mindset.
162162+163163+Robert C. Martin has written a great post about BDD’s Given-When-Then concept where he thinks of them as a finite state machine.
164164+165165+### Givens
166166+167167+The purpose of Given steps is to put the system in a known state before the user (or external system) starts interacting with the system (in the When steps). Avoid talking about user interaction in givens. If you have worked with use cases, givens are your preconditions.
168168+169169+Two good examples of using Givens are:
170170+171171+ To create records (model instances) or set up the database:
172172+173173+ Given there are no users on site
174174+ Given the database is clean
175175+176176+ Authenticate a user (An exception to the no-interaction recommendation. Things that “happened earlier” are ok):
177177+178178+ Given I am logged in as "Everzet"
179179+180180+It’s ok to call into the layer “inside” the UI layer here (in symfony: talk to the models).
181181+182182+And for all the symfony users out there, we recommend using a Given step with a tables arguments to set up records instead of fixtures. This way you can read the scenario all in one place and make sense out of it without having to jump between files:
183183+184184+Given there are users:
185185+ | username | password | email |
186186+ | everzet | 123456 | everzet@knplabs.com |
187187+ | fabpot | 22@222 | fabpot@symfony.com |
188188+189189+### Whens
190190+191191+The purpose of When steps is to describe the key action the user performs (or, using Robert C. Martin’s metaphor, the state transition).
192192+193193+Two good examples of Whens use are:
194194+195195+ Interact with a web page (the Mink library gives you many web-friendly When steps out of the box):
196196+197197+ When I am on "/some/page"
198198+ When I fill "username" with "everzet"
199199+ When I fill "password" with "123456"
200200+ When I press "login"
201201+202202+ Interact with some CLI library (call commands and record output):
203203+204204+ When I call "ls -la"
205205+206206+### Thens
207207+208208+The purpose of Then steps is to observe outcomes. The observations should be related to the business value/benefit in your feature description. The observations should inspect the output of the system (a report, user interface, message, command output) and not something deeply buried inside it (that has no business value and is instead part of the implementation).
209209+210210+ Verify that something related to the Given+When is (or is not) in the output
211211+ Check that some external system has received the expected message (was an email with specific content successfully sent?)
212212+213213+When I call "echo hello"
214214+Then the output should be "hello"
215215+216216+While it might be tempting to implement Then steps to just look in the database – resist the temptation. You should only verify output that is observable by the user (or external system). Database data itself is only visible internally to your application, but is then finally exposed by the output of your system in a web browser, on the command-line or an email message.
217217+218218+### And, But
219219+220220+If you have several Given, When or Then steps you can write:
221221+222222+Scenario: Multiple Givens
223223+ Given one thing
224224+ Given an other thing
225225+ Given yet an other thing
226226+ When I open my eyes
227227+ Then I see something
228228+ Then I don't see something else
229229+230230+Or you can use And or But steps, allowing your Scenario to read more fluently:
231231+232232+Scenario: Multiple Givens
233233+ Given one thing
234234+ And an other thing
235235+ And yet an other thing
236236+ When I open my eyes
237237+ Then I see something
238238+ But I don't see something else
239239+240240+If you prefer, you can indent scenario steps in a more programmatic way, much in the same way your actual code is indented to provide visual context:
241241+242242+Scenario: Multiple Givens
243243+ Given one thing
244244+ And an other thing
245245+ And yet an other thing
246246+ When I open my eyes
247247+ Then I see something
248248+ But I don't see something else
249249+250250+### Multiline Arguments
251251+252252+The regular expression matching in steps lets you capture small strings from your steps and receive them in your step definitions. However, there are times when you want to pass a richer data structure from a step to a step definition.
253253+254254+This is what multiline step arguments are for. They are written on lines immediately following a step, and are passed to the step definition method as the last argument.
255255+256256+Multiline step arguments come in two flavours: tables or pystrings.
257257+258258+### Tables
259259+260260+Tables as arguments to steps are handy for specifying a larger data set - usually as input to a Given or as expected output from a Then.
261261+262262+Scenario:
263263+ Given the following people exist:
264264+ | name | email | phone |
265265+ | Aslak | aslak@email.com | 123 |
266266+ | Joe | joe@email.com | 234 |
267267+ | Bryan | bryan@email.org | 456 |
268268+269269+Don’t be confused with tables from scenario outlines - syntactically they are identical, but have a different purpose.
270270+271271+A matching definition for this step looks like this:
272272+273273+/**
274274+ * @Given /the following people exist:/
275275+ */
276276+public function thePeopleExist(TableNode $table)
277277+{
278278+ $hash = $table->getHash();
279279+ foreach ($hash as $row) {
280280+ // $row['name'], $row['email'], $row['phone']
281281+ }
282282+}
283283+284284+A table is injected into a definition as a TableNode object, from which you can get hash by columns (TableNode::getHash() method) or by rows (TableNode::getRowsHash()).
285285+286286+### PyStrings
287287+288288+Multiline Strings (also known as PyStrings) are handy for specifying a larger piece of text. This is done using the so-called PyString syntax. The text should be offset by delimiters consisting of three double-quote marks (""") on lines by themselves:
289289+290290+Scenario:
291291+ Given a blog post named "Random" with:
292292+ """
293293+ Some Title, Eh?
294294+ ===============
295295+ Here is the first paragraph of my blog post.
296296+ Lorem ipsum dolor sit amet, consectetur adipiscing
297297+ elit.
298298+ """
299299+300300+The inspiration for PyString comes from Python where """ is used to delineate docstrings, much in the way /* ... */ is used for multiline docblocks in PHP.
301301+302302+In your step definition, there’s no need to find this text and match it in your regular expression. The text will automatically be passed as the last argument into the step definition method. For example:
303303+304304+/**
305305+ * @Given /a blog post named "([^"]+)" with:/
306306+ */
307307+public function blogPost($title, PyStringNode $markdown)
308308+{
309309+ $this->createPost($title, $markdown->getRaw());
310310+}
311311+312312+PyStrings are stored in a PyStringNode instance, which you can simply convert to a string with (string) $pystring or $pystring->getRaw() as in the example above.
313313+314314+Indentation of the opening """ is not important, although common practice is two spaces in from the enclosing step. The indentation inside the triple quotes, however, is significant. Each line of the string passed to the step definition’s callback will be de-indented according to the opening """. Indentation beyond the column of the opening """ will therefore be preserved.
315315+316316+## Tags
317317+318318+Tags are a great way to organize your features and scenarios. Consider this example:
319319+320320+@billing
321321+Feature: Verify billing
322322+323323+ @important
324324+ Scenario: Missing product description
325325+326326+ Scenario: Several products
327327+328328+A Scenario or Feature can have as many tags as you like, just separate them with spaces:
329329+330330+@billing @bicker @annoy
331331+Feature: Verify billing