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 ที่ละเอียดกว่านี้ผมมีตัวอย่าง ที่นี่