Testing that URL strings are correct

#1

Hey everyone, I’m working on an application where we include links to external, public, non-Elm pages (documentation, company website, etc.), and I would like to test that these URLs are correct. For example, maybe some item in the documentation is renamed, causing a change to the URL, and I want to know the link I am including in my application is now dead.

The simplest setup I can think of is an integration test that just requests the page and tests that it gets HTTP 200 back (potential for flakyness if external pages are down not withstanding). Is there any way to accomplish something like this in Elm at the moment? It seems to me that elm-test is only for isolated tests, so to make such a test, I would have to start up a full Elm application, which can then report the results back. But can I do so in e.g. a Node binary that can be run as part of a test setup?

#2

To my knowledge, testing commands is not yet part of elm-test. This means that you cannot test http calls (you would require an http call to check if the link returns valid response).

You can however extract the links into a resource record and test that outside of Elm. So you could have some externalLinks record field in the Flags you pass to Elm and test the validity of that record using JS.

#3

I ended up doing the opposite of this actually, keeping the URLs in Elm instead. I then created a new test Elm project next to the existing project, which imports the urls from the existing project (Elm 0.19 if anyone is interested).

In my test project elm.json, I add the source of the real project ala

"source-directories": [
    "src",
    "../path/to/real/elm"
]

And then I have my UrlList.elm file:

port module UrlList exposing (main)

import Urls exposing (url1, url2)
import Platform exposing (worker)


port fromElm : List String -> Cmd msg


main =
    let
        urls =
            [ url1
            , url2
            ]
    in
    worker
        { init = \() -> ( (), fromElm urls )
        , update = \() -> \() -> ( (), Cmd.none )
        , subscriptions = \_ -> Sub.none
        }

Which I compile to urlList.js and call from main.js:

const linkTest = require('./urlList');
const https = require('https');
const process = require('process');

let urlFailed = false;

const app = linkTest.Elm.UrlList.init();

app.ports.fromElm.subscribe(urls => {
    let responsesReturned = 0;

    urls.forEach(url => {
        https.get(url, (res) => {
            const statusCode = res.statusCode;
            if (statusCode >= 400 && statusCode < 500) {
                console.log("\"" + url + "\" had status code: " + statusCode);
                urlFailed = true;
            }

            responsesReturned += 1;
            if (responsesReturned === urls.length) {
                onAllResponsesGathered();
            }
        });
    });
});

function onAllResponsesGathered() {
    if (urlFailed) {
        process.exit(1);
    } else {
        process.exit(0);
    }
}

which I call with node main.js

closed #4

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.