# Automatically grading CSS

While in principle, it is possible to use [Selenium](https://app.gitbook.com/o/-MKoTuXczViPzaai1tw3/s/-MKAQsDlg_P20iQy3JDs/~/changes/190/faq/automatic-grading-questions/autotest-v2/web-development-assignments-selenium-tests) to test the `css` properties defined for `html` elements, we advise against doing so in CodeGrade. The reason is that we run Selenium tests by using a web browser in headless mode, which can result in `css` rules working differently than they would while running your web browser with a normal display.\
\
Alternatively, we can use [Semgrep](https://semgrep.dev/) to test the structure of the `css` rules defined by the student.

## Design Semgrep patterns for testing CSS rules

Semgrep is used to perform code analysis by writing syntax rules in a human-readable format. Rules are made by generic or language-specific patterns, which are then searched for in the student's code. In Semgrep's [pattern syntax](https://semgrep.dev/docs/writing-rules/pattern-syntax/), you have:

* **Equivalences**: Matching code that *means the same thing* even though it looks different;
* **Wildcards / ellipsis (...)**: Matching any statement, expression or variable;
* **Metavariables ($X)**: Matching unknown expressions that you do not yet know what they will exactly look like, but want to be the same variable in multiple parts of your pattern;
* **Logical operators:** it is possible to logically combine simpler patterns to create more complex aggregate patterns.&#x20;

Let's inspect an example of a **Semgrep** pattern that checks the properties of a `btn` `css` class:

<pre data-line-numbers><code>patterns:
<strong>      - pattern-inside: |
</strong><strong>         .btn { ... }
</strong>      - pattern: |
<strong>         ...
</strong><strong>         margin: 20px;
</strong><strong>         ...
</strong><strong>      - pattern: |
</strong><strong>          ...
</strong><strong>          width: $ANYVALUE;
</strong><strong>          ...
</strong></code></pre>

* Line 1: with `patterns` we indicate that our overall pattern is composed of multiple sub-patterns;
* Lines 2 to 3: we require that the patterns that will be defined later have to be found within the body of a class named `btn`;
* Lines 4 to 7: we require that our pattern contains a margin setting of exactly 20 pixels;
* Lines 8 to 11: we require that our pattern contains a width setting with any possible value (notice the use of a metavariable)

{% hint style="info" %}
We suggest using the online [Semgrep editor](https://semgrep.dev/playground/new) to quickly develop new rules for testing `css` rules.
{% endhint %}

## Instructions

<figure><img src="https://2172486256-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MKAQsDlg_P20iQy3JDs%2Fuploads%2FzLD8yP7yIkWZRynGpiVe%2FScreenshot%202024-05-28%20at%2016.31.20.png?alt=media&#x26;token=67057413-2ba4-40c7-b067-1d3085177c2b" alt=""><figcaption><p>A Semgrep test for Css rules. The test configuration is hidden to the students and the test is connected to a rubric category.</p></figcaption></figure>

1. In the **Setup** section of your AutoTest, drag and drop a **Script Block** into your configuration and type the following bash commands:

   ```bash
   python -mvenv ~/.venv/semgrep_1.43.0
   source ~/.venv/semgrep_1.43.0/bin/activate
   python -m pip install semgrep==1.43.0
   ```
2. In the Tests section of your AutoTest, drag and drop a **Code Structure Test** block. Specify the name of the CSS file you want to test in the "Student file" field.
3. Drag and drop a **Positive Match** block into your configuration and nest it within the Code Structure Test block. Copy and paste your Semgrep rule in the provided editor.
4. Build and Publish your snapshot.
