Git Product home page Git Product logo

frontend-grading-engine's Introduction

Udacity Feedback Chrome Extension

Immediate, visual feedback about any website's HTML, CSS and JavaScript.

Installing from Source

  1. Clone this repo
  2. npm install - install dependencies
  3. gulp watch or just gulp - build the grading engine
  4. Load in Chrome
  • Open the Extensions window (chrome://extensions)
  • Check 'Developer Mode'
  • Click 'Load unpacked extension...'
  • Select ext/

More on development

Loading Tests

On sites you own

Add the following meta tag:

<meta name="udacity-grader" content="relative_path_to_tests.json">

There are two optional attributes: libraries and unit-tests. libraries is always optional and unit-tests is only necessary for JS quizzes. More on JS tests here.

On sites you don't own

Click on the Udacity browser action. Choose 'Load tests' and navigate to a JSON.

API

JSON

Typical structure is an array of:

suite
|_name
|_code
|_tests
  |_description
  |_definition
  | |_nodes
  | |_collector
  | |_reporter
  |
  |_[flags]

Example:

[{
  "name": "Learning Udacity Feedback",
  "code": "This can be an encouraging message",
  "tests": [
    {
      "description": "Test 1 has correct bg color",
      "definition": {
        "nodes": ".test1",
        "cssProperty": "backgroundColor",
        "equals": "rgb(204, 204, 255)"
      }
    }
  ]
},
{
  "name": "More 'dacity Feedback",
  "code": "Some message",
  "tests": [
    {
      "description": "Test 2 says 'Hello, world!'",
      "definition": {
        "nodes": ".test2",
        "get": "innerHTML",
        "hasSubstring": "^Hello, world!$"
      }
    },
    {
      "description": "Test 3 has two columns",
      "definition": {
        "nodes": ".test4",
        "get": "count",
        "equals": 2
      }
    },
    {
      "description": "Test 4 has been dispatched",
      "definition": {
        "waitForEvent": "ud-test",
        "exists": true
      },
      "flags": {
        "noRepeat": true
      }
    }
  ]
}]

Note that the feedback JSON must be an array of objects

  • "name": the name of the suite. The word "Test" or "Tests" gets appended when this name shows up in the widget as a heading for its child tests.
  • "code": a message to display when all tests in the suite pass. Why is it called a code? It's sometimes the code I make students copy and paste into a quiz on the Udacity site to prove they finished the quiz.
  • "tests": an array of test objects
    • "description": shows up in the test widget. Try to keep titles short, as long titles don't wrap well in the current version.
    • "definition": an object with collector and reporter properties. More on this below.
    • "flags": optional flags to alter the way a test is run. The most common is noRepeat, which ensures that a test runs only once rather than repeatedly.

How to write a "definition"

Think about this sentence as you write tests:

I want the nodes of [selector] to have [some property] that [compares to some value].

1) Start with "nodes". Most* tests against the DOM need some nodes to examine. This is the start of a "collector".

"definition": {
  "nodes": "selector",
  ...
}

*Exceptions: collecting a user-agent string, device pixel ratio, or in conjunction with "waitForEvent".

2) Decide what value you want to collect and test.

CSS:

"definition": {
  "nodes": ".anything"
  "cssProperty": "backgroundColor",
  ...
}

The "cssProperty" can be the camelCase version of any CSS property. "cssProperty" takes advantage of window.getComputedStyle().

  • Colors will be returned in the form of "rgb(255, 255, 255)". Note the spaces.
  • All width, margin, etc measurements are returned as pixel values, not percentages.

Attribute:

"definition": {
  "nodes": "input"
  "attribute": "for",
  ...
}

Any attribute works.

Absolute Position:

"definition": {
  "nodes": ".left-nav"
  "absolutePosition": "side",
  ...
}

Side must be one of: top, left, bottom, or right. Currently, the position returned is relative to the viewport.

Count, innerHTML, ChildPosition, UAString (user-agent string), DPR (device pixel ratio):

"definition": {
  "nodes": ".box"
  "get": "count",
  ...
}

