github.com/simpleiot/simpleiot@v0.18.3/frontend/lib/test.mjs (about)

     1  import assert from "node:assert"
     2  import WebSocket from "ws"
     3  import { connect } from "./siot-nats.mjs"
     4  
     5  import { inspect } from "node:util"
     6  inspect.defaultOptions.depth = 10
     7  // Using the Mocha test framework: https://mochajs.org/
     8  
     9  // Tell eslint about the additional globals that will be used
    10  /* global global, it, describe, before */
    11  
    12  global.WebSocket = WebSocket
    13  let c, rootID, adminID
    14  
    15  it("connects", async () => {
    16  	c = await connect()
    17  })
    18  describe("simpleiot-js", () => {
    19  	// abort tests if connection failed
    20  	before(function () {
    21  		if (!c) {
    22  			this.skip()
    23  		}
    24  	})
    25  
    26  	it("gets root node", async () => {
    27  		const roots = await c.getNodeChildren("root")
    28  		assert.strictEqual(roots.length, 1, "should have 1 root")
    29  
    30  		// Check root node
    31  		const [root] = roots
    32  		assert.strictEqual(root.type, "device", "root type should be 'device'")
    33  		assert.strictEqual(root.parent, "root", "root parent should be 'root'")
    34  		assert.strictEqual(root.edgepointsList.length, 1, "should have 1 edgepoint")
    35  		const [tombstone] = root.edgepointsList
    36  		assert.strictEqual(tombstone.type, "tombstone", "should have tombstone")
    37  		assert.strictEqual(tombstone.tombstone, 0, "tombstone is 0")
    38  
    39  		rootID = root.id
    40  	})
    41  
    42  	it("gets root node by ID", async function () {
    43  		if (!rootID) {
    44  			return this.skip()
    45  		}
    46  
    47  		const roots = await c.getNode(rootID)
    48  		assert.strictEqual(roots.length, 1, "should have 1 root")
    49  
    50  		const [root] = roots
    51  		assert.strictEqual(root.id, rootID, "root id should match")
    52  		assert.strictEqual(root.type, "device", "root type should be 'device'")
    53  		assert.strictEqual(root.parent, "root", "parent should be root")
    54  		assert.strictEqual(
    55  			root.edgepointsList.length,
    56  			1,
    57  			"only tombstone edge point"
    58  		)
    59  		assert.strictEqual(
    60  			root.edgepointsList[0].type,
    61  			"tombstone",
    62  			"edge point should be tombstone"
    63  		)
    64  		assert.strictEqual(root.edgepointsList[0].value, 0, "tombstone should be 0")
    65  	})
    66  
    67  	it("gets nodes recursively", async () => {
    68  		const roots = await c.getNodeChildren("root", { recursive: true })
    69  		assert.strictEqual(roots.length, 1, "should have 1 root")
    70  
    71  		// Check root node
    72  		const [root] = roots
    73  		assert.strictEqual(root.children.length, 1, "root should have 1 child")
    74  		const [user] = root.children
    75  		assert.strictEqual(user.type, "user", "child node type should be 'user'")
    76  		assert.strictEqual(user.parent, root.id, "invalid parent")
    77  		const [tombstone] = root.edgepointsList
    78  		assert.strictEqual(tombstone.type, "tombstone", "should have tombstone")
    79  		assert.strictEqual(tombstone.tombstone, 0, "tombstone is 0")
    80  
    81  		// Check default points
    82  		const { text: first } = user.pointsList.find((p) => p.type === "firstName")
    83  		assert.strictEqual(
    84  			first,
    85  			"admin",
    86  			"firstName of admin user is not default value"
    87  		)
    88  		const { text: email } = user.pointsList.find((p) => p.type === "email")
    89  		assert.strictEqual(
    90  			email,
    91  			"admin",
    92  			"email of admin user is not default value"
    93  		)
    94  
    95  		adminID = user.id
    96  	})
    97  
    98  	it("publishes points for user name", async function () {
    99  		if (!adminID) {
   100  			return this.skip()
   101  		}
   102  		await c.sendNodePoints(
   103  			adminID,
   104  			[
   105  				{ type: "firstName", text: "John" },
   106  				{ type: "lastName", text: "Doe" },
   107  			],
   108  			{ ack: true }
   109  		)
   110  
   111  		// Get updated node
   112  		const [user] = await c.getNode(adminID)
   113  		const first = user.pointsList.find((p) => p.type === "firstName")
   114  		const last = user.pointsList.find((p) => p.type === "lastName")
   115  		assert.strictEqual(first.text, "John", "unchanged firstName " + first.text)
   116  		assert.strictEqual(last.text, "Doe", "unchanged lastName " + last.text)
   117  	})
   118  
   119  	const nodeID = "faux-sensor-1"
   120  	it("creates a device node", async function () {
   121  		if (!rootID) {
   122  			return this.skip()
   123  		}
   124  
   125  		// Create `nodeID`
   126  		await c.sendNodePoints(
   127  			nodeID,
   128  			[{ type: "description", text: nodeID + " (created by test suite)" }],
   129  			{ ack: true }
   130  		)
   131  		await c.sendEdgePoints(
   132  			nodeID,
   133  			rootID,
   134  			[{ type: "tombstone" }, { type: "nodeType", text: "device" }],
   135  			{
   136  				ack: true,
   137  			}
   138  		)
   139  	})
   140  
   141  	it("subscribes / publishes node points", async function () {
   142  		const ITERATIONS = 10
   143  		let temperature = 30
   144  		let humidity = 55
   145  		let pointsRx = 0
   146  
   147  		// Subscribe and start reading points asynchronously
   148  		const sub = c.subscribePoints(nodeID)
   149  		const readPromise = (async function readPoints() {
   150  			for await (const { points } of sub) {
   151  				points.forEach((p) => {
   152  					if (p.type === "temperature") {
   153  						assert.strictEqual(p.value, temperature)
   154  					} else if (p.type === "humidity") {
   155  						assert.strictEqual(p.value, humidity)
   156  					} else {
   157  						throw new Error("unknown point type: " + p.type)
   158  					}
   159  					pointsRx++
   160  				})
   161  			}
   162  		})()
   163  		// Note: Add no-op `catch` to avoid unhandled Promise rejection
   164  		readPromise.catch((err) => {})
   165  
   166  		// Send out node points
   167  		for (let i = 0; i < ITERATIONS; i++) {
   168  			await c.sendNodePoints(
   169  				nodeID,
   170  				[
   171  					{ type: "temperature", value: ++temperature },
   172  					{ type: "humidity", value: ++humidity },
   173  				],
   174  				{ ack: true }
   175  			)
   176  		}
   177  
   178  		// Close subscription and handle errors
   179  		await sub.close()
   180  		await readPromise
   181  
   182  		// Check to ensure we read all points
   183  		assert.strictEqual(
   184  			pointsRx,
   185  			ITERATIONS * 2,
   186  			"did not receive all published points"
   187  		)
   188  	})
   189  
   190  	it("closes", async () => {
   191  		await c.close()
   192  	})
   193  })