surrealdb / surrealdb.js

SurrealDB SDK for JavaScript
https://surrealdb.com
Apache License 2.0
289 stars 47 forks source link

test: add basic tests #20

Closed oberbeck closed 1 year ago

oberbeck commented 2 years ago

Currently we are heavily refactoring the codebase and brought together the deno/JS/NodeJS code base.

From here on it makes sense to add basic code coverage to assure nothing breaks with new changes.

Decisions to make:

mathe42 commented 2 years ago

I propose if #21 is merged this to make in deno with the deno test tools. Or something non runtime specific that works with deno,browser,node,bun.

oberbeck commented 2 years ago

Since we want to support all the runtimes, I think it makes sense to be able to run the tests in all of them.

mathe42 commented 2 years ago

Yes but:

Assuming all runtimes are equal with WebSockets (yes for node we nede ws but that is just a spec-compliant implementation). So if it works in Deno and all runtimes know if they use their nativ WebSocket or ws it works for all runtimes.

oberbeck commented 1 year ago

Yes but:

Assuming all runtimes are equal with WebSockets (yes for node we nede ws but that is just a spec-compliant implementation). So if it works in Deno and all runtimes know if they use their nativ WebSocket or ws it works for all runtimes.

Do you still think so, especially after looking at eg: https://github.com/surrealdb/surrealdb.js/pull/29/files#diff-bee239710d6adb6ea30da43de12674e14478bb6907e5e1b2d447e12c7bcae81cL2

mathe42 commented 1 year ago

Yes for unit test this doesn't change anything. But you might want to add type tests with different targets.

mathe42 commented 1 year ago

I would propose to add a build - test for now...

mathe42 commented 1 year ago

see #31

mathe42 commented 1 year ago

Maybe an e2e test is a good idea:

Create a JS file of form:

export default (client) => {
  // ...
}

That does a lot of client requests etc.

Than have an entry file for node, deno, bun that uses that file.

The test would be as follows:

  1. Setup Node + Deno + Bun
  2. Build dist folder
  3. Start SurrealDB in a Docker-Container (specific version)
  4. run deno script
  5. export DB into file and compare that with a snapshot of that file (filecontents the same = test passed)
  6. restart DB (and reset it)
  7. Same for Node and Bun
oberbeck commented 1 year ago
  1. Setup Node + Deno + Bun

Maybe we could put this already in a container?

  1. run deno script

What kind of script are you thinking about?

  1. export DB into file and compare that with a snapshot of that file (filecontents the same = test passed)

Why not use the lib itself to read from the DB?

mathe42 commented 1 year ago

Maybe we could put this already in a container?

This are a few lines in the github action no need for a container setup

What kind of script are you thinking about?

A lot of stuff where you use all of the methods etc. Same script for Deno, Bun, Node just different import.

Why not use the lib itself to read from the DB?

With a complete DB dump we can check that Node, Deno, Bun all leave the DB in the exact same state.

oberbeck commented 1 year ago

sounds good! I can have a look into it, or are you already on it?

mathe42 commented 1 year ago

@oberbeck maybe you can create the script (for Node that we can then adopt for Deno + Bun) and I create the github action etc as I have some experience with that...

oberbeck commented 1 year ago

@oberbeck maybe you can create the script (for Node that we can then adopt for Deno + Bun) and I create the github action etc as I have some experience with that...

just to be clear, we are talking about the implementation of https://github.com/surrealdb/surrealdb.js/blob/bb7615506683ab5ae855a63e94faa86b2d3045bf/test/e2e/shared.js#L1-L6 correct?

oberbeck commented 1 year ago

On first sight, this sounds like a nice strategy. However, it seems comparing the exports is not trivial at the moment. SurrealDB uses random IDs which differs between equal runs.

The following is the dump of the Example queries:

Deno Run 1

UPDATE person:1wdyu3v8ffeir1gd0zyf CONTENT { id: person:1wdyu3v8ffeir1gd0zyf, identifier: "kpcn1um31u", marketing: true, name: { first: "Tobie", last: "Morgan Hitchcock" }, title: "Founder & CEO" };
UPDATE person:jaime CONTENT { id: person:jaime, marketing: true };

Deno Run 2

UPDATE person:hgc8ostw76u4lwmgts6j CONTENT { id: person:hgc8ostw76u4lwmgts6j, identifier: "gcg7m7m4yo", marketing: true, name: { first: "Tobie", last: "Morgan Hitchcock" }, title: "Founder & CEO" };
UPDATE person:jaime CONTENT { id: person:jaime, marketing: true };
mathe42 commented 1 year ago

Maybe our snapshot can have $ID$ where a random ID is included (we know the length so the check code would be simple)...

oberbeck commented 1 year ago

Further, an interesting catch is when run with NodeJs I receive the following output (note the different order of the create/update operations):

NodeJs Run 1

UPDATE person:jaime CONTENT { id: person:jaime, marketing: true };
UPDATE person:t5jjg7km7sn3lz34m9zy CONTENT { id: person:t5jjg7km7sn3lz34m9zy, identifier: "gf7g10bx15", marketing: true, name: { first: "Tobie", last: "Morgan Hitchcock" }, title: "Founder & CEO" };

NodeJs Run 2

UPDATE person:jaime CONTENT { id: person:jaime, marketing: true };
UPDATE person:mj8r279mrcq3jf5w2hly CONTENT { id: person:mj8r279mrcq3jf5w2hly, identifier: "x6olzyy85a", marketing: true, name: { first: "Tobie", last: "Morgan Hitchcock" }, title: "Founder & CEO" };
mathe42 commented 1 year ago

Is it the same of you await each operation?

oberbeck commented 1 year ago

Is it the same of you await each operation?

yes, Im running the same script :D

/**
 * @type{(a: import('../../src/index.ts').default) => void}
 */
export default async (db) => {
    console.log("Signin as a namespace, database, or root user");
    await db.signin({
        user: "root",
        pass: "root",
    }).catch(e=>console.error(e));

    console.log("Select a specific namespace / database");
    await db.use("test", "test");

    console.log("Create a new person with a random id");
    let created = await db.create("person", {
        title: "Founder & CEO",
        name: {
            first: "Tobie",
            last: "Morgan Hitchcock",
        },
        marketing: true,
        identifier: Math.random().toString(36).substr(2, 10),
    });

    console.log("Update a person record with a specific id");
    let updated = await db.change("person:jaime", {
        marketing: true,
    });

    console.log("Select all people records");
    let people = await db.select("person");

    console.log("Perform a custom advanced query");
    let groups = await db.query(
        "SELECT marketing, count() FROM type::table($tb) GROUP BY marketing",
        {
            tb: "person",
        }
    );

    console.log("closing");
    await db.close();
};
oberbeck commented 1 year ago

OK, seems to be some kind of async/random issue:

Deno Run 3

UPDATE person:8zpm55qj2wfcad78c4kn CONTENT { id: person:8zpm55qj2wfcad78c4kn, identifier: "l1nvuhot6v", marketing: true, name: { first: "Tobie", last: "Morgan Hitchcock" }, title: "Founder & CEO" };
UPDATE person:jaime CONTENT { id: person:jaime, marketing: true };

NodeJs Run 3

UPDATE person:1dksegxcz2k0sf1h0moy CONTENT { id: person:1dksegxcz2k0sf1h0moy, identifier: "a0su3u2f1c", marketing: true, name: { first: "Tobie", last: "Morgan Hitchcock" }, title: "Founder & CEO" };
UPDATE person:jaime CONTENT { id: person:jaime, marketing: true };