These tests ("count", "innerHTML", "childPositions", "UAString", "DPR") use "get" and they are the only tests that use "get". Remember the asterix from earlier about the necessity of "nodes"? Device pixel ratios and user-agent strings are exceptions - you can "get": "UAString" or "get": "DPR" without "nodes".

"Child position? I haven't seen anything about children." - a question you might be asking yourself. Let me answer it.

Children

"definition": {
  "nodes": ".flex-container",
  "children": "div",
  "absolutePosition": "side",
  ...
}

"children" is a deep children selector.

In this example, it was used to select all the divs inside a flex container. Now, reporters will run tests against all of the child divs, not the parent flex container.

3) Decide how you want to grade the values you just collected. This is a "reporter".

Equals

"definition": {
  "nodes": ".flex",
  "get": "count",
  "equals": 4
}

or

"definition": {
  "nodes": "input.billing-address",
  "attribute": "for",
  "equals": "billing-address"
}

or

"definition": {
  "nodes": ".inline",
  "cssProperty": "display",
  "equals": [
    "inline",
    "inline-block"
  ]
}

Set the "equals" value to a string, a number, or an array of strings and numbers.

This test looks for a strict equality match of either the value or one of the values in the array. In the first example, the test passes when the count of nodes returned by the selector equals four. In the second, the for attribute of <input class="billing-address"> must be set to "billing-address". In the third example, the test passes if display is either inline or inline-block.

If you want to compare strings and would prefer to use regex, try "hasSubstring".

Exists

"definition": {
  "nodes": "input.billing-address",
  "attribute": "for",
  "exists": true
}

In this example, rather than looking for a specific for, I'm just checking to see that it exists at all. The value doesn't matter. If "exists": false, then the test will only pass if the attribute does not exist.

Comparison

"definition": {
  "nodes": ".flex",
  "get": "count",
  "isLessThan": 4
}

"isLessThan" and "isGreaterThan" share identical behavior.

  "definition": {
    "nodes": ".flex",
    "get": "count",
    "isInRange": {
      "lower": 4,
      "upper": 10
    }
  }

Set an "upper" and a "lower" value for "isInRange".

Substrings

"definition": {
  "nodes": ".text",
  "get": "innerHTML",
  "hasSubstring": "([A-Z])\w+"
}

Run regex tests against strings with "hasSubstring". If one or more match groups are returned, the test passes.

NOTE: you must escape \s! eg. \wHello will break, but \\wHello will work.

You can pass an array to "hasSubstring" if you want to match one regex out of many.

"definition": {
  "nodes": ".text",
  "get": "innerHTML",
  "hasSubstring": ["([A-Z])\w+", "([a-z])\w+"]
}

There is an alternate syntax with optional configs for "hasSubstring".

"definition": {
  "nodes": ".text",
  "get": "innerHTML",
  "hasSubstring": {
    "expected": [
      "([A-Z])\\w+",
      "$another^"
    ],
    "minValues": 1,
    "maxValues": 2
  }
}

This test checks that either one or both of the expected values are found.

If you set "hasSubstring" to an object with an array of "expected" regexes, you can optionally use "minValues" and "maxValues" to determine how many of the expected values need to match in order for the test to pass. Unless otherwise specified, only one value from the "expected" array will need to be matched in order for the test to pass.

Utility Properties - not, limit

"definition": {
  "nodes": ".text",
  "get": "innerHTML",
  "not": true,
  "hasSubstring": "([A-Z])\\w+"
}

Switch behavior with "not". A failing test will now pass and vice versa.

"definition": {
  "nodes": ".title",
  "cssProperty": "marginTop",
  "limit": 1,
  "equals": 10
}

Currently, the values supported by "limit" are any number >= 1, "all" (default), and "some".

Remember, by default every node collected by "nodes" or "children" must pass the test specified. To change that, use "limit". If it is any number, 0 < numberCorrect <= limit values must pass in order for the test to pass. If more than one value passes, the test fails. In the case of "some", one or more values must pass in order for the test to pass.

Flags

"definition": {
  "nodes": ".small",
  "cssProperty": "borderLeft",
  "equals": 10
},
"flags": {
  "noRepeat": true
}

Options here currently include "noRepeat" and "alwaysRun".

