Unit test firebase rules with targaryen

Firebase Rules คือ?

มันคือการที่เรากำหนดสิทธิ์ ให้สามารถอ่านเขียนได้ตาม business logic ของเรา เช่น ถ้าเป็น app ที่เกี่ยวกับการ chat เราคงไม่อยากให้คนที่ไม่ได้อยู่ในห้องแชท มาส่งข้อความในห้องนั้นได้ หรือ ถ้าเป็น app จองห้องสมุด เราคงไม่อยากให้คนที่ไม่เคย login เข้าระบบเราทำการจองได้ สำหรับรายละเอียดเพิ่มเติมนั้นพี่ Jirawatee เขียนเรื่องนี้ไว้ดีมาก อ่านเพิ่มเติมได้ ที่นี่

ทำไมต้องใช้ targaryen

ปกติการ test firebase rules จะทำได้ค่อนข้างยาก ไม่เขียน rule ด้วย bolt ก็ต้องแก้ไฟล์ firebase.rules.json แล้วอัพโหลดไป simulate ที่ server ถ้าเราใช้ targaryen เราสามารถ unit test firebase rule ได้โดยที่ไม่ต้องเขียน bolt แล้วก็ไม่ต้องอัพโหลดไปที่ server ซึ่งสะดวกกว่ามากๆ

Setup Project

บทความนี้จะใช้ ava เป็น test runner นะ ซึ่ง targaryen ไม่มี plugin ให้ ava syntax ก็จะดูแปลก ๆ หน่อยนะครับ

เริ่มด้วยสร้างไฟล์ package.json ด้วย

{
"scripts": {
"test": "ava tests/*.test.js --verbose"
},
"devDependencies": {
"ava": "^0.24.0",
"targaryen": "^3.0.5"
}
}

แล้วรัน

npm install

จากนั้นสร้างไฟล์ simple.test.js ใน folder tests ด้วย

const test = require('ava')
const targaryen = require('targaryen')
const rules = {
rules: {
'.read': 'auth !== null',
'.write': 'auth !== null'
}
};
const data = {
message: {
0: {
text: 'hello'
}
}
}
const database = targaryen.database(rules, data)
test(`Anonymous user shouldn't be able to read/write `, t => {
t.is(database.read('/message').allowed, false)
t.is(database.write('/message', {1: {text: 'hey' }}).allowed, false)
})
test('Logged in user should be able to read/write', t => {
t.is(database.as({uid: 'someuid'}).read('/message').allowed, true)
t.is(database.as({uid: 'someuid'}).write('/message', {1: {text: 'hey' }}).allowed, true)
})

มาอธิบายโค้ดกัน

const rules = {
rules: {
'.read': 'auth !== null',
'.write': 'auth !== null'
}
};

rules จะเปรียบเป็น firebase.rules.json ตามปกติแล้วถ้าเป็นโปรเจคที่ใช้ firebase เราควรจะต้อง require มา

const database = targaryen.database(rules, data)

บรรทัดนี้จะเป็นการ create database จาก rules และ data ที่เรา set ไว้เพื่อจะได้เอาไป test write, read ทีหลัง ดูรายละเอียดเพิ่มเติมได้จาก ที่นี่

test(`Anonymous user shouldn't be able to read/write `, t => {
t.is(database.read('/message').allowed, false)
t.is(database.write('/message', {1: {text: 'hey' }}).allowed, false)
})

โค้ดชุดนี้จะเป็นการเริ่มเทส โดยผมคาดหวังว่าถ้าเป็น anonymous user จะไม่สามารถ อ่านหรือเขียนลง /message ได้

ถ้าอ่านตาม api ด้านบนจะเห็นว่า database.read(object) จะ return Result มา ซึ่งตัว Result เนี่ยเราจะสามารถใช้ property allowed ได้

test('Logged in user should be able to read/write', t => {
t.is(database.as({uid: 'someuid'}).read('/message').allowed, true)
t.is(database.as({uid: 'someuid'}).write('/message', {1: {text: 'hey' }}).allowed, true)
})

ต่อไปจะเป็นคำสั่ง database.as(object) คำสั่งนี้จะทำการ login ด้วย object ที่เราส่งไปซึ่งจะ return เป็น database ทำให้เราสามารถใช้ .read ได้

มาลอง run test กันด้วย

npm test

จะได้ผลลัพธ์ประมาณนี้

√ Anonymous user shouldn't be able to read/write
√ Logged in user should be able to read/write
2 tests passed

เบื้องต้นในการ test firebase rules ด้วย targayen ก็มีประมาณนี้แหละครับ สำหรับ case ที่ต้องการ rules ที่ละเอียดกว่านี้ผมมีตัวอย่าง ที่นี่

References

--

--

--

เรื่องเล่าประสบการณ์จากการคลุกคลานของทีมงานที่อยากจะเติบโตไปด้วยกัน

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
aunn

aunn

More from Medium

What are Hybrid/ Cross-platform applications?

Black lady talking on mobile phone and using a laptop

React Native and Flutter: A Detailed Comparison

Cache Web3 Events with Firebase CloudFunctions and Typescript

Passing data from one to another screen on Flutter