mirror of
https://github.com/microsoft/playwright.git
synced 2025-06-26 21:40:17 +00:00
fix(store): support text and binary values (#21006)
This commit is contained in:
parent
d12d35f124
commit
60e5a93832
@ -14,6 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export function isJsonMimeType(mimeType: string) {
|
||||
return !!mimeType.match(/^(application\/json|application\/.*?\+json|text\/(x-)?json)(;\s*charset=.*)?$/);
|
||||
}
|
||||
|
||||
export function isTextualMimeType(mimeType: string) {
|
||||
return !!mimeType.match(/^(text\/.*?|application\/(json|(x-)?javascript|xml.*?|ecmascript|graphql|x-www-form-urlencoded)|image\/svg(\+xml)?|application\/.*?(\+json|\+xml))(;\s*charset=.*)?$/);
|
||||
}
|
||||
@ -18,6 +18,8 @@ import fs from 'fs';
|
||||
import path from 'path';
|
||||
import type { TestStore } from '../types/test';
|
||||
import { currentConfig } from './common/globals';
|
||||
import { mime } from 'playwright-core/lib/utilsBundle';
|
||||
import { isJsonMimeType, isString, isTextualMimeType } from 'playwright-core/lib/utils';
|
||||
|
||||
class JsonStore implements TestStore {
|
||||
async delete(name: string) {
|
||||
@ -28,8 +30,13 @@ class JsonStore implements TestStore {
|
||||
async get<T>(name: string) {
|
||||
const file = this.path(name);
|
||||
try {
|
||||
const data = await fs.promises.readFile(file, 'utf-8');
|
||||
return JSON.parse(data) as T;
|
||||
const type = contentType(name);
|
||||
if (type === 'binary')
|
||||
return await fs.promises.readFile(file) as T;
|
||||
const text = await fs.promises.readFile(file, 'utf-8');
|
||||
if (type === 'json')
|
||||
return JSON.parse(text) as T;
|
||||
return text as T;
|
||||
} catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
@ -52,10 +59,39 @@ class JsonStore implements TestStore {
|
||||
await fs.promises.rm(file, { force: true });
|
||||
return;
|
||||
}
|
||||
const data = JSON.stringify(value, undefined, 2);
|
||||
let data: string | Buffer = '';
|
||||
switch (contentType(name)) {
|
||||
case 'json': {
|
||||
if (Buffer.isBuffer(value))
|
||||
throw new Error('JSON value must be an Object');
|
||||
data = JSON.stringify(value, undefined, 2);
|
||||
break;
|
||||
}
|
||||
case 'text': {
|
||||
if (!isString(value))
|
||||
throw new Error('Textual value must be a string');
|
||||
data = value as string;
|
||||
break;
|
||||
}
|
||||
case 'binary': {
|
||||
if (!Buffer.isBuffer(value))
|
||||
throw new Error('Binary value must be a Buffer');
|
||||
data = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
await fs.promises.mkdir(path.dirname(file), { recursive: true });
|
||||
await fs.promises.writeFile(file, data);
|
||||
}
|
||||
}
|
||||
|
||||
function contentType(name: string): 'json'|'text'|'binary' {
|
||||
const mimeType = mime.getType(path.basename(name)) ?? 'application/octet-string';
|
||||
if (isJsonMimeType(mimeType))
|
||||
return 'json';
|
||||
if (isTextualMimeType(mimeType))
|
||||
return 'text';
|
||||
return 'binary';
|
||||
}
|
||||
|
||||
export const store = new JsonStore();
|
||||
|
||||
@ -27,15 +27,15 @@ test('should provide store fixture', async ({ runInlineTest }) => {
|
||||
import { test, store, expect } from '@playwright/test';
|
||||
test('should store number', async ({ }) => {
|
||||
expect(store).toBeTruthy();
|
||||
expect(await store.get('number')).toBe(undefined);
|
||||
await store.set('number', 2022)
|
||||
expect(await store.get('number')).toBe(2022);
|
||||
expect(await store.get('number.json')).toBe(undefined);
|
||||
await store.set('number.json', 2022)
|
||||
expect(await store.get('number.json')).toBe(2022);
|
||||
});
|
||||
test('should store object', async ({ }) => {
|
||||
expect(store).toBeTruthy();
|
||||
expect(await store.get('object')).toBe(undefined);
|
||||
await store.set('object', { 'a': 2022 })
|
||||
expect(await store.get('object')).toEqual({ 'a': 2022 });
|
||||
expect(await store.get('object.json')).toBe(undefined);
|
||||
await store.set('object.json', { 'a': 2022 })
|
||||
expect(await store.get('object.json')).toEqual({ 'a': 2022 });
|
||||
});
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
@ -63,27 +63,27 @@ test('should share store state between project setup and tests', async ({ runInl
|
||||
'store.setup.ts': `
|
||||
import { test, store, expect } from '@playwright/test';
|
||||
test('should initialize store', async ({ }) => {
|
||||
expect(await store.get('number')).toBe(undefined);
|
||||
await store.set('number', 2022)
|
||||
expect(await store.get('number')).toBe(2022);
|
||||
expect(await store.get('number.json')).toBe(undefined);
|
||||
await store.set('number.json', 2022)
|
||||
expect(await store.get('number.json')).toBe(2022);
|
||||
|
||||
expect(await store.get('object')).toBe(undefined);
|
||||
await store.set('object', { 'a': 2022 })
|
||||
expect(await store.get('object')).toEqual({ 'a': 2022 });
|
||||
expect(await store.get('object.json')).toBe(undefined);
|
||||
await store.set('object.json', { 'a': 2022 })
|
||||
expect(await store.get('object.json')).toEqual({ 'a': 2022 });
|
||||
});
|
||||
`,
|
||||
'a.test.ts': `
|
||||
import { test, store, expect } from '@playwright/test';
|
||||
test('should get data from setup', async ({ }) => {
|
||||
expect(await store.get('number')).toBe(2022);
|
||||
expect(await store.get('object')).toEqual({ 'a': 2022 });
|
||||
expect(await store.get('number.json')).toBe(2022);
|
||||
expect(await store.get('object.json')).toEqual({ 'a': 2022 });
|
||||
});
|
||||
`,
|
||||
'b.test.ts': `
|
||||
import { test, store, expect } from '@playwright/test';
|
||||
test('should get data from setup', async ({ }) => {
|
||||
expect(await store.get('number')).toBe(2022);
|
||||
expect(await store.get('object')).toEqual({ 'a': 2022 });
|
||||
expect(await store.get('number.json')).toBe(2022);
|
||||
expect(await store.get('object.json')).toEqual({ 'a': 2022 });
|
||||
});
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
@ -99,17 +99,17 @@ test('should persist store state between project runs', async ({ runInlineTest }
|
||||
'a.test.ts': `
|
||||
import { test, store, expect } from '@playwright/test';
|
||||
test('should have no data on first run', async ({ }) => {
|
||||
expect(await store.get('number')).toBe(undefined);
|
||||
await store.set('number', 2022)
|
||||
expect(await store.get('object')).toBe(undefined);
|
||||
await store.set('object', { 'a': 2022 })
|
||||
expect(await store.get('number.json')).toBe(undefined);
|
||||
await store.set('number.json', 2022)
|
||||
expect(await store.get('object.json')).toBe(undefined);
|
||||
await store.set('object.json', { 'a': 2022 })
|
||||
});
|
||||
`,
|
||||
'b.test.ts': `
|
||||
import { test, store, expect } from '@playwright/test';
|
||||
test('should get data from previous run', async ({ }) => {
|
||||
expect(await store.get('number')).toBe(2022);
|
||||
expect(await store.get('object')).toEqual({ 'a': 2022 });
|
||||
expect(await store.get('number.json')).toBe(2022);
|
||||
expect(await store.get('object.json')).toEqual({ 'a': 2022 });
|
||||
});
|
||||
`,
|
||||
};
|
||||
@ -152,13 +152,13 @@ test('should load context storageState from store', async ({ runInlineTest, serv
|
||||
expect(await store.get('user')).toBe(undefined);
|
||||
await page.goto('${server.PREFIX}/setcookie.html');
|
||||
const state = await page.context().storageState();
|
||||
await store.set('user', state);
|
||||
await store.set('user.json', state);
|
||||
});
|
||||
`,
|
||||
'a.test.ts': `
|
||||
import { test, store, expect } from '@playwright/test';
|
||||
test.use({
|
||||
storageState: async ({}, use) => use(store.get('user'))
|
||||
storageState: async ({}, use) => use(store.get('user.json'))
|
||||
})
|
||||
test('should get data from setup', async ({ page }) => {
|
||||
await page.goto('${server.EMPTY_PAGE}');
|
||||
@ -290,3 +290,48 @@ test('should delete value', async ({ runInlineTest }) => {
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.passed).toBe(1);
|
||||
});
|
||||
|
||||
test('should support text, json and binary values', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'a.test.ts': `
|
||||
import { test, store, expect } from '@playwright/test';
|
||||
test('json', async ({ }) => {
|
||||
await store.set('key.json', {'a': 2023});
|
||||
expect(await store.get('key.json')).toEqual({ 'a': 2023 });
|
||||
});
|
||||
test('text', async ({ }) => {
|
||||
await store.set('key.txt', 'Hello');
|
||||
expect(await store.get('key.txt')).toEqual('Hello');
|
||||
});
|
||||
test('binary', async ({ }) => {
|
||||
const buf = Buffer.alloc(256);
|
||||
for (let i = 0; i < 256; i++)
|
||||
buf[i] = i;
|
||||
await store.set('key.png', buf);
|
||||
expect(await store.get('key.png')).toEqual(buf);
|
||||
});
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.passed).toBe(3);
|
||||
});
|
||||
|
||||
test('should throw on unsupported value type for given key extension', async ({ runInlineTest }) => {
|
||||
const result = await runInlineTest({
|
||||
'a.test.ts': `
|
||||
import { test, store, expect } from '@playwright/test';
|
||||
test('json', async ({ }) => {
|
||||
const buf = Buffer.alloc(5);
|
||||
await store.set('key.json', buf);
|
||||
});
|
||||
test('text', async ({ }) => {
|
||||
await store.set('key.txt', {});
|
||||
});
|
||||
test('binary', async ({ }) => {
|
||||
await store.set('key.png', {});
|
||||
});
|
||||
`,
|
||||
}, { workers: 1 });
|
||||
expect(result.exitCode).toBe(1);
|
||||
expect(result.failed).toBe(3);
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user