By default, a test runs every 1000ms until it either passes or encounters an error. If "noRepeat" is set, the test only runs once when the widget loads and does not rerun every 1000ms. If "alwaysRun", the test continues to run even after it passes.

### JavaScript Tests

"definition": {
  "waitForEvent": "custom-event",
  "exists": true
}

For security reasons, you can only run JavaScript tests against pages that you control. You can trigger tests by dispatching custom events from inside your application or from a script linked in the unit-tests attribute of the meta tag. Set "waitForEvent" to a custom event. As soon as the custom event is detected, the test passes.

Example of a custom event:

window.dispatchEvent(new CustomEvent('ud-test', {'detail': 'passed'}));

I like to use the jsgrader library for writing JS tests because it supports grading checkpoints (logic to say "stop grading if this test fails"). You can use it too by setting libraries="jsgrader" in the meta tag.].

Test States and Debugging

wrong answer, right answer, error

Green tests with ✓ have passed, red tests with ✗ have failed and yellow tests with ?? have some kind of error. If there is an error, run UdacityFEGradingEngine.debug(); from the console to see why the yellow tests are erring.

You can find an options page in chrome://extensions. Use the options page to see and modify the list of domains on which the extension will run.

How Udacity Feedback Works

At the core of Udacity Feedback is the grading engine. The grading engine performs two tasks: collecting information from the DOM and reporting on it. Each test creates its own instance of the grading engine which queries the DOM once a second (unless otherwise specified).

Overview of the source code:

  • TA (Teaching Assistant). The TA orchestrates the DOM querying and comparison logic of the grading engine. There is a collection aspect (src/js/TACollectors.js) and a reporting aspect (src/js/TAReporters.js). Collectors pull info from the DOM. Reporters are responsible for the logic of evaluating the information. The TA executes tests as a series of async methods pulled from a Queue.
  • Gradebook. Every TA has an instance of a Gradebook, which determines the pass/fail state of a test. Some tests have multiple parts (eg. examining every element of some class to ensure that all have a blue background - each element is a part of the test). The Gradebook compares the parts to the comparison functions as set by the TA and decides if the test has passed or failed.
  • Target. A Target represents a single piece of information pulled from the DOM. Almost every Target has an associated element and some value. Targets may include child Targets. Tests that result in multiple pieces of information create a tree of Targets (sometimes called a 'Bullseye' in comments).
  • Suite and ActiveTest. An individual test (ie. one line in the widget) is an instance of an ActiveTest. ActiveTests are organized into Suites. Each Suite comes with its own name, which is displayed above its set of tests in the widget.
  • Registrar. This file contains the logic for creating new tests when the Feedback is turned on and removing tests when the Feedback is turned off.
  • The <test-widget> and everything inside of it were built as custom elements with HTML imports.

Development Workflow

  1. Run gulp watch from /
  2. Make changes.
  3. Open /sample/index.html to run regression testing.
  4. If you're adding a new feature:
  • Add new passing and failing tests to /sample/tests.json (and modify /sample/index.html if necessary).
  • Update this README to reflect changes (include examples!).
  1. Submit a pull request!

Did you read this far? You're awesome :)

Archival Note

This repository is deprecated; therefore, we are going to archive it. However, learners will be able to fork it to their personal Github account but cannot submit PRs to this repository. If you have any issues or suggestions to make, feel free to:

frontend-grading-engine's People

Contributors

cameronwp avatar notetiene avatar sudkul avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

frontend-grading-engine's Issues

warn students that zooming their browsers will affect test results

I've seen some complaints that zooming prevents tests from passing, especially when tests are related to any kind of pixel calculation. Let's consider adding a feature where we warn students to stay at 100% zoom so that tests pass.

The alternative is to actually account for zoom with pixel calculations. My intuition is that this is more trouble than its worth, but I could be wrong.

Firefox: Lesson 3.5 Udacity Feedback Not Working

The linked JSON page isn’t at the same origin and directory as the document.

I was searching all over the place for an answer. I'm running 57.0.4 (64-bit).

