summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/IndexedDB/name-scopes.html
blob: d92f706e0a7bc3f120c4fac5330d81dd6acb6ed6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<!doctype html>
<meta charset="utf-8">
<title>
  IndexedDB: scoping for database / object store / index names, and index keys
</title>
<link rel="help" href="https://w3c.github.io/IndexedDB/#constructs">
<link rel="author" href="pwnall@chromium.org" title="Victor Costan">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/support-promises.js"></script>
<script>
'use strict';

// Creates the structure inside a test database.
//
// The structure includes two stores with identical indexes and nearly-similar
// records. The records differ in the "path" attribute values, which are used to
// verify that IndexedDB returns the correct records when queried.
//
// databaseName appears redundant, but we don't want to rely on database.name.
const buildStores = (database, databaseName, useUniqueKeys) => {
  for (let storeName of ['x', 'y']) {
    const store = database.createObjectStore(
        storeName, { keyPath: 'pKey', autoIncrement: true });
    for (let indexName of ['x', 'y']) {
      store.createIndex(
          indexName, `${indexName}Key`, { unique: useUniqueKeys });
    }

    for (let xKeyRoot of ['x', 'y']) {
      for (let yKeyRoot of ['x', 'y']) {
        let xKey, yKey;
        if (useUniqueKeys) {
          xKey = `${xKeyRoot}${yKeyRoot}`;
          yKey = `${yKeyRoot}${xKeyRoot}`;
        } else {
          xKey = xKeyRoot;
          yKey = yKeyRoot;
        }
        const path = `${databaseName}-${storeName}-${xKeyRoot}-${yKeyRoot}`;
        store.put({ xKey: xKey, yKey: yKey, path: path });
      }
    }
  }
};

// Creates two databases with identical structures.
const buildDatabases = (testCase, useUniqueKeys) => {
  return createNamedDatabase(
      testCase, 'x', database => buildStores(database, 'x', useUniqueKeys))
      .then(database => database.close())
      .then(() => createNamedDatabase(
          testCase, 'y', database => buildStores(database, 'y', useUniqueKeys)))
      .then(database => database.close());
};

// Reads all the store's values using an index.
//
// Returns a Promise that resolves with an array of values.
const readIndex = (testCase, index) => {
  return new Promise((resolve, reject) => {
    const results = [];
    const request = index.openCursor(IDBKeyRange.bound('a', 'z'), 'next');
    request.onsuccess = () => {
      const cursor = request.result;
      if (cursor) {
        results.push(cursor.value);
        cursor.continue();
      } else {
        resolve(results);
      }
    }
  });
}

// Verifies that a database contains the expected records.
const checkDatabaseContent =
    (testCase, database, databaseName, usedUniqueKeys) => {
  const promises = [];
  const transaction = database.transaction(['x', 'y'], 'readonly');
  for (let storeName of ['x', 'y']) {
    const store = transaction.objectStore(storeName);
    for (let indexName of ['x', 'y']) {
      const index = store.index(indexName);

      const promise = readIndex(testCase, index).then((results) => {
        assert_array_equals(
            results.map(result => `${result.path}:${result.pKey}`).sort(),
            [`${databaseName}-${storeName}-x-x:1`,
             `${databaseName}-${storeName}-x-y:2`,
             `${databaseName}-${storeName}-y-x:3`,
             `${databaseName}-${storeName}-y-y:4`],
            'The results should include all records put into the store');

        let expectedKeys = (usedUniqueKeys) ?
            ['xx:xx', 'xy:yx', 'yx:xy', 'yy:yy'] : ['x:x', 'x:y', 'y:x', 'y:y'];
        assert_array_equals(
            results.map(result => `${result.xKey}:${result.yKey}`).sort(),
            expectedKeys,
            'The results should include all the index keys put in the store');

        assert_array_equals(
            results.map(result => result[`${indexName}Key`]),
            results.map(result => result[`${indexName}Key`]).sort(),
            'The results should be sorted by the index key');
      });
      promises.push(promise);
    }
  }

  return Promise.all(promises).then(() => database);
}

promise_test(testCase => {
  return buildDatabases(testCase, false)
      .then(() => openNamedDatabase(testCase, 'x', 1))
      .then(database => checkDatabaseContent(testCase, database, 'x', false))
      .then(database => database.close())
      .then(() => openNamedDatabase(testCase, 'y', 1))
      .then(database => checkDatabaseContent(testCase, database, 'y', false))
      .then(database => database.close());
}, 'Non-unique index keys');

promise_test(testCase => {
  return buildDatabases(testCase, true)
      .then(() => openNamedDatabase(testCase, 'x', 1))
      .then(database => checkDatabaseContent(testCase, database, 'x', true))
      .then(database => database.close())
      .then(() => openNamedDatabase(testCase, 'y', 1))
      .then(database => checkDatabaseContent(testCase, database, 'y', true))
      .then(database => database.close());
}, 'Unique index keys');

</script>