Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,37 @@ jobs:
- name: "Test Swift Package"
run: swift test --skip IntegrationTests

integration-tests:
name: Integration Tests (Linux)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: "Cache Swift Package"
uses: actions/cache@v5
with:
path: .build
key: ${{ runner.os }}-spm-integration-${{ hashFiles('**/Package.resolved') }}
restore-keys: |
${{ runner.os }}-spm-integration-
- name: "Setup Supabase CLI"
uses: supabase/setup-cli@v1
with:
version: latest
- name: "Start Supabase"
working-directory: Tests/IntegrationTests
run: supabase start
- name: "Reset Database"
working-directory: Tests/IntegrationTests
run: supabase db reset
- name: "Run Integration Tests"
env:
INTEGRATION_TESTS: 1
run: swift test --filter IntegrationTests
- name: "Stop Supabase"
working-directory: Tests/IntegrationTests
if: always()
run: supabase stop

# android:
# name: Android
# runs-on: ubuntu-latest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ final class PostgrestBasicTests: XCTestCase {
)

func testBasicSelectTable() async throws {
let response = try await client.from("users").select().execute().value as AnyJSON
let response = try await client.from("users").select("age_range,catchphrase,data,status,username").execute().value as AnyJSON
assertInlineSnapshot(of: response, as: .json) {
"""
[
Expand Down
7 changes: 4 additions & 3 deletions Tests/IntegrationTests/PostgrestIntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,11 @@ final class IntegrationTests: XCTestCase {
"INTEGRATION_TESTS not defined."
)

// Run fresh test by deleting all data. Delete without a where clause isn't supported, so have
// to do this `neq` trick to delete all data.
// Run fresh test by deleting test data. Delete without a where clause isn't supported, so have
// to do this `neq` trick to delete all data. For users, only delete rows with email (test data),
// leaving seed data with username intact.
try await client.from("todos").delete().neq("id", value: UUID().uuidString).execute()
try await client.from("users").delete().neq("id", value: UUID().uuidString).execute()
try await client.from("users").delete().not("email", operator: .is, value: AnyJSON.null).execute()
}

func testIntegration() async throws {
Expand Down
2 changes: 1 addition & 1 deletion Tests/IntegrationTests/supabase/.temp/cli-latest
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v2.22.12
v2.67.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
-- Create custom types
CREATE TYPE user_status AS ENUM ('ONLINE', 'OFFLINE');

-- Users table (supports both PostgrestIntegrationTests and PostgrestBasicTests)
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email TEXT,
username TEXT UNIQUE,
age_range int4range,
catchphrase TEXT,
data JSONB,
status user_status
);

-- Todos table
CREATE TABLE todos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
description TEXT NOT NULL,
is_complete BOOLEAN NOT NULL DEFAULT false,
tags TEXT[] DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);

-- Channels table
CREATE TABLE channels (
id SERIAL PRIMARY KEY,
slug TEXT NOT NULL
);

-- Messages table
CREATE TABLE messages (
id SERIAL PRIMARY KEY,
channel_id INTEGER REFERENCES channels(id),
data JSONB,
message TEXT,
username TEXT REFERENCES users(username)
);

-- Key-value storage table for Realtime tests
CREATE TABLE key_value_storage (
key TEXT PRIMARY KEY,
value JSONB
);

-- Create updatable view (for PostgrestBasicTests)
CREATE VIEW updatable_view AS
SELECT username, 1 AS non_updatable_column
FROM users
WHERE username IS NOT NULL;

-- RPC function to get status
CREATE OR REPLACE FUNCTION get_status(name_param TEXT)
RETURNS TEXT AS $$
BEGIN
RETURN (SELECT status::TEXT FROM users WHERE username = name_param);
END;
$$ LANGUAGE plpgsql;

-- RPC function that returns void
CREATE OR REPLACE FUNCTION void_func()
RETURNS VOID AS $$
BEGIN
-- Does nothing
END;
$$ LANGUAGE plpgsql;

-- RPC function to delete current user (for AuthClientIntegrationTests)
CREATE OR REPLACE FUNCTION delete_user()
RETURNS VOID AS $$
BEGIN
DELETE FROM auth.users WHERE id = auth.uid();
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- RPC function to get username and status (for PostgrestFilterTests)
CREATE OR REPLACE FUNCTION get_username_and_status(name_param TEXT)
RETURNS TABLE(username TEXT, status user_status) AS $$
BEGIN
RETURN QUERY SELECT u.username, u.status FROM users u WHERE u.username = name_param;
END;
$$ LANGUAGE plpgsql;

-- RPC function to get array element (for PostgrestTransformsTests)
CREATE OR REPLACE FUNCTION get_array_element(arr TEXT[], index INT)
RETURNS TEXT AS $$
BEGIN
RETURN arr[index];
END;
$$ LANGUAGE plpgsql;

-- Enable Row Level Security
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE todos ENABLE ROW LEVEL SECURITY;
ALTER TABLE messages ENABLE ROW LEVEL SECURITY;
ALTER TABLE channels ENABLE ROW LEVEL SECURITY;
ALTER TABLE key_value_storage ENABLE ROW LEVEL SECURITY;

-- Create permissive policies for testing (allow all operations)
CREATE POLICY "Allow all operations on users" ON users FOR ALL USING (true) WITH CHECK (true);
CREATE POLICY "Allow all operations on todos" ON todos FOR ALL USING (true) WITH CHECK (true);
CREATE POLICY "Allow all operations on messages" ON messages FOR ALL USING (true) WITH CHECK (true);
CREATE POLICY "Allow all operations on channels" ON channels FOR ALL USING (true) WITH CHECK (true);
CREATE POLICY "Allow all operations on key_value_storage" ON key_value_storage FOR ALL USING (true) WITH CHECK (true);

-- Enable realtime for key_value_storage table
ALTER PUBLICATION supabase_realtime ADD TABLE key_value_storage;
20 changes: 20 additions & 0 deletions Tests/IntegrationTests/supabase/seed.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
-- Seed data for users table (PostgrestBasicTests)
INSERT INTO users (username, age_range, catchphrase, data, status) VALUES
('supabot', '[1,2)', '''cat'' ''fat''', NULL, 'ONLINE'),
('kiwicopple', '[25,35)', '''bat'' ''cat''', NULL, 'OFFLINE'),
('awailas', '[25,35)', '''bat'' ''rat''', NULL, 'ONLINE'),
('dragarcia', '[20,30)', '''fat'' ''rat''', NULL, 'ONLINE');

-- Seed data for channels table
INSERT INTO channels (id, slug) VALUES
(1, 'public'),
(2, 'random');

-- Seed data for messages table
INSERT INTO messages (id, channel_id, data, message, username) VALUES
(1, 1, NULL, 'Hello World 👋', 'supabot'),
(2, 2, NULL, 'Perfection is attained, not when there is nothing more to add, but when there is nothing left to take away.', 'supabot');

-- Reset sequences to continue from seed data
SELECT setval('channels_id_seq', (SELECT MAX(id) FROM channels));
SELECT setval('messages_id_seq', (SELECT MAX(id) FROM messages));
Loading