Instead of automatically working, what you have to do is:

  1. Navigate to http://udacity.github.io/fend/fend-refresh/lesson2/problem-set/headers/tests.json
  2. Click save
  3. Save to the directory in the same folder as index.html
  4. Using your text editor, for the meta tag named udacity-grader, change the content value to tests.json
  5. The grader should now work!

It should not be this cumbersome, but if this is the way it was intended, please include a tutorial!

Lesson 3 - Make all the headers

Hi everybody :) I am very new to all of this and I am stuck with this lesson 3 - make all the headers as I don't understand where I can put my practice code for h1-h4. I've downloaded the Udacity Feedback extension and the Headers file but I am not sure where to get a necessary code to finish a test?
capture

Udacity Feedback Extension not working on Firefox

On Firefox, there is a problem getting a code for solving Project 2, part 2 (Lesson 8.14) and Lesson 9.10 (quiz). It works in Chrome but when running the Udacity Feedback Extension in Firefox, I get this error in red: The linked JSON page isn’t at the same origin and directory as the document. If you look at the ratings of the Udacity extension on Firefox, apparently this has been an issue for a while.

suddenly not working

The extension was working for me two days ago and now it wont work. I've followed the instructions same as I did the first time, but it still wont work.

Turn Feedback On

In Quiz 5, Make All the Headers, I don't know how to turn the feedback on when I load my website. I created the code and see the language. Please provide solutions.

Udacity Feedback: Tree to HTML Quiz Test Results

For such a simple quiz, I am unable to pass/understand this quiz's requirements. I've tried saving in different formats, recreating the files, and even using different IDEs. Am I missing something here?

My code:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Tree to HTML</title>
  <!-- the next line loads the tests for the Udacity Feedback extension -->
  <meta name="udacity-grader" content="http://udacity.github.io/fend/fend-refresh/lesson2/problem-set/tree-to-html/tests.json">
</head>
<body>
  <h1>This is my header</h1>
    <div
      <p>Here is my first paragraph.</p>
      <p>Here is my second paragraph.</p>
    </div>
</body>
</html>

The error reported:
X Paragraphs have content

Criteria code:

"description": "Paragraphs have content",
      "definition": {
        "nodes": "p",
        "get": "innerHTML",
        "hasSubstring": ".+"

hi

I need help

getting shorthand or used value css property may result in a test failing

When using the window.getComputedStyle method to get a CSS value, it may not return the actual value. Depending on the browser implementation, the browser can return an empty String or a deliberately wrong value (for security in that case).

As an example, getting the padding shorthand CSS property in Firefox will fail because it complies to the CSS specifications (surprisingly Chrome doesn't).

It might be worth complying to the various browser implementations. See https://developer.mozilla.org/en-US/docs/Web/CSS/used_value#Difference_from_computed_values

loading JSON with file input not working

Loading a JSON local file from the file input doesn't seem to work. It should work even when a website is not whitelisted to allow testing arbitrary websites. Otherwise, someone would always see the widget (with "No tests loaded") when browsing on the website.

Support Add-on SDK

We need to support the 2 last versions of a Web Browser. Since Firefox is planning to fully support WebExtensions in 2 years, we need to use the Add-on SDK as a fallback/temporary solution.

No Feedback Code

The extension is not providing me a code to paste into the classroom, anyone else encounter this too?

Why are source files placed in two places?

In the repository, there are two places where source files are placed:

  • src/
  • ext/src/

Given that we use a building tool, shouldn't we use only one directory to make the extension? It's much easier to maintain.

Udacity feedback icon

Udacuty feedback icon has disappeared form my desktop. How can I pin it back? trying to reinstall it's showing it is installed.

Oversized Main Div

On the chrome extension, the main div for the popup is bigger than the body, creating an ugly scroll bar. See the screenshot:

screenshot

I can help fix this with a quick patch if there's no particular reason why the div width should be fixed at 800px!

Font sizing is affected by body

Noticed by @jamesparkes: if you set font-size for the body, it also affects the font-size of the text in the feedback widget. it might be worth giving the text in the widget some default styling

implement em, rem, % units

Given that:

  • Getting a CSS property using the window.getComputedStyle method will only give sizes as pixel unit.
  • Quizzes will ask for a relative unit size.
  • Browser/OS styles will vary and may result in a different absolute unit.

We should implement a function to calculate the computed value in different units.

Udacity Feedback Extension not recognize font awesome icon

Hi team, thanks for providing Responsive Images as a good course for me. It's a good thing that web developer should care about images, typography when develop website. When I'm using fontawesome to get facebook, twitter, google+, and digg, the Udacity feedback extension doesn't respons it (I have refresh it several times in Google Chrome browser). This is the screenshot:

responsive images feedback course

This is the Gist Code

But, when I see your project-2 solution, it use the We Love Font Icons website as the provider font icon. Why only this website can recognized by Udacity feedback extension? I think it should be fix it, so that's not only We Love Font Icons but Font awesome and other font icons website can recognized by Udacity feedback extension. Thank you very much.

P.S. I have give this issue on responsive-images repository. I give this issue on this repo to get your fast response answer.

Udacity feedback: FEWD Google Challenge Lesson 3: HTML Syntax Problem Set Make a List Solution is Incorrect

The instructions ask for an unordered list but the solution shows an ordered list.

Instructions
I want you to: (Look! Another unordered list!) Add an unordered list element with three child elements (one each for HTML, CSS, and JavaScript).

Correct answer
`

Create an unordered list! Make a list of the three web languages: HTML, CSS and JavaScript.

  • HTML
  • CSS
  • JavaScript
`

Provided solution
`

Any time you see a sequence of similar objects in a web site, it's probably a list. That goes for lists of articles on your favorite news app as well as things like videos on YouTube or Netflix.

  1. HTML
  2. CSS
  3. JavaScript
`

Thank you!

Not able to download Json

I am not able download a json file. When I save a file in atom it saves as an HTML and wont let me save as json to use the udacity feedback tool. I am missing something?

make the Safari wrapper a library

To increase modularity and its functionalities, it might be interesting to make a library out of the Safari wrapper. From my knowledge, it's the most complete WebExtensions wrapper for Safari available.

We could also make it a NPM task that will inject the needed functionalities of an extension to work on Safari.

add a last child selector

On tests that need to select the last child element, a fixed children number is usually used. If someone adds an element before the last child, it may mark the test as incorrect.

index.html problem loading into Chrome

Hi, I was able to open "index.html" without any problem two days ago. Now, when I try to open it in Chrome it opens a window that converts pdf and docs!?! wtf? Anyone know what could be the issue?

Not working for FEND 13.6

I was just working in a prior lesson and the Udacity Feedback extension / grader was working. Got to this lesson, opened the link, and no extension. (The extension icon is in my Chrome browser.) The page loads, but the grader never loads.

Failed to load GE.js

While the build process works fine generating the Grading Engine (GE.js), its path is not correct. That's what I get:

chrome-extension://keffdhbdajnlclhjikaagcmkcbmfmojm/app/js/libs/GE.js Failed to load resource: net::ERR_FILE_NOT_FOUND

gejs_not_found

kitten

.kitten-image{
        border: 5px dashed #fa8072;
        border-radius: 5px;
        box-shadow: 5px 5px 20px rgb(204,204,204);
        cursor: pointer;

Set the test-widget (iframe) height according to its content height

Using an iFrame instead of WebComponents for the test-widget introduced an unexpected behaviour, namely:

  • The Height of the test-widget window can only be fixed. It can't grow as content is added in the iFrame. The workaround I found is to calculate the iFrame window's height and pass it to the test-widget container. However, it doesn't seem to work when listening for DOMContentLoaded because when an iFrame is created, it also create a dummy document. It may be possible to emulate that event with a MutationListener.

add warning in Chrome when using `file://`

Previously, there was a warning in Chrome about using the extension with the file:// scheme. Chrome doesn't support loading files from that scheme using XMLHttpRequest. Also, since the file input doesn't work anymore ( #21 ), it was a noisy warning I decided to remove.

Actually there may be a workaround by using the filesystem API, but injecting it might be much more complicated.

emit event when a test passes

I'm getting requests for insight into when tests pass. We want to build sites that are also able react to tests passing (eg. changing text color, CSS, to give additional indication that tests pass). Let's add a defined test and suite pass event API